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(NSOpenGLContext);
|
||||||
DECLARE_WXCOCOA_OBJC_CLASS(NSOpenGLPixelFormat);
|
DECLARE_WXCOCOA_OBJC_CLASS(NSOpenGLPixelFormat);
|
||||||
DECLARE_WXCOCOA_OBJC_CLASS( NSPrintInfo );
|
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__ */
|
#endif /* __WXMAC__ &__DARWIN__ */
|
||||||
|
|
||||||
#ifdef __WXMAC__
|
#ifdef __WXMAC__
|
||||||
@@ -3267,6 +3273,7 @@ typedef struct _GdkDragContext GdkDragContext;
|
|||||||
|
|
||||||
#if defined(__WXGTK3__)
|
#if defined(__WXGTK3__)
|
||||||
typedef struct _GdkWindow GdkWindow;
|
typedef struct _GdkWindow GdkWindow;
|
||||||
|
typedef struct _GdkEventSequence GdkEventSequence;
|
||||||
#elif defined(__WXGTK20__)
|
#elif defined(__WXGTK20__)
|
||||||
typedef struct _GdkDrawable GdkWindow;
|
typedef struct _GdkDrawable GdkWindow;
|
||||||
typedef struct _GdkDrawable GdkPixmap;
|
typedef struct _GdkDrawable GdkPixmap;
|
||||||
|
@@ -631,6 +631,13 @@ class WXDLLIMPEXP_FWD_CORE wxInitDialogEvent;
|
|||||||
class WXDLLIMPEXP_FWD_CORE wxUpdateUIEvent;
|
class WXDLLIMPEXP_FWD_CORE wxUpdateUIEvent;
|
||||||
class WXDLLIMPEXP_FWD_CORE wxClipboardTextEvent;
|
class WXDLLIMPEXP_FWD_CORE wxClipboardTextEvent;
|
||||||
class WXDLLIMPEXP_FWD_CORE wxHelpEvent;
|
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
|
// 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_THUMBTRACK, wxScrollWinEvent);
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SCROLLWIN_THUMBRELEASE, 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
|
// System events
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SIZE, wxSizeEvent);
|
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SIZE, wxSizeEvent);
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_MOVE, wxMoveEvent);
|
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_MOVE, wxMoveEvent);
|
||||||
@@ -1850,6 +1865,197 @@ private:
|
|||||||
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSetCursorEvent);
|
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
|
// Keyboard input event class
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3908,7 +4114,12 @@ typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
|
|||||||
typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
|
typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
|
||||||
typedef void (wxEvtHandler::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
|
typedef void (wxEvtHandler::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
|
||||||
typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&);
|
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) \
|
#define wxCommandEventHandler(func) \
|
||||||
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
|
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
|
||||||
@@ -3983,6 +4194,18 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
|||||||
wxEVENT_HANDLER_CAST(wxMouseCaptureLostEventFunction, func)
|
wxEVENT_HANDLER_CAST(wxMouseCaptureLostEventFunction, func)
|
||||||
#define wxClipboardTextEventHandler(func) \
|
#define wxClipboardTextEventHandler(func) \
|
||||||
wxEVENT_HANDLER_CAST(wxClipboardTextEventFunction, 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
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
@@ -4317,6 +4540,14 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
|||||||
EVT_COMMAND_SCROLL_THUMBRELEASE(winid, func) \
|
EVT_COMMAND_SCROLL_THUMBRELEASE(winid, func) \
|
||||||
EVT_COMMAND_SCROLL_CHANGED(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
|
// Convenience macros for commonly-used commands
|
||||||
#define EVT_CHECKBOX(winid, func) wx__DECLARE_EVT1(wxEVT_CHECKBOX, winid, wxCommandEventHandler(func))
|
#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))
|
#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 bool Reparent( wxWindowBase *newParent ) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void WarpPointer(int x, int y) 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,
|
virtual void Refresh( bool eraseBackground = true,
|
||||||
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
||||||
|
@@ -100,6 +100,7 @@ public:
|
|||||||
virtual bool Reparent(wxWindowBase *newParent) wxOVERRIDE;
|
virtual bool Reparent(wxWindowBase *newParent) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void WarpPointer(int x, int y) wxOVERRIDE;
|
virtual void WarpPointer(int x, int y) wxOVERRIDE;
|
||||||
|
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void Refresh( bool eraseBackground = true,
|
virtual void Refresh( bool eraseBackground = true,
|
||||||
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;
|
||||||
@@ -360,6 +361,16 @@ public:
|
|||||||
bool HandleMouseWheel(wxMouseWheelAxis axis,
|
bool HandleMouseWheel(wxMouseWheelAxis axis,
|
||||||
WXWPARAM wParam, WXLPARAM lParam);
|
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 HandleChar(WXWPARAM wParam, WXLPARAM lParam);
|
||||||
bool HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam);
|
bool HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam);
|
||||||
bool HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam);
|
bool HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam);
|
||||||
|
@@ -128,6 +128,7 @@ public :
|
|||||||
void SetToolTip( wxToolTip* tooltip );
|
void SetToolTip( wxToolTip* tooltip );
|
||||||
|
|
||||||
void InstallEventHandler( WXWidget control = NULL );
|
void InstallEventHandler( WXWidget control = NULL );
|
||||||
|
bool EnableTouchEvents(int eventsMask);
|
||||||
|
|
||||||
virtual bool ShouldHandleKeyNavigation(const wxKeyEvent &event) const;
|
virtual bool ShouldHandleKeyNavigation(const wxKeyEvent &event) const;
|
||||||
bool DoHandleKeyNavigation(const wxKeyEvent &event);
|
bool DoHandleKeyNavigation(const wxKeyEvent &event);
|
||||||
@@ -143,6 +144,15 @@ public :
|
|||||||
void SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent *nsEvent);
|
void SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent *nsEvent);
|
||||||
virtual bool SetupCursor(NSEvent* event);
|
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
|
#if !wxOSX_USE_NATIVE_FLIPPED
|
||||||
void SetFlipped(bool flipped);
|
void SetFlipped(bool flipped);
|
||||||
|
@@ -326,6 +326,8 @@ public :
|
|||||||
|
|
||||||
virtual void InstallEventHandler( WXWidget control = NULL ) = 0;
|
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
|
// Mechanism used to keep track of whether a change should send an event
|
||||||
// Do SendEvents(false) when starting actions that would trigger programmatic events
|
// Do SendEvents(false) when starting actions that would trigger programmatic events
|
||||||
// and SendEvents(true) at the end of the block.
|
// 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 SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack = true );
|
||||||
|
|
||||||
void InstallEventHandler( WXWidget control = NULL );
|
void InstallEventHandler( WXWidget control = NULL );
|
||||||
|
bool EnableTouchEvents(int WXUNUSED(eventsMask)) { return false; }
|
||||||
|
|
||||||
virtual void DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow);
|
virtual void DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow);
|
||||||
|
|
||||||
|
@@ -77,6 +77,7 @@ public:
|
|||||||
virtual void SetFocus() wxOVERRIDE;
|
virtual void SetFocus() wxOVERRIDE;
|
||||||
|
|
||||||
virtual void WarpPointer( int x, int y ) wxOVERRIDE;
|
virtual void WarpPointer( int x, int y ) wxOVERRIDE;
|
||||||
|
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void Refresh( bool eraseBackground = true,
|
virtual void Refresh( bool eraseBackground = true,
|
||||||
const wxRect *rect = NULL ) wxOVERRIDE;
|
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
|
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()
|
// flags for SendSizeEvent()
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -1033,6 +1047,13 @@ public:
|
|||||||
virtual bool HasCapture() const
|
virtual bool HasCapture() const
|
||||||
{ return (wxWindow *)this == GetCapture(); }
|
{ 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
|
// painting the window
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
|
@@ -3644,6 +3644,251 @@ public:
|
|||||||
void SetPosition(int pos);
|
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
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
#if wxUSE_BASE
|
#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()
|
flags for SendSizeEvent()
|
||||||
*/
|
*/
|
||||||
@@ -3424,6 +3486,28 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void WarpPointer(int x, int y);
|
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)
|
$(SAMPLES_CXXFLAGS) $(CPPFLAGS) $(CXXFLAGS)
|
||||||
EVENT_OBJECTS = \
|
EVENT_OBJECTS = \
|
||||||
$(__event___win32rc) \
|
$(__event___win32rc) \
|
||||||
event_event.o
|
event_event.o \
|
||||||
|
event_gestures.o
|
||||||
|
|
||||||
### Conditionally set variables: ###
|
### Conditionally set variables: ###
|
||||||
|
|
||||||
@@ -177,6 +178,8 @@ event_sample_rc.o: $(srcdir)/../../samples/sample.rc
|
|||||||
event_event.o: $(srcdir)/event.cpp
|
event_event.o: $(srcdir)/event.cpp
|
||||||
$(CXXC) -c -o $@ $(EVENT_CXXFLAGS) $(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:
|
# Include dependency info, if present:
|
||||||
@IF_GNU_MAKE@-include ./.deps/*.d
|
@IF_GNU_MAKE@-include ./.deps/*.d
|
||||||
|
@@ -4,7 +4,8 @@
|
|||||||
<include file="../../build/bakefiles/common_samples.bkl"/>
|
<include file="../../build/bakefiles/common_samples.bkl"/>
|
||||||
|
|
||||||
<exe id="event" template="wx_sample" template_append="wx_append">
|
<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>core</wx-lib>
|
||||||
<wx-lib>base</wx-lib>
|
<wx-lib>base</wx-lib>
|
||||||
</exe>
|
</exe>
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
#include "gestures.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// event constants
|
// event constants
|
||||||
@@ -144,6 +145,9 @@ public:
|
|||||||
void OnClickDynamicHandlerButton(wxCommandEvent& event);
|
void OnClickDynamicHandlerButton(wxCommandEvent& event);
|
||||||
void OnClickStaticHandlerFrame(wxCommandEvent& event);
|
void OnClickStaticHandlerFrame(wxCommandEvent& event);
|
||||||
|
|
||||||
|
// Gesture
|
||||||
|
void OnGesture(wxCommandEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// symbolic names for the status bar fields
|
// symbolic names for the status bar fields
|
||||||
enum
|
enum
|
||||||
@@ -178,6 +182,8 @@ private:
|
|||||||
// the button used to highlight the event handlers execution order
|
// the button used to highlight the event handlers execution order
|
||||||
MyEvtTestButton *m_testBtn;
|
MyEvtTestButton *m_testBtn;
|
||||||
|
|
||||||
|
wxWindowRef m_gestureFrame;
|
||||||
|
|
||||||
|
|
||||||
// any class wishing to process wxWidgets events must use this macro
|
// any class wishing to process wxWidgets events must use this macro
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
@@ -220,7 +226,8 @@ enum
|
|||||||
Event_Push,
|
Event_Push,
|
||||||
Event_Pop,
|
Event_Pop,
|
||||||
Event_Custom,
|
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_Test, MyFrame::OnTest)
|
||||||
EVT_MENU(Event_Push, MyFrame::OnPushEventHandler)
|
EVT_MENU(Event_Push, MyFrame::OnPushEventHandler)
|
||||||
EVT_MENU(Event_Pop, MyFrame::OnPopEventHandler)
|
EVT_MENU(Event_Pop, MyFrame::OnPopEventHandler)
|
||||||
|
EVT_MENU(Event_Gesture, MyFrame::OnGesture)
|
||||||
|
|
||||||
EVT_UPDATE_UI(Event_Pop, MyFrame::OnUpdateUIPop)
|
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->AppendSeparator();
|
||||||
menuEvent->Append(Event_Custom, wxT("Fire c&ustom event\tCtrl-U"),
|
menuEvent->Append(Event_Custom, wxT("Fire c&ustom event\tCtrl-U"),
|
||||||
wxT("Generate a custom event"));
|
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...
|
// now append the freshly created menu to the menu bar...
|
||||||
wxMenuBar *menuBar = new wxMenuBar();
|
wxMenuBar *menuBar = new wxMenuBar();
|
||||||
@@ -447,7 +457,8 @@ MyFrame::~MyFrame()
|
|||||||
|
|
||||||
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
// true is to force the frame to close
|
if ( m_gestureFrame )
|
||||||
|
m_gestureFrame->Close(true);
|
||||||
Close(true);
|
Close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,6 +588,19 @@ void MyFrame::OnPopEventHandler(wxCommandEvent& WXUNUSED(event))
|
|||||||
#endif // wxUSE_STATUSBAR
|
#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))
|
void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxLogMessage(wxT("This is the test event handler in the main frame"));
|
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!"));
|
wxLogMessage(wxT("Got a custom event!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -286,6 +286,17 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\event.cpp">
|
RelativePath=".\event.cpp">
|
||||||
</File>
|
</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>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Resource Files"
|
Name="Resource Files"
|
||||||
|
@@ -810,6 +810,20 @@
|
|||||||
RelativePath=".\event.cpp"
|
RelativePath=".\event.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</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>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Resource Files"
|
Name="Resource Files"
|
||||||
|
@@ -782,6 +782,20 @@
|
|||||||
RelativePath=".\event.cpp"
|
RelativePath=".\event.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</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>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Resource Files"
|
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. \
|
-I$(SETUPHDIR) -I.\..\..\include $(____CAIRO_INCLUDEDIR_FILENAMES_p) -I. \
|
||||||
$(__DLLFLAG_p) -I.\..\..\samples -DNOPCH $(CPPFLAGS) $(CXXFLAGS)
|
$(__DLLFLAG_p) -I.\..\..\samples -DNOPCH $(CPPFLAGS) $(CXXFLAGS)
|
||||||
EVENT_OBJECTS = \
|
EVENT_OBJECTS = \
|
||||||
$(OBJS)\event_event.obj
|
$(OBJS)\event_event.obj \
|
||||||
|
$(OBJS)\event_gestures.obj
|
||||||
|
|
||||||
### Conditionally set variables: ###
|
### Conditionally set variables: ###
|
||||||
|
|
||||||
@@ -237,3 +238,5 @@ $(OBJS)\event_sample.res: .\..\..\samples\sample.rc
|
|||||||
$(OBJS)\event_event.obj: .\event.cpp
|
$(OBJS)\event_event.obj: .\event.cpp
|
||||||
$(CXX) -q -c -P -o$@ $(EVENT_CXXFLAGS) .\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)
|
$(__EXCEPTIONSFLAG_6) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
|
||||||
EVENT_OBJECTS = \
|
EVENT_OBJECTS = \
|
||||||
$(OBJS)\event_sample_rc.o \
|
$(OBJS)\event_sample_rc.o \
|
||||||
$(OBJS)\event_event.o
|
$(OBJS)\event_event.o \
|
||||||
|
$(OBJS)\event_gestures.o
|
||||||
|
|
||||||
### Conditionally set variables: ###
|
### Conditionally set variables: ###
|
||||||
|
|
||||||
@@ -226,6 +227,9 @@ $(OBJS)\event_sample_rc.o: ./../../samples/sample.rc
|
|||||||
$(OBJS)\event_event.o: ./event.cpp
|
$(OBJS)\event_event.o: ./event.cpp
|
||||||
$(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $<
|
$(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $<
|
||||||
|
|
||||||
|
$(OBJS)\event_gestures.o: ./gestures.cpp
|
||||||
|
$(CXX) -c -o $@ $(EVENT_CXXFLAGS) $(CPPDEPS) $<
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
|
|
||||||
|
@@ -31,7 +31,8 @@ EVENT_CXXFLAGS = /M$(__RUNTIME_LIBS_10)$(__DEBUGRUNTIME_4) /DWIN32 \
|
|||||||
/I.\..\..\samples /DNOPCH $(__RTTIFLAG_11) $(__EXCEPTIONSFLAG_12) \
|
/I.\..\..\samples /DNOPCH $(__RTTIFLAG_11) $(__EXCEPTIONSFLAG_12) \
|
||||||
$(CPPFLAGS) $(CXXFLAGS)
|
$(CPPFLAGS) $(CXXFLAGS)
|
||||||
EVENT_OBJECTS = \
|
EVENT_OBJECTS = \
|
||||||
$(OBJS)\event_event.obj
|
$(OBJS)\event_event.obj \
|
||||||
|
$(OBJS)\event_gestures.obj
|
||||||
EVENT_RESOURCES = \
|
EVENT_RESOURCES = \
|
||||||
$(OBJS)\event_sample.res
|
$(OBJS)\event_sample.res
|
||||||
|
|
||||||
@@ -360,3 +361,5 @@ $(OBJS)\event_sample.res: .\..\..\samples\sample.rc
|
|||||||
$(OBJS)\event_event.obj: .\event.cpp
|
$(OBJS)\event_event.obj: .\event.cpp
|
||||||
$(CXX) /c /nologo /TP /Fo$@ $(EVENT_CXXFLAGS) .\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(wxMouseCaptureChangedEvent, wxEvent);
|
||||||
wxIMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent);
|
wxIMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent);
|
||||||
wxIMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent);
|
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
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
#if wxUSE_BASE
|
#if wxUSE_BASE
|
||||||
@@ -258,6 +265,14 @@ wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEDOWN, wxScrollWinEvent );
|
|||||||
wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEvent );
|
wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEvent );
|
||||||
wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBRELEASE, 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
|
// System events
|
||||||
wxDEFINE_EVENT( wxEVT_SIZE, wxSizeEvent );
|
wxDEFINE_EVENT( wxEVT_SIZE, wxSizeEvent );
|
||||||
wxDEFINE_EVENT( wxEVT_SIZING, wxSizeEvent );
|
wxDEFINE_EVENT( wxEVT_SIZING, wxSizeEvent );
|
||||||
|
@@ -227,6 +227,80 @@ static GList* gs_sizeRevalidateList;
|
|||||||
static bool gs_inSizeAllocate;
|
static bool gs_inSizeAllocate;
|
||||||
#endif
|
#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
|
// debug
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -2624,6 +2698,10 @@ wxWindowGTK::~wxWindowGTK()
|
|||||||
gs_sizeRevalidateList = g_list_remove_all(gs_sizeRevalidateList, this);
|
gs_sizeRevalidateList = g_list_remove_all(gs_sizeRevalidateList, this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef wxGTK_HAS_GESTURES_SUPPORT
|
||||||
|
wxWindowGestures::EraseForObject(this);
|
||||||
|
#endif // wxGTK_HAS_GESTURES_SUPPORT
|
||||||
|
|
||||||
if (m_widget)
|
if (m_widget)
|
||||||
{
|
{
|
||||||
// Note that gtk_widget_destroy() does not destroy the widget, it just
|
// 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 )
|
void wxWindowGTK::ConnectWidget( GtkWidget *widget )
|
||||||
{
|
{
|
||||||
static bool isSourceAttached;
|
static bool isSourceAttached;
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include "wx/textctrl.h"
|
#include "wx/textctrl.h"
|
||||||
#include "wx/menuitem.h"
|
#include "wx/menuitem.h"
|
||||||
#include "wx/module.h"
|
#include "wx/module.h"
|
||||||
|
#include "wx/vector.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
|
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
|
||||||
@@ -205,6 +206,82 @@ bool gs_insideCaptureChanged = false;
|
|||||||
|
|
||||||
} // anonymous namespace
|
} // 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
|
// 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)
|
void wxWindowMSW::MSWUpdateUIState(int action, int state)
|
||||||
{
|
{
|
||||||
// we send WM_CHANGEUISTATE so if nothing needs changing then the system
|
// we send WM_CHANGEUISTATE so if nothing needs changing then the system
|
||||||
@@ -3124,6 +3318,84 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
|
|||||||
}
|
}
|
||||||
break;
|
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
|
// CTLCOLOR messages are sent by children to query the parent for their
|
||||||
// colors
|
// colors
|
||||||
case WM_CTLCOLORMSGBOX:
|
case WM_CTLCOLORMSGBOX:
|
||||||
@@ -5474,6 +5746,144 @@ void wxWindowMSW::GenerateMouseLeave()
|
|||||||
(void)HandleWindowEvent(event);
|
(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
|
// keyboard handling
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@@ -528,29 +528,35 @@ bool g_lastButtonWasFakeRight = false ;
|
|||||||
- (CGFloat)scrollingDeltaY;
|
- (CGFloat)scrollingDeltaY;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
void wxWidgetCocoaImpl::SetupCoordinates(wxCoord &x, wxCoord &y, NSEvent* nsEvent)
|
static void
|
||||||
|
wxSetupCoordinates(NSView* view, wxCoord &x, wxCoord &y, NSEvent* nsEvent)
|
||||||
{
|
{
|
||||||
NSRect locationInWindow = NSZeroRect;
|
NSRect locationInWindow = NSZeroRect;
|
||||||
locationInWindow.origin = [nsEvent locationInWindow];
|
locationInWindow.origin = [nsEvent locationInWindow];
|
||||||
|
|
||||||
// adjust coordinates for the window of the target view
|
// adjust coordinates for the window of the target view
|
||||||
if ( [nsEvent window] != [m_osxView window] )
|
if ( [nsEvent window] != [view window] )
|
||||||
{
|
{
|
||||||
if ( [nsEvent window] != nil )
|
if ( [nsEvent window] != nil )
|
||||||
locationInWindow = [[nsEvent window] convertRectToScreen:locationInWindow];
|
locationInWindow = [[nsEvent window] convertRectToScreen:locationInWindow];
|
||||||
|
|
||||||
if ( [m_osxView window] != nil )
|
if ( [view window] != nil )
|
||||||
locationInWindow = [[m_osxView window] convertRectFromScreen:locationInWindow];
|
locationInWindow = [[view window] convertRectFromScreen:locationInWindow];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPoint locationInView = [m_osxView convertPoint:locationInWindow.origin fromView:nil];
|
NSPoint locationInView = [view convertPoint:locationInWindow.origin fromView:nil];
|
||||||
wxPoint locationInViewWX = wxFromNSPoint( m_osxView, locationInView );
|
wxPoint locationInViewWX = wxFromNSPoint( view, locationInView );
|
||||||
|
|
||||||
x = locationInViewWX.x;
|
x = locationInViewWX.x;
|
||||||
y = locationInViewWX.y;
|
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 )
|
void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
|
||||||
{
|
{
|
||||||
int eventType = [nsEvent type];
|
int eventType = [nsEvent type];
|
||||||
@@ -1042,6 +1048,71 @@ void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
|
|||||||
impl->insertText(text, self, _cmd);
|
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)
|
BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event)
|
||||||
{
|
{
|
||||||
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
|
||||||
@@ -1428,6 +1499,559 @@ void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
|
|||||||
m_lastKeyDownEvent = NULL;
|
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)
|
void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@@ -1775,7 +2399,7 @@ void wxOSXCocoaClassAddWXMethods(Class c)
|
|||||||
wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
||||||
wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
||||||
wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
|
||||||
|
|
||||||
wxOSX_CLASS_ADD_METHOD(c, @selector(magnifyWithEvent:), (IMP)wxOSX_mouseEvent, "v@:@")
|
wxOSX_CLASS_ADD_METHOD(c, @selector(magnifyWithEvent:), (IMP)wxOSX_mouseEvent, "v@:@")
|
||||||
|
|
||||||
wxOSX_CLASS_ADD_METHOD(c, @selector(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" )
|
wxOSX_CLASS_ADD_METHOD(c, @selector(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" )
|
||||||
@@ -1875,6 +2499,10 @@ wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
|||||||
// gc aware handling
|
// gc aware handling
|
||||||
if ( m_osxView )
|
if ( m_osxView )
|
||||||
CFRelease(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
|
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];
|
NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil];
|
||||||
[m_osxView addTrackingArea: area];
|
[m_osxView addTrackingArea: area];
|
||||||
[area release];
|
[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)
|
bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
|
||||||
{
|
{
|
||||||
|
@@ -1429,6 +1429,11 @@ void wxWindowMac::WarpPointer(int x_pos, int y_pos)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxWindowMac::EnableTouchEvents(int eventsMask)
|
||||||
|
{
|
||||||
|
return GetPeer() ? GetPeer()->EnableTouchEvents(eventsMask) : false;
|
||||||
|
}
|
||||||
|
|
||||||
int wxWindowMac::GetScrollPos(int orient) const
|
int wxWindowMac::GetScrollPos(int orient) const
|
||||||
{
|
{
|
||||||
#if wxUSE_SCROLLBAR
|
#if wxUSE_SCROLLBAR
|
||||||
|
Reference in New Issue
Block a user