Merge branch 'gesture-events'
Integrate GSoC 2017 work by Prashant Kumar implementing support for gesture events. Closes https://github.com/wxWidgets/wxWidgets/pull/551 Closes https://github.com/wxWidgets/wxWidgets/pull/565
This commit is contained in:
@@ -3104,6 +3104,12 @@ DECLARE_WXCOCOA_OBJC_CLASS(NSView);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSOpenGLContext);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSOpenGLPixelFormat);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS( NSPrintInfo );
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSGestureRecognizer);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSPanGestureRecognizer);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSMagnificationGestureRecognizer);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSRotationGestureRecognizer);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSPressGestureRecognizer);
|
||||
DECLARE_WXCOCOA_OBJC_CLASS(NSTouch);
|
||||
#endif /* __WXMAC__ &__DARWIN__ */
|
||||
|
||||
#ifdef __WXMAC__
|
||||
@@ -3267,6 +3273,7 @@ typedef struct _GdkDragContext GdkDragContext;
|
||||
|
||||
#if defined(__WXGTK3__)
|
||||
typedef struct _GdkWindow GdkWindow;
|
||||
typedef struct _GdkEventSequence GdkEventSequence;
|
||||
#elif defined(__WXGTK20__)
|
||||
typedef struct _GdkDrawable GdkWindow;
|
||||
typedef struct _GdkDrawable GdkPixmap;
|
||||
|
@@ -631,6 +631,13 @@ class WXDLLIMPEXP_FWD_CORE wxInitDialogEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxUpdateUIEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxClipboardTextEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxHelpEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxGestureEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxPanGestureEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxZoomGestureEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxRotateGestureEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxTwoFingerTapEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxLongPressEvent;
|
||||
class WXDLLIMPEXP_FWD_CORE wxPressAndTapEvent;
|
||||
|
||||
|
||||
// Command events
|
||||
@@ -736,6 +743,14 @@ wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SCROLLWIN_PAGEDOWN, wxScrollWin
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEvent);
|
||||
|
||||
// Gesture events
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_GESTURE_PAN, wxPanGestureEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_GESTURE_ZOOM, wxZoomGestureEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_GESTURE_ROTATE, wxRotateGestureEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_TWO_FINGER_TAP, wxTwoFingerTapEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LONG_PRESS, wxLongPressEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_PRESS_AND_TAP, wxPressAndTapEvent);
|
||||
|
||||
// System events
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SIZE, wxSizeEvent);
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_MOVE, wxMoveEvent);
|
||||
@@ -1850,6 +1865,197 @@ private:
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSetCursorEvent);
|
||||
};
|
||||
|
||||
// Gesture Event
|
||||
|
||||
const unsigned int wxTwoFingerTimeInterval = 200;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGestureEvent : public wxEvent
|
||||
{
|
||||
public:
|
||||
wxGestureEvent(wxWindowID winid = 0, wxEventType type = wxEVT_NULL)
|
||||
: wxEvent(winid, type)
|
||||
{
|
||||
m_isStart = false;
|
||||
m_isEnd = false;
|
||||
}
|
||||
|
||||
wxGestureEvent(const wxGestureEvent& event) : wxEvent(event)
|
||||
{
|
||||
m_pos = event.m_pos;
|
||||
m_isStart = event.m_isStart;
|
||||
m_isEnd = event.m_isEnd;
|
||||
}
|
||||
|
||||
const wxPoint& GetPosition() const { return m_pos; }
|
||||
void SetPosition(const wxPoint& pos) { m_pos = pos; }
|
||||
bool IsGestureStart() const { return m_isStart; }
|
||||
void SetGestureStart(bool isStart = true) { m_isStart = isStart; }
|
||||
bool IsGestureEnd() const { return m_isEnd; }
|
||||
void SetGestureEnd(bool isEnd = true) { m_isEnd = isEnd; }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxGestureEvent(*this); }
|
||||
|
||||
protected:
|
||||
wxPoint m_pos;
|
||||
bool m_isStart, m_isEnd;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxGestureEvent);
|
||||
|
||||
};
|
||||
|
||||
// Pan Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_GESTURE_PAN
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxPanGestureEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxPanGestureEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_GESTURE_PAN)
|
||||
{
|
||||
}
|
||||
|
||||
wxPanGestureEvent(const wxPanGestureEvent& event)
|
||||
: wxGestureEvent(event),
|
||||
m_delta(event.m_delta)
|
||||
{
|
||||
}
|
||||
|
||||
wxPoint GetDelta() const { return m_delta; }
|
||||
void SetDelta(const wxPoint& delta) { m_delta = delta; }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxPanGestureEvent(*this); }
|
||||
|
||||
private:
|
||||
wxPoint m_delta;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxPanGestureEvent);
|
||||
};
|
||||
|
||||
// Zoom Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_GESTURE_ZOOM
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxZoomGestureEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxZoomGestureEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_GESTURE_ZOOM)
|
||||
{ m_zoomFactor = 1.0; }
|
||||
|
||||
wxZoomGestureEvent(const wxZoomGestureEvent& event) : wxGestureEvent(event)
|
||||
{
|
||||
m_zoomFactor = event.m_zoomFactor;
|
||||
}
|
||||
|
||||
double GetZoomFactor() const { return m_zoomFactor; }
|
||||
void SetZoomFactor(double zoomFactor) { m_zoomFactor = zoomFactor; }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxZoomGestureEvent(*this); }
|
||||
|
||||
private:
|
||||
double m_zoomFactor;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxZoomGestureEvent);
|
||||
};
|
||||
|
||||
// Rotate Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_GESTURE_ROTATE
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRotateGestureEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxRotateGestureEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_GESTURE_ROTATE)
|
||||
{ m_rotationAngle = 0.0; }
|
||||
|
||||
wxRotateGestureEvent(const wxRotateGestureEvent& event) : wxGestureEvent(event)
|
||||
{
|
||||
m_rotationAngle = event.m_rotationAngle;
|
||||
}
|
||||
|
||||
double GetRotationAngle() const { return m_rotationAngle; }
|
||||
void SetRotationAngle(double rotationAngle) { m_rotationAngle = rotationAngle; }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxRotateGestureEvent(*this); }
|
||||
|
||||
private:
|
||||
double m_rotationAngle;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxRotateGestureEvent);
|
||||
};
|
||||
|
||||
// Two Finger Tap Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_TWO_FINGER_TAP
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxTwoFingerTapEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxTwoFingerTapEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_TWO_FINGER_TAP)
|
||||
{ }
|
||||
|
||||
wxTwoFingerTapEvent(const wxTwoFingerTapEvent& event) : wxGestureEvent(event)
|
||||
{ }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxTwoFingerTapEvent(*this); }
|
||||
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxTwoFingerTapEvent);
|
||||
};
|
||||
|
||||
// Long Press Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_LONG_PRESS
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxLongPressEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxLongPressEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_LONG_PRESS)
|
||||
{ }
|
||||
|
||||
wxLongPressEvent(const wxLongPressEvent& event) : wxGestureEvent(event)
|
||||
{ }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxLongPressEvent(*this); }
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxLongPressEvent);
|
||||
};
|
||||
|
||||
// Press And Tap Gesture Event
|
||||
|
||||
/*
|
||||
wxEVT_PRESS_AND_TAP
|
||||
*/
|
||||
|
||||
class WXDLLIMPEXP_CORE wxPressAndTapEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
wxPressAndTapEvent(wxWindowID winid = 0)
|
||||
: wxGestureEvent(winid, wxEVT_PRESS_AND_TAP)
|
||||
{ }
|
||||
|
||||
wxPressAndTapEvent(const wxPressAndTapEvent& event) : wxGestureEvent(event)
|
||||
{ }
|
||||
|
||||
virtual wxEvent *Clone() const { return new wxPressAndTapEvent(*this); }
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxPressAndTapEvent);
|
||||
};
|
||||
|
||||
// Keyboard input event class
|
||||
|
||||
/*
|
||||
@@ -3908,7 +4114,12 @@ typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
|
||||
typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
|
||||
typedef void (wxEvtHandler::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
|
||||
typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&);
|
||||
|
||||
typedef void (wxEvtHandler::*wxPanGestureEventFunction)(wxPanGestureEvent&);
|
||||
typedef void (wxEvtHandler::*wxZoomGestureEventFunction)(wxZoomGestureEvent&);
|
||||
typedef void (wxEvtHandler::*wxRotateGestureEventFunction)(wxRotateGestureEvent&);
|
||||
typedef void (wxEvtHandler::*wxTwoFingerTapEventFunction)(wxTwoFingerTapEvent&);
|
||||
typedef void (wxEvtHandler::*wxLongPressEventFunction)(wxLongPressEvent&);
|
||||
typedef void (wxEvtHandler::*wxPressAndTapEventFunction)(wxPressAndTapEvent&);
|
||||
|
||||
#define wxCommandEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
|
||||
@@ -3983,6 +4194,18 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
||||
wxEVENT_HANDLER_CAST(wxMouseCaptureLostEventFunction, func)
|
||||
#define wxClipboardTextEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxClipboardTextEventFunction, func)
|
||||
#define wxPanGestureEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxPanGestureEventFunction, func)
|
||||
#define wxZoomGestureEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxZoomGestureEventFunction, func)
|
||||
#define wxRotateGestureEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxRotateGestureEventFunction, func)
|
||||
#define wxTwoFingerTapEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxTwoFingerTapEventFunction, func)
|
||||
#define wxLongPressEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxLongPressEventFunction, func)
|
||||
#define wxPressAndTapEvent(func) \
|
||||
wxEVENT_HANDLER_CAST(wxPressAndTapEventFunction, func)
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
@@ -4317,6 +4540,14 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
||||
EVT_COMMAND_SCROLL_THUMBRELEASE(winid, func) \
|
||||
EVT_COMMAND_SCROLL_CHANGED(winid, func)
|
||||
|
||||
// Gesture events
|
||||
#define EVT_GESTURE_PAN(winid, func) wx__DECLARE_EVT1(wxEVT_GESTURE_PAN, winid, wxPanGestureEventHandler(func))
|
||||
#define EVT_GESTURE_ZOOM(winid, func) wx__DECLARE_EVT1(wxEVT_GESTURE_ZOOM, winid, wxZoomGestureEventHandler(func))
|
||||
#define EVT_GESTURE_ROTATE(winid, func) wx__DECLARE_EVT1(wxEVT_GESTURE_ROTATE, winid, wxRotateGestureEventHandler(func))
|
||||
#define EVT_TWO_FINGER_TAP(winid, func) wx__DECLARE_EVT1(wxEVT_TWO_FINGER_TAP, winid, wxTwoFingerTapEventHandler(func))
|
||||
#define EVT_LONG_PRESS(winid, func) wx__DECLARE_EVT1(wxEVT_LONG_PRESS, winid, wxLongPressEventHandler(func))
|
||||
#define EVT_PRESS_AND_TAP(winid, func) wx__DECLARE_EVT1(wxEVT_PRESS_AND_TAP, winid, wxPressAndTapEvent(func))
|
||||
|
||||
// Convenience macros for commonly-used commands
|
||||
#define EVT_CHECKBOX(winid, func) wx__DECLARE_EVT1(wxEVT_CHECKBOX, winid, wxCommandEventHandler(func))
|
||||
#define EVT_CHOICE(winid, func) wx__DECLARE_EVT1(wxEVT_CHOICE, winid, wxCommandEventHandler(func))
|
||||
|
@@ -77,6 +77,9 @@ public:
|
||||
virtual bool Reparent( wxWindowBase *newParent ) wxOVERRIDE;
|
||||
|
||||
virtual void WarpPointer(int x, int y) wxOVERRIDE;
|
||||
#ifdef __WXGTK3__
|
||||
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
|
||||
#endif // __WXGTK3__
|
||||
|
||||
virtual void Refresh( bool eraseBackground = true,
|
||||
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
||||
|
@@ -100,6 +100,7 @@ public:
|
||||
virtual bool Reparent(wxWindowBase *newParent) wxOVERRIDE;
|
||||
|
||||
virtual void WarpPointer(int x, int y) wxOVERRIDE;
|
||||
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
|
||||
|
||||
virtual void Refresh( bool eraseBackground = true,
|
||||
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
||||
@@ -360,6 +361,16 @@ public:
|
||||
bool HandleMouseWheel(wxMouseWheelAxis axis,
|
||||
WXWPARAM wParam, WXLPARAM lParam);
|
||||
|
||||
// Common gesture event initialization, returns true if it is the initial
|
||||
// event (GF_BEGIN set in flags), false otherwise.
|
||||
bool InitGestureEvent(wxGestureEvent& event, const wxPoint& pt, WXDWORD flags);
|
||||
|
||||
bool HandlePanGesture(const wxPoint& pt, WXDWORD flags);
|
||||
bool HandleZoomGesture(const wxPoint& pt, WXDWORD fingerDistance, WXDWORD flags);
|
||||
bool HandleRotateGesture(const wxPoint& pt, WXDWORD angleArgument, WXDWORD flags);
|
||||
bool HandleTwoFingerTap(const wxPoint& pt, WXDWORD flags);
|
||||
bool HandlePressAndTap(const wxPoint& pt, WXDWORD flags);
|
||||
|
||||
bool HandleChar(WXWPARAM wParam, WXLPARAM lParam);
|
||||
bool HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam);
|
||||
bool HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam);
|
||||
|
@@ -128,6 +128,7 @@ public :
|
||||
void SetToolTip( wxToolTip* tooltip );
|
||||
|
||||
void InstallEventHandler( WXWidget control = NULL );
|
||||
bool EnableTouchEvents(int eventsMask);
|
||||
|
||||
virtual bool ShouldHandleKeyNavigation(const wxKeyEvent &event) const;
|
||||
bool DoHandleKeyNavigation(const wxKeyEvent &event);
|
||||
@@ -143,6 +144,15 @@ public :
|
||||
void SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent *nsEvent);
|
||||
virtual bool SetupCursor(NSEvent* event);
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
virtual void PanGestureEvent(NSPanGestureRecognizer *panGestureRecognizer);
|
||||
virtual void ZoomGestureEvent(NSMagnificationGestureRecognizer *magnificationGestureRecognizer);
|
||||
virtual void RotateGestureEvent(NSRotationGestureRecognizer *rotationGestureRecognizer);
|
||||
virtual void LongPressEvent(NSPressGestureRecognizer *pressGestureRecognizer);
|
||||
virtual void TouchesBegan(NSEvent *event);
|
||||
virtual void TouchesMoved(NSEvent *event);
|
||||
virtual void TouchesEnded(NSEvent *event);
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
|
||||
#if !wxOSX_USE_NATIVE_FLIPPED
|
||||
void SetFlipped(bool flipped);
|
||||
|
@@ -326,6 +326,8 @@ public :
|
||||
|
||||
virtual void InstallEventHandler( WXWidget control = NULL ) = 0;
|
||||
|
||||
virtual bool EnableTouchEvents(int eventsMask) = 0;
|
||||
|
||||
// Mechanism used to keep track of whether a change should send an event
|
||||
// Do SendEvents(false) when starting actions that would trigger programmatic events
|
||||
// and SendEvents(true) at the end of the block.
|
||||
|
@@ -105,6 +105,7 @@ public :
|
||||
void SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack = true );
|
||||
|
||||
void InstallEventHandler( WXWidget control = NULL );
|
||||
bool EnableTouchEvents(int WXUNUSED(eventsMask)) { return false; }
|
||||
|
||||
virtual void DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow);
|
||||
|
||||
|
@@ -77,6 +77,7 @@ public:
|
||||
virtual void SetFocus() wxOVERRIDE;
|
||||
|
||||
virtual void WarpPointer( int x, int y ) wxOVERRIDE;
|
||||
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
|
||||
|
||||
virtual void Refresh( bool eraseBackground = true,
|
||||
const wxRect *rect = NULL ) wxOVERRIDE;
|
||||
|
84
include/wx/private/extfield.h
Normal file
84
include/wx/private/extfield.h
Normal file
@@ -0,0 +1,84 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/private/extfield.h
|
||||
// Purpose: Declare wxExternalField helper
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2017-11-21
|
||||
// Copyright: (c) 2017 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_PRIVATE_EXTFIELD_H_
|
||||
#define _WX_PRIVATE_EXTFIELD_H_
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxExternalField: store object data outside of it
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This class allows to store some data without consuming space for the objects
|
||||
// that don't need it and can be useful for avoiding to add rarely used fields
|
||||
// to the classes that are used by many objects, e.g. wxWindow.
|
||||
//
|
||||
// Note that using this class costs in speed and convenience of access to the
|
||||
// field, which requires a hash lookup instead of accessing it directly. It
|
||||
// also only currently works for heap-allocated fields as it's probably never
|
||||
// worth using it for fields of simple types.
|
||||
//
|
||||
// Template parameter Object is the class that "contains" the field, Field is
|
||||
// the type of the field itself and FieldMap is the hash map, defined
|
||||
// separately using WX_DECLARE_HASH_MAP(), with Object* as the key and Field*
|
||||
// as the value type.
|
||||
template <typename Object, typename Field, typename FieldMap>
|
||||
class wxExternalField
|
||||
{
|
||||
public:
|
||||
typedef Object ObjectType;
|
||||
typedef Field FieldType;
|
||||
typedef FieldMap MapType;
|
||||
|
||||
// Store the field object to be used for the given object, replacing the
|
||||
// existing one, if any.
|
||||
//
|
||||
// This method takes ownership of the field pointer which will be destroyed
|
||||
// by EraseForObject().
|
||||
static void StoreForObject(ObjectType* obj, FieldType* field)
|
||||
{
|
||||
const typename MapType::iterator it = ms_map.find(obj);
|
||||
if ( it != ms_map.end() )
|
||||
{
|
||||
delete it->second;
|
||||
it->second = field;
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_map.insert(typename MapType::value_type(obj, field));
|
||||
}
|
||||
}
|
||||
|
||||
// Find the object for the corresponding window.
|
||||
static FieldType* FromObject(ObjectType* obj)
|
||||
{
|
||||
const typename MapType::const_iterator it = ms_map.find(obj);
|
||||
return it == ms_map.end() ? NULL : it->second;
|
||||
}
|
||||
|
||||
// Erase the object used for the corresponding window, return true if there
|
||||
// was one or false otherwise.
|
||||
static bool EraseForObject(ObjectType* obj)
|
||||
{
|
||||
const typename MapType::iterator it = ms_map.find(obj);
|
||||
if ( it == ms_map.end() )
|
||||
return false;
|
||||
|
||||
delete it->second;
|
||||
ms_map.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static FieldMap ms_map;
|
||||
};
|
||||
|
||||
template <typename O, typename F, typename M>
|
||||
M wxExternalField<O, F, M>::ms_map;
|
||||
|
||||
#endif // _WX_PRIVATE_EXTFIELD_H_
|
@@ -133,6 +133,20 @@ enum wxShowEffect
|
||||
wxSHOW_EFFECT_MAX
|
||||
};
|
||||
|
||||
// Values for EnableTouchEvents() mask.
|
||||
enum
|
||||
{
|
||||
wxTOUCH_NONE = 0x0000,
|
||||
wxTOUCH_VERTICAL_PAN_GESTURE = 0x0001,
|
||||
wxTOUCH_HORIZONTAL_PAN_GESTURE = 0x0002,
|
||||
wxTOUCH_PAN_GESTURES = wxTOUCH_VERTICAL_PAN_GESTURE |
|
||||
wxTOUCH_HORIZONTAL_PAN_GESTURE,
|
||||
wxTOUCH_ZOOM_GESTURE = 0x0004,
|
||||
wxTOUCH_ROTATE_GESTURE = 0x0008,
|
||||
wxTOUCH_PRESS_GESTURES = 0x0010,
|
||||
wxTOUCH_ALL_GESTURES = 0x001f
|
||||
};
|
||||
|
||||
// flags for SendSizeEvent()
|
||||
enum
|
||||
{
|
||||
@@ -1033,6 +1047,13 @@ public:
|
||||
virtual bool HasCapture() const
|
||||
{ return (wxWindow *)this == GetCapture(); }
|
||||
|
||||
// enable the specified touch events for this window, return false if
|
||||
// the requested events are not supported
|
||||
virtual bool EnableTouchEvents(int WXUNUSED(eventsMask))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// painting the window
|
||||
// -------------------
|
||||
|
||||
|
@@ -3644,6 +3644,251 @@ public:
|
||||
void SetPosition(int pos);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** @class wxGestureEvent
|
||||
This is the base class for all supported gesture events.
|
||||
|
||||
@note Gesture events are not generated by default, you must call
|
||||
wxWindow::EnableTouchEvents() with the appropriate parameter to
|
||||
request their generation.
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@see wxPanGestureEvent, wxZoomGestureEvent, wxRotateGestureEvent
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxGestureEvent : public wxEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxGestureEvent(wxWindowID winid = 0, wxEventType type = wxEVT_NULL);
|
||||
|
||||
/**
|
||||
Returns the position where the event took effect, in client coordinates: position of Pan event,
|
||||
center of zoom for Zoom event, center of rotation for Rotate event, center of box formed by 2 fingers
|
||||
for Two Finger Tap event and position of the pressed finger for Press and Tap Event.
|
||||
*/
|
||||
const wxPoint& GetPosition() const;
|
||||
|
||||
/**
|
||||
Returns true if the event was the first in a gesture sequence.
|
||||
*/
|
||||
bool IsGestureStart() const;
|
||||
|
||||
/**
|
||||
Returns true if the event was the last in a gesture sequence.
|
||||
*/
|
||||
bool IsGestureEnd() const;
|
||||
|
||||
/**
|
||||
Sets the position where the event took effect, in client coordinates: position of Pan event,
|
||||
center of zoom for Zoom event, center of rotation for Rotate event.
|
||||
*/
|
||||
void SetPosition(const wxPoint& pos);
|
||||
|
||||
/**
|
||||
Sets the event to be the first in a gesture sequence.
|
||||
*/
|
||||
void SetGestureStart(bool isStart = true);
|
||||
|
||||
/**
|
||||
Sets the event to be the last in a gesture sequence.
|
||||
*/
|
||||
void SetGestureEnd(bool isEnd = true);
|
||||
};
|
||||
|
||||
|
||||
/** @class wxPanGestureEvent
|
||||
|
||||
This event is generated when the user moves a finger on the surface.
|
||||
|
||||
wxGTK also generates this event during mouse dragging (mouse motion while a left mouse button is depressed).
|
||||
|
||||
Note that OSX requires the primary mouse button to be pressed while performing the finger movement.
|
||||
|
||||
@beginEventTable{wxPanGestureEvent}
|
||||
@event{EVT_GESTURE_PAN(id, func)}
|
||||
Process a @c wxEVT_GESTURE_PAN.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxPanGestureEvent : class wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxPanGestureEvent(wxWindowID winid = 0);
|
||||
|
||||
/**
|
||||
Returns the distance covered since the previous panning event.
|
||||
*/
|
||||
wxPoint GetDelta() const;
|
||||
|
||||
/**
|
||||
Sets the distance covered since the previous panning event.
|
||||
*/
|
||||
void SetDelta(const wxPoint& delta);
|
||||
};
|
||||
|
||||
|
||||
/** @class wxZoomGestureEvent
|
||||
|
||||
This event is generated when two fingers pinch the surface to zoom in or out.
|
||||
|
||||
@beginEventTable{wxZoomGestureEvent}
|
||||
@event{EVT_GESTURE_ZOOM(id, func)}
|
||||
Process a @c wxEVT_GESTURE_ZOOM.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxZoomGestureEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxZoomGestureEvent(wxWindowID windid = 0);
|
||||
|
||||
/**
|
||||
Returns the zoom Factor since the gesture started. Hence, starting of the gesture
|
||||
is considered as 1:1. A value greater than 1.0 means we should enlarge
|
||||
(or zoom in), a value less than 1.0 means we should shrink (or zoom out).
|
||||
*/
|
||||
double GetZoomFactor() const;
|
||||
|
||||
/**
|
||||
Sets the zoom Factor.
|
||||
*/
|
||||
double SetZoomFactor() const;
|
||||
};
|
||||
|
||||
|
||||
/** @class wxRotateGestureEvent
|
||||
|
||||
This event is generated when two fingers move in opposite directions on the surface.
|
||||
|
||||
@beginEventTable{wxRotateGestureEvent}
|
||||
@event{EVT_GESTURE_ROTATE(id, func)}
|
||||
Process a @c wxEVT_GESTURE_ROTATE.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxRotateGestureEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxRotateGestureEvent(wxWindowID windid = 0);
|
||||
|
||||
/**
|
||||
Returns the total angle of rotation in radians in clockwise direction since the
|
||||
gesture was first started i.e. when IsGestureStart() returned true. This value is always
|
||||
greater than or equal to zero.
|
||||
*/
|
||||
double GetRotationAngle() const;
|
||||
|
||||
/**
|
||||
Sets the total angle of rotation in radians in clockwise direction since the
|
||||
gesture was first started i.e. when IsGestureStart() returned true. This value is always
|
||||
greater than or equal to zero.
|
||||
*/
|
||||
void SetRotationAngle(double rotationAngle);
|
||||
};
|
||||
|
||||
/** @class wxTwoFingerTapEvent
|
||||
|
||||
This event is generated when two fingers touch the surface at the same time.
|
||||
|
||||
@beginEventTable{wxTwoFingerTapEvent}
|
||||
@event{EVT_TWO_FINGER_TAP(id, func)}
|
||||
Process a @c wxEVT_TWO_FINGER_TAP.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxTwoFingerTapEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxTwoFingerTapEvent(wxWindowID windid = 0);
|
||||
};
|
||||
|
||||
/** @class wxLongPressEvent
|
||||
|
||||
This event is generated when one finger touches the surface and remains stationary.
|
||||
|
||||
Note that currently it is only generated under wxGTK and wxOSX.
|
||||
|
||||
wxGTK also generates this event when left mouse button is being pressed for some minimum duration of time.
|
||||
|
||||
@beginEventTable{wxLongPressEvent}
|
||||
@event{EVT_LONG_PRESS(id, func)}
|
||||
Process a @c wxEVT_LONG_PRESS.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxLongPressEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxLongPressEvent(wxWindowID windid = 0);
|
||||
};
|
||||
|
||||
/** @class wxPressAndTapEvent
|
||||
|
||||
This event is generated when the user press the surface with one finger and taps with another.
|
||||
|
||||
Note that once started the event will also be generated when the finger that was pressed moves on surface.
|
||||
|
||||
@beginEventTable{wxPressAndTapEvent}
|
||||
@event{EVT_PRESS_AND_TAP(id, func)}
|
||||
Process a @c wxEVT_PRESS_AND_TAP.
|
||||
@endEventTable
|
||||
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
class wxPressAndTapEvent : public wxGestureEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructor.
|
||||
*/
|
||||
wxPressAndTapEvent(wxWindowID windid = 0);
|
||||
};
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#if wxUSE_BASE
|
||||
|
@@ -52,6 +52,68 @@ enum wxShowEffect
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Values for wxWindow::EnableTouchEvents() mask.
|
||||
|
||||
The values other than ::wxTOUCH_NONE and ::wxTOUCH_ALL_GESTURES can be
|
||||
combined together to request enabling events for the specified gestures and
|
||||
for them only.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/**
|
||||
Don't generate any touch events.
|
||||
*/
|
||||
wxTOUCH_NONE,
|
||||
|
||||
/**
|
||||
Generate wxPanGestureEvent for vertical pans.
|
||||
|
||||
Note that under macOS horizontal pan events are also enabled when this
|
||||
flag is specified.
|
||||
*/
|
||||
wxTOUCH_VERTICAL_PAN_GESTURE,
|
||||
|
||||
/**
|
||||
Generate wxPanGestureEvent for horizontal pans.
|
||||
|
||||
Note that under macOS vertical pan events are also enabled when this
|
||||
flag is specified.
|
||||
*/
|
||||
wxTOUCH_HORIZONTAL_PAN_GESTURE,
|
||||
|
||||
/**
|
||||
Generate wxPanGestureEvent for any pans.
|
||||
|
||||
This is just a convenient combination of wxTOUCH_VERTICAL_PAN_GESTURE
|
||||
and wxTOUCH_HORIZONTAL_PAN_GESTURE.
|
||||
*/
|
||||
wxTOUCH_PAN_GESTURES,
|
||||
|
||||
/**
|
||||
Generate wxZoomGestureEvent.
|
||||
*/
|
||||
wxTOUCH_ZOOM_GESTURE,
|
||||
|
||||
/**
|
||||
Generate wxRotateGestureEvent.
|
||||
*/
|
||||
wxTOUCH_ROTATE_GESTURE,
|
||||
|
||||
/**
|
||||
Generate events for press or tap gestures such as wxTwoFingerTapEvent,
|
||||
wxLongPressEvent and wxPressAndTapEvent.
|
||||
*/
|
||||
wxTOUCH_PRESS_GESTURES,
|
||||
|
||||
/**
|
||||
Enable all supported gesture events.
|
||||
*/
|
||||
wxTOUCH_ALL_GESTURES
|
||||
};
|
||||
|
||||
/**
|
||||
flags for SendSizeEvent()
|
||||
*/
|
||||
@@ -3424,6 +3486,28 @@ public:
|
||||
*/
|
||||
virtual void WarpPointer(int x, int y);
|
||||
|
||||
/**
|
||||
Request generation of touch events for this window.
|
||||
|
||||
Each call to this function supersedes the previous ones, i.e. if you
|
||||
want to receive events for both zoom and rotate gestures, you need to
|
||||
call
|
||||
@code
|
||||
EnableTouchEvents(wxTOUCH_ZOOM_GESTURE | wxTOUCH_ROTATE_GESTURE);
|
||||
@endcode
|
||||
instead of calling it twice in a row as the second call would disable
|
||||
the first gesture.
|
||||
|
||||
@param eventsMask Either wxTOUCH_NONE or wxTOUCH_ALL_GESTURES to
|
||||
disable or enable gesture events for this window.
|
||||
|
||||
@return @true if the specified events were enabled or @false if the
|
||||
current platform doesn't support touch events.
|
||||
|
||||
@since 3.1.1
|
||||
*/
|
||||
virtual bool EnableTouchEvents(int eventsMask);
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
@@ -49,7 +49,8 @@ EVENT_CXXFLAGS = -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
|
||||
$(SAMPLES_CXXFLAGS) $(CPPFLAGS) $(CXXFLAGS)
|
||||
EVENT_OBJECTS = \
|
||||
$(__event___win32rc) \
|
||||
event_event.o
|
||||
event_event.o \
|
||||
event_gestures.o
|
||||
|
||||
### Conditionally set variables: ###
|
||||
|
||||
@@ -177,6 +178,8 @@ event_sample_rc.o: $(srcdir)/../../samples/sample.rc
|
||||
event_event.o: $(srcdir)/event.cpp
|
||||
$(CXXC) -c -o $@ $(EVENT_CXXFLAGS) $(srcdir)/event.cpp
|
||||
|
||||
event_gestures.o: $(srcdir)/gestures.cpp
|
||||
$(CXXC) -c -o $@ $(EVENT_CXXFLAGS) $(srcdir)/gestures.cpp
|
||||
|
||||
# Include dependency info, if present:
|
||||
@IF_GNU_MAKE@-include ./.deps/*.d
|
||||
|
@@ -4,7 +4,8 @@
|
||||
<include file="../../build/bakefiles/common_samples.bkl"/>
|
||||
|
||||
<exe id="event" template="wx_sample" template_append="wx_append">
|
||||
<sources>event.cpp</sources>
|
||||
<sources> event.cpp gestures.cpp </sources>
|
||||
<headers> gestures.h </headers>
|
||||
<wx-lib>core</wx-lib>
|
||||
<wx-lib>base</wx-lib>
|
||||
</exe>
|
||||
|
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <wx/statline.h>
|
||||
#include <wx/log.h>
|
||||
#include "gestures.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event constants
|
||||
@@ -144,6 +145,9 @@ public:
|
||||
void OnClickDynamicHandlerButton(wxCommandEvent& event);
|
||||
void OnClickStaticHandlerFrame(wxCommandEvent& event);
|
||||
|
||||
// Gesture
|
||||
void OnGesture(wxCommandEvent& event);
|
||||
|
||||
private:
|
||||
// symbolic names for the status bar fields
|
||||
enum
|
||||
@@ -178,6 +182,8 @@ private:
|
||||
// the button used to highlight the event handlers execution order
|
||||
MyEvtTestButton *m_testBtn;
|
||||
|
||||
wxWindowRef m_gestureFrame;
|
||||
|
||||
|
||||
// any class wishing to process wxWidgets events must use this macro
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
@@ -220,7 +226,8 @@ enum
|
||||
Event_Push,
|
||||
Event_Pop,
|
||||
Event_Custom,
|
||||
Event_Test
|
||||
Event_Test,
|
||||
Event_Gesture
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -252,6 +259,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU(Event_Test, MyFrame::OnTest)
|
||||
EVT_MENU(Event_Push, MyFrame::OnPushEventHandler)
|
||||
EVT_MENU(Event_Pop, MyFrame::OnPopEventHandler)
|
||||
EVT_MENU(Event_Gesture, MyFrame::OnGesture)
|
||||
|
||||
EVT_UPDATE_UI(Event_Pop, MyFrame::OnUpdateUIPop)
|
||||
|
||||
@@ -381,6 +389,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
||||
menuEvent->AppendSeparator();
|
||||
menuEvent->Append(Event_Custom, wxT("Fire c&ustom event\tCtrl-U"),
|
||||
wxT("Generate a custom event"));
|
||||
menuEvent->Append(Event_Gesture, wxT("&Gesture events\tCtrl-G"),
|
||||
wxT("Gesture event"));
|
||||
|
||||
// now append the freshly created menu to the menu bar...
|
||||
wxMenuBar *menuBar = new wxMenuBar();
|
||||
@@ -447,7 +457,8 @@ MyFrame::~MyFrame()
|
||||
|
||||
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
// true is to force the frame to close
|
||||
if ( m_gestureFrame )
|
||||
m_gestureFrame->Close(true);
|
||||
Close(true);
|
||||
}
|
||||
|
||||
@@ -577,6 +588,19 @@ void MyFrame::OnPopEventHandler(wxCommandEvent& WXUNUSED(event))
|
||||
#endif // wxUSE_STATUSBAR
|
||||
}
|
||||
|
||||
void MyFrame::OnGesture(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if ( m_gestureFrame )
|
||||
{
|
||||
m_gestureFrame->Raise();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gestureFrame = new MyGestureFrame();
|
||||
m_gestureFrame->Show(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxLogMessage(wxT("This is the test event handler in the main frame"));
|
||||
@@ -602,4 +626,3 @@ void MyFrame::OnProcessCustom(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxLogMessage(wxT("Got a custom event!"));
|
||||
}
|
||||
|
||||
|
@@ -286,6 +286,17 @@
|
||||
<File
|
||||
RelativePath=".\event.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gestures.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\gestures.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
@@ -810,6 +810,20 @@
|
||||
RelativePath=".\event.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gestures.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\gestures.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
@@ -782,6 +782,20 @@
|
||||
RelativePath=".\event.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gestures.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\gestures.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
221
samples/event/gestures.cpp
Normal file
221
samples/event/gestures.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
#include "gestures.h"
|
||||
#include "wx/dcgraph.h"
|
||||
|
||||
#include "../image/horse.xpm"
|
||||
|
||||
MyGestureFrame::MyGestureFrame()
|
||||
: wxFrame(NULL, wxID_ANY, "Multi-touch Gestures", wxDefaultPosition, wxSize(800, 600))
|
||||
{
|
||||
// Create controls
|
||||
MyGesturePanel *myPanel = new MyGesturePanel(this);
|
||||
m_logText = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(wxDefaultCoord, 100), wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH);
|
||||
|
||||
// Add controls to sizer
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
sizer->Add(myPanel, wxSizerFlags(1).Expand());
|
||||
sizer->Add(m_logText, wxSizerFlags().Expand());
|
||||
SetSizer(sizer);
|
||||
|
||||
// Log to the text control
|
||||
delete wxLog::SetActiveTarget(new wxLogTextCtrl(m_logText));
|
||||
|
||||
// Bind all gestures to the same event handler, which must run before
|
||||
// the other handlers, to clear the log window
|
||||
myPanel->Bind(wxEVT_GESTURE_PAN, &MyGestureFrame::OnGesture, this);
|
||||
myPanel->Bind(wxEVT_GESTURE_ZOOM, &MyGestureFrame::OnGesture, this);
|
||||
myPanel->Bind(wxEVT_GESTURE_ROTATE, &MyGestureFrame::OnGesture, this);
|
||||
myPanel->Bind(wxEVT_TWO_FINGER_TAP, &MyGestureFrame::OnGesture, this);
|
||||
myPanel->Bind(wxEVT_LONG_PRESS, &MyGestureFrame::OnGesture, this);
|
||||
myPanel->Bind(wxEVT_PRESS_AND_TAP, &MyGestureFrame::OnGesture, this);
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, &MyGestureFrame::OnQuit, this);
|
||||
}
|
||||
|
||||
MyGesturePanel::MyGesturePanel(MyGestureFrame *parent)
|
||||
: wxPanel(parent, wxID_ANY),
|
||||
m_bitmap(horse_xpm)
|
||||
{
|
||||
Bind(wxEVT_PAINT, &MyGesturePanel::OnPaint, this);
|
||||
|
||||
if ( !EnableTouchEvents(wxTOUCH_ALL_GESTURES) )
|
||||
{
|
||||
wxLogError("Failed to enable touch events");
|
||||
|
||||
// Still bind event handlers just in case they still work?
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
Bind(wxEVT_GESTURE_PAN, &MyGesturePanel::OnPan, this);
|
||||
Bind(wxEVT_GESTURE_ZOOM, &MyGesturePanel::OnZoom, this);
|
||||
Bind(wxEVT_GESTURE_ROTATE, &MyGesturePanel::OnRotate, this);
|
||||
Bind(wxEVT_TWO_FINGER_TAP, &MyGesturePanel::OnTwoFingerTap, this);
|
||||
Bind(wxEVT_LONG_PRESS, &MyGesturePanel::OnLongPress, this);
|
||||
Bind(wxEVT_PRESS_AND_TAP, &MyGesturePanel::OnPressAndTap, this);
|
||||
|
||||
m_lastZoomFactor = 1.0;
|
||||
}
|
||||
|
||||
void MyGestureFrame::OnQuit(wxCloseEvent& WXUNUSED(event))
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void MyGestureFrame::OnGesture(wxGestureEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
m_logText->Clear();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||
{
|
||||
wxPaintDC paintDC(this);
|
||||
|
||||
wxGCDC dc(paintDC);
|
||||
|
||||
dc.Clear();
|
||||
|
||||
dc.SetTransformMatrix(m_affineMatrix);
|
||||
dc.DrawBitmap(m_bitmap, wxRound(m_translateDistance.m_x), wxRound(m_translateDistance.m_y));
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnPan(wxPanGestureEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Pan gesture started\n");
|
||||
}
|
||||
|
||||
const wxPoint delta = event.GetDelta();
|
||||
wxLogMessage("Pan gesture performed with delta = (%d,%d), "
|
||||
"with current position (%d,%d)",
|
||||
delta.x, delta.y,
|
||||
event.GetPosition().x, event.GetPosition().y);
|
||||
|
||||
// Transform the distance using the transpose of the matrix,
|
||||
// in order to translate the image to match the screen coordinates
|
||||
wxMatrix2D m;
|
||||
m_affineMatrix.Get(&m, NULL);
|
||||
|
||||
wxPoint2DDouble deltaD(m.m_11 * delta.x + m.m_12 * delta.y,
|
||||
m.m_21 * delta.x + m.m_22 * delta.y);
|
||||
|
||||
// Add it to the total translation
|
||||
m_translateDistance += deltaD;
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Pan gesture Ended\n");
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnZoom(wxZoomGestureEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Zoom gesture started\n");
|
||||
|
||||
m_lastZoomFactor = 1.0;
|
||||
}
|
||||
|
||||
wxLogMessage("Zoom gesture performed with zoom center at (%d, %d) and zoom Factor = %f\n",
|
||||
event.GetPosition().x, event.GetPosition().y, event.GetZoomFactor());
|
||||
|
||||
const wxPoint& zoomCenter = event.GetPosition();
|
||||
|
||||
// Translate to zoom center
|
||||
m_affineMatrix.Translate(zoomCenter.x, zoomCenter.y);
|
||||
// Scale
|
||||
m_affineMatrix.Scale(event.GetZoomFactor() / m_lastZoomFactor, event.GetZoomFactor() / m_lastZoomFactor);
|
||||
// Translate back
|
||||
m_affineMatrix.Translate(-zoomCenter.x, -zoomCenter.y);
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Zoom gesture Ended\n");
|
||||
}
|
||||
|
||||
m_lastZoomFactor = event.GetZoomFactor();
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnRotate(wxRotateGestureEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Rotate gesture started\n");
|
||||
|
||||
m_lastRotationAngle = 0.0;
|
||||
}
|
||||
|
||||
wxLogMessage("Rotate gesture performed with rotation center at (%d, %d) and cumulative rotation angle = %f\n",
|
||||
event.GetPosition().x, event.GetPosition().y, event.GetRotationAngle());
|
||||
|
||||
const wxPoint& rotationCenter = event.GetPosition();
|
||||
|
||||
// Translate to rotation center
|
||||
m_affineMatrix.Translate(rotationCenter.x, rotationCenter.y);
|
||||
// Rotate
|
||||
m_affineMatrix.Rotate(event.GetRotationAngle() - m_lastRotationAngle);
|
||||
// Translate back
|
||||
m_affineMatrix.Translate(-rotationCenter.x, -rotationCenter.y);
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Rotate gesture Ended\n");
|
||||
}
|
||||
|
||||
m_lastRotationAngle = event.GetRotationAngle();
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnTwoFingerTap(wxTwoFingerTapEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Two Finger Tap gesture gesture started\n");
|
||||
}
|
||||
|
||||
wxLogMessage("Two Finger Tap gesture performed at (%d, %d)\n", event.GetPosition().x, event.GetPosition().y);
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Two Finger Tap gesture Ended\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnLongPress(wxLongPressEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Long Press gesture started\n");
|
||||
}
|
||||
|
||||
wxLogMessage("Long Press gesture performed at (%d,%d)\n", event.GetPosition().x, event.GetPosition().y);
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Long Press gesture Ended\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MyGesturePanel::OnPressAndTap(wxPressAndTapEvent& event)
|
||||
{
|
||||
if ( event.IsGestureStart() )
|
||||
{
|
||||
wxLogMessage("Press and Tap gesture started\n");
|
||||
}
|
||||
|
||||
wxLogMessage("Press and Tap gesture performed at (%d,%d)\n", event.GetPosition().x, event.GetPosition().y);
|
||||
|
||||
if ( event.IsGestureEnd() )
|
||||
{
|
||||
wxLogMessage("Press and Tap gesture Ended\n");
|
||||
}
|
||||
}
|
39
samples/event/gestures.h
Normal file
39
samples/event/gestures.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _WX_GESTURES_H_
|
||||
#define _WX_GESTURES_H_
|
||||
|
||||
#include "wx/wx.h"
|
||||
|
||||
class MyGestureFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
MyGestureFrame();
|
||||
|
||||
void OnGesture(wxGestureEvent& event);
|
||||
void OnQuit(wxCloseEvent& event);
|
||||
|
||||
private:
|
||||
wxTextCtrl *m_logText;
|
||||
};
|
||||
|
||||
class MyGesturePanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
MyGesturePanel(MyGestureFrame* parent);
|
||||
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnPan(wxPanGestureEvent& event);
|
||||
void OnZoom(wxZoomGestureEvent& event);
|
||||
void OnRotate(wxRotateGestureEvent& event);
|
||||
void OnTwoFingerTap(wxTwoFingerTapEvent& event);
|
||||
void OnLongPress(wxLongPressEvent& event);
|
||||
void OnPressAndTap(wxPressAndTapEvent& event);
|
||||
|
||||
private:
|
||||
wxBitmap m_bitmap;
|
||||
wxPoint2DDouble m_translateDistance;
|
||||
wxAffineMatrix2D m_affineMatrix;
|
||||
double m_lastZoomFactor;
|
||||
double m_lastRotationAngle;
|
||||
};
|
||||
|
||||
#endif // _WX_GESTURES_H_
|
@@ -36,7 +36,8 @@ EVENT_CXXFLAGS = $(__RUNTIME_LIBS_7) -I$(BCCDIR)\include $(__DEBUGINFO) \
|
||||
-I$(SETUPHDIR) -I.\..\..\include $(____CAIRO_INCLUDEDIR_FILENAMES_p) -I. \
|
||||
$(__DLLFLAG_p) -I.\..\..\samples -DNOPCH $(CPPFLAGS) $(CXXFLAGS)
|
||||
EVENT_OBJECTS = \
|
||||
$(OBJS)\event_event.obj
|
||||
$(OBJS)\event_event.obj \
|
||||
$(OBJS)\event_gestures.obj
|
||||
|
||||
### Conditionally set variables: ###
|
||||
|
||||
@@ -237,3 +238,5 @@ $(OBJS)\event_sample.res: .\..\..\samples\sample.rc
|
||||
$(OBJS)\event_event.obj: .\event.cpp
|
||||
$(CXX) -q -c -P -o$@ $(EVENT_CXXFLAGS) .\event.cpp
|
||||
|
||||
$(OBJS)\event_gestures.obj: .\gestures.cpp
|
||||
$(CXX) -q -c -P -o$@ $(EVENT_CXXFLAGS) .\gestures.cpp
|
||||
|
@@ -30,7 +30,8 @@ EVENT_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG_2) $(__THREADSFLAG) \
|
||||
$(__EXCEPTIONSFLAG_6) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
|
||||
EVENT_OBJECTS = \
|
||||
$(OBJS)\event_sample_rc.o \
|
||||
$(OBJS)\event_event.o
|
||||
$(OBJS)\event_event.o \
|
||||
$(OBJS)\event_gestures.o
|
||||
|
||||
### Conditionally set variables: ###
|
||||
|
||||
@@ -226,6 +227,9 @@ $(OBJS)\event_sample_rc.o: ./../../samples/sample.rc
|
||||
$(OBJS)\event_event.o: ./event.cpp
|
||||
$(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $<
|
||||
|
||||
$(OBJS)\event_gestures.o: ./gestures.cpp
|
||||
$(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $<
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
||||
|
@@ -31,7 +31,8 @@ EVENT_CXXFLAGS = /M$(__RUNTIME_LIBS_10)$(__DEBUGRUNTIME_4) /DWIN32 \
|
||||
/I.\..\..\samples /DNOPCH $(__RTTIFLAG_11) $(__EXCEPTIONSFLAG_12) \
|
||||
$(CPPFLAGS) $(CXXFLAGS)
|
||||
EVENT_OBJECTS = \
|
||||
$(OBJS)\event_event.obj
|
||||
$(OBJS)\event_event.obj \
|
||||
$(OBJS)\event_gestures.obj
|
||||
EVENT_RESOURCES = \
|
||||
$(OBJS)\event_sample.res
|
||||
|
||||
@@ -360,3 +361,5 @@ $(OBJS)\event_sample.res: .\..\..\samples\sample.rc
|
||||
$(OBJS)\event_event.obj: .\event.cpp
|
||||
$(CXX) /c /nologo /TP /Fo$@ $(EVENT_CXXFLAGS) .\event.cpp
|
||||
|
||||
$(OBJS)\event_gestures.obj: .\gestures.cpp
|
||||
$(CXX) /c /nologo /TP /Fo$@ $(EVENT_CXXFLAGS) .\gestures.cpp
|
||||
|
@@ -103,6 +103,13 @@
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxGestureEvent, wxEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxPanGestureEvent, wxGestureEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxZoomGestureEvent, wxGestureEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxRotateGestureEvent, wxGestureEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxTwoFingerTapEvent, wxGestureEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxLongPressEvent, wxGestureEvent);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxPressAndTapEvent, wxGestureEvent);
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#if wxUSE_BASE
|
||||
@@ -258,6 +265,14 @@ wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEDOWN, wxScrollWinEvent );
|
||||
wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEvent );
|
||||
wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEvent );
|
||||
|
||||
// Gesture events
|
||||
wxDEFINE_EVENT( wxEVT_GESTURE_PAN, wxPanGestureEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GESTURE_ZOOM, wxZoomGestureEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GESTURE_ROTATE, wxRotateGestureEvent );
|
||||
wxDEFINE_EVENT( wxEVT_TWO_FINGER_TAP, wxTwoFingerTapEvent );
|
||||
wxDEFINE_EVENT( wxEVT_LONG_PRESS, wxLongPressEvent );
|
||||
wxDEFINE_EVENT( wxEVT_PRESS_AND_TAP, wxPressAndTapEvent );
|
||||
|
||||
// System events
|
||||
wxDEFINE_EVENT( wxEVT_SIZE, wxSizeEvent );
|
||||
wxDEFINE_EVENT( wxEVT_SIZING, wxSizeEvent );
|
||||
|
@@ -227,6 +227,80 @@ static GList* gs_sizeRevalidateList;
|
||||
static bool gs_inSizeAllocate;
|
||||
#endif
|
||||
|
||||
#if GTK_CHECK_VERSION(3,14,0)
|
||||
#define wxGTK_HAS_GESTURES_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifdef wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
#include "wx/hashmap.h"
|
||||
#include "wx/private/extfield.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Per-window data for gestures support.
|
||||
class wxWindowGesturesData
|
||||
{
|
||||
public:
|
||||
// This class has rather unusual "resurrectable" semantics: it is
|
||||
// initialized by the ctor as usual, but may then be uninitialized by
|
||||
// calling Free() and re-initialized again by calling Reinit().
|
||||
wxWindowGesturesData(wxWindow* win, GtkWidget *widget, int eventsMask)
|
||||
{
|
||||
Reinit(win, widget, eventsMask);
|
||||
}
|
||||
|
||||
~wxWindowGesturesData()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void Reinit(wxWindow* win, GtkWidget *widget, int eventsMask);
|
||||
void Free();
|
||||
|
||||
unsigned int m_touchCount;
|
||||
unsigned int m_lastTouchTime;
|
||||
int m_gestureState;
|
||||
int m_allowedGestures;
|
||||
int m_activeGestures;
|
||||
wxPoint m_lastTouchPoint;
|
||||
GdkEventSequence* m_touchSequence;
|
||||
|
||||
GtkGesture* m_vertical_pan_gesture;
|
||||
GtkGesture* m_horizontal_pan_gesture;
|
||||
GtkGesture* m_zoom_gesture;
|
||||
GtkGesture* m_rotate_gesture;
|
||||
GtkGesture* m_long_press_gesture;
|
||||
};
|
||||
|
||||
WX_DECLARE_HASH_MAP(wxWindow*, wxWindowGesturesData*,
|
||||
wxPointerHash, wxPointerEqual,
|
||||
wxWindowGesturesMap);
|
||||
|
||||
typedef wxExternalField<wxWindow,
|
||||
wxWindowGesturesData,
|
||||
wxWindowGesturesMap> wxWindowGestures;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// This is true when the gesture has just started (currently used for pan gesture only)
|
||||
static bool gs_gestureStart = false;
|
||||
|
||||
// Last offset for the pan gesture, this is used to calculate deltas for pan gesture event
|
||||
static double gs_lastOffset = 0;
|
||||
|
||||
// Last scale provided by GTK
|
||||
static gdouble gs_lastScale = 1.0;
|
||||
|
||||
// This is used to set the angle when rotate gesture ends.
|
||||
static gdouble gs_lastAngle = 0;
|
||||
|
||||
// Last Zoom/Rotate gesture point
|
||||
static wxPoint gs_lastGesturePoint;
|
||||
|
||||
#endif // wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// debug
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2624,6 +2698,10 @@ wxWindowGTK::~wxWindowGTK()
|
||||
gs_sizeRevalidateList = g_list_remove_all(gs_sizeRevalidateList, this);
|
||||
#endif
|
||||
|
||||
#ifdef wxGTK_HAS_GESTURES_SUPPORT
|
||||
wxWindowGestures::EraseForObject(this);
|
||||
#endif // wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
if (m_widget)
|
||||
{
|
||||
// Note that gtk_widget_destroy() does not destroy the widget, it just
|
||||
@@ -2825,6 +2903,676 @@ static gboolean source_dispatch(GSource*, GSourceFunc, void*)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
// Currently used for Press and Tap gesture only
|
||||
enum GestureStates
|
||||
{
|
||||
begin = 1,
|
||||
update,
|
||||
end
|
||||
};
|
||||
|
||||
enum TrackedGestures
|
||||
{
|
||||
two_finger_tap = 0x0001,
|
||||
press_and_tap = 0x0002,
|
||||
horizontal_pan = 0x0004,
|
||||
vertical_pan = 0x0008
|
||||
};
|
||||
|
||||
static void
|
||||
pan_gesture_begin_callback(GtkGesture* WXUNUSED(gesture), GdkEventSequence* WXUNUSED(sequence), wxWindowGTK* WXUNUSED(win))
|
||||
{
|
||||
gs_gestureStart = true;
|
||||
|
||||
// Set it to 0, as this will be used to calculate the deltas for new pan gesture
|
||||
gs_lastOffset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
horizontal_pan_gesture_end_callback(GtkGesture* gesture, GdkEventSequence* sequence, wxWindowGTK* win)
|
||||
{
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// Do not process horizontal pan, if there was no "pan" signal for it.
|
||||
if ( !(data->m_allowedGestures & horizontal_pan) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_point(gesture, sequence, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data->m_allowedGestures &= ~horizontal_pan;
|
||||
|
||||
wxPanGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureEnd();
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
vertical_pan_gesture_end_callback(GtkGesture* gesture, GdkEventSequence* sequence, wxWindowGTK* win)
|
||||
{
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// Do not process vertical pan, if there was no "pan" signal for it.
|
||||
if ( !(data->m_allowedGestures & vertical_pan) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_point(gesture, sequence, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data->m_allowedGestures &= ~vertical_pan;
|
||||
|
||||
wxPanGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureEnd();
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
pan_gesture_callback(GtkGesture* gesture, GtkPanDirection direction, gdouble offset, wxWindowGTK* win)
|
||||
{
|
||||
// The function that retrieves the GdkEventSequence (which will further be used to get the gesture point)
|
||||
// should be called only when the gestrure is active
|
||||
if ( !gtk_gesture_is_active(gesture) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GdkEventSequence* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
|
||||
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_point(gesture, sequence, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wxPanGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// This is the difference between this and the last pan gesture event in the current sequence
|
||||
int delta = wxRound(offset - gs_lastOffset);
|
||||
|
||||
switch ( direction )
|
||||
{
|
||||
case GTK_PAN_DIRECTION_UP:
|
||||
data->m_allowedGestures |= vertical_pan;
|
||||
event.SetDelta(wxPoint(0, -delta));
|
||||
break;
|
||||
|
||||
case GTK_PAN_DIRECTION_DOWN:
|
||||
data->m_allowedGestures |= vertical_pan;
|
||||
event.SetDelta(wxPoint(0, delta));
|
||||
break;
|
||||
|
||||
case GTK_PAN_DIRECTION_RIGHT:
|
||||
data->m_allowedGestures |= horizontal_pan;
|
||||
event.SetDelta(wxPoint(delta, 0));
|
||||
break;
|
||||
|
||||
case GTK_PAN_DIRECTION_LEFT:
|
||||
data->m_allowedGestures |= horizontal_pan;
|
||||
event.SetDelta(wxPoint(-delta, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
// Update gs_lastOffset
|
||||
gs_lastOffset = offset;
|
||||
|
||||
if ( gs_gestureStart )
|
||||
{
|
||||
event.SetGestureStart();
|
||||
gs_gestureStart = false;
|
||||
}
|
||||
|
||||
// Cancel press and tap gesture if it is not active during "pan" signal.
|
||||
if( !(data->m_activeGestures & press_and_tap) )
|
||||
{
|
||||
data->m_allowedGestures &= ~press_and_tap;
|
||||
}
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_gesture_callback(GtkGesture* gesture, gdouble scale, wxWindowGTK* win)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_bounding_box_center(gesture, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wxZoomGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetZoomFactor(scale);
|
||||
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
// Cancel "Two FInger Tap Event" if scale has changed
|
||||
if ( wxRound(scale * 1000) != wxRound(gs_lastScale * 1000) )
|
||||
{
|
||||
data->m_allowedGestures &= ~two_finger_tap;
|
||||
}
|
||||
|
||||
gs_lastScale = scale;
|
||||
|
||||
// Save this point because the point obtained through gtk_gesture_get_bounding_box_center()
|
||||
// in the "end" signal is not a zoom center
|
||||
gs_lastGesturePoint = wxPoint(wxRound(x), wxRound(y));
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_gesture_begin_callback(GtkGesture* gesture, GdkEventSequence* WXUNUSED(sequence), wxWindowGTK* win)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_bounding_box_center(gesture, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gs_lastScale = 1.0;
|
||||
|
||||
wxZoomGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureStart();
|
||||
|
||||
// Save this point because the point obtained through gtk_gesture_get_bounding_box_center()
|
||||
// in the "end" signal is not a zoom center
|
||||
gs_lastGesturePoint = wxPoint(wxRound(x), wxRound(y));
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_gesture_end_callback(GtkGesture* WXUNUSED(gesture), GdkEventSequence* WXUNUSED(sequence), wxWindowGTK* win)
|
||||
{
|
||||
wxZoomGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(gs_lastGesturePoint);
|
||||
event.SetGestureEnd();
|
||||
event.SetZoomFactor(gs_lastScale);
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_gesture_begin_callback(GtkGesture* gesture, GdkEventSequence* WXUNUSED(sequence), wxWindowGTK* win)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_bounding_box_center(gesture, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wxRotateGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureStart();
|
||||
|
||||
// Save this point because the point obtained through gtk_gesture_get_bounding_box_center()
|
||||
// in the "end" signal is not a rotation center
|
||||
gs_lastGesturePoint = wxPoint(wxRound(x), wxRound(y));
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_gesture_callback(GtkGesture* gesture, gdouble WXUNUSED(angle_delta), gdouble angle, wxWindowGTK* win)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
if ( !gtk_gesture_get_bounding_box_center(gesture, &x, &y) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wxRotateGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
|
||||
event.SetRotationAngle(angle);
|
||||
|
||||
// Save the angle to set it when the gesture ends.
|
||||
gs_lastAngle = angle;
|
||||
|
||||
// Save this point because the point obtained through gtk_gesture_get_bounding_box_center()
|
||||
// in the "end" signal is not a rotation center
|
||||
gs_lastGesturePoint = wxPoint(wxRound(x), wxRound(y));
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_gesture_end_callback(GtkGesture* WXUNUSED(gesture), GdkEventSequence* WXUNUSED(sequence), wxWindowGTK* win)
|
||||
{
|
||||
wxRotateGestureEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(gs_lastGesturePoint);
|
||||
event.SetGestureEnd();
|
||||
event.SetRotationAngle(gs_lastAngle);
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
long_press_gesture_callback(GtkGesture* WXUNUSED(gesture), gdouble x, gdouble y, wxWindowGTK* win)
|
||||
{
|
||||
wxLongPressEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureStart();
|
||||
event.SetGestureEnd();
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
wxEmitTwoFingerTapEvent(GdkEventTouch* gdk_event, wxWindowGTK* win)
|
||||
{
|
||||
wxTwoFingerTapEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
double lastX = data->m_lastTouchPoint.x;
|
||||
double lastY = data->m_lastTouchPoint.y;
|
||||
|
||||
// Calculate smaller of x coordinate between 2 touches
|
||||
double left = lastX <= gdk_event->x ? lastX : gdk_event->x;
|
||||
|
||||
// Calculate smaller of y coordinate between 2 touches
|
||||
double up = lastY <= gdk_event->y ? lastY : gdk_event->y;
|
||||
|
||||
// Calculate gesture point .i.e center of the box formed by two touches
|
||||
double x = left + abs(lastX - gdk_event->x)/2;
|
||||
double y = up + abs(lastY - gdk_event->y)/2;
|
||||
|
||||
event.SetPosition(wxPoint(wxRound(x), wxRound(y)));
|
||||
event.SetGestureStart();
|
||||
event.SetGestureEnd();
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
wxEmitPressAndTapEvent(GdkEventTouch* gdk_event, wxWindowGTK* win)
|
||||
{
|
||||
wxPressAndTapEvent event(win->GetId());
|
||||
|
||||
event.SetEventObject(win);
|
||||
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
switch ( data->m_gestureState )
|
||||
{
|
||||
case begin:
|
||||
event.SetGestureStart();
|
||||
break;
|
||||
|
||||
case update:
|
||||
// Update touch point as the touch corresponding to "press" is moving
|
||||
if ( data->m_touchSequence == gdk_event->sequence )
|
||||
{
|
||||
data->m_lastTouchPoint.x = gdk_event->x;
|
||||
data->m_lastTouchPoint.y = gdk_event->y;
|
||||
}
|
||||
break;
|
||||
|
||||
case end:
|
||||
event.SetGestureEnd();
|
||||
break;
|
||||
}
|
||||
|
||||
event.SetPosition(data->m_lastTouchPoint);
|
||||
|
||||
win->GTKProcessEvent(event);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindowGTK* win)
|
||||
{
|
||||
wxWindowGesturesData* const data = wxWindowGestures::FromObject(win);
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
switch ( gdk_event->type )
|
||||
{
|
||||
case GDK_TOUCH_BEGIN:
|
||||
data->m_touchCount++;
|
||||
|
||||
data->m_allowedGestures &= ~two_finger_tap;
|
||||
|
||||
if ( data->m_touchCount == 1 )
|
||||
{
|
||||
data->m_lastTouchTime = gdk_event->time;
|
||||
data->m_lastTouchPoint.x = gdk_event->x;
|
||||
data->m_lastTouchPoint.y = gdk_event->y;
|
||||
|
||||
// Save the sequence which identifies touch corresponding to "press"
|
||||
data->m_touchSequence = gdk_event->sequence;
|
||||
|
||||
// "Press and Tap Event" may occur in future
|
||||
data->m_allowedGestures |= press_and_tap;
|
||||
}
|
||||
|
||||
// Check if two fingers are placed together .i.e difference between their time stamps is <= 200 milliseconds
|
||||
else if ( data->m_touchCount == 2 && gdk_event->time - data->m_lastTouchTime <= wxTwoFingerTimeInterval )
|
||||
{
|
||||
// "Two Finger Tap Event" may be possible in the future
|
||||
data->m_allowedGestures |= two_finger_tap;
|
||||
|
||||
// Cancel "Press and Tap Event"
|
||||
data->m_allowedGestures &= ~press_and_tap;
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_TOUCH_UPDATE:
|
||||
// If press and tap gesture is active and touch corresponding to that gesture is moving
|
||||
if ( (data->m_activeGestures & press_and_tap) && gdk_event->sequence == data->m_touchSequence )
|
||||
{
|
||||
data->m_gestureState = update;
|
||||
wxEmitPressAndTapEvent(gdk_event, win);
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
data->m_touchCount--;
|
||||
|
||||
if ( data->m_touchCount == 1 )
|
||||
{
|
||||
data->m_lastTouchTime = gdk_event->time;
|
||||
|
||||
// If the touch corresponding to "press" is present and "tap" is produced by some ather touch
|
||||
if ( (data->m_allowedGestures & press_and_tap) && gdk_event->sequence != data->m_touchSequence )
|
||||
{
|
||||
// Press and Tap gesture becomes active now
|
||||
if ( !(data->m_activeGestures & press_and_tap) )
|
||||
{
|
||||
data->m_gestureState = begin;
|
||||
data->m_activeGestures |= press_and_tap;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
data->m_gestureState = update;
|
||||
}
|
||||
|
||||
wxEmitPressAndTapEvent(gdk_event, win);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if "Two Finger Tap Event" is possible and both the fingers have been lifted up together
|
||||
else if ( (data->m_allowedGestures & two_finger_tap) && !data->m_touchCount
|
||||
&& gdk_event->time - data->m_lastTouchTime <= wxTwoFingerTimeInterval )
|
||||
{
|
||||
// Process Two Finger Tap Event
|
||||
wxEmitTwoFingerTapEvent(gdk_event, win);
|
||||
}
|
||||
|
||||
// If the gesture was active and the touch corresponding to "press" is no longer on the screen
|
||||
if ( (data->m_activeGestures & press_and_tap) && gdk_event->sequence == data->m_touchSequence )
|
||||
{
|
||||
data->m_gestureState = end;
|
||||
|
||||
data->m_activeGestures &= ~press_and_tap;
|
||||
|
||||
data->m_allowedGestures &= ~press_and_tap;
|
||||
|
||||
wxEmitPressAndTapEvent(gdk_event, win);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wxWindowGesturesData::Reinit(wxWindowGTK* win,
|
||||
GtkWidget *widget,
|
||||
int eventsMask)
|
||||
{
|
||||
m_touchCount = 0;
|
||||
m_lastTouchTime = 0;
|
||||
m_gestureState = 0;
|
||||
m_allowedGestures = 0;
|
||||
m_activeGestures = 0;
|
||||
m_touchSequence = NULL;
|
||||
|
||||
if ( eventsMask & wxTOUCH_VERTICAL_PAN_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_VERTICAL_PAN_GESTURE;
|
||||
|
||||
m_vertical_pan_gesture = gtk_gesture_pan_new(widget, GTK_ORIENTATION_VERTICAL);
|
||||
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(m_vertical_pan_gesture), GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_connect (m_vertical_pan_gesture, "begin",
|
||||
G_CALLBACK(pan_gesture_begin_callback), win);
|
||||
g_signal_connect (m_vertical_pan_gesture, "pan",
|
||||
G_CALLBACK(pan_gesture_callback), win);
|
||||
g_signal_connect (m_vertical_pan_gesture, "end",
|
||||
G_CALLBACK(vertical_pan_gesture_end_callback), win);
|
||||
g_signal_connect (m_vertical_pan_gesture, "cancel",
|
||||
G_CALLBACK(vertical_pan_gesture_end_callback), win);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertical_pan_gesture = NULL;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_HORIZONTAL_PAN_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_HORIZONTAL_PAN_GESTURE;
|
||||
|
||||
m_horizontal_pan_gesture = gtk_gesture_pan_new(widget, GTK_ORIENTATION_HORIZONTAL);
|
||||
|
||||
// Pan signals are also generated in case of "left mouse down + mouse move". This can be disabled by
|
||||
// calling gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(m_horizontal_pan_gesture), TRUE) and
|
||||
// gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(verticaal_pan_gesture), TRUE) which will allow
|
||||
// pan signals only for Touch events.
|
||||
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(m_horizontal_pan_gesture), GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_connect (m_horizontal_pan_gesture, "begin",
|
||||
G_CALLBACK(pan_gesture_begin_callback), win);
|
||||
g_signal_connect (m_horizontal_pan_gesture, "pan",
|
||||
G_CALLBACK(pan_gesture_callback), win);
|
||||
g_signal_connect (m_horizontal_pan_gesture, "end",
|
||||
G_CALLBACK(horizontal_pan_gesture_end_callback), win);
|
||||
g_signal_connect (m_horizontal_pan_gesture, "cancel",
|
||||
G_CALLBACK(horizontal_pan_gesture_end_callback), win);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_horizontal_pan_gesture = NULL;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ZOOM_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ZOOM_GESTURE;
|
||||
|
||||
m_zoom_gesture = gtk_gesture_zoom_new(widget);
|
||||
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(m_zoom_gesture), GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_connect (m_zoom_gesture, "begin",
|
||||
G_CALLBACK(zoom_gesture_begin_callback), win);
|
||||
g_signal_connect (m_zoom_gesture, "scale-changed",
|
||||
G_CALLBACK(zoom_gesture_callback), win);
|
||||
g_signal_connect (m_zoom_gesture, "end",
|
||||
G_CALLBACK(zoom_gesture_end_callback), win);
|
||||
g_signal_connect (m_zoom_gesture, "cancel",
|
||||
G_CALLBACK(zoom_gesture_end_callback), win);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_zoom_gesture = NULL;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ROTATE_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ROTATE_GESTURE;
|
||||
|
||||
m_rotate_gesture = gtk_gesture_rotate_new(widget);
|
||||
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(m_rotate_gesture), GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_connect (m_rotate_gesture, "begin",
|
||||
G_CALLBACK(rotate_gesture_begin_callback), win);
|
||||
g_signal_connect (m_rotate_gesture, "angle-changed",
|
||||
G_CALLBACK(rotate_gesture_callback), win);
|
||||
g_signal_connect (m_rotate_gesture, "end",
|
||||
G_CALLBACK(rotate_gesture_end_callback), win);
|
||||
g_signal_connect (m_rotate_gesture, "cancel",
|
||||
G_CALLBACK(rotate_gesture_end_callback), win);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotate_gesture = NULL;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_PRESS_GESTURES )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_PRESS_GESTURES;
|
||||
|
||||
m_long_press_gesture = gtk_gesture_long_press_new(widget);
|
||||
|
||||
// "pressed" signal is also generated when left mouse is down for some minimum duration of time.
|
||||
// This can be disable by calling gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(m_long_press_gesture), TRUE)
|
||||
// which will allow "pressed" signal only for Touch events.
|
||||
|
||||
gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(m_long_press_gesture), GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_connect (m_long_press_gesture, "pressed",
|
||||
G_CALLBACK(long_press_gesture_callback), win);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_long_press_gesture = NULL;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( eventsMask == 0, "Unknown touch event mask bit specified" );
|
||||
|
||||
gtk_widget_add_events(widget, GDK_TOUCHPAD_GESTURE_MASK);
|
||||
|
||||
g_signal_connect (widget, "touch-event",
|
||||
G_CALLBACK(touch_callback), win);
|
||||
}
|
||||
|
||||
void wxWindowGesturesData::Free()
|
||||
{
|
||||
g_clear_object(&m_vertical_pan_gesture);
|
||||
g_clear_object(&m_horizontal_pan_gesture);
|
||||
g_clear_object(&m_zoom_gesture);
|
||||
g_clear_object(&m_rotate_gesture);
|
||||
g_clear_object(&m_long_press_gesture);
|
||||
|
||||
// We don't current remove GDK_TOUCHPAD_GESTURE_MASK as this can't be done
|
||||
// for a window as long as it's realized, and this might still be the case
|
||||
// if we're called from EnableTouchEvents(wxTOUCH_NONE) and not from the
|
||||
// dtor, but it shouldn't really be a problem.
|
||||
}
|
||||
|
||||
#endif // wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
// This method must be always defined for GTK+ 3 as it's declared in the
|
||||
// header, where we can't (easily) test for wxGTK_HAS_GESTURES_SUPPORT.
|
||||
#ifdef __WXGTK3__
|
||||
|
||||
bool wxWindowGTK::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
#ifdef wxGTK_HAS_GESTURES_SUPPORT
|
||||
// Check if gestures support is also available during run-time.
|
||||
if ( gtk_check_version(3, 14, 0) == NULL )
|
||||
{
|
||||
wxWindowGesturesData* const dataOld = wxWindowGestures::FromObject(this);
|
||||
|
||||
if ( eventsMask == wxTOUCH_NONE )
|
||||
{
|
||||
// Reset the gestures data used by this object, but don't destroy
|
||||
// it, as we could be called from an event handler, in which case
|
||||
// this object could be still used after the event handler returns.
|
||||
if ( dataOld )
|
||||
dataOld->Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget* const widget = GetConnectWidget();
|
||||
|
||||
if ( dataOld )
|
||||
{
|
||||
dataOld->Reinit(this, widget, eventsMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxWindowGesturesData* const
|
||||
dataNew = new wxWindowGesturesData(this, widget, eventsMask);
|
||||
wxWindowGestures::StoreForObject(this, dataNew);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // wxGTK_HAS_GESTURES_SUPPORT
|
||||
|
||||
return wxWindowBase::EnableTouchEvents(eventsMask);
|
||||
}
|
||||
|
||||
#endif // __WXGTK3__
|
||||
|
||||
void wxWindowGTK::ConnectWidget( GtkWidget *widget )
|
||||
{
|
||||
static bool isSourceAttached;
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include "wx/textctrl.h"
|
||||
#include "wx/menuitem.h"
|
||||
#include "wx/module.h"
|
||||
#include "wx/vector.h"
|
||||
#endif
|
||||
|
||||
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
|
||||
@@ -205,6 +206,82 @@ bool gs_insideCaptureChanged = false;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#ifdef WM_GESTURE
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Class used to dynamically load gestures related API functions.
|
||||
class GestureFuncs
|
||||
{
|
||||
public:
|
||||
// Must be called before using any other methods of this class (and they
|
||||
// can't be used if this one returns false).
|
||||
static bool IsOk()
|
||||
{
|
||||
if ( !ms_gestureSymbolsLoaded )
|
||||
{
|
||||
ms_gestureSymbolsLoaded = true;
|
||||
LoadGestureSymbols();
|
||||
}
|
||||
|
||||
return ms_pfnGetGestureInfo &&
|
||||
ms_pfnCloseGestureInfoHandle &&
|
||||
ms_pfnSetGestureConfig;
|
||||
}
|
||||
|
||||
typedef BOOL (WINAPI *GetGestureInfo_t)(HGESTUREINFO, PGESTUREINFO);
|
||||
|
||||
static GetGestureInfo_t GetGestureInfo()
|
||||
{
|
||||
return ms_pfnGetGestureInfo;
|
||||
}
|
||||
|
||||
typedef BOOL (WINAPI *CloseGestureInfoHandle_t)(HGESTUREINFO);
|
||||
|
||||
static CloseGestureInfoHandle_t CloseGestureInfoHandle()
|
||||
{
|
||||
return ms_pfnCloseGestureInfoHandle;
|
||||
}
|
||||
|
||||
typedef BOOL
|
||||
(WINAPI *SetGestureConfig_t)(HWND, DWORD, UINT, PGESTURECONFIG, UINT);
|
||||
|
||||
static SetGestureConfig_t SetGestureConfig()
|
||||
{
|
||||
return ms_pfnSetGestureConfig;
|
||||
}
|
||||
|
||||
private:
|
||||
static void LoadGestureSymbols()
|
||||
{
|
||||
wxLoadedDLL dll(wxS("user32.dll"));
|
||||
|
||||
wxDL_INIT_FUNC(ms_pfn, GetGestureInfo, dll);
|
||||
wxDL_INIT_FUNC(ms_pfn, CloseGestureInfoHandle, dll);
|
||||
wxDL_INIT_FUNC(ms_pfn, SetGestureConfig, dll);
|
||||
}
|
||||
|
||||
static GetGestureInfo_t ms_pfnGetGestureInfo;
|
||||
static CloseGestureInfoHandle_t ms_pfnCloseGestureInfoHandle;
|
||||
static SetGestureConfig_t ms_pfnSetGestureConfig;
|
||||
|
||||
static bool ms_gestureSymbolsLoaded;
|
||||
};
|
||||
|
||||
GestureFuncs::GetGestureInfo_t
|
||||
GestureFuncs::ms_pfnGetGestureInfo = NULL;
|
||||
GestureFuncs::CloseGestureInfoHandle_t
|
||||
GestureFuncs::ms_pfnCloseGestureInfoHandle = NULL;
|
||||
GestureFuncs::SetGestureConfig_t
|
||||
GestureFuncs::ms_pfnSetGestureConfig = NULL;
|
||||
|
||||
bool GestureFuncs::ms_gestureSymbolsLoaded = false;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#endif // WM_GESTURE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -830,6 +907,123 @@ void wxWindowMSW::WarpPointer(int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWindowMSW::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
#ifdef WM_GESTURE
|
||||
if ( GestureFuncs::IsOk() )
|
||||
{
|
||||
// Static struct used when we need to use just a single configuration.
|
||||
GESTURECONFIG config = {0, 0, 0};
|
||||
|
||||
GESTURECONFIG* ptrConfigs = &config;
|
||||
UINT numConfigs = 1;
|
||||
|
||||
// This is used only if we need to allocate the configurations
|
||||
// dynamically.
|
||||
wxVector<GESTURECONFIG> configs;
|
||||
|
||||
// There are two simple cases: enabling or disabling all gestures.
|
||||
if ( eventsMask == wxTOUCH_NONE )
|
||||
{
|
||||
config.dwBlock = GC_ALLGESTURES;
|
||||
}
|
||||
else if ( eventsMask == wxTOUCH_ALL_GESTURES )
|
||||
{
|
||||
config.dwWant = GC_ALLGESTURES;
|
||||
}
|
||||
else // Need to enable the individual gestures
|
||||
{
|
||||
int wantedPan = 0;
|
||||
switch ( eventsMask & wxTOUCH_PAN_GESTURES )
|
||||
{
|
||||
case wxTOUCH_VERTICAL_PAN_GESTURE:
|
||||
wantedPan = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
|
||||
break;
|
||||
|
||||
case wxTOUCH_HORIZONTAL_PAN_GESTURE:
|
||||
wantedPan = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
|
||||
break;
|
||||
|
||||
case wxTOUCH_PAN_GESTURES:
|
||||
wantedPan = GC_PAN;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
// This is the only other possibility and wantedPan is
|
||||
// already initialized to 0 anyhow, so don't do anything,
|
||||
// just list it for completeness.
|
||||
break;
|
||||
}
|
||||
|
||||
if ( wantedPan )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_PAN_GESTURES;
|
||||
|
||||
config.dwID = GID_PAN;
|
||||
config.dwWant = wantedPan;
|
||||
configs.push_back(config);
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ZOOM_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ZOOM_GESTURE;
|
||||
|
||||
config.dwID = GID_ZOOM;
|
||||
config.dwWant = GC_ZOOM;
|
||||
configs.push_back(config);
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ROTATE_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ROTATE_GESTURE;
|
||||
|
||||
config.dwID = GID_ROTATE;
|
||||
config.dwWant = GC_ROTATE;
|
||||
configs.push_back(config);
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_PRESS_GESTURES )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_PRESS_GESTURES;
|
||||
|
||||
config.dwID = GID_TWOFINGERTAP;
|
||||
config.dwWant = GC_TWOFINGERTAP;
|
||||
configs.push_back(config);
|
||||
|
||||
config.dwID = GID_PRESSANDTAP;
|
||||
config.dwWant = GC_PRESSANDTAP;
|
||||
configs.push_back(config);
|
||||
}
|
||||
|
||||
// As we clear all the known bits if they're set in the code above,
|
||||
// there should be nothing left.
|
||||
wxCHECK_MSG( eventsMask == 0, false,
|
||||
wxS("Unknown touch event mask bit specified") );
|
||||
|
||||
ptrConfigs = &configs[0];
|
||||
}
|
||||
|
||||
if ( !GestureFuncs::SetGestureConfig()
|
||||
(
|
||||
m_hWnd,
|
||||
0, // Reserved, must be always 0.
|
||||
numConfigs, // Number of gesture configurations.
|
||||
ptrConfigs, // Pointer to the first one.
|
||||
sizeof(GESTURECONFIG) // Size of each configuration.
|
||||
)
|
||||
)
|
||||
{
|
||||
wxLogLastError("SetGestureConfig");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // WM_GESTURE
|
||||
|
||||
return wxWindowBase::EnableTouchEvents(eventsMask);
|
||||
}
|
||||
|
||||
void wxWindowMSW::MSWUpdateUIState(int action, int state)
|
||||
{
|
||||
// we send WM_CHANGEUISTATE so if nothing needs changing then the system
|
||||
@@ -3124,6 +3318,84 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef WM_GESTURE
|
||||
case WM_GESTURE:
|
||||
{
|
||||
if ( !GestureFuncs::IsOk() )
|
||||
break;
|
||||
|
||||
HGESTUREINFO hGestureInfo = reinterpret_cast<HGESTUREINFO>(lParam);
|
||||
|
||||
WinStruct<GESTUREINFO> gestureInfo;
|
||||
if ( !GestureFuncs::GetGestureInfo()(hGestureInfo, &gestureInfo) )
|
||||
{
|
||||
wxLogLastError("GetGestureInfo");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( gestureInfo.hwndTarget != GetHWND() )
|
||||
{
|
||||
wxLogDebug("This is Not the window targeted by this gesture!");
|
||||
}
|
||||
|
||||
const wxPoint pt = ScreenToClient
|
||||
(
|
||||
wxPoint(gestureInfo.ptsLocation.x,
|
||||
gestureInfo.ptsLocation.y)
|
||||
);
|
||||
|
||||
// dwID field is used to determine the type of gesture
|
||||
switch ( gestureInfo.dwID )
|
||||
{
|
||||
case GID_PAN:
|
||||
// Point contains the current position of the pan.
|
||||
processed = HandlePanGesture(pt, gestureInfo.dwFlags);
|
||||
break;
|
||||
|
||||
case GID_ZOOM:
|
||||
// Point is the mid-point of 2 fingers and ullArgument
|
||||
// contains the distance between the fingers in its lower
|
||||
// half
|
||||
processed = HandleZoomGesture
|
||||
(
|
||||
pt,
|
||||
static_cast<DWORD>(gestureInfo.ullArguments),
|
||||
gestureInfo.dwFlags
|
||||
);
|
||||
break;
|
||||
|
||||
case GID_ROTATE:
|
||||
// Point is the center point of rotation and ullArguments
|
||||
// contains the angle of rotation
|
||||
processed = HandleRotateGesture
|
||||
(
|
||||
pt,
|
||||
static_cast<DWORD>(gestureInfo.ullArguments),
|
||||
gestureInfo.dwFlags
|
||||
);
|
||||
break;
|
||||
|
||||
case GID_TWOFINGERTAP:
|
||||
processed = HandleTwoFingerTap(pt, gestureInfo.dwFlags);
|
||||
break;
|
||||
|
||||
case GID_PRESSANDTAP:
|
||||
processed = HandlePressAndTap(pt, gestureInfo.dwFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( processed )
|
||||
{
|
||||
// If processed, we must call this to avoid memory leaks
|
||||
if ( !GestureFuncs::CloseGestureInfoHandle()(hGestureInfo) )
|
||||
{
|
||||
wxLogLastError("CloseGestureInfoHandle");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif // WM_GESTURE
|
||||
|
||||
// CTLCOLOR messages are sent by children to query the parent for their
|
||||
// colors
|
||||
case WM_CTLCOLORMSGBOX:
|
||||
@@ -5474,6 +5746,144 @@ void wxWindowMSW::GenerateMouseLeave()
|
||||
(void)HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
#ifdef WM_GESTURE
|
||||
// ---------------------------------------------------------------------------
|
||||
// Gesture events
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool wxWindowMSW::InitGestureEvent(wxGestureEvent& event,
|
||||
const wxPoint& pt,
|
||||
WXDWORD flags)
|
||||
{
|
||||
event.SetEventObject(this);
|
||||
event.SetTimestamp(::GetMessageTime());
|
||||
event.SetPosition(pt);
|
||||
|
||||
if ( flags & GF_BEGIN )
|
||||
event.SetGestureStart();
|
||||
|
||||
if ( flags & GF_END )
|
||||
event.SetGestureEnd();
|
||||
|
||||
return (flags & GF_BEGIN) != 0;
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandlePanGesture(const wxPoint& pt, WXDWORD flags)
|
||||
{
|
||||
// wxEVT_GESTURE_PAN
|
||||
wxPanGestureEvent event(GetId());
|
||||
|
||||
// This is used to calculate the pan delta.
|
||||
static wxPoint s_previousLocation;
|
||||
|
||||
// If the gesture has just started, store the current point to determine
|
||||
// the pan delta later on.
|
||||
if ( InitGestureEvent(event, pt, flags) )
|
||||
{
|
||||
s_previousLocation = pt;
|
||||
}
|
||||
|
||||
// Determine the horizontal and vertical changes
|
||||
event.SetDelta(pt - s_previousLocation);
|
||||
|
||||
// Update the last gesture event point
|
||||
s_previousLocation = pt;
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandleZoomGesture(const wxPoint& pt,
|
||||
WXDWORD fingerDistance,
|
||||
WXDWORD flags)
|
||||
{
|
||||
// wxEVT_GESTURE_ZOOM
|
||||
wxZoomGestureEvent event(GetId());
|
||||
|
||||
// These are used to calculate the center of the zoom and zoom factor
|
||||
static wxPoint s_previousLocation;
|
||||
static int s_intialFingerDistance;
|
||||
|
||||
// This flag indicates that the gesture has just started, store the current
|
||||
// point and distance between the fingers for future calculations.
|
||||
if ( InitGestureEvent(event, pt, flags) )
|
||||
{
|
||||
s_previousLocation = pt;
|
||||
s_intialFingerDistance = fingerDistance;
|
||||
}
|
||||
|
||||
// Calculate center point of the zoom. Human beings are not very good at
|
||||
// moving two fingers at exactly the same rate outwards/inwards and there
|
||||
// is usually some error, which can cause the center to shift slightly. So,
|
||||
// it is recommended to take the average of center of fingers in the
|
||||
// current and last positions.
|
||||
const wxPoint ptCenter = (s_previousLocation + pt)/2;
|
||||
|
||||
const double zoomFactor = (double) fingerDistance / s_intialFingerDistance;
|
||||
|
||||
event.SetZoomFactor(zoomFactor);
|
||||
|
||||
event.SetPosition(ptCenter);
|
||||
|
||||
// Update gesture event point
|
||||
s_previousLocation = pt;
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandleRotateGesture(const wxPoint& pt,
|
||||
WXDWORD angleArgument,
|
||||
WXDWORD flags)
|
||||
{
|
||||
// wxEVT_GESTURE_ROTATE
|
||||
wxRotateGestureEvent event(GetId());
|
||||
|
||||
if ( InitGestureEvent(event, pt, flags) )
|
||||
{
|
||||
event.SetRotationAngle(angleArgument);
|
||||
}
|
||||
else // Not the first event.
|
||||
{
|
||||
// Use angleArgument to obtain the cumulative angle since the gesture
|
||||
// was first started. This angle is in radians and MSW returns negative
|
||||
// angle for clockwise rotation and positive otherwise, so, multiply
|
||||
// angle by -1 for positive angle for clockwise and negative in case of
|
||||
// counterclockwise.
|
||||
double angle = -GID_ROTATE_ANGLE_FROM_ARGUMENT(angleArgument);
|
||||
|
||||
// If the rotation is anti-clockwise convert the angle to its
|
||||
// corresponding positive value in a clockwise sense.
|
||||
if ( angle < 0 )
|
||||
{
|
||||
angle += 2 * M_PI;
|
||||
}
|
||||
|
||||
// Set the angle
|
||||
event.SetRotationAngle(angle);
|
||||
}
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandleTwoFingerTap(const wxPoint& pt, WXDWORD flags)
|
||||
{
|
||||
// wxEVT_TWO_FINGER_TAP
|
||||
wxTwoFingerTapEvent event(GetId());
|
||||
|
||||
InitGestureEvent(event, pt, flags);
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandlePressAndTap(const wxPoint& pt, WXDWORD flags)
|
||||
{
|
||||
wxPressAndTapEvent event(GetId());
|
||||
|
||||
InitGestureEvent(event, pt, flags);
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
}
|
||||
#endif // WM_GESTURE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// keyboard handling
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@@ -528,29 +528,35 @@ bool g_lastButtonWasFakeRight = false ;
|
||||
- (CGFloat)scrollingDeltaY;
|
||||
@end
|
||||
|
||||
void wxWidgetCocoaImpl::SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent* nsEvent)
|
||||
static void
|
||||
wxSetupCoordinates(NSView* view, wxCoord &x, wxCoord &y, NSEvent* nsEvent)
|
||||
{
|
||||
NSRect locationInWindow = NSZeroRect;
|
||||
locationInWindow.origin = [nsEvent locationInWindow];
|
||||
|
||||
// adjust coordinates for the window of the target view
|
||||
if ( [nsEvent window] != [m_osxView window] )
|
||||
if ( [nsEvent window] != [view window] )
|
||||
{
|
||||
if ( [nsEvent window] != nil )
|
||||
locationInWindow = [[nsEvent window] convertRectToScreen:locationInWindow];
|
||||
|
||||
if ( [m_osxView window] != nil )
|
||||
locationInWindow = [[m_osxView window] convertRectFromScreen:locationInWindow];
|
||||
if ( [view window] != nil )
|
||||
locationInWindow = [[view window] convertRectFromScreen:locationInWindow];
|
||||
}
|
||||
|
||||
NSPoint locationInView = [m_osxView convertPoint:locationInWindow.origin fromView:nil];
|
||||
wxPoint locationInViewWX = wxFromNSPoint( m_osxView, locationInView );
|
||||
NSPoint locationInView = [view convertPoint:locationInWindow.origin fromView:nil];
|
||||
wxPoint locationInViewWX = wxFromNSPoint( view, locationInView );
|
||||
|
||||
x = locationInViewWX.x;
|
||||
y = locationInViewWX.y;
|
||||
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent* nsEvent)
|
||||
{
|
||||
wxSetupCoordinates(m_osxView, x, y, nsEvent);
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
|
||||
{
|
||||
int eventType = [nsEvent type];
|
||||
@@ -1042,6 +1048,71 @@ void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
|
||||
impl->insertText(text, self, _cmd);
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
void wxOSX_panGestureEvent(NSView* self, SEL _cmd, NSPanGestureRecognizer* panGestureRecognizer)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->PanGestureEvent(panGestureRecognizer);
|
||||
}
|
||||
|
||||
void wxOSX_zoomGestureEvent(NSView* self, SEL _cmd, NSMagnificationGestureRecognizer* magnificationGestureRecognizer)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->ZoomGestureEvent(magnificationGestureRecognizer);
|
||||
}
|
||||
|
||||
void wxOSX_rotateGestureEvent(NSView* self, SEL _cmd, NSRotationGestureRecognizer* rotationGestureRecognizer)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->RotateGestureEvent(rotationGestureRecognizer);
|
||||
}
|
||||
|
||||
void wxOSX_longPressEvent(NSView* self, SEL _cmd, NSPressGestureRecognizer* pressGestureRecognizer)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl ==NULL )
|
||||
return;
|
||||
|
||||
impl->LongPressEvent(pressGestureRecognizer);
|
||||
}
|
||||
|
||||
void wxOSX_touchesBegan(NSView* self, SEL _cmd, NSEvent *event)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->TouchesBegan(event);
|
||||
}
|
||||
|
||||
void wxOSX_touchesMoved(NSView* self, SEL _cmd, NSEvent *event)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->TouchesMoved(event);
|
||||
}
|
||||
|
||||
void wxOSX_touchesEnded(NSView* self, SEL _cmd, NSEvent *event)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
if ( impl == NULL )
|
||||
return;
|
||||
|
||||
impl->TouchesEnded(event);
|
||||
}
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
|
||||
BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event)
|
||||
{
|
||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||
@@ -1428,6 +1499,559 @@ void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
|
||||
m_lastKeyDownEvent = NULL;
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
|
||||
// Class containing data used for gestures support.
|
||||
class wxCocoaGesturesImpl
|
||||
{
|
||||
public:
|
||||
wxCocoaGesturesImpl(wxWidgetCocoaImpl* impl, NSView* view, int eventsMask)
|
||||
: m_win(impl->GetWXPeer()),
|
||||
m_view(view)
|
||||
{
|
||||
m_touchCount = 0;
|
||||
m_lastTouchTime = 0;
|
||||
m_allowedGestures = 0;
|
||||
m_activeGestures = 0;
|
||||
m_initialTouch = NULL;
|
||||
|
||||
Class cls = [m_view class];
|
||||
|
||||
if ( eventsMask & wxTOUCH_PAN_GESTURES )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_PAN_GESTURES;
|
||||
|
||||
m_panGestureRecognizer =
|
||||
[[NSPanGestureRecognizer alloc] initWithTarget:m_view action: @selector(handlePanGesture:)];
|
||||
if ( !class_respondsToSelector(cls, @selector(handlePanGesture:)) )
|
||||
class_addMethod(cls, @selector(handlePanGesture:), (IMP) wxOSX_panGestureEvent, "v@:@" );
|
||||
[m_view addGestureRecognizer:m_panGestureRecognizer];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_panGestureRecognizer = nil;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ZOOM_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ZOOM_GESTURE;
|
||||
|
||||
m_magnificationGestureRecognizer =
|
||||
[[NSMagnificationGestureRecognizer alloc] initWithTarget:m_view action: @selector(handleZoomGesture:)];
|
||||
if ( !class_respondsToSelector(cls, @selector(handleZoomGesture:)) )
|
||||
class_addMethod(cls, @selector(handleZoomGesture:), (IMP) wxOSX_zoomGestureEvent, "v@:@" );
|
||||
[m_view addGestureRecognizer:m_magnificationGestureRecognizer];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_magnificationGestureRecognizer = nil;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_ROTATE_GESTURE )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_ROTATE_GESTURE;
|
||||
|
||||
m_rotationGestureRecognizer =
|
||||
[[NSRotationGestureRecognizer alloc] initWithTarget:m_view action: @selector(handleRotateGesture:)];
|
||||
if ( !class_respondsToSelector(cls, @selector(handleRotateGesture:)) )
|
||||
class_addMethod(cls, @selector(handleRotateGesture:), (IMP) wxOSX_rotateGestureEvent, "v@:@" );
|
||||
[m_view addGestureRecognizer:m_rotationGestureRecognizer];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationGestureRecognizer = nil;
|
||||
}
|
||||
|
||||
if ( eventsMask & wxTOUCH_PRESS_GESTURES )
|
||||
{
|
||||
eventsMask &= ~wxTOUCH_PRESS_GESTURES;
|
||||
|
||||
m_pressGestureRecognizer =
|
||||
[[NSPressGestureRecognizer alloc] initWithTarget:m_view action: @selector(handleLongPressGesture:)];
|
||||
if ( !class_respondsToSelector(cls, @selector(handleLongPressGesture:)) )
|
||||
class_addMethod(cls, @selector(handleLongPressGesture:), (IMP) wxOSX_longPressEvent, "v@:@" );
|
||||
[m_view addGestureRecognizer:m_pressGestureRecognizer];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pressGestureRecognizer = nil;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( eventsMask == 0, "Unknown touch event mask bit specified" );
|
||||
|
||||
if ( !class_respondsToSelector(cls, @selector(touchesBeganWithEvent:)) )
|
||||
class_addMethod(cls, @selector(touchesBeganWithEvent:), (IMP) wxOSX_touchesBegan, "v@:@" );
|
||||
if ( !class_respondsToSelector(cls, @selector(touchesMovedWithEvent:)) )
|
||||
class_addMethod(cls, @selector(touchesMovedWithEvent:), (IMP) wxOSX_touchesMoved, "v@:@" );
|
||||
if ( !class_respondsToSelector(cls, @selector(touchesEndedWithEvent:)) )
|
||||
class_addMethod(cls, @selector(touchesEndedWithEvent:), (IMP) wxOSX_touchesEnded, "v@:@" );
|
||||
}
|
||||
|
||||
~wxCocoaGesturesImpl()
|
||||
{
|
||||
[m_panGestureRecognizer release];
|
||||
[m_magnificationGestureRecognizer release];
|
||||
[m_rotationGestureRecognizer release];
|
||||
[m_pressGestureRecognizer release];
|
||||
[m_initialTouch release];
|
||||
}
|
||||
|
||||
void TouchesBegan(NSEvent* event);
|
||||
void TouchesMoved(NSEvent* event);
|
||||
void TouchesEnded(NSEvent* event);
|
||||
|
||||
private:
|
||||
wxWindowMac* const m_win;
|
||||
NSView* const m_view;
|
||||
|
||||
NSPanGestureRecognizer *m_panGestureRecognizer;
|
||||
NSMagnificationGestureRecognizer *m_magnificationGestureRecognizer;
|
||||
NSRotationGestureRecognizer *m_rotationGestureRecognizer;
|
||||
NSPressGestureRecognizer *m_pressGestureRecognizer;
|
||||
|
||||
int m_allowedGestures;
|
||||
int m_activeGestures;
|
||||
unsigned int m_touchCount;
|
||||
unsigned int m_lastTouchTime;
|
||||
|
||||
// Used to keep track of the touch corresponding to "press" in Press and Tap gesture
|
||||
NSTouch* m_initialTouch;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxCocoaGesturesImpl);
|
||||
};
|
||||
|
||||
// We keep all existing wxCocoaGesturesImpl objects in a
|
||||
// wxWidgetCocoaImpl-indexed map. We do this instead of just having a data
|
||||
// member containing wxCocoaGesturesImpl pointer in wxWidgetCocoaImpl
|
||||
// itself because most windows don't need it and it seems wasteful to
|
||||
// always increase their size unnecessarily.
|
||||
|
||||
#include "wx/hashmap.h"
|
||||
WX_DECLARE_HASH_MAP(wxWidgetCocoaImpl*, wxCocoaGesturesImpl*,
|
||||
wxPointerHash, wxPointerEqual,
|
||||
wxCocoaGesturesImplMap);
|
||||
|
||||
#include "wx/private/extfield.h"
|
||||
typedef wxExternalField<wxWidgetCocoaImpl,
|
||||
wxCocoaGesturesImpl,
|
||||
wxCocoaGesturesImplMap> wxCocoaGestures;
|
||||
|
||||
void wxWidgetCocoaImpl::PanGestureEvent(NSPanGestureRecognizer* panGestureRecognizer)
|
||||
{
|
||||
NSGestureRecognizerState gestureState;
|
||||
|
||||
switch ( [panGestureRecognizer state] )
|
||||
{
|
||||
case NSGestureRecognizerStateBegan:
|
||||
gestureState = NSGestureRecognizerStateBegan;
|
||||
break;
|
||||
case NSGestureRecognizerStateChanged:
|
||||
break;
|
||||
case NSGestureRecognizerStateEnded:
|
||||
case NSGestureRecognizerStateCancelled:
|
||||
gestureState = NSGestureRecognizerStateEnded;
|
||||
break;
|
||||
// Do not process any other states
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
wxPanGestureEvent wxevent(GetWXPeer()->GetId());
|
||||
wxevent.SetEventObject(GetWXPeer());
|
||||
|
||||
NSPoint nspoint = [panGestureRecognizer locationInView:m_osxView];
|
||||
wxPoint pt = wxFromNSPoint(m_osxView, nspoint);
|
||||
|
||||
wxevent.SetPosition(pt);
|
||||
|
||||
nspoint = [panGestureRecognizer translationInView:m_osxView];
|
||||
pt = wxFromNSPoint(m_osxView, nspoint);
|
||||
|
||||
static wxPoint s_lastLocation;
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateBegan )
|
||||
{
|
||||
wxevent.SetGestureStart();
|
||||
s_lastLocation = wxPoint(0, 0);
|
||||
}
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateEnded )
|
||||
{
|
||||
wxevent.SetGestureEnd();
|
||||
}
|
||||
|
||||
// Set the offset
|
||||
wxevent.SetDelta(pt - s_lastLocation);
|
||||
|
||||
s_lastLocation = pt;
|
||||
|
||||
GetWXPeer()->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::ZoomGestureEvent(NSMagnificationGestureRecognizer* magnificationGestureRecognizer)
|
||||
{
|
||||
NSGestureRecognizerState gestureState;
|
||||
|
||||
switch ( [magnificationGestureRecognizer state] )
|
||||
{
|
||||
case NSGestureRecognizerStateBegan:
|
||||
gestureState = NSGestureRecognizerStateBegan;
|
||||
break;
|
||||
case NSGestureRecognizerStateChanged:
|
||||
break;
|
||||
case NSGestureRecognizerStateEnded:
|
||||
case NSGestureRecognizerStateCancelled:
|
||||
gestureState = NSGestureRecognizerStateEnded;
|
||||
break;
|
||||
// Do not process any other states
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
wxZoomGestureEvent wxevent(GetWXPeer()->GetId());
|
||||
wxevent.SetEventObject(GetWXPeer());
|
||||
|
||||
NSPoint nspoint = [magnificationGestureRecognizer locationInView:m_osxView];
|
||||
wxPoint pt = wxFromNSPoint(m_osxView, nspoint);
|
||||
|
||||
wxevent.SetPosition(pt);
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateBegan )
|
||||
{
|
||||
wxevent.SetGestureStart();
|
||||
}
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateEnded )
|
||||
{
|
||||
wxevent.SetGestureEnd();
|
||||
}
|
||||
|
||||
double magnification = [magnificationGestureRecognizer magnification];
|
||||
|
||||
// Add 1.0 get the magnification.
|
||||
magnification += 1.0;
|
||||
|
||||
wxevent.SetZoomFactor(magnification);
|
||||
|
||||
GetWXPeer()->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::RotateGestureEvent(NSRotationGestureRecognizer* rotationGestureRecognizer)
|
||||
{
|
||||
NSGestureRecognizerState gestureState;
|
||||
|
||||
switch ( [rotationGestureRecognizer state] )
|
||||
{
|
||||
case NSGestureRecognizerStateBegan:
|
||||
gestureState = NSGestureRecognizerStateBegan;
|
||||
break;
|
||||
case NSGestureRecognizerStateChanged:
|
||||
break;
|
||||
case NSGestureRecognizerStateEnded:
|
||||
case NSGestureRecognizerStateCancelled:
|
||||
gestureState = NSGestureRecognizerStateEnded;
|
||||
break;
|
||||
// Do not process any other states
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
wxRotateGestureEvent wxevent(GetWXPeer()->GetId());
|
||||
wxevent.SetEventObject(GetWXPeer());
|
||||
|
||||
NSPoint nspoint = [rotationGestureRecognizer locationInView:m_osxView];
|
||||
wxPoint pt = wxFromNSPoint(m_osxView, nspoint);
|
||||
|
||||
wxevent.SetPosition(pt);
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateBegan )
|
||||
{
|
||||
wxevent.SetGestureStart();
|
||||
}
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateEnded )
|
||||
{
|
||||
wxevent.SetGestureEnd();
|
||||
}
|
||||
// Multiply the returned rotation angle with -1 to obtain the angle in a clockwise sense.
|
||||
double angle = -[rotationGestureRecognizer rotation];
|
||||
|
||||
// If the rotation is anti-clockwise convert the angle to its corresponding positive value in a clockwise sense.
|
||||
if ( angle < 0 )
|
||||
{
|
||||
angle += 2 * M_PI;
|
||||
}
|
||||
|
||||
wxevent.SetRotationAngle(angle);
|
||||
|
||||
GetWXPeer()->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::LongPressEvent(NSPressGestureRecognizer* pressGestureRecognizer)
|
||||
{
|
||||
NSGestureRecognizerState gestureState;
|
||||
|
||||
switch ( [pressGestureRecognizer state] )
|
||||
{
|
||||
case NSGestureRecognizerStateBegan:
|
||||
gestureState = NSGestureRecognizerStateBegan;
|
||||
break;
|
||||
case NSGestureRecognizerStateChanged:
|
||||
break;
|
||||
case NSGestureRecognizerStateEnded:
|
||||
case NSGestureRecognizerStateCancelled:
|
||||
gestureState = NSGestureRecognizerStateEnded;
|
||||
break;
|
||||
// Do not process any other states
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
wxLongPressEvent wxevent(GetWXPeer()->GetId());
|
||||
wxevent.SetEventObject(GetWXPeer());
|
||||
|
||||
NSPoint nspoint = [pressGestureRecognizer locationInView:m_osxView];
|
||||
wxPoint pt = wxFromNSPoint(m_osxView, nspoint);
|
||||
|
||||
wxevent.SetPosition(pt);
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateBegan )
|
||||
{
|
||||
wxevent.SetGestureStart();
|
||||
}
|
||||
|
||||
if ( gestureState == NSGestureRecognizerStateEnded )
|
||||
{
|
||||
wxevent.SetGestureEnd();
|
||||
}
|
||||
|
||||
GetWXPeer()->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
enum TrackedGestures
|
||||
{
|
||||
two_finger_tap = 0x0001,
|
||||
press_and_tap = 0x0002
|
||||
};
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromObject(this) )
|
||||
gestures->TouchesBegan(event);
|
||||
}
|
||||
|
||||
void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event)
|
||||
{
|
||||
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:m_view];
|
||||
|
||||
m_touchCount += touches.count;
|
||||
m_allowedGestures &= ~two_finger_tap;
|
||||
|
||||
// Check if 2 fingers are placed together
|
||||
if ( m_touchCount == 2 && touches.count == 2 )
|
||||
{
|
||||
// Two Finger Tap Event may occur in future
|
||||
m_allowedGestures |= two_finger_tap;
|
||||
|
||||
// Cancel Press and Tap Event
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Time of event in milliseconds
|
||||
const unsigned int eventTimeStamp = event.timestamp * 1000 + 0.5;
|
||||
|
||||
if ( m_touchCount == 1 )
|
||||
{
|
||||
// Save the time of event
|
||||
m_lastTouchTime = eventTimeStamp;
|
||||
|
||||
// Press and Tap may occur in future
|
||||
m_allowedGestures |= press_and_tap;
|
||||
|
||||
NSArray* array = [touches allObjects];
|
||||
|
||||
// Save the touch corresponding to "press"
|
||||
m_initialTouch = [[array objectAtIndex:0] copy];
|
||||
}
|
||||
|
||||
touches = [event touchesMatchingPhase:NSTouchPhaseStationary inView:m_view];
|
||||
|
||||
// Check if 2 fingers are placed within the time interval of 200 milliseconds
|
||||
if ( m_touchCount == 2 && touches.count == 1 && eventTimeStamp - m_lastTouchTime <= wxTwoFingerTimeInterval )
|
||||
{
|
||||
// Two Finger Tap Event may occur in future
|
||||
m_allowedGestures |= two_finger_tap;
|
||||
|
||||
// Cancel Press and Tap
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
|
||||
[m_initialTouch release];
|
||||
}
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromObject(this) )
|
||||
gestures->TouchesMoved(event);
|
||||
}
|
||||
|
||||
void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event)
|
||||
{
|
||||
// Cancel Two Finger Tap Event if there is any movement
|
||||
m_allowedGestures &= ~two_finger_tap;
|
||||
|
||||
if ( !(m_allowedGestures & press_and_tap) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:m_view];
|
||||
|
||||
NSArray* array = [touches allObjects];
|
||||
|
||||
// Iterate through all moving touches to check if the touch corresponding to "press"
|
||||
// in Press and Tap event is moving.
|
||||
for ( int i = 0; i < [array count]; ++i )
|
||||
{
|
||||
NSTouch* touch = [array objectAtIndex:i];
|
||||
|
||||
// Check if this touch and m_initialTouch are same
|
||||
if ( [touch.identity isEqual:m_initialTouch.identity] )
|
||||
{
|
||||
// Process Press and Tap Event if the touch corresponding to "press" is moving
|
||||
// and the gesture is active.
|
||||
if ( m_activeGestures & press_and_tap )
|
||||
{
|
||||
wxPressAndTapEvent wxevent(m_win->GetId());
|
||||
wxevent.SetEventObject(m_win);
|
||||
|
||||
// Get the mouse coordinates
|
||||
wxCoord x, y;
|
||||
wxSetupCoordinates(m_view, x, y, event);
|
||||
wxevent.SetPosition(wxPoint (x,y));
|
||||
|
||||
m_win->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
// Cancel Press and Tap Event if the touch corresponding to "press" is moving
|
||||
// and the gesture is not active.
|
||||
else
|
||||
{
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromObject(this) )
|
||||
gestures->TouchesEnded(event);
|
||||
}
|
||||
|
||||
void wxCocoaGesturesImpl::TouchesEnded(NSEvent* event)
|
||||
{
|
||||
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:m_view];
|
||||
|
||||
m_touchCount -= touches.count;
|
||||
|
||||
// Time of event in milliseconds
|
||||
const unsigned int eventTimeStamp = event.timestamp * 1000 + 0.5;
|
||||
|
||||
// Check if 2 fingers are lifted off together or if 2 fingers are lifted off within the time interval of 200 milliseconds
|
||||
if ( (!m_touchCount && (m_allowedGestures & two_finger_tap)) &&
|
||||
(touches.count == 2 ||
|
||||
(touches.count == 1 && eventTimeStamp - m_lastTouchTime <= wxTwoFingerTimeInterval)) )
|
||||
{
|
||||
wxTwoFingerTapEvent wxevent(m_win->GetId());
|
||||
wxevent.SetEventObject(m_win);
|
||||
wxevent.SetGestureStart();
|
||||
wxevent.SetGestureEnd();
|
||||
|
||||
// Get the mouse coordinates
|
||||
wxCoord x, y;
|
||||
wxSetupCoordinates(m_view, x, y, event);
|
||||
wxevent.SetPosition(wxPoint (x,y));
|
||||
|
||||
m_win->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
// If Two Finger Tap Event is possible in future then save the timestamp to use it when the other touch
|
||||
// leaves the surface.
|
||||
else if ( m_touchCount == 1 && (m_allowedGestures & two_finger_tap) )
|
||||
{
|
||||
m_lastTouchTime = eventTimeStamp;
|
||||
}
|
||||
|
||||
// Check if Press and Tap event is possible.
|
||||
else if ( m_allowedGestures & press_and_tap )
|
||||
{
|
||||
NSArray* array = [touches allObjects];
|
||||
|
||||
// True if touch that ended is the touch corresponding to "press"
|
||||
bool isPressTouch = false;
|
||||
|
||||
// Iterate through all ended touches
|
||||
for( int i = 0; i < [array count]; ++i )
|
||||
{
|
||||
NSTouch* touch = [array objectAtIndex:i];
|
||||
|
||||
// Check if touch that ended is the touch corresponding to "press"
|
||||
if ( [touch.identity isEqual:m_initialTouch.identity] )
|
||||
{
|
||||
isPressTouch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel Press and Tap Event if the touch corresponding to press is ended
|
||||
// and Press and Tap was not active
|
||||
if ( isPressTouch && !(m_activeGestures & press_and_tap) )
|
||||
{
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
return;
|
||||
}
|
||||
|
||||
wxPressAndTapEvent wxevent(m_win->GetId());
|
||||
wxevent.SetEventObject(m_win);
|
||||
|
||||
// Get the mouse coordinates
|
||||
wxCoord x, y;
|
||||
wxSetupCoordinates(m_view, x, y, event);
|
||||
wxevent.SetPosition(wxPoint (x,y));
|
||||
|
||||
if ( !(m_activeGestures & press_and_tap) )
|
||||
{
|
||||
wxevent.SetGestureStart();
|
||||
m_activeGestures |= press_and_tap;
|
||||
}
|
||||
|
||||
// End Press and Tap Event if the touch corresponding to "press" is lifted off
|
||||
else if ( isPressTouch )
|
||||
{
|
||||
wxevent.SetGestureEnd();
|
||||
|
||||
m_activeGestures &= ~press_and_tap;
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
[m_initialTouch release];
|
||||
}
|
||||
|
||||
m_win->HandleWindowEvent(wxevent);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
m_allowedGestures &= ~press_and_tap;
|
||||
m_allowedGestures &= ~two_finger_tap;
|
||||
m_activeGestures &= ~press_and_tap;
|
||||
}
|
||||
}
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
|
||||
void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -1875,6 +2499,10 @@ wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
||||
// gc aware handling
|
||||
if ( m_osxView )
|
||||
CFRelease(m_osxView);
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
wxCocoaGestures::EraseForObject(this);
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
}
|
||||
|
||||
bool wxWidgetCocoaImpl::IsVisible() const
|
||||
@@ -2791,7 +3419,42 @@ void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
|
||||
NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil];
|
||||
[m_osxView addTrackingArea: area];
|
||||
[area release];
|
||||
}
|
||||
|
||||
bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
if ( wxPlatformInfo::Get().CheckOSVersion(10, 10) )
|
||||
{
|
||||
if ( IsUserPane() )
|
||||
{
|
||||
if ( eventsMask == wxTOUCH_NONE )
|
||||
{
|
||||
if ( wxCocoaGestures::EraseForObject(this) )
|
||||
{
|
||||
[m_osxView setAcceptsTouchEvents:NO];
|
||||
}
|
||||
//else: we didn't have any gesture data anyhow
|
||||
}
|
||||
else // We do want to have gesture events.
|
||||
{
|
||||
wxCocoaGestures::StoreForObject
|
||||
(
|
||||
this,
|
||||
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
||||
);
|
||||
|
||||
[m_osxView setAcceptsTouchEvents:YES];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||
|
||||
wxUnusedVar(eventsMask);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
|
||||
{
|
||||
|
@@ -1429,6 +1429,11 @@ void wxWindowMac::WarpPointer(int x_pos, int y_pos)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxWindowMac::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
return GetPeer() ? GetPeer()->EnableTouchEvents(eventsMask) : false;
|
||||
}
|
||||
|
||||
int wxWindowMac::GetScrollPos(int orient) const
|
||||
{
|
||||
#if wxUSE_SCROLLBAR
|
||||
|
Reference in New Issue
Block a user