summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2015-03-23 21:07:10 +0000
committerCaolán McNamara <caolanm@redhat.com>2015-03-26 09:14:00 +0000
commit903a420609252aff12d9481b5fd8cc8d1f1d445f (patch)
tree1b5266949021523603134c793ae4f1d286980618
parent82f4f6b19febb607d8823923380777f27e0ab3d9 (diff)
add GtkSwipeGesture support and implement swipe left/right to change slides
keep it simple for now. deliver to the same target window that gets the MouseWheel events, maybe worth combining MouseWheel and Gestures into the same thing and use it in slideshows so swipe toward the left to advance to the next slide, to the right to return to the previous slide. swipes are followed by mouse up events, impress already has a similar hack to hide an mouse-up from the (incredibly complicated) interaction with the slideshow so simply use that Change-Id: Ib34f6fa0f15f3aa34eef887eb9d5642de9e5cdd1
-rw-r--r--include/vcl/cmdevt.hxx30
-rw-r--r--sd/source/ui/inc/slideshow.hxx2
-rw-r--r--sd/source/ui/slideshow/slideshow.cxx5
-rw-r--r--sd/source/ui/slideshow/slideshowimpl.cxx21
-rw-r--r--sd/source/ui/slideshow/slideshowimpl.hxx1
-rw-r--r--sd/source/ui/view/viewshel.cxx10
-rw-r--r--vcl/inc/salwtype.hxx10
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx3
-rw-r--r--vcl/source/window/winproc.cxx83
-rw-r--r--vcl/unx/gtk/window/gtksalframe.cxx30
10 files changed, 178 insertions, 17 deletions
diff --git a/include/vcl/cmdevt.hxx b/include/vcl/cmdevt.hxx
index 6e85c1ef8360..8e62e256fa73 100644
--- a/include/vcl/cmdevt.hxx
+++ b/include/vcl/cmdevt.hxx
@@ -336,10 +336,26 @@ inline CommandSelectionChangeData::CommandSelectionChangeData( sal_uLong nStart,
mnEnd = nEnd;
}
+class VCL_DLLPUBLIC CommandSwipeData
+{
+ double mnVelocityX;
+ double mnVelocityY;
+public:
+ CommandSwipeData()
+ : mnVelocityX(0)
+ , mnVelocityY(0)
+ {
+ }
+ CommandSwipeData(double nVelocityX, double nVelocityY)
+ : mnVelocityX(nVelocityX)
+ , mnVelocityY(nVelocityY)
+ {
+ }
+ double getVelocityX() const { return mnVelocityX; }
+ double getVelocityY() const { return mnVelocityY; }
+};
// - CommandEvent -
-
-
#define COMMAND_CONTEXTMENU ((sal_uInt16)1)
#define COMMAND_STARTDRAG ((sal_uInt16)2)
#define COMMAND_WHEEL ((sal_uInt16)3)
@@ -359,7 +375,7 @@ inline CommandSelectionChangeData::CommandSelectionChangeData( sal_uLong nStart,
#define COMMAND_SELECTIONCHANGE ((sal_uInt16)18)
#define COMMAND_PREPARERECONVERSION ((sal_uInt16)19)
#define COMMAND_QUERYCHARPOSITION ((sal_uInt16)20)
-
+#define COMMAND_SWIPE ((sal_uInt16)21)
class VCL_DLLPUBLIC CommandEvent
{
@@ -387,6 +403,7 @@ public:
const CommandDialogData* GetDialogData() const;
CommandMediaData* GetMediaData() const;
const CommandSelectionChangeData* GetSelectionChangeData() const;
+ const CommandSwipeData* GetSwipeData() const;
};
inline CommandEvent::CommandEvent()
@@ -469,6 +486,13 @@ inline const CommandSelectionChangeData* CommandEvent::GetSelectionChangeData()
return NULL;
}
+inline const CommandSwipeData* CommandEvent::GetSwipeData() const
+{
+ if( mnCommand == COMMAND_SWIPE )
+ return (const CommandSwipeData*)(mpData);
+ else
+ return NULL;
+}
#endif // INCLUDED_VCL_CMDEVT_HXX
diff --git a/sd/source/ui/inc/slideshow.hxx b/sd/source/ui/inc/slideshow.hxx
index f4cc6c2909c2..d6ef3ae77717 100644
--- a/sd/source/ui/inc/slideshow.hxx
+++ b/sd/source/ui/inc/slideshow.hxx
@@ -52,6 +52,7 @@ class Rectangle;
namespace vcl { class Window; }
class SfxRequest;
class WorkWindow;
+class CommandSwipeData;
struct ImplSVEvent;
// TODO: Remove
@@ -154,6 +155,7 @@ public:
/** sets or clears the pause state of the running slideshow.
!!!! This should only be called by the SdShowWindow !!!!*/
bool pause( bool bPause );
+ bool swipe(const CommandSwipeData &rSwipeData);
// settings
bool isFullScreen(); // a.k.a. FuSlideShow::IsFullScreen()
diff --git a/sd/source/ui/slideshow/slideshow.cxx b/sd/source/ui/slideshow/slideshow.cxx
index ff04b309fa9d..cfcf5e36fc35 100644
--- a/sd/source/ui/slideshow/slideshow.cxx
+++ b/sd/source/ui/slideshow/slideshow.cxx
@@ -1059,6 +1059,11 @@ bool SlideShow::isDrawingPossible()
return mxController.is() && mxController->getUsePen();
}
+bool SlideShow::swipe(const CommandSwipeData& rSwipeData)
+{
+ return mxController.is() && mxController->swipe(rSwipeData);
+}
+
void SlideShow::StartInPlacePresentationConfigurationCallback()
{
if( mnInPlaceConfigEvent != 0 )
diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx b/sd/source/ui/slideshow/slideshowimpl.cxx
index b4220e299704..fdbff3f78d68 100644
--- a/sd/source/ui/slideshow/slideshowimpl.cxx
+++ b/sd/source/ui/slideshow/slideshowimpl.cxx
@@ -1109,6 +1109,7 @@ bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProp
try
{
mxShow = Reference< XSlideShow >( createSlideShow(), UNO_QUERY_THROW );
+
mxView = new SlideShowView(
*mpShowWindow,
mpDoc,
@@ -1232,6 +1233,26 @@ void SlideshowImpl::slideEnded(const bool bReverse)
gotoNextSlide();
}
+bool SlideshowImpl::swipe(const CommandSwipeData &rSwipeData)
+{
+ if (mbUsePen)
+ return false;
+
+ double nVelocityX = rSwipeData.getVelocityX();
+ if (nVelocityX > 0)
+ {
+ gotoPreviousSlide();
+ }
+ else
+ {
+ gotoNextEffect();
+ }
+ //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
+ //to the swipe instead
+ mxView->ignoreNextMouseReleased();
+ return true;
+}
+
void SlideshowImpl::removeShapeEvents()
{
if( mxShow.is() && mxListenerProxy.is() ) try
diff --git a/sd/source/ui/slideshow/slideshowimpl.hxx b/sd/source/ui/slideshow/slideshowimpl.hxx
index 5506007286f8..97fe5e3342f3 100644
--- a/sd/source/ui/slideshow/slideshowimpl.hxx
+++ b/sd/source/ui/slideshow/slideshowimpl.hxx
@@ -218,6 +218,7 @@ public:
void slideEnded(const bool bReverse);
void hyperLinkClicked(const OUString & hyperLink) throw (css::uno::RuntimeException);
void click(const css::uno::Reference< css::drawing::XShape > & xShape, const css::awt::MouseEvent & aOriginalEvent);
+ bool swipe(const CommandSwipeData &rSwipeData);
/// ends the presentation async
void endPresentation();
diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx
index feb3b11973c8..22fc056d9345 100644
--- a/sd/source/ui/view/viewshel.cxx
+++ b/sd/source/ui/view/viewshel.cxx
@@ -641,6 +641,16 @@ bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi
switch( rCEvt.GetCommand() )
{
+ case COMMAND_SWIPE:
+ {
+ rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
+ if (xSlideShow.is())
+ {
+ const CommandSwipeData* pSwipeData = rCEvt.GetSwipeData();
+ bDone = xSlideShow->swipe(*pSwipeData);
+ }
+ }
+ break;
case COMMAND_WHEEL:
{
Reference< XSlideShowController > xSlideShowController( SlideShow::GetSlideShowController(GetViewShellBase() ) );
diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx
index 9b394c42895d..febc4c217c86 100644
--- a/vcl/inc/salwtype.hxx
+++ b/vcl/inc/salwtype.hxx
@@ -78,6 +78,7 @@ class FontSelectPattern;
#define SALEVENT_EXTERNALZOOM ((sal_uInt16)46)
#define SALEVENT_EXTERNALSCROLL ((sal_uInt16)47)
#define SALEVENT_QUERYCHARPOSITION ((sal_uInt16)48)
+#define SALEVENT_SWIPE ((sal_uInt16)49)
// MOUSELEAVE must send, when the pointer leave the client area and
// the mouse is not captured
@@ -278,6 +279,15 @@ struct SalInputContext
sal_uLong mnOptions;
};
+struct SalSwipeEvent
+{
+ double mnVelocityX;
+ double mnVelocityY;
+ long mnX;
+ long mnY;
+};
+
+
typedef void (*SALTIMERPROC)( bool idle );
#endif // INCLUDED_VCL_INC_SALWTYPE_HXX
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index d5148b757dff..53fec5834a84 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -237,6 +237,9 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
static void signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer );
#if GTK_CHECK_VERSION(3,0,0)
static gboolean signalDraw( GtkWidget*, cairo_t *cr, gpointer );
+#if GTK_CHECK_VERSION(3,14,0)
+ static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
+#endif
#else
static gboolean signalExpose( GtkWidget*, GdkEventExpose*, gpointer );
#endif
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
index e58bfe0f3ab6..bd333580a6e2 100644
--- a/vcl/source/window/winproc.cxx
+++ b/vcl/source/window/winproc.cxx
@@ -633,6 +633,7 @@ bool ImplHandleMouseEvent( vcl::Window* pWindow, MouseNotifyEvent nSVEvent, bool
Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
+
// tracking window gets the mouse events
if ( pSVData->maWinData.mpTrackWin )
pChild = pSVData->maWinData.mpTrackWin;
@@ -1374,13 +1375,12 @@ static bool shouldReusePreviousMouseWindow(const SalWheelMouseEvent& rPrevEvt, c
return (rEvt.mnX == rPrevEvt.mnX && rEvt.mnY == rPrevEvt.mnY && rEvt.mnTime-rPrevEvt.mnTime < 500/*ms*/);
}
-class HandleWheelEvent
+class HandleGestureEvent
{
-private:
+protected:
ImplSVData* m_pSVData;
vcl::Window *m_pWindow;
Point m_aMousePos;
- CommandWheelData m_aWheelData;
public:
@@ -1395,10 +1395,27 @@ public:
}
};
- HandleWheelEvent(vcl::Window *pWindow, const SalWheelMouseEvent& rEvt, bool bScaleDirectly)
+ HandleGestureEvent(vcl::Window *pWindow, const Point &rMousePos)
: m_pSVData(ImplGetSVData())
, m_pWindow(pWindow)
- , m_aMousePos(rEvt.mnX, rEvt.mnY)
+ , m_aMousePos(rMousePos)
+ {
+ }
+ bool Setup();
+ WindowDescription FindTarget();
+ vcl::Window *Dispatch(const WindowDescription& rTarget);
+ virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) = 0;
+ void Teardown(const WindowDescription& rTarget);
+ virtual ~HandleGestureEvent() {}
+};
+
+class HandleWheelEvent : public HandleGestureEvent
+{
+private:
+ CommandWheelData m_aWheelData;
+public:
+ HandleWheelEvent(vcl::Window *pWindow, const SalWheelMouseEvent& rEvt, bool bScaleDirectly)
+ : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY))
{
CommandWheelMode nMode;
sal_uInt16 nCode = rEvt.mnCode;
@@ -1421,18 +1438,14 @@ public:
m_aWheelData = CommandWheelData(rEvt.mnDelta, rEvt.mnNotchDelta, rEvt.mnScrollLines, nMode, nCode, bHorz, bPixel);
}
- bool Setup();
- WindowDescription FindTarget();
- vcl::Window *Dispatch(const WindowDescription& rTarget);
- bool CallCommand(vcl::Window *pWindow, const Point &rMousePos)
+ virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) SAL_OVERRIDE
{
return ImplCallWheelCommand(pWindow, rMousePos, &m_aWheelData);
}
bool HandleEvent(const SalWheelMouseEvent& rEvt);
- void Teardown(const WindowDescription& rTarget);
};
-bool HandleWheelEvent::Setup()
+bool HandleGestureEvent::Setup()
{
ImplDelData aDogTag( m_pWindow );
@@ -1445,7 +1458,7 @@ bool HandleWheelEvent::Setup()
return true;
}
-HandleWheelEvent::WindowDescription HandleWheelEvent::FindTarget()
+HandleGestureEvent::WindowDescription HandleGestureEvent::FindTarget()
{
// first check any floating window ( eg. drop down listboxes)
bool bIsFloat = false;
@@ -1482,7 +1495,7 @@ HandleWheelEvent::WindowDescription HandleWheelEvent::FindTarget()
return WindowDescription(pMouseWindow, bIsFloat);
}
-vcl::Window *HandleWheelEvent::Dispatch(const WindowDescription& rTarget)
+vcl::Window *HandleGestureEvent::Dispatch(const WindowDescription& rTarget)
{
vcl::Window *pMouseWindow = rTarget.m_pMouseWindow;
@@ -1524,7 +1537,7 @@ vcl::Window *HandleWheelEvent::Dispatch(const WindowDescription& rTarget)
return pDispatchedTo;
}
-void HandleWheelEvent::Teardown(const WindowDescription& rTarget)
+void HandleGestureEvent::Teardown(const WindowDescription& rTarget)
{
// close floaters
if (!rTarget.m_bIsFloat && m_pSVData->maWinData.mpFirstFloat)
@@ -1574,6 +1587,43 @@ static bool ImplHandleWheelEvent( vcl::Window* pWindow, const SalWheelMouseEvent
return aHandler.HandleEvent(rEvt);
}
+class HandleSwipeEvent : public HandleGestureEvent
+{
+private:
+ CommandSwipeData m_aSwipeData;
+public:
+ HandleSwipeEvent(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
+ : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY))
+ {
+ m_aSwipeData = CommandSwipeData(rEvt.mnVelocityX, rEvt.mnVelocityY);
+ }
+ virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) SAL_OVERRIDE
+ {
+ return ImplCallCommand(pWindow, COMMAND_SWIPE, &m_aSwipeData);
+ }
+ bool HandleEvent();
+};
+
+bool HandleSwipeEvent::HandleEvent()
+{
+ if (!Setup())
+ return false;
+
+ WindowDescription aTarget = FindTarget();
+
+ bool bHandled = Dispatch(aTarget) != NULL;
+
+ Teardown(aTarget);
+
+ return bHandled;
+}
+
+static bool ImplHandleSwipe(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
+{
+ HandleSwipeEvent aHandler(pWindow, rEvt);
+ return aHandler.HandleEvent();
+}
+
#define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020)
static void ImplHandlePaint( vcl::Window* pWindow, const Rectangle& rBoundRect, bool bImmediateUpdate )
@@ -2618,6 +2668,11 @@ bool ImplWindowFrameProc( vcl::Window* pWindow, SalFrame* /*pFrame*/,
case SALEVENT_QUERYCHARPOSITION:
ImplHandleSalQueryCharPosition( pWindow, (SalQueryCharPositionEvent*)pEvent );
break;
+
+ case SALEVENT_SWIPE:
+ nRet = ImplHandleSwipe(pWindow, *(const SalSwipeEvent*)pEvent);
+ break;
+
#ifdef DBG_UTIL
default:
SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << nEvent << ")" );
diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx
index b678d819283d..0c5ff07c0500 100644
--- a/vcl/unx/gtk/window/gtksalframe.cxx
+++ b/vcl/unx/gtk/window/gtksalframe.cxx
@@ -989,6 +989,13 @@ void GtkSalFrame::InitCommon()
g_signal_connect( G_OBJECT(m_pWindow), "button-release-event", G_CALLBACK(signalButton), this );
#if GTK_CHECK_VERSION(3,0,0)
g_signal_connect( G_OBJECT(m_pWindow), "draw", G_CALLBACK(signalDraw), this );
+#if GTK_CHECK_VERSION(3,14,0)
+ GtkGesture *pSwipe = gtk_gesture_swipe_new(m_pWindow);
+ g_signal_connect(pSwipe, "swipe", G_CALLBACK(gestureSwipe), this);
+ gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER (pSwipe), GTK_PHASE_TARGET);
+ g_object_weak_ref(G_OBJECT(m_pWindow), (GWeakNotify)g_object_unref, pSwipe);
+#endif
+
#else
g_signal_connect( G_OBJECT(m_pWindow), "expose-event", G_CALLBACK(signalExpose), this );
#endif
@@ -3170,6 +3177,7 @@ bool GtkSalFrame::Dispatch( const XEvent* pEvent )
gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
{
GtkSalFrame* pThis = (GtkSalFrame*)frame;
+
SalMouseEvent aEvent;
sal_uInt16 nEventType = 0;
switch( pEvent->type )
@@ -3297,6 +3305,28 @@ gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEvent* pEvent, gpointer frame
return true;
}
+#if GTK_CHECK_VERSION(3,14,0)
+void GtkSalFrame::gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame)
+{
+ GtkSalFrame* pThis = (GtkSalFrame*)frame;
+
+ SalSwipeEvent aEvent;
+ aEvent.mnVelocityX = velocity_x;
+ aEvent.mnVelocityY = velocity_y;
+
+ gdouble x, y;
+ GdkEventSequence *sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
+ //I feel I want the first point of the sequence, not the last point which
+ //the docs say this gives, but for the moment assume we start and end
+ //within the same vcl window
+ gtk_gesture_get_point(GTK_GESTURE(gesture), sequence, &x, &y);
+ aEvent.mnX = x;
+ aEvent.mnY = y;
+
+ pThis->CallCallback(SALEVENT_SWIPE, &aEvent);
+}
+#endif
+
gboolean GtkSalFrame::signalMotion( GtkWidget*, GdkEventMotion* pEvent, gpointer frame )
{
GtkSalFrame* pThis = (GtkSalFrame*)frame;