Use global map for storing wxCocoaGesturesImpl

This decreases the speed of access to this struct (which shouldn't
matter that much) but avoids allocating an extra and almost always
unneeded pointer for each and every window, which seems like a good
trade-off.
This commit is contained in:
Vadim Zeitlin
2017-11-21 23:43:15 +01:00
parent 3aefb679e4
commit 9cb1f25a25
2 changed files with 69 additions and 23 deletions

View File

@@ -200,11 +200,6 @@ 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
// Data used for gesture support, if available.
class wxCocoaGesturesImpl* m_gesturesImpl;
#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

@@ -24,6 +24,7 @@
#endif #endif
#include "wx/evtloop.h" #include "wx/evtloop.h"
#include "wx/hashmap.h"
#if wxUSE_CARET #if wxUSE_CARET
#include "wx/caret.h" #include "wx/caret.h"
@@ -1501,6 +1502,11 @@ void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
class wxCocoaGesturesImpl;
WX_DECLARE_HASH_MAP(wxWidgetCocoaImpl*, wxCocoaGesturesImpl*,
wxPointerHash, wxPointerEqual,
wxCocoaGesturesImplMap);
// Class containing data used for gestures support. // Class containing data used for gestures support.
class wxCocoaGesturesImpl class wxCocoaGesturesImpl
{ {
@@ -1596,11 +1602,58 @@ public:
[m_initialTouch release]; [m_initialTouch release];
} }
// We keep all existing wxCocoaGesturesImpl objects in a
// wxWidgetCocoaImpl-indexed map. We do this instead of just having a data
// member containing wxCocoaGesturesImpl pointer in wxWidgetCocoaImpl
// itself because most windows don't need it and it seems wasteful to
// always increase their size unnecessarily.
// Store the object to be used for the given window, replacing the existing
// one, if any.
//
// This method takes ownership of wxCocoaGesturesImpl pointer which will be
// destroyed by EraseForWindow().
static void StoreForWindow(wxWidgetCocoaImpl* impl, wxCocoaGesturesImpl* obj)
{
const wxCocoaGesturesImplMap::iterator it = ms_map.find(impl);
if ( it != ms_map.end() )
{
delete it->second;
it->second = obj;
}
else
{
ms_map.insert(wxCocoaGesturesImplMap::value_type(impl, obj));
}
}
// Find the object for the corresponding window.
static wxCocoaGesturesImpl* FromWindow(wxWidgetCocoaImpl* impl)
{
const wxCocoaGesturesImplMap::const_iterator it = ms_map.find(impl);
return it == ms_map.end() ? NULL : it->second;
}
// Erase the object used for the corresponding window, return true if there
// was one or false otherwise.
static bool EraseForWindow(wxWidgetCocoaImpl* impl)
{
const wxCocoaGesturesImplMap::iterator it = ms_map.find(impl);
if ( it == ms_map.end() )
return false;
delete it->second;
ms_map.erase(it);
return true;
}
void TouchesBegan(NSEvent* event); void TouchesBegan(NSEvent* event);
void TouchesMoved(NSEvent* event); void TouchesMoved(NSEvent* event);
void TouchesEnded(NSEvent* event); void TouchesEnded(NSEvent* event);
private: private:
static wxCocoaGesturesImplMap ms_map;
wxWindowMac* const m_win; wxWindowMac* const m_win;
NSView* const m_view; NSView* const m_view;
@@ -1620,6 +1673,8 @@ private:
wxDECLARE_NO_COPY_CLASS(wxCocoaGesturesImpl); wxDECLARE_NO_COPY_CLASS(wxCocoaGesturesImpl);
}; };
wxCocoaGesturesImplMap wxCocoaGesturesImpl::ms_map;
void wxWidgetCocoaImpl::PanGestureEvent(NSPanGestureRecognizer* panGestureRecognizer) void wxWidgetCocoaImpl::PanGestureEvent(NSPanGestureRecognizer* panGestureRecognizer)
{ {
NSGestureRecognizerState gestureState; NSGestureRecognizerState gestureState;
@@ -1820,8 +1875,8 @@ enum TrackedGestures
void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event) void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event)
{ {
if ( m_gesturesImpl ) if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
m_gesturesImpl->TouchesBegan(event); gestures->TouchesBegan(event);
} }
void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event) void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event)
@@ -1877,8 +1932,8 @@ void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event)
void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event) void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event)
{ {
if ( m_gesturesImpl ) if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
m_gesturesImpl->TouchesMoved(event); gestures->TouchesMoved(event);
} }
void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event) void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event)
@@ -1933,8 +1988,8 @@ void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event)
void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event) void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event)
{ {
if ( m_gesturesImpl ) if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
m_gesturesImpl->TouchesEnded(event); gestures->TouchesEnded(event);
} }
void wxCocoaGesturesImpl::TouchesEnded(NSEvent* event) void wxCocoaGesturesImpl::TouchesEnded(NSEvent* event)
@@ -2465,10 +2520,6 @@ 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_gesturesImpl = NULL;
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
} }
wxWidgetCocoaImpl::~wxWidgetCocoaImpl() wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
@@ -2489,7 +2540,7 @@ wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
CFRelease(m_osxView); CFRelease(m_osxView);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
delete m_gesturesImpl; wxCocoaGesturesImpl::EraseForWindow(this);
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
} }
@@ -3416,21 +3467,21 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
{ {
if ( IsUserPane() ) if ( IsUserPane() )
{ {
// We need to get rid of the old data, if we have it, in any case.
delete m_gesturesImpl;
if ( eventsMask == wxTOUCH_NONE ) if ( eventsMask == wxTOUCH_NONE )
{ {
if ( m_gesturesImpl ) if ( wxCocoaGesturesImpl::EraseForWindow(this) )
{ {
m_gesturesImpl = NULL;
[m_osxView setAcceptsTouchEvents:NO]; [m_osxView setAcceptsTouchEvents:NO];
} }
//else: we didn't have any gesture data anyhow
} }
else // We do want to have gesture events. else // We do want to have gesture events.
{ {
m_gesturesImpl = new wxCocoaGesturesImpl(this, m_osxView, eventsMask); wxCocoaGesturesImpl::StoreForWindow
(
this,
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
);
[m_osxView setAcceptsTouchEvents:YES]; [m_osxView setAcceptsTouchEvents:YES];
} }