Skip to content

Commit

Permalink
#5231: Fix ScreenUpdateBlocker not being able to block window draw ev…
Browse files Browse the repository at this point in the history
…ents before the main loop kicks in.
  • Loading branch information
codereader committed Jun 28, 2020
1 parent d967ebd commit fb542d8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 21 deletions.
63 changes: 44 additions & 19 deletions radiant/ui/mainframe/ScreenUpdateBlocker.cpp
Expand Up @@ -8,20 +8,17 @@
namespace ui {

ScreenUpdateBlocker::ScreenUpdateBlocker(const std::string& title, const std::string& message, bool forceDisplay) :
wxutil::ModalProgressDialog(title, GlobalMainFrame().getWxTopLevelWindow()),
_pulseAllowed(true)
_dialog(nullptr),
_pulseAllowed(true),
_title(title)
{
// Set the "screen updates disabled" flag (also disables autosaver)
GlobalMainFrame().disableScreenUpdates();

// Connect the realize signal to remove the window decorations
if (GlobalMainFrame().isActiveApp() || forceDisplay)
{
// Show this window immediately
Show();

// Eat all window events
_disabler.reset(new wxWindowDisabler(this));
showModalProgressDialog();
}

// Process pending events to fully show the dialog
Expand All @@ -30,9 +27,20 @@ ScreenUpdateBlocker::ScreenUpdateBlocker(const std::string& title, const std::st
// Register for the "is-active" changed event, to display this dialog
// as soon as Radiant is getting the focus again
GlobalMainFrame().getWxTopLevelWindow()->Bind(wxEVT_SET_FOCUS, &ScreenUpdateBlocker::onMainWindowFocus, this);
}

void ScreenUpdateBlocker::showModalProgressDialog()
{
_dialog = new wxutil::ModalProgressDialog(_title, GlobalMainFrame().getWxTopLevelWindow());

Bind(wxEVT_CLOSE_WINDOW, &ScreenUpdateBlocker::onCloseEvent, this);
Bind(wxEVT_IDLE, [&](wxIdleEvent&) { pulse(); });
_dialog->Bind(wxEVT_CLOSE_WINDOW, &ScreenUpdateBlocker::onCloseEvent, this);
_dialog->Bind(wxEVT_IDLE, [&](wxIdleEvent&) { pulse(); });

// Show this window immediately
_dialog->Show();

// Eat all window events
_disabler.reset(new wxWindowDisabler(_dialog));
}

ScreenUpdateBlocker::~ScreenUpdateBlocker()
Expand All @@ -42,6 +50,11 @@ ScreenUpdateBlocker::~ScreenUpdateBlocker()
// Process pending events to flush keystroke buffer etc.
wxTheApp->Yield(true);

if (_dialog != nullptr)
{
_dialog->Destroy();
}

// Remove the event blocker, if appropriate
_disabler.reset();

Expand All @@ -54,15 +67,18 @@ ScreenUpdateBlocker::~ScreenUpdateBlocker()

void ScreenUpdateBlocker::pulse()
{
if (_pulseAllowed)
if (_pulseAllowed && _dialog != nullptr)
{
ModalProgressDialog::Pulse();
_dialog->Pulse();
}
}

void ScreenUpdateBlocker::doSetProgress(float progress)
{
ModalProgressDialog::setFraction(progress);
if (_dialog != nullptr)
{
_dialog->setFraction(progress);
}

_pulseAllowed = false;
}
Expand All @@ -74,29 +90,38 @@ void ScreenUpdateBlocker::setProgress(float progress)

void ScreenUpdateBlocker::doSetMessage(const std::string& message)
{
ModalProgressDialog::setText(message);
if (_dialog != nullptr)
{
_dialog->setText(message);
}
}

void ScreenUpdateBlocker::setMessage(const std::string& message)
{
doSetMessage(message);

Refresh();
Update();
if (_dialog != nullptr)
{
_dialog->Refresh();
_dialog->Update();
}
}

void ScreenUpdateBlocker::setMessageAndProgress(const std::string& message, float progress)
{
ModalProgressDialog::setTextAndFraction(message, progress);
if (_dialog != nullptr)
{
_dialog->setTextAndFraction(message, progress);
}
}

void ScreenUpdateBlocker::onMainWindowFocus(wxFocusEvent& ev)
{
// The Radiant main window has changed its active state, let's see if it became active
// and if yes, show this blocker dialog.
if (GlobalMainFrame().getWxTopLevelWindow()->IsActive() && !IsShownOnScreen())
// and if yes, show the blocker dialog.
if (GlobalMainFrame().getWxTopLevelWindow()->IsActive() && _dialog == nullptr)
{
Show();
showModalProgressDialog();
}
}

Expand Down
9 changes: 7 additions & 2 deletions radiant/ui/mainframe/ScreenUpdateBlocker.h
Expand Up @@ -9,15 +9,18 @@ namespace ui
{

class ScreenUpdateBlocker :
public IScopedScreenUpdateBlocker,
public wxutil::ModalProgressDialog
public IScopedScreenUpdateBlocker
{
private:
wxutil::ModalProgressDialog* _dialog;

std::unique_ptr<wxWindowDisabler> _disabler;

// Once we received a call to setProgress() further calls to pulse() are forbidden
bool _pulseAllowed;

std::string _title;

public:
// Pass the window title and the text message to the constructor
ScreenUpdateBlocker(const std::string& title, const std::string& message, bool forceDisplay = false);
Expand All @@ -36,6 +39,8 @@ class ScreenUpdateBlocker :
// Called whenever the main window is changing its "active" state property.
void onMainWindowFocus(wxFocusEvent& ev);
void onCloseEvent(wxCloseEvent& ev);

void showModalProgressDialog();
};

} // namespace ui

0 comments on commit fb542d8

Please sign in to comment.