Merge multi-touch gestures event branch

This is a squashed commit of the SOC2017_GESTURES branch from
https://github.com/prashantkn94/wxWidgets.git

Closes https://github.com/wxWidgets/wxWidgets/pull/551
This commit is contained in:
prashantkn94
2017-09-10 21:13:32 +05:30
committed by Vadim Zeitlin
parent aef4edb969
commit 261b04b5a3
21 changed files with 2318 additions and 10 deletions

View File

@@ -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;

View File

@@ -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,201 @@ 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)
{
m_deltaX = 0;
m_deltaY = 0;
}
wxPanGestureEvent(const wxPanGestureEvent& event) : wxGestureEvent(event)
{
m_deltaX = event.m_deltaX;
m_deltaY = event.m_deltaY;
}
int GetDeltaX() const { return m_deltaX; }
void SetDeltaX(int DeltaX) { m_deltaX = DeltaX; }
int GetDeltaY() const { return m_deltaY; }
void SetDeltaY(int DeltaY) { m_deltaY = DeltaY; }
virtual wxEvent *Clone() const { return new wxPanGestureEvent(*this); }
private:
int m_deltaX, m_deltaY;
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 +4118,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 +4198,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 +4544,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))

View File

@@ -355,6 +355,16 @@ public:
wxRegion m_nativeUpdateRegion; // not transformed for RTL wxRegion m_nativeUpdateRegion; // not transformed for RTL
#if defined(__WXGTK3__)
unsigned int m_touchCount;
unsigned int m_lastTouchTime;
int m_gestureState;
int m_allowedGestures;
int m_activeGestures;
wxPoint m_lastTouchPoint;
GdkEventSequence* m_touchSequence;
#endif
protected: protected:
// implement the base class pure virtuals // implement the base class pure virtuals
virtual void DoGetTextExtent(const wxString& string, virtual void DoGetTextExtent(const wxString& string,

View File

@@ -360,6 +360,12 @@ public:
bool HandleMouseWheel(wxMouseWheelAxis axis, bool HandleMouseWheel(wxMouseWheelAxis axis,
WXWPARAM wParam, WXLPARAM lParam); WXWPARAM wParam, WXLPARAM lParam);
bool HandlePanGesture(int x, int y, WXDWORD flags);
bool HandleZoomGesture(int x, int y, WXDWORD fingerDistance, WXDWORD flags);
bool HandleRotateGesture(int x, int y, WXDWORD angleArgument, WXDWORD flags);
bool HandleTwoFingerTap(int x, int y, WXDWORD flags);
bool HandlePressAndTap(int x, int y, 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);

View File

@@ -143,6 +143,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);
@@ -190,6 +199,21 @@ protected:
// events, don't resend them // events, don't resend them
bool m_hasEditor; bool m_hasEditor;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
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;
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxWidgetCocoaImpl); wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxWidgetCocoaImpl);
}; };

View File

@@ -3644,6 +3644,257 @@ public:
void SetPosition(int pos); void SetPosition(int pos);
}; };
/** @class wxGestureEvent
This is the base class for all supported gesture events.
@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 horizontal component of the distance covered since the previous Pan event.
*/
int GetDeltaX() const;
/**
Returns the vertical component of the distance covered since the previous Pan event.
*/
int GetDeltaY() const;
/**
Sets the horizontal component of the distance covered since the previous Pan event.
*/
int SetDeltaX(int DeltaX);
/**
Sets the vertical component of the distance covered since the previous Pan event.
*/
int SetDeltaY(int DeltaY);
};
/** @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

View File

@@ -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

View File

@@ -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>

View File

@@ -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;
MyGestureFrame *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)
@@ -290,6 +298,8 @@ bool MyApp::OnInit()
if ( !wxApp::OnInit() ) if ( !wxApp::OnInit() )
return false; return false;
wxImage::AddHandler(new wxJPEGHandler);
// create the main application window // create the main application window
MyFrame *frame = new MyFrame(wxT("Event wxWidgets Sample"), MyFrame *frame = new MyFrame(wxT("Event wxWidgets Sample"),
wxPoint(50, 50), wxSize(600, 340)); wxPoint(50, 50), wxSize(600, 340));
@@ -381,6 +391,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();
@@ -577,6 +589,12 @@ void MyFrame::OnPopEventHandler(wxCommandEvent& WXUNUSED(event))
#endif // wxUSE_STATUSBAR #endif // wxUSE_STATUSBAR
} }
void MyFrame::OnGesture(wxCommandEvent& WXUNUSED(event))
{
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 +620,3 @@ void MyFrame::OnProcessCustom(wxCommandEvent& WXUNUSED(event))
{ {
wxLogMessage(wxT("Got a custom event!")); wxLogMessage(wxT("Got a custom event!"));
} }

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

216
samples/event/gestures.cpp Normal file
View File

@@ -0,0 +1,216 @@
#include "gestures.h"
#include "wx/dcgraph.h"
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)
{
// Load an image
if ( !m_bitmap.LoadFile("../image/horse.jpg", wxBITMAP_TYPE_JPEG) )
{
wxLogError("Can't load the image");
}
else
{
Bind(wxEVT_PAINT, &MyGesturePanel::OnPaint, this);
}
// 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");
}
wxLogMessage("Pan gesture performed with deltaX = %d and deltaY = %d, with current position (%d,%d)\n",
event.GetDeltaX(), event.GetDeltaY(), event.GetPosition().x, event.GetPosition().y);
// Transform the distance using the tranpose of the matrix,
// in order to translate the image to match the screen coordinates
wxMatrix2D m;
m_affineMatrix.Get(&m, NULL);
wxPoint2DDouble delta(m.m_11 * event.GetDeltaX() + m.m_12 * event.GetDeltaY(),
m.m_21 * event.GetDeltaX() + m.m_22 * event.GetDeltaY());
// Add it to the total translation
m_translateDistance += delta;
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
View 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_

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 );

View File

@@ -228,6 +228,23 @@ static GList* gs_sizeRevalidateList;
static bool gs_inSizeAllocate; static bool gs_inSizeAllocate;
#endif #endif
#if GTK_CHECK_VERSION(3,14,0)
// 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 // GTK_CHECK_VERSION(3,14,0)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// debug // debug
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2430,6 +2447,13 @@ void wxWindowGTK::Init()
m_imKeyEvent = NULL; m_imKeyEvent = NULL;
m_dirtyTabOrder = false; m_dirtyTabOrder = false;
#if GTK_CHECK_VERSION(3,14,0)
m_touchCount = 0;
m_lastTouchTime = 0;
m_allowedGestures = 0;
m_activeGestures = 0;
#endif // GTK_CHECK_VERSION(3,14,0)
} }
wxWindowGTK::wxWindowGTK() wxWindowGTK::wxWindowGTK()
@@ -2828,6 +2852,455 @@ static gboolean source_dispatch(GSource*, GSourceFunc, void*)
} }
} }
#if GTK_CHECK_VERSION(3,14,0)
// 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)
{
// Do not process horizontal pan, if there was no "pan" signal for it.
if ( !(win->m_allowedGestures & horizontal_pan) )
{
return;
}
gdouble x, y;
if ( !gtk_gesture_get_point(gesture, sequence, &x, &y) )
{
return;
}
win->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)
{
// Do not process vertical pan, if there was no "pan" signal for it.
if ( !(win->m_allowedGestures & vertical_pan) )
{
return;
}
gdouble x, y;
if ( !gtk_gesture_get_point(gesture, sequence, &x, &y) )
{
return;
}
win->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)));
// 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:
win->m_allowedGestures |= vertical_pan;
event.SetDeltaY(-delta);
break;
case GTK_PAN_DIRECTION_DOWN:
win->m_allowedGestures |= vertical_pan;
event.SetDeltaY(delta);
break;
case GTK_PAN_DIRECTION_RIGHT:
win->m_allowedGestures |= horizontal_pan;
event.SetDeltaX(delta);
break;
case GTK_PAN_DIRECTION_LEFT:
win->m_allowedGestures |= horizontal_pan;
event.SetDeltaX(-delta);
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( !(win->m_activeGestures & press_and_tap) )
{
win->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);
// Cancel "Two FInger Tap Event" if scale has changed
if ( wxRound(scale * 1000) != wxRound(gs_lastScale * 1000) )
{
win->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);
double lastX = win->m_lastTouchPoint.x;
double lastY = win->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);
switch ( win->m_gestureState )
{
case begin:
event.SetGestureStart();
break;
case update:
// Update touch point as the touch corresponding to "press" is moving
if ( win->m_touchSequence == gdk_event->sequence )
{
win->m_lastTouchPoint.x = gdk_event->x;
win->m_lastTouchPoint.y = gdk_event->y;
}
break;
case end:
event.SetGestureEnd();
break;
}
event.SetPosition(win->m_lastTouchPoint);
win->GTKProcessEvent(event);
}
static void
touch_callback(GtkWidget* WXUNUSED(widget), GdkEventTouch* gdk_event, wxWindowGTK* win)
{
switch ( gdk_event->type )
{
case GDK_TOUCH_BEGIN:
win->m_touchCount++;
win->m_allowedGestures &= ~two_finger_tap;
if ( win->m_touchCount == 1 )
{
win->m_lastTouchTime = gdk_event->time;
win->m_lastTouchPoint.x = gdk_event->x;
win->m_lastTouchPoint.y = gdk_event->y;
// Save the sequence which identifies touch corresponding to "press"
win->m_touchSequence = gdk_event->sequence;
// "Press and Tap Event" may occur in future
win->m_allowedGestures |= press_and_tap;
}
// Check if two fingers are placed together .i.e difference between their time stamps is <= 200 milliseconds
else if ( win->m_touchCount == 2 && gdk_event->time - win->m_lastTouchTime <= wxTwoFingerTimeInterval )
{
// "Two Finger Tap Event" may be possible in the future
win->m_allowedGestures |= two_finger_tap;
// Cancel "Press and Tap Event"
win->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 ( (win->m_activeGestures & press_and_tap) && gdk_event->sequence == win->m_touchSequence )
{
win->m_gestureState = update;
wxEmitPressAndTapEvent(gdk_event, win);
}
break;
case GDK_TOUCH_END:
case GDK_TOUCH_CANCEL:
win->m_touchCount--;
if ( win->m_touchCount == 1 )
{
win->m_lastTouchTime = gdk_event->time;
// If the touch corresponding to "press" is present and "tap" is produced by some ather touch
if ( (win->m_allowedGestures & press_and_tap) && gdk_event->sequence != win->m_touchSequence )
{
// Press and Tap gesture becomes active now
if ( !(win->m_activeGestures & press_and_tap) )
{
win->m_gestureState = begin;
win->m_activeGestures |= press_and_tap;
}
else
{
win->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 ( (win->m_allowedGestures & two_finger_tap) && !win->m_touchCount
&& gdk_event->time - win->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 ( (win->m_activeGestures & press_and_tap) && gdk_event->sequence == win->m_touchSequence )
{
win->m_gestureState = end;
win->m_activeGestures &= ~press_and_tap;
win->m_allowedGestures &= ~press_and_tap;
wxEmitPressAndTapEvent(gdk_event, win);
}
break;
default:
break;
}
}
#endif // GTK_CHECK_VERSION(3,14,0)
void wxWindowGTK::ConnectWidget( GtkWidget *widget ) void wxWindowGTK::ConnectWidget( GtkWidget *widget )
{ {
static bool isSourceAttached; static bool isSourceAttached;
@@ -2870,6 +3343,81 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
G_CALLBACK (gtk_window_enter_callback), this); G_CALLBACK (gtk_window_enter_callback), this);
g_signal_connect (widget, "leave_notify_event", g_signal_connect (widget, "leave_notify_event",
G_CALLBACK (gtk_window_leave_callback), this); G_CALLBACK (gtk_window_leave_callback), this);
#if GTK_CHECK_VERSION(3,14,0)
if ( gtk_check_version(3, 14, 0) == NULL )
{
GtkGesture* vertical_pan_gesture = gtk_gesture_pan_new(widget, GTK_ORIENTATION_VERTICAL);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(vertical_pan_gesture), GTK_PHASE_TARGET);
g_signal_connect (vertical_pan_gesture, "begin",
G_CALLBACK(pan_gesture_begin_callback), this);
g_signal_connect (vertical_pan_gesture, "pan",
G_CALLBACK(pan_gesture_callback), this);
g_signal_connect (vertical_pan_gesture, "end",
G_CALLBACK(vertical_pan_gesture_end_callback), this);
g_signal_connect (vertical_pan_gesture, "cancel",
G_CALLBACK(vertical_pan_gesture_end_callback), this);
GtkGesture* 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(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(horizontal_pan_gesture), GTK_PHASE_TARGET);
g_signal_connect (horizontal_pan_gesture, "begin",
G_CALLBACK(pan_gesture_begin_callback), this);
g_signal_connect (horizontal_pan_gesture, "pan",
G_CALLBACK(pan_gesture_callback), this);
g_signal_connect (horizontal_pan_gesture, "end",
G_CALLBACK(horizontal_pan_gesture_end_callback), this);
g_signal_connect (horizontal_pan_gesture, "cancel",
G_CALLBACK(horizontal_pan_gesture_end_callback), this);
GtkGesture* zoom_gesture = gtk_gesture_zoom_new(widget);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(zoom_gesture), GTK_PHASE_TARGET);
g_signal_connect (zoom_gesture, "begin",
G_CALLBACK(zoom_gesture_begin_callback), this);
g_signal_connect (zoom_gesture, "scale-changed",
G_CALLBACK(zoom_gesture_callback), this);
g_signal_connect (zoom_gesture, "end",
G_CALLBACK(zoom_gesture_end_callback), this);
g_signal_connect (zoom_gesture, "cancel",
G_CALLBACK(zoom_gesture_end_callback), this);
GtkGesture* rotate_gesture = gtk_gesture_rotate_new(widget);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER(rotate_gesture), GTK_PHASE_TARGET);
g_signal_connect (rotate_gesture, "begin",
G_CALLBACK(rotate_gesture_begin_callback), this);
g_signal_connect (rotate_gesture, "angle-changed",
G_CALLBACK(rotate_gesture_callback), this);
g_signal_connect (rotate_gesture, "end",
G_CALLBACK(rotate_gesture_end_callback), this);
g_signal_connect (rotate_gesture, "cancel",
G_CALLBACK(rotate_gesture_end_callback), this);
GtkGesture* 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(long_press_gesture), TRUE)
// which will allow "pressed" signal only for Touch events.
gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(long_press_gesture), GTK_PHASE_TARGET);
g_signal_connect (long_press_gesture, "pressed",
G_CALLBACK(long_press_gesture_callback), this);
g_signal_connect (widget, "touch-event",
G_CALLBACK(touch_callback), this);
}
#endif // GTK_CHECK_VERSION(3,14,0)
} }
void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)

View File

@@ -205,6 +205,85 @@ bool gs_insideCaptureChanged = false;
} // anonymous namespace } // anonymous namespace
namespace
{
// Class used to dynamically load gestures related API functions.
#ifdef WM_GESTURE
class GestureFuncs
{
public:
static bool IsOk()
{
if ( !ms_gestureSymbolsLoaded )
LoadGestureSymbols();
return ms_pfnGetGestureInfo && ms_pfnCloseGestureInfoHandle && ms_pfnSetGestureConfig;
}
typedef BOOL (WINAPI *GetGestureInfo_t)(HGESTUREINFO, PGESTUREINFO);
static GetGestureInfo_t GetGestureInfo()
{
if ( !ms_gestureSymbolsLoaded )
LoadGestureSymbols();
return ms_pfnGetGestureInfo;
}
typedef BOOL (WINAPI *CloseGestureInfoHandle_t)(HGESTUREINFO);
static CloseGestureInfoHandle_t CloseGestureInfoHandle()
{
if ( !ms_gestureSymbolsLoaded )
LoadGestureSymbols();
return ms_pfnCloseGestureInfoHandle;
}
typedef BOOL (WINAPI *SetGestureConfig_t)(HWND, DWORD, UINT, PGESTURECONFIG, UINT);
static SetGestureConfig_t SetGestureConfig()
{
if ( !ms_gestureSymbolsLoaded )
LoadGestureSymbols();
return ms_pfnSetGestureConfig;
}
private:
static void LoadGestureSymbols()
{
wxDynamicLibrary dll("User32.dll");
wxDL_INIT_FUNC(ms_pfn, GetGestureInfo, dll);
wxDL_INIT_FUNC(ms_pfn, CloseGestureInfoHandle, dll);
wxDL_INIT_FUNC(ms_pfn, SetGestureConfig, dll);
ms_gestureSymbolsLoaded = true;
}
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;
#endif // WM_GESTURE
} // anonymous namespace
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// private functions // private functions
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -3124,6 +3203,97 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
} }
break; break;
#ifdef WM_GESTURE
case WM_GESTURE:
{
if ( !GestureFuncs::IsOk() )
{
processed = false;
break;
}
// gestureInfo will contain the information about the gesture
GESTUREINFO gestureInfo = {0};
gestureInfo.cbSize = sizeof(GESTUREINFO);
// This should fill gestureInfo with the gesture details
if ( !GestureFuncs::GetGestureInfo()((HGESTUREINFO)lParam, &gestureInfo) )
{
wxLogLastError("GetGestureInfo");
processed = false;
break;
}
if ( gestureInfo.hwndTarget != GetHWND() )
{
wxLogDebug("This is Not the window targeted by this gesture!");
}
int x = gestureInfo.ptsLocation.x;
int y = gestureInfo.ptsLocation.y;
ScreenToClient(&x, &y);
// dwID field is used to determine the type of gesture
switch ( gestureInfo.dwID )
{
// Pan gesture
case GID_PAN:
{
// (x,y) is the current position of the pan
processed = HandlePanGesture(x, y, gestureInfo.dwFlags);
break;
}
// Zoom gesture
case GID_ZOOM:
{
// (x,y) is the mid-point of 2 fingers
// ullArgument field is a 64-bit unsigned integer, but the relevant information
// is in it's lower 4 bytes and represents distance between the fingers
// this is used to extract those lower 4 bytes
DWORD fingerDistance = (DWORD)((gestureInfo.ullArguments) & 0x00000000ffffffff);
processed = HandleZoomGesture(x, y, fingerDistance, gestureInfo.dwFlags);
break;
}
// Rotate gesture
case GID_ROTATE:
{
// (x,y) is the center point of rotation
// Again, we need the lower 4 bytes and this will used as an argument
// to obtain the angle to rotate
DWORD angleArgument = (DWORD)((gestureInfo.ullArguments) & 0x00000000ffffffff);
processed = HandleRotateGesture(x, y, angleArgument, gestureInfo.dwFlags);
break;
}
// Two Finger tap gesture
case GID_TWOFINGERTAP:
{
processed = HandleTwoFingerTap(x, y, gestureInfo.dwFlags);
break;
}
// Press and Tap gesture
case GID_PRESSANDTAP:
{
processed = HandlePressAndTap(x, y, gestureInfo.dwFlags);
break;
}
}
if ( processed )
{
// If processed, we must call this to avoid memory leaks
if ( !GestureFuncs::CloseGestureInfoHandle()((HGESTUREINFO)lParam) )
{
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:
@@ -3660,6 +3830,20 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
return false; return false;
} }
#ifdef WM_GESTURE
if ( GestureFuncs::IsOk() )
{
// Configure to receive all gestures
GESTURECONFIG gestureConfig = {0, GC_ALLGESTURES, 0};
// This functions sets the configuration to the window. Second argument is reserved to be 0.
// Third argument is the number of elements in gestureConfig array, currently equal to 1
if ( !GestureFuncs::SetGestureConfig()(m_hWnd, 0, 1, &gestureConfig, sizeof(GESTURECONFIG)) )
{
wxLogLastError("SetGestureConfig");
}
}
#endif // WM_GESTURE
SubclassWin(m_hWnd); SubclassWin(m_hWnd);
@@ -5470,6 +5654,181 @@ void wxWindowMSW::GenerateMouseLeave()
(void)HandleWindowEvent(event); (void)HandleWindowEvent(event);
} }
#ifdef WM_GESTURE
// ---------------------------------------------------------------------------
// Gesture events
// ---------------------------------------------------------------------------
bool wxWindowMSW::HandlePanGesture(int x, int y, WXDWORD flags)
{
// wxEVT_GESTURE_PAN
wxPanGestureEvent event(GetId());
// These are used to calculate the pan delta
static int s_previousLocationX, s_previousLocationY;
// This flag indicates that the gesture has just started
// Store the current point to determine the pan delta later on
if ( flags & GF_BEGIN )
{
s_previousLocationX = x;
s_previousLocationY = y;
event.SetGestureStart();
}
if ( flags & GF_END )
{
event.SetGestureEnd();
}
// Determine the horizontal and vertical changes
int DeltaX = x - s_previousLocationX, DeltaY = y - s_previousLocationY;
event.SetEventObject(this);
event.SetTimestamp(::GetMessageTime());
event.SetPosition(wxPoint(x, y));
event.SetDeltaX(DeltaX);
event.SetDeltaY(DeltaY);
// Update the last gesture event point
s_previousLocationX = x;
s_previousLocationY = y;
return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleZoomGesture(int x, int y, WXDWORD fingerDistance, WXDWORD flags)
{
// wxEVT_GESTURE_ZOOM
wxZoomGestureEvent event(GetId());
// These are used to calculate the center of the zoom and zoom factor
static int s_previousLocationX, s_previousLocationY, s_intialFingerDistance;
// This flag indicates that the gesture has just started
// Store the current point and distance between the fingers for future calculations
if ( flags & GF_BEGIN )
{
s_previousLocationX = x;
s_previousLocationY = y;
s_intialFingerDistance = fingerDistance;
event.SetGestureStart();
}
if ( flags & GF_END )
{
event.SetGestureEnd();
}
// Calculate center point of the zoom
// Human beings are not very good at moving two fingers at exactly the same rate outwards/inwards
// 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
wxPoint pt;
pt.x = (s_previousLocationX + x) / 2;
pt.y = (s_previousLocationY + y) / 2;
double zoomFactor = (double) fingerDistance / (double) s_intialFingerDistance;
event.SetZoomFactor(zoomFactor);
event.SetEventObject(this);
event.SetTimestamp(::GetMessageTime());
// This is not a gesture point but the center of a zoom
event.SetPosition(pt);
// Update gesture event point
s_previousLocationX = x;
s_previousLocationY = y;
return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleRotateGesture(int x, int y, WXDWORD angleArgument, WXDWORD flags)
{
// wxEVT_GESTURE_ROTATE
wxRotateGestureEvent event(GetId());
// This flag indicates that the gesture has just started
if ( flags & GF_BEGIN )
{
event.SetGestureStart();
}
else
{
// Use angleArgument to obtain the cumulative angle since the gesture was first
// started. This angle is in radians
// 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);
}
if ( flags & GF_END )
{
event.SetGestureEnd();
}
event.SetEventObject(this);
event.SetTimestamp(::GetMessageTime());
event.SetPosition(wxPoint(x, y));
return HandleWindowEvent(event);
}
bool wxWindowMSW::HandleTwoFingerTap(int x, int y, WXDWORD flags)
{
// wxEVT_TWO_FINGER_TAP
wxTwoFingerTapEvent event(GetId());
if ( flags & GF_BEGIN )
{
event.SetGestureStart();
}
event.SetEventObject(this);
event.SetTimestamp(::GetMessageTime());
event.SetPosition(wxPoint(x, y));
if ( flags & GF_END )
{
event.SetGestureEnd();
}
return HandleWindowEvent(event);
}
bool wxWindowMSW::HandlePressAndTap(int x, int y, WXDWORD flags)
{
wxPressAndTapEvent event(GetId());
if ( flags & GF_BEGIN )
{
event.SetGestureStart();
}
event.SetEventObject(this);
event.SetTimestamp(::GetMessageTime());
event.SetPosition(wxPoint(x, y));
if ( flags & GF_END )
{
event.SetGestureEnd();
}
return HandleWindowEvent(event);
}
#endif // WM_GESTURE
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// keyboard handling // keyboard handling
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -1042,6 +1042,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 +1493,408 @@ 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
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 int s_lastLocationX = 0, s_lastLocationY = 0;
if ( gestureState == NSGestureRecognizerStateBegan )
{
wxevent.SetGestureStart();
s_lastLocationX = 0;
s_lastLocationY = 0;
}
if ( gestureState == NSGestureRecognizerStateEnded )
{
wxevent.SetGestureEnd();
}
// Set the offsets
wxevent.SetDeltaX(pt.x - s_lastLocationX);
wxevent.SetDeltaY(pt.y - s_lastLocationY);
s_lastLocationX = pt.x;
s_lastLocationY = pt.y;
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)
{
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:m_osxView];
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_osxView];
// 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)
{
// 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_osxView];
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(GetWXPeer()->GetId());
wxevent.SetEventObject(GetWXPeer());
// Get the mouse coordinates
wxCoord x, y;
SetupCoordinates(x, y, event);
wxevent.SetPosition(wxPoint (x,y));
GetWXPeer()->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)
{
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:m_osxView];
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(GetWXPeer()->GetId());
wxevent.SetEventObject(GetWXPeer());
wxevent.SetGestureStart();
wxevent.SetGestureEnd();
// Get the mouse coordinates
wxCoord x, y;
SetupCoordinates(x, y, event);
wxevent.SetPosition(wxPoint (x,y));
GetWXPeer()->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(GetWXPeer()->GetId());
wxevent.SetEventObject(GetWXPeer());
// Get the mouse coordinates
wxCoord x, y;
SetupCoordinates(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];
}
GetWXPeer()->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 +2242,17 @@ 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@:@" )
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
wxOSX_CLASS_ADD_METHOD(c, @selector(handlePanGesture:), (IMP) wxOSX_panGestureEvent, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(handleZoomGesture:), (IMP) wxOSX_zoomGestureEvent, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(handleRotateGesture:), (IMP) wxOSX_rotateGestureEvent, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(handleLongPressGesture:), (IMP) wxOSX_longPressEvent, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(touchesBeganWithEvent:), (IMP) wxOSX_touchesBegan, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(touchesMovedWithEvent:), (IMP) wxOSX_touchesMoved, "v@:@" )
wxOSX_CLASS_ADD_METHOD(c, @selector(touchesEndedWithEvent:), (IMP) wxOSX_touchesEnded, "v@:@" )
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
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@:@" )
@@ -1857,6 +2334,14 @@ void wxWidgetCocoaImpl::Init()
#endif #endif
m_lastKeyDownEvent = NULL; m_lastKeyDownEvent = NULL;
m_hasEditor = false; m_hasEditor = false;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
m_touchCount = 0;
m_lastTouchTime = 0;
m_allowedGestures = 0;
m_activeGestures = 0;
m_initialTouch = NULL;
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
} }
wxWidgetCocoaImpl::~wxWidgetCocoaImpl() wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
@@ -1875,6 +2360,22 @@ 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
if ( wxPlatformInfo::Get().CheckOSVersion(10, 10) )
{
if ( IsUserPane() )
{
[m_panGestureRecognizer release];
[m_magnificationGestureRecognizer release];
[m_rotationGestureRecognizer release];
[m_pressGestureRecognizer release];
if ( m_initialTouch )
[m_initialTouch release];
}
}
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
} }
bool wxWidgetCocoaImpl::IsVisible() const bool wxWidgetCocoaImpl::IsVisible() const
@@ -2791,7 +3292,34 @@ 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];
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
if ( wxPlatformInfo::Get().CheckOSVersion(10, 10) )
{
if ( IsUserPane() )
{
m_panGestureRecognizer =
[[NSPanGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handlePanGesture:)];
m_magnificationGestureRecognizer =
[[NSMagnificationGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleZoomGesture:)];
m_rotationGestureRecognizer =
[[NSRotationGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleRotateGesture:)];
m_pressGestureRecognizer =
[[NSPressGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleLongPressGesture:)];
[m_osxView addGestureRecognizer:m_panGestureRecognizer];
[m_osxView addGestureRecognizer:m_magnificationGestureRecognizer];
[m_osxView addGestureRecognizer:m_rotationGestureRecognizer];
[m_osxView addGestureRecognizer:m_pressGestureRecognizer];
[m_osxView setAcceptsTouchEvents:YES];
}
}
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
}
bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text) bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
{ {