1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-29 14:48:39 +02:00

Fixes some focus issues under wxGTK and bug

This commit is contained in:
Leland Lucius 2015-08-14 16:15:28 -05:00
parent 1a54947e92
commit 13c7484458
2 changed files with 109 additions and 90 deletions

@ -1009,24 +1009,27 @@ ProgressDialog::ProgressDialog(const wxString & title,
// //
ProgressDialog::~ProgressDialog() ProgressDialog::~ProgressDialog()
{ {
// Delete the window disabler before hiding the dialog to allow
// focus to return to the original window.
if (mDisable) if (mDisable)
{ {
delete mDisable; delete mDisable;
mDisable = NULL; mDisable = NULL;
} }
else if (mTopParent)
if (IsShown())
{ {
Show(false); mTopParent->Enable(true);
}
Beep(); Beep();
} }
}
void ProgressDialog::Init() void ProgressDialog::Init()
{ {
mLastValue = 0; mLastValue = 0;
mDisable = NULL; mDisable = NULL;
mTopParent = NULL;
mIsTransparent = true;
} }
bool ProgressDialog::Create(const wxString & title, bool ProgressDialog::Create(const wxString & title,
@ -1041,7 +1044,8 @@ bool ProgressDialog::Create(const wxString & title,
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxDEFAULT_DIALOG_STYLE |
wxFRAME_FLOAT_ON_PARENT); wxFRAME_FLOAT_ON_PARENT |
wxTRANSPARENT_WINDOW);
if (!success) if (!success)
{ {
return false; return false;
@ -1166,6 +1170,18 @@ bool ProgressDialog::Create(const wxString & title,
mCancel = false; mCancel = false;
mStop = false; mStop = false;
// Because wxGTK is very sensitive about maintaining focus when
// this window is not shown, we always show it. But, since we
// want a 500ms delay before it's actually visible for those
// quick tasks, we show it as transparent. If the initial
// delay is exceeded, then we reset the dialog to full opacity.
SetTransparent(0);
mIsTransparent = true;
wxDialog::Show(true);
if (flags & pdlgAppModal)
{
// Even though we won't necessarily show the dialog due to the 500ms // Even though we won't necessarily show the dialog due to the 500ms
// delay, we MUST disable other windows/menus anyway since we run the risk // delay, we MUST disable other windows/menus anyway since we run the risk
// of allowing other tasks to run before this one is complete. // of allowing other tasks to run before this one is complete.
@ -1179,10 +1195,12 @@ bool ProgressDialog::Create(const wxString & title,
// while it's recording, it has a ProgressDialog, so really, // while it's recording, it has a ProgressDialog, so really,
// no editing in any project until Timer Record finishes. // no editing in any project until Timer Record finishes.
mDisable = new wxWindowDisabler(this); mDisable = new wxWindowDisabler(this);
}
// On OSX at least, creating the disabler causes the dialog to show, so else
// just hide it again until the delay has been reached. {
Show(false); mTopParent = wxGetTopLevelParent(GetParent());
mTopParent->Enable(false);
}
return true; return true;
} }
@ -1190,8 +1208,7 @@ bool ProgressDialog::Create(const wxString & title,
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(int value, const wxString & message)
ProgressDialog::Update(int value, const wxString & message)
{ {
if (mCancel) if (mCancel)
{ {
@ -1203,7 +1220,19 @@ ProgressDialog::Update(int value, const wxString & message)
return eProgressStopped; return eProgressStopped;
} }
SetMessage(message); wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
wxLongLong_t elapsed = now - mStartTime;
if (elapsed < 500)
{
return eProgressSuccess;
}
if (mIsTransparent)
{
SetTransparent(255);
mIsTransparent = false;
}
if (value <= 0) if (value <= 0)
{ {
@ -1215,16 +1244,10 @@ ProgressDialog::Update(int value, const wxString & message)
value = 1000; value = 1000;
} }
wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
wxLongLong_t elapsed = now - mStartTime;
wxLongLong_t estimate = elapsed * 1000ll / value; wxLongLong_t estimate = elapsed * 1000ll / value;
wxLongLong_t remains = (estimate + mStartTime) - now; wxLongLong_t remains = (estimate + mStartTime) - now;
if (!IsShown() && elapsed > 500) SetMessage(message);
{
Show(true);
wxDialog::Update();
}
if (value != mLastValue) if (value != mLastValue)
{ {
@ -1233,7 +1256,7 @@ ProgressDialog::Update(int value, const wxString & message)
mLastValue = value; mLastValue = value;
} }
// Only update if a full second has passed.or track progress is complete // Only update if a full second has passed or track progress is complete
if ((now - mLastUpdate > 1000) || (value == 1000)) if ((now - mLastUpdate > 1000) || (value == 1000))
{ {
wxTimeSpan tsElapsed(0, 0, 0, elapsed); wxTimeSpan tsElapsed(0, 0, 0, elapsed);
@ -1270,8 +1293,7 @@ ProgressDialog::Update(int value, const wxString & message)
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(double current, const wxString & message)
ProgressDialog::Update(double current, const wxString & message)
{ {
return Update((int)(current * 1000), message); return Update((int)(current * 1000), message);
} }
@ -1279,8 +1301,7 @@ ProgressDialog::Update(double current, const wxString & message)
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxString & message)
ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxString & message)
{ {
if (total != 0) if (total != 0)
{ {
@ -1295,8 +1316,7 @@ ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxStrin
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & message)
ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & message)
{ {
if (total.GetValue() != 0) if (total.GetValue() != 0)
{ {
@ -1311,8 +1331,7 @@ ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & me
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString & message)
ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString & message)
{ {
if (total != 0) if (total != 0)
{ {
@ -1327,8 +1346,7 @@ ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(int current, int total, const wxString & message)
ProgressDialog::Update(int current, int total, const wxString & message)
{ {
if (total != 0) if (total != 0)
{ {
@ -1343,8 +1361,7 @@ ProgressDialog::Update(int current, int total, const wxString & message)
// //
// Update the time and, optionally, the message // Update the time and, optionally, the message
// //
int int ProgressDialog::Update(double current, double total, const wxString & message)
ProgressDialog::Update(double current, double total, const wxString & message)
{ {
if (total != 0) if (total != 0)
{ {
@ -1356,12 +1373,10 @@ ProgressDialog::Update(double current, double total, const wxString & message)
} }
} }
// //
// Update the message text // Update the message text
// //
void void ProgressDialog::SetMessage(const wxString & message)
ProgressDialog::SetMessage(const wxString & message)
{ {
if (!message.IsEmpty()) if (!message.IsEmpty())
{ {
@ -1400,33 +1415,28 @@ ProgressDialog::SetMessage(const wxString & message)
SetClientSize(ds); SetClientSize(ds);
wxDialog::Update(); wxDialog::Update();
} }
} }
} }
void void ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
{ {
FindWindowById(wxID_CANCEL, this)->Disable(); FindWindowById(wxID_CANCEL, this)->Disable();
mCancel = true; mCancel = true;
} }
void void ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
{ {
FindWindowById(wxID_OK, this)->Disable(); FindWindowById(wxID_OK, this)->Disable();
mCancel = false; mCancel = false;
mStop = true; mStop = true;
} }
void void ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
{ {
mCancel = true; mCancel = true;
} }
void void ProgressDialog::Beep() const
ProgressDialog::Beep()
{ {
int after; int after;
bool should; bool should;
@ -1441,10 +1451,12 @@ ProgressDialog::Beep()
wxBusyCursor busy; wxBusyCursor busy;
wxSound s; wxSound s;
if (name.IsEmpty()) { if (name.IsEmpty())
{
s.Create(sizeof(beep), beep); s.Create(sizeof(beep), beep);
} }
else { else
{
s.Create(name); s.Create(name);
} }
@ -1476,28 +1488,24 @@ int TimerProgressDialog::Update(const wxString & message /*= wxEmptyString*/)
return eProgressStopped; return eProgressStopped;
} }
// Copied from wx 3.0.2 generic progress dialog wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
// wxLongLong_t elapsed = now - mStartTime;
// we have to yield because not only we want to update the display but
// also to process the clicks on the cancel and skip buttons
// NOTE: using YieldFor() this call shouldn't give re-entrancy problems
// for event handlers not interested to UI/user-input events.
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
wxDialog::Update(); if (elapsed < 500)
{
return eProgressSuccess;
}
if (mIsTransparent)
{
SetTransparent(255);
mIsTransparent = false;
}
SetMessage(message); SetMessage(message);
wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
wxLongLong_t elapsed = now - mStartTime;
wxLongLong_t remains = mStartTime + mDuration - now; wxLongLong_t remains = mStartTime + mDuration - now;
if (!IsShown() && elapsed > 500)
{
Show(true);
wxDialog::Update();
}
int nGaugeValue = (1000 * elapsed) / mDuration; // range = [0,1000] int nGaugeValue = (1000 * elapsed) / mDuration; // range = [0,1000]
// Running in TimerRecordDialog::RunWaitDialog(), for some unknown reason, // Running in TimerRecordDialog::RunWaitDialog(), for some unknown reason,
// nGaugeValue here is often a little over 1000. // nGaugeValue here is often a little over 1000.
@ -1528,10 +1536,16 @@ int TimerProgressDialog::Update(const wxString & message /*= wxEmptyString*/)
// Copied from wx 3.0.2 generic progress dialog // Copied from wx 3.0.2 generic progress dialog
// //
// allow the window to repaint: // we have to yield because not only we want to update the display but
// NOTE: since we yield only for UI events with this call, there // also to process the clicks on the cancel and skip buttons
// should be no side-effects // NOTE: using YieldFor() this call shouldn't give re-entrancy problems
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI); // for event handlers not interested to UI/user-input events.
//
// LL: Added timer category to prevent extreme delays when processing effects
// (and probably other things). I do not yet know why this happens and
// I'm not too keen on having timer events processed here, but you do
// what you have to do.
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT | wxEVT_CATEGORY_TIMER);
return eProgressSuccess; return eProgressSuccess;
} }

@ -40,8 +40,9 @@ enum ProgressDialogFlags
pdlgEmptyFlags = 0x00000000, pdlgEmptyFlags = 0x00000000,
pdlgHideStopButton = 0x00000001, pdlgHideStopButton = 0x00000001,
pdlgHideCancelButton = 0x00000002, pdlgHideCancelButton = 0x00000002,
pdlgAppModal = 0x00000004,
pdlgDefaultFlags = pdlgEmptyFlags pdlgDefaultFlags = pdlgAppModal
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -53,9 +54,9 @@ class AUDACITY_DLL_API ProgressDialog:public wxDialog
public: public:
ProgressDialog(); ProgressDialog();
ProgressDialog(const wxString & title, const wxString & message = wxEmptyString, ProgressDialogFlags flags = pdlgDefaultFlags); ProgressDialog(const wxString & title, const wxString & message = wxEmptyString, ProgressDialogFlags flags = pdlgDefaultFlags);
~ProgressDialog(); virtual ~ProgressDialog();
bool Create(const wxString & title, const wxString & message = wxEmptyString, ProgressDialogFlags flags = pdlgDefaultFlags); virtual bool Create(const wxString & title, const wxString & message = wxEmptyString, ProgressDialogFlags flags = pdlgDefaultFlags);
int Update(int value, const wxString & message = wxEmptyString); int Update(int value, const wxString & message = wxEmptyString);
int Update(double current, const wxString & message = wxEmptyString); int Update(double current, const wxString & message = wxEmptyString);
@ -78,19 +79,23 @@ protected:
bool mCancel; bool mCancel;
bool mStop; bool mStop;
bool mIsTransparent;
private: private:
void Init(); void Init();
void OnCancel(wxCommandEvent & e); void OnCancel(wxCommandEvent & e);
void OnStop(wxCommandEvent & e); void OnStop(wxCommandEvent & e);
void OnCloseWindow(wxCloseEvent & e); void OnCloseWindow(wxCloseEvent & e);
void Beep(); void Beep() const;
private: private:
// This guarantees we have an active event loop...possible during OnInit() // This guarantees we have an active event loop...possible during OnInit()
wxEventLoopGuarantor mLoop; wxEventLoopGuarantor mLoop;
wxStaticText *mMessage; wxWindow *mTopParent;
wxWindowDisabler *mDisable; wxWindowDisabler *mDisable;
wxStaticText *mMessage;
int mLastW; int mLastW;
int mLastH; int mLastH;
@ -103,7 +108,7 @@ class AUDACITY_DLL_API TimerProgressDialog : public ProgressDialog
TimerProgressDialog(const wxLongLong_t duration, TimerProgressDialog(const wxLongLong_t duration,
const wxString & title, const wxString & title,
const wxString & message = wxEmptyString, const wxString & message = wxEmptyString,
ProgressDialogFlags flags = pdlgDefaultFlags); ProgressDialogFlags flags = pdlgEmptyFlags);
int Update(const wxString & message = wxEmptyString); int Update(const wxString & message = wxEmptyString);
protected: protected: