mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 08:09:32 +02:00
Fixes some focus issues under wxGTK and bug #1116
This commit is contained in:
parent
1a54947e92
commit
13c7484458
@ -1009,24 +1009,27 @@ ProgressDialog::ProgressDialog(const wxString & title,
|
||||
//
|
||||
ProgressDialog::~ProgressDialog()
|
||||
{
|
||||
// Delete the window disabler before hiding the dialog to allow
|
||||
// focus to return to the original window.
|
||||
if (mDisable)
|
||||
{
|
||||
delete mDisable;
|
||||
mDisable = NULL;
|
||||
}
|
||||
|
||||
if (IsShown())
|
||||
else if (mTopParent)
|
||||
{
|
||||
Show(false);
|
||||
|
||||
Beep();
|
||||
mTopParent->Enable(true);
|
||||
}
|
||||
|
||||
Beep();
|
||||
}
|
||||
|
||||
void ProgressDialog::Init()
|
||||
{
|
||||
mLastValue = 0;
|
||||
mDisable = NULL;
|
||||
mTopParent = NULL;
|
||||
mIsTransparent = true;
|
||||
}
|
||||
|
||||
bool ProgressDialog::Create(const wxString & title,
|
||||
@ -1041,7 +1044,8 @@ bool ProgressDialog::Create(const wxString & title,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE |
|
||||
wxFRAME_FLOAT_ON_PARENT);
|
||||
wxFRAME_FLOAT_ON_PARENT |
|
||||
wxTRANSPARENT_WINDOW);
|
||||
if (!success)
|
||||
{
|
||||
return false;
|
||||
@ -1166,23 +1170,37 @@ bool ProgressDialog::Create(const wxString & title,
|
||||
mCancel = false;
|
||||
mStop = false;
|
||||
|
||||
// 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
|
||||
// of allowing other tasks to run before this one is complete.
|
||||
//
|
||||
// Reviewed this code per Proposed Features #1, at
|
||||
// http://wiki.audacityteam.org/wiki/Proposal_Timer_Record_Improvements.
|
||||
// Note that this causes a problem for Timer Record wait dialog
|
||||
// (see TimerRecordDialog::RunWaitDialog()), because it makes it
|
||||
// impossible to do any editing, even in other open projects,
|
||||
// while waiting for Timer Record to start -- and then also
|
||||
// while it's recording, it has a ProgressDialog, so really,
|
||||
// no editing in any project until Timer Record finishes.
|
||||
mDisable = new wxWindowDisabler(this);
|
||||
// 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;
|
||||
|
||||
// On OSX at least, creating the disabler causes the dialog to show, so
|
||||
// just hide it again until the delay has been reached.
|
||||
Show(false);
|
||||
wxDialog::Show(true);
|
||||
|
||||
if (flags & pdlgAppModal)
|
||||
{
|
||||
// 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
|
||||
// of allowing other tasks to run before this one is complete.
|
||||
//
|
||||
// Reviewed this code per Proposed Features #1, at
|
||||
// http://wiki.audacityteam.org/wiki/Proposal_Timer_Record_Improvements.
|
||||
// Note that this causes a problem for Timer Record wait dialog
|
||||
// (see TimerRecordDialog::RunWaitDialog()), because it makes it
|
||||
// impossible to do any editing, even in other open projects,
|
||||
// while waiting for Timer Record to start -- and then also
|
||||
// while it's recording, it has a ProgressDialog, so really,
|
||||
// no editing in any project until Timer Record finishes.
|
||||
mDisable = new wxWindowDisabler(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTopParent = wxGetTopLevelParent(GetParent());
|
||||
mTopParent->Enable(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1190,8 +1208,7 @@ bool ProgressDialog::Create(const wxString & title,
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(int value, const wxString & message)
|
||||
int ProgressDialog::Update(int value, const wxString & message)
|
||||
{
|
||||
if (mCancel)
|
||||
{
|
||||
@ -1203,7 +1220,19 @@ ProgressDialog::Update(int value, const wxString & message)
|
||||
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)
|
||||
{
|
||||
@ -1215,16 +1244,10 @@ ProgressDialog::Update(int value, const wxString & message)
|
||||
value = 1000;
|
||||
}
|
||||
|
||||
wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
|
||||
wxLongLong_t elapsed = now - mStartTime;
|
||||
wxLongLong_t estimate = elapsed * 1000ll / value;
|
||||
wxLongLong_t remains = (estimate + mStartTime) - now;
|
||||
|
||||
if (!IsShown() && elapsed > 500)
|
||||
{
|
||||
Show(true);
|
||||
wxDialog::Update();
|
||||
}
|
||||
SetMessage(message);
|
||||
|
||||
if (value != mLastValue)
|
||||
{
|
||||
@ -1233,7 +1256,7 @@ ProgressDialog::Update(int value, const wxString & message)
|
||||
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))
|
||||
{
|
||||
wxTimeSpan tsElapsed(0, 0, 0, elapsed);
|
||||
@ -1270,8 +1293,7 @@ ProgressDialog::Update(int value, const wxString & message)
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(double current, const wxString & message)
|
||||
int ProgressDialog::Update(double current, const wxString & 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
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxString & message)
|
||||
int ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxString & message)
|
||||
{
|
||||
if (total != 0)
|
||||
{
|
||||
@ -1295,8 +1316,7 @@ ProgressDialog::Update(wxULongLong_t current, wxULongLong_t total, const wxStrin
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & message)
|
||||
int ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & message)
|
||||
{
|
||||
if (total.GetValue() != 0)
|
||||
{
|
||||
@ -1311,8 +1331,7 @@ ProgressDialog::Update(wxLongLong current, wxLongLong total, const wxString & me
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString & message)
|
||||
int ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString & message)
|
||||
{
|
||||
if (total != 0)
|
||||
{
|
||||
@ -1327,8 +1346,7 @@ ProgressDialog::Update(wxLongLong_t current, wxLongLong_t total, const wxString
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(int current, int total, const wxString & message)
|
||||
int ProgressDialog::Update(int current, int total, const wxString & message)
|
||||
{
|
||||
if (total != 0)
|
||||
{
|
||||
@ -1343,8 +1361,7 @@ ProgressDialog::Update(int current, int total, const wxString & message)
|
||||
//
|
||||
// Update the time and, optionally, the message
|
||||
//
|
||||
int
|
||||
ProgressDialog::Update(double current, double total, const wxString & message)
|
||||
int ProgressDialog::Update(double current, double total, const wxString & message)
|
||||
{
|
||||
if (total != 0)
|
||||
{
|
||||
@ -1356,12 +1373,10 @@ ProgressDialog::Update(double current, double total, const wxString & message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Update the message text
|
||||
//
|
||||
void
|
||||
ProgressDialog::SetMessage(const wxString & message)
|
||||
void ProgressDialog::SetMessage(const wxString & message)
|
||||
{
|
||||
if (!message.IsEmpty())
|
||||
{
|
||||
@ -1400,33 +1415,28 @@ ProgressDialog::SetMessage(const wxString & message)
|
||||
SetClientSize(ds);
|
||||
wxDialog::Update();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
||||
void ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
FindWindowById(wxID_CANCEL, this)->Disable();
|
||||
mCancel = true;
|
||||
}
|
||||
|
||||
void
|
||||
ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
|
||||
void ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
FindWindowById(wxID_OK, this)->Disable();
|
||||
mCancel = false;
|
||||
mStop = true;
|
||||
}
|
||||
|
||||
void
|
||||
ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
|
||||
void ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
|
||||
{
|
||||
mCancel = true;
|
||||
}
|
||||
|
||||
void
|
||||
ProgressDialog::Beep()
|
||||
void ProgressDialog::Beep() const
|
||||
{
|
||||
int after;
|
||||
bool should;
|
||||
@ -1441,10 +1451,12 @@ ProgressDialog::Beep()
|
||||
wxBusyCursor busy;
|
||||
wxSound s;
|
||||
|
||||
if (name.IsEmpty()) {
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
s.Create(sizeof(beep), beep);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
s.Create(name);
|
||||
}
|
||||
|
||||
@ -1476,28 +1488,24 @@ int TimerProgressDialog::Update(const wxString & message /*= wxEmptyString*/)
|
||||
return eProgressStopped;
|
||||
}
|
||||
|
||||
// Copied from wx 3.0.2 generic progress dialog
|
||||
//
|
||||
// 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();
|
||||
wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
|
||||
wxLongLong_t elapsed = now - mStartTime;
|
||||
|
||||
if (elapsed < 500)
|
||||
{
|
||||
return eProgressSuccess;
|
||||
}
|
||||
|
||||
if (mIsTransparent)
|
||||
{
|
||||
SetTransparent(255);
|
||||
mIsTransparent = false;
|
||||
}
|
||||
|
||||
SetMessage(message);
|
||||
|
||||
wxLongLong_t now = wxGetLocalTimeMillis().GetValue();
|
||||
wxLongLong_t elapsed = now - mStartTime;
|
||||
wxLongLong_t remains = mStartTime + mDuration - now;
|
||||
|
||||
if (!IsShown() && elapsed > 500)
|
||||
{
|
||||
Show(true);
|
||||
wxDialog::Update();
|
||||
}
|
||||
|
||||
int nGaugeValue = (1000 * elapsed) / mDuration; // range = [0,1000]
|
||||
// Running in TimerRecordDialog::RunWaitDialog(), for some unknown reason,
|
||||
// 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
|
||||
//
|
||||
// allow the window to repaint:
|
||||
// NOTE: since we yield only for UI events with this call, there
|
||||
// should be no side-effects
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
|
||||
// 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.
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
@ -40,8 +40,9 @@ enum ProgressDialogFlags
|
||||
pdlgEmptyFlags = 0x00000000,
|
||||
pdlgHideStopButton = 0x00000001,
|
||||
pdlgHideCancelButton = 0x00000002,
|
||||
pdlgAppModal = 0x00000004,
|
||||
|
||||
pdlgDefaultFlags = pdlgEmptyFlags
|
||||
pdlgDefaultFlags = pdlgAppModal
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -53,9 +54,9 @@ class AUDACITY_DLL_API ProgressDialog:public wxDialog
|
||||
public:
|
||||
ProgressDialog();
|
||||
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(double current, const wxString & message = wxEmptyString);
|
||||
@ -78,19 +79,23 @@ protected:
|
||||
bool mCancel;
|
||||
bool mStop;
|
||||
|
||||
bool mIsTransparent;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void OnCancel(wxCommandEvent & e);
|
||||
void OnStop(wxCommandEvent & e);
|
||||
void OnCloseWindow(wxCloseEvent & e);
|
||||
void Beep();
|
||||
void Beep() const;
|
||||
|
||||
private:
|
||||
// This guarantees we have an active event loop...possible during OnInit()
|
||||
wxEventLoopGuarantor mLoop;
|
||||
|
||||
wxStaticText *mMessage;
|
||||
wxWindow *mTopParent;
|
||||
wxWindowDisabler *mDisable;
|
||||
|
||||
wxStaticText *mMessage;
|
||||
int mLastW;
|
||||
int mLastH;
|
||||
|
||||
@ -99,14 +104,14 @@ private:
|
||||
|
||||
class AUDACITY_DLL_API TimerProgressDialog : public ProgressDialog
|
||||
{
|
||||
public:
|
||||
public:
|
||||
TimerProgressDialog(const wxLongLong_t duration,
|
||||
const wxString & title,
|
||||
const wxString & message = wxEmptyString,
|
||||
ProgressDialogFlags flags = pdlgDefaultFlags);
|
||||
const wxString & title,
|
||||
const wxString & message = wxEmptyString,
|
||||
ProgressDialogFlags flags = pdlgEmptyFlags);
|
||||
int Update(const wxString & message = wxEmptyString);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
wxLongLong_t mDuration;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user