Bug 406 - Label creation/other non-dialogue editing and keyboard selection hang on long projects

This is part 1...

Provides some relief to the selection "hang"

This patch adds the ability for the keyboard based commands (like cursor left,
extend selection right, etc.) to know when the key has been released.

When the patch is applied the current state is saved only when the key is
released and not every time it repeats.

Here's an example of the difference it makes.

This video show the selection "hang", but also watch the CPU usage.  All I'm
doing is pressing SHIFT+RIGHT ARROW.

http://youtu.be/tdMntDwGSkM

This one is the same thing bug with the patch applied.  Notice that the
selection "hang" no longer occurs and look at the CPU usage!

http://youtu.be/EpXNsQ4Cky0
This commit is contained in:
lllucius 2013-10-23 18:01:14 +00:00
parent 0bee195b0e
commit 03f5088b6a
8 changed files with 90 additions and 40 deletions

View File

@ -138,6 +138,16 @@ AudacityProjectCommandFunctor::AudacityProjectCommandFunctor(AudacityProject *pr
{
mProject = project;
mCommandFunction = commandFunction;
mCommandKeyFunction = NULL;
mCommandListFunction = NULL;
}
AudacityProjectCommandFunctor::AudacityProjectCommandFunctor(AudacityProject *project,
audCommandKeyFunction commandFunction)
{
mProject = project;
mCommandFunction = NULL;
mCommandKeyFunction = commandFunction;
mCommandListFunction = NULL;
}
@ -146,6 +156,7 @@ AudacityProjectCommandFunctor::AudacityProjectCommandFunctor(AudacityProject *pr
{
mProject = project;
mCommandFunction = NULL;
mCommandKeyFunction = NULL;
mCommandListFunction = commandFunction;
}
@ -155,16 +166,19 @@ AudacityProjectCommandFunctor::AudacityProjectCommandFunctor(AudacityProject *pr
{
mProject = project;
mCommandFunction = NULL;
mCommandKeyFunction = NULL;
mCommandListFunction = commandFunction;
mExplicitIndices = explicitIndices;
}
void AudacityProjectCommandFunctor::operator()(int index )
void AudacityProjectCommandFunctor::operator()(int index, const wxEvent * evt)
{
if (mCommandListFunction && mExplicitIndices.GetCount() > 0)
(mProject->*(mCommandListFunction)) (mExplicitIndices[index]);
else if (mCommandListFunction)
(mProject->*(mCommandListFunction)) (index);
else if (mCommandKeyFunction)
(mProject->*(mCommandKeyFunction)) (evt);
else
(mProject->*(mCommandFunction)) ();
}
@ -1116,21 +1130,21 @@ void AudacityProject::CreateMenusAndCommands()
c->AddCommand(wxT("Toggle"), _("Toggle Focused Track"), FN(OnToggle), wxT("Return"));
c->AddCommand(wxT("ToggleAlt"), _("Toggle Focused Track"), FN(OnToggle), wxT("NUMPAD_ENTER"));
c->AddCommand(wxT("CursorLeft"), _("Cursor Left"), FN(OnCursorLeft), wxT("Left\tallowdup"));
c->AddCommand(wxT("CursorRight"), _("Cursor Right"), FN(OnCursorRight), wxT("Right\tallowdup"));
c->AddCommand(wxT("CursorLeft"), _("Cursor Left"), FN(OnCursorLeft), wxT("Left\twantevent\tallowdup"));
c->AddCommand(wxT("CursorRight"), _("Cursor Right"), FN(OnCursorRight), wxT("Right\twantevent\tallowdup"));
c->AddCommand(wxT("CursorShortJumpLeft"), _("Cursor Short Jump Left"), FN(OnCursorShortJumpLeft), wxT(","));
c->AddCommand(wxT("CursorShortJumpRight"), _("Cursor Short Jump Right"), FN(OnCursorShortJumpRight), wxT("."));
c->AddCommand(wxT("CursorLongJumpLeft"), _("Cursor Long Jump Left"), FN(OnCursorLongJumpLeft), wxT("Shift+,"));
c->AddCommand(wxT("CursorLongJumpRight"), _("Cursor Long Jump Right"), FN(OnCursorLongJumpRight), wxT("Shift+."));
c->AddCommand(wxT("SelExtLeft"), _("Selection Extend Left"), FN(OnSelExtendLeft), wxT("Shift+Left\tallowdup"));
c->AddCommand(wxT("SelExtRight"), _("Selection Extend Right"), FN(OnSelExtendRight), wxT("Shift+Right\tallowdup"));
c->AddCommand(wxT("SelExtLeft"), _("Selection Extend Left"), FN(OnSelExtendLeft), wxT("Shift+Left\twantevent\tallowdup"));
c->AddCommand(wxT("SelExtRight"), _("Selection Extend Right"), FN(OnSelExtendRight), wxT("Shift+Right\twantevent\tallowdup"));
c->AddCommand(wxT("SelSetExtLeft"), _("Set (or Extend) Left Selection"), FN(OnSelSetExtendLeft));
c->AddCommand(wxT("SelSetExtRight"), _("Set (or Extend) Right Selection"), FN(OnSelSetExtendRight));
c->AddCommand(wxT("SelCntrLeft"), _("Selection Contract Left"), FN(OnSelContractLeft), wxT("Ctrl+Shift+Right"));
c->AddCommand(wxT("SelCntrRight"), _("Selection Contract Right"), FN(OnSelContractRight), wxT("Ctrl+Shift+Left"));
c->AddCommand(wxT("SelCntrLeft"), _("Selection Contract Left"), FN(OnSelContractLeft), wxT("Ctrl+Shift+Right\twantevent"));
c->AddCommand(wxT("SelCntrRight"), _("Selection Contract Right"), FN(OnSelContractRight), wxT("Ctrl+Shift+Left\twantevent"));
c->AddCommand(wxT("TrackPan"), _("Change pan on focused track"), FN(OnTrackPan), wxT("Shift+P"));
c->AddCommand(wxT("TrackPanLeft"), _("Pan left on focused track"), FN(OnTrackPanLeft), wxT("Alt+Shift+Left"));
@ -2166,14 +2180,14 @@ void AudacityProject::OnToggle()
mTrackPanel->OnToggle( );
}
void AudacityProject::OnCursorLeft()
void AudacityProject::OnCursorLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( false, false );
mTrackPanel->OnCursorLeft( false, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnCursorRight()
void AudacityProject::OnCursorRight(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( false, false );
mTrackPanel->OnCursorRight( false, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnCursorShortJumpLeft()
@ -2206,24 +2220,24 @@ void AudacityProject::OnSelSetExtendRight()
mTrackPanel->OnBoundaryMove( false, false);
}
void AudacityProject::OnSelExtendLeft()
void AudacityProject::OnSelExtendLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( true, false );
mTrackPanel->OnCursorLeft( true, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelExtendRight()
void AudacityProject::OnSelExtendRight(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( true, false );
mTrackPanel->OnCursorRight( true, false, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelContractLeft()
void AudacityProject::OnSelContractLeft(const wxEvent * evt)
{
mTrackPanel->OnCursorRight( true, true );
mTrackPanel->OnCursorRight( true, true, evt->GetEventType() == wxEVT_KEY_UP );
}
void AudacityProject::OnSelContractRight()
void AudacityProject::OnSelContractRight(const wxEvent * evt)
{
mTrackPanel->OnCursorLeft( true, true );
mTrackPanel->OnCursorLeft( true, true, evt->GetEventType() == wxEVT_KEY_UP );
}
//this pops up a dialog which allows the left selection to be set.

View File

@ -136,12 +136,12 @@ void OnCursorDown();
void OnShiftDown();
void OnToggle();
void OnCursorLeft();
void OnCursorRight();
void OnSelExtendLeft();
void OnSelExtendRight();
void OnSelContractLeft();
void OnSelContractRight();
void OnCursorLeft(const wxEvent * evt);
void OnCursorRight(const wxEvent * evt);
void OnSelExtendLeft(const wxEvent * evt);
void OnSelExtendRight(const wxEvent * evt);
void OnSelContractLeft(const wxEvent * evt);
void OnSelContractRight(const wxEvent * evt);
void OnCursorShortJumpLeft();
void OnCursorShortJumpRight();

View File

@ -1707,7 +1707,7 @@ bool AudacityProject::HandleKeyUp(wxKeyEvent & event)
if (event.GetKeyCode() == WXK_CONTROL)
mTrackPanel->HandleControlKey(false);
return false;
return mCommandManager.HandleKey(event, GetUpdateFlags(), 0xFFFFFFFF);
}
void AudacityProject::OnMenuEvent(wxMenuEvent & event)

View File

@ -569,6 +569,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
};
typedef void (AudacityProject::*audCommandFunction)();
typedef void (AudacityProject::*audCommandKeyFunction)(const wxEvent *);
typedef void (AudacityProject::*audCommandListFunction)(int);
// Previously this was in menus.cpp, and the declaration of the
@ -578,15 +579,18 @@ class AUDACITY_DLL_API AudacityProjectCommandFunctor : public CommandFunctor
public:
AudacityProjectCommandFunctor(AudacityProject *project,
audCommandFunction commandFunction);
AudacityProjectCommandFunctor(AudacityProject *project,
audCommandKeyFunction commandFunction);
AudacityProjectCommandFunctor(AudacityProject *project,
audCommandListFunction commandFunction);
AudacityProjectCommandFunctor(AudacityProject *project,
audCommandListFunction commandFunction,
wxArrayInt explicitIndices);
virtual void operator()(int index = 0);
virtual void operator()(int index = 0, const wxEvent *evt = NULL);
private:
AudacityProject *mProject;
audCommandFunction mCommandFunction;
audCommandKeyFunction mCommandKeyFunction;
audCommandListFunction mCommandListFunction;
wxArrayInt mExplicitIndices;
};

View File

@ -6479,8 +6479,20 @@ void TrackPanel::ScrollIntoView(int x)
ScrollIntoView(PositionToTime(x, GetLeftOffset()));
}
void TrackPanel::OnCursorLeft( bool shift, bool ctrl )
void TrackPanel::OnCursorLeft( bool shift, bool ctrl, bool keyup )
{
if( keyup )
{
int token = GetProject()->GetAudioIOToken();
if( token > 0 && gAudioIO->IsStreamActive( token ) )
{
return;
}
MakeParentModifyState();
return;
}
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
wxLongLong curtime = ::wxGetLocalTimeMillis();
@ -6579,12 +6591,22 @@ void TrackPanel::OnCursorLeft( bool shift, bool ctrl )
// Make sure it's visible
ScrollIntoView( mViewInfo->sel0 );
}
MakeParentModifyState();
}
void TrackPanel::OnCursorRight( bool shift, bool ctrl )
void TrackPanel::OnCursorRight( bool shift, bool ctrl, bool keyup )
{
if( keyup )
{
int token = GetProject()->GetAudioIOToken();
if( token > 0 && gAudioIO->IsStreamActive( token ) )
{
return;
}
MakeParentModifyState();
return;
}
// If the last adjustment was very recent, we are
// holding the key down and should move faster.
wxLongLong curtime = ::wxGetLocalTimeMillis();
@ -6685,8 +6707,6 @@ void TrackPanel::OnCursorRight( bool shift, bool ctrl )
// Make sure new position is in view
ScrollIntoView( mViewInfo->sel1 );
}
MakeParentModifyState();
}
// Handles moving a selection edge with the keyboard in snap-to-time mode;

View File

@ -235,8 +235,8 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
virtual void OnNextTrack(bool shift = false);
virtual void OnToggle();
virtual void OnCursorLeft(bool shift, bool ctrl);
virtual void OnCursorRight(bool shift, bool ctrl);
virtual void OnCursorLeft(bool shift, bool ctrl, bool keyup = false);
virtual void OnCursorRight(bool shift, bool ctrl, bool keyup = false);
virtual void OnCursorMove(bool forward, bool jump, bool longjump);
virtual void OnBoundaryMove(bool left, bool boundaryContract);
virtual void ScrollIntoView(double pos);

View File

@ -695,6 +695,7 @@ int CommandManager::NewIdentifier(wxString name, wxString label, wxMenu *menu,
tmpEntry->flags = mDefaultFlags;
tmpEntry->mask = mDefaultMask;
tmpEntry->enabled = true;
tmpEntry->wantevent = (label.Find(wxT("\twantevent")) != wxNOT_FOUND);
// Key from preferences overridse the default key given
gPrefs->SetPath(wxT("/NewKeys"));
@ -1000,7 +1001,7 @@ void CommandManager::TellUserWhyDisallowed( wxUint32 flagsGot, wxUint32 flagsReq
/// returning true iff successful. If you pass any flags,
///the command won't be executed unless the flags are compatible
///with the command's flags.
bool CommandManager::HandleCommandEntry(CommandListEntry * entry, wxUint32 flags, wxUint32 mask)
bool CommandManager::HandleCommandEntry(CommandListEntry * entry, wxUint32 flags, wxUint32 mask, const wxEvent * evt)
{
if (!entry || !entry->enabled)
return false;
@ -1025,7 +1026,7 @@ bool CommandManager::HandleCommandEntry(CommandListEntry * entry, wxUint32 flags
}
}
(*(entry->callback))(entry->index);
(*(entry->callback))(entry->index, evt);
return true;
}
@ -1050,7 +1051,17 @@ bool CommandManager::HandleKey(wxKeyEvent &evt, wxUint32 flags, wxUint32 mask)
{
wxString keyStr = KeyEventToKeyString(evt);
CommandListEntry *entry = mCommandKeyHash[keyStr];
return HandleCommandEntry( entry, flags, mask );
if (evt.GetEventType() == wxEVT_KEY_DOWN)
{
return HandleCommandEntry( entry, flags, mask, &evt );
}
if (entry && entry->wantevent)
{
return HandleCommandEntry( entry, flags, mask, &evt );
}
return false;
}
/// HandleTextualCommand() allows us a limitted version of script/batch

View File

@ -25,7 +25,7 @@ class AUDACITY_DLL_API CommandFunctor
public:
CommandFunctor(){};
virtual ~CommandFunctor(){};
virtual void operator()(int index = 0) = 0;
virtual void operator()(int index = 0, const wxEvent *e = NULL) = 0;
};
struct MenuBarListEntry
@ -55,6 +55,7 @@ struct CommandListEntry
int index;
int count;
bool enabled;
bool wantevent;
wxUint32 flags;
wxUint32 mask;
};
@ -180,7 +181,7 @@ class AUDACITY_DLL_API CommandManager: public XMLTagHandler
//
// Executing commands
//
bool HandleCommandEntry(CommandListEntry * entry, wxUint32 flags, wxUint32 mask);
bool HandleCommandEntry(CommandListEntry * entry, wxUint32 flags, wxUint32 mask, const wxEvent * evt = NULL);
bool HandleMenuID(int id, wxUint32 flags, wxUint32 mask);
bool HandleKey(wxKeyEvent &evt, wxUint32 flags, wxUint32 mask);
bool HandleTextualCommand(wxString & Str, wxUint32 flags, wxUint32 mask);