Add wxWindow::EnableTouchEvents()

Don't request touch event generation for all windows by default, this
has an inherent overhead and is not needed for 99% of the application
windows, so require calling EnableTouchEvents() explicitly to do it
instead.

Note that this requires properly initializing gesture recognizers in
wxOSX now that they're not always allocated, otherwise releasing them
when destroying the window would crash.
This commit is contained in:
Vadim Zeitlin 2017-11-21 19:23:34 +01:00
parent e7f4e232fa
commit 842dd1cfd9
14 changed files with 131 additions and 36 deletions

View File

@ -77,6 +77,9 @@ public:
virtual bool Reparent( wxWindowBase *newParent ) wxOVERRIDE;
virtual void WarpPointer(int x, int y) wxOVERRIDE;
#ifdef __WXGTK3__
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
#endif // __WXGTK3__
virtual void Refresh( bool eraseBackground = true,
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;

View File

@ -100,6 +100,7 @@ public:
virtual bool Reparent(wxWindowBase *newParent) wxOVERRIDE;
virtual void WarpPointer(int x, int y) wxOVERRIDE;
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
virtual void Refresh( bool eraseBackground = true,
const wxRect *rect = (const wxRect *) NULL ) wxOVERRIDE;

View File

@ -128,6 +128,7 @@ public :
void SetToolTip( wxToolTip* tooltip );
void InstallEventHandler( WXWidget control = NULL );
bool EnableTouchEvents(int eventsMask);
virtual bool ShouldHandleKeyNavigation(const wxKeyEvent &event) const;
bool DoHandleKeyNavigation(const wxKeyEvent &event);

View File

@ -326,6 +326,8 @@ public :
virtual void InstallEventHandler( WXWidget control = NULL ) = 0;
virtual bool EnableTouchEvents(int eventsMask) = 0;
// Mechanism used to keep track of whether a change should send an event
// Do SendEvents(false) when starting actions that would trigger programmatic events
// and SendEvents(true) at the end of the block.

View File

@ -105,6 +105,7 @@ public :
void SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack = true );
void InstallEventHandler( WXWidget control = NULL );
bool EnableTouchEvents(int WXUNUSED(eventsMask)) { return false; }
virtual void DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow);

View File

@ -77,6 +77,7 @@ public:
virtual void SetFocus() wxOVERRIDE;
virtual void WarpPointer( int x, int y ) wxOVERRIDE;
virtual bool EnableTouchEvents(int eventsMask) wxOVERRIDE;
virtual void Refresh( bool eraseBackground = true,
const wxRect *rect = NULL ) wxOVERRIDE;

View File

@ -133,6 +133,13 @@ enum wxShowEffect
wxSHOW_EFFECT_MAX
};
// Values for EnableTouchEvents() mask.
enum
{
wxTOUCH_NONE = 0x0000,
wxTOUCH_ALL_GESTURES = 0x00ff
};
// flags for SendSizeEvent()
enum
{
@ -1033,6 +1040,13 @@ public:
virtual bool HasCapture() const
{ return (wxWindow *)this == GetCapture(); }
// enable the specified touch events for this window, return false if
// the requested events are not supported
virtual bool EnableTouchEvents(int WXUNUSED(eventsMask))
{
return false;
}
// painting the window
// -------------------

View File

@ -3649,6 +3649,10 @@ public:
/** @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}

View File

@ -3424,6 +3424,19 @@ public:
*/
virtual void WarpPointer(int x, int y);
/**
Request generation of touch events for this window.
@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);
//@}

View File

@ -43,6 +43,13 @@ MyGesturePanel::MyGesturePanel(MyGestureFrame *parent) : wxPanel(parent, wxID_AN
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);

View File

@ -3435,6 +3435,26 @@ wxWindowGesturesData::~wxWindowGesturesData()
#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 )
{
m_gesturesData = new wxWindowGesturesData(this, GetConnectWidget());
return true;
}
#endif // wxGTK_HAS_GESTURES_SUPPORT
return wxWindowBase::EnableTouchEvents(eventsMask);
}
#endif // __WXGTK3__
void wxWindowGTK::ConnectWidget( GtkWidget *widget )
{
static bool isSourceAttached;
@ -3477,12 +3497,6 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
G_CALLBACK (gtk_window_enter_callback), this);
g_signal_connect (widget, "leave_notify_event",
G_CALLBACK (gtk_window_leave_callback), this);
#ifdef wxGTK_HAS_GESTURES_SUPPORT
// Check if gestures support is also available during run-time.
if ( gtk_check_version(3, 14, 0) == NULL )
m_gesturesData = new wxWindowGesturesData(this, widget);
#endif // wxGTK_HAS_GESTURES_SUPPORT
}
void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height)

View File

@ -906,6 +906,35 @@ void wxWindowMSW::WarpPointer(int x, int y)
}
}
bool wxWindowMSW::EnableTouchEvents(int eventsMask)
{
#ifdef WM_GESTURE
if ( GestureFuncs::IsOk() && eventsMask == wxTOUCH_ALL_GESTURES )
{
// Configure to receive all gestures
GESTURECONFIG gestureConfig = {0, GC_ALLGESTURES, 0};
if ( !GestureFuncs::SetGestureConfig()
(
m_hWnd,
0, // Reserved, must be always 0.
1, // Number of gesture configurations.
&gestureConfig, // Pointer to the first one.
sizeof(GESTURECONFIG) // Size of each configuration.
)
)
{
wxLogLastError("SetGestureConfig");
return false;
}
return true;
}
#endif // WM_GESTURE
return wxWindowBase::EnableTouchEvents(eventsMask);
}
void wxWindowMSW::MSWUpdateUIState(int action, int state)
{
// we send WM_CHANGEUISTATE so if nothing needs changing then the system
@ -3814,26 +3843,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
return false;
}
#ifdef WM_GESTURE
if ( GestureFuncs::IsOk() )
{
// Configure to receive all gestures
GESTURECONFIG gestureConfig = {0, GC_ALLGESTURES, 0};
if ( !GestureFuncs::SetGestureConfig()
(
m_hWnd,
0, // Reserved, must be always 0.
1, // Number of gesture configurations.
&gestureConfig, // Pointer to the first one.
sizeof(GESTURECONFIG) // Size of each configuration.
)
)
{
wxLogLastError("SetGestureConfig");
}
}
#endif // WM_GESTURE
SubclassWin(m_hWnd);

View File

@ -2240,16 +2240,6 @@ void wxOSXCocoaClassAddWXMethods(Class c)
wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (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(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" )
@ -2333,6 +2323,11 @@ void wxWidgetCocoaImpl::Init()
m_hasEditor = false;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
m_panGestureRecognizer = nil;
m_magnificationGestureRecognizer = nil;
m_rotationGestureRecognizer = nil;
m_pressGestureRecognizer = nil;
m_touchCount = 0;
m_lastTouchTime = 0;
m_allowedGestures = 0;
@ -3289,23 +3284,43 @@ void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil];
[m_osxView addTrackingArea: area];
[area release];
}
bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
if ( wxPlatformInfo::Get().CheckOSVersion(10, 10) )
{
if ( IsUserPane() )
{
Class cls = [m_osxView class];
m_panGestureRecognizer =
[[NSPanGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handlePanGesture:)];
if ( !class_respondsToSelector(cls, @selector(handlePanGesture:)) )
class_addMethod(cls, @selector(handlePanGesture:), (IMP) wxOSX_panGestureEvent, "v@:@" );
m_magnificationGestureRecognizer =
[[NSMagnificationGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleZoomGesture:)];
if ( !class_respondsToSelector(cls, @selector(handleZoomGesture:)) )
class_addMethod(cls, @selector(handleZoomGesture:), (IMP) wxOSX_zoomGestureEvent, "v@:@" );
m_rotationGestureRecognizer =
[[NSRotationGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleRotateGesture:)];
if ( !class_respondsToSelector(cls, @selector(handleRotateGesture:)) )
class_addMethod(cls, @selector(handleRotateGesture:), (IMP) wxOSX_rotateGestureEvent, "v@:@" );
m_pressGestureRecognizer =
[[NSPressGestureRecognizer alloc] initWithTarget:m_osxView action: @selector(handleLongPressGesture:)];
if ( !class_respondsToSelector(cls, @selector(handleLongPressGesture:)) )
class_addMethod(cls, @selector(handleLongPressGesture:), (IMP) wxOSX_longPressEvent, "v@:@" );
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@:@" );
[m_osxView addGestureRecognizer:m_panGestureRecognizer];
[m_osxView addGestureRecognizer:m_magnificationGestureRecognizer];
@ -3313,9 +3328,14 @@ void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
[m_osxView addGestureRecognizer:m_pressGestureRecognizer];
[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)

View File

@ -1429,6 +1429,11 @@ void wxWindowMac::WarpPointer(int x_pos, int y_pos)
#endif
}
bool wxWindowMac::EnableTouchEvents(int eventsMask)
{
return GetPeer() ? GetPeer()->EnableTouchEvents(eventsMask) : false;
}
int wxWindowMac::GetScrollPos(int orient) const
{
#if wxUSE_SCROLLBAR