aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gui/gui-manager.cpp28
-rw-r--r--gui/gui-manager.h16
-rw-r--r--gui/launcher.cpp5
-rw-r--r--gui/options.cpp5
4 files changed, 52 insertions, 2 deletions
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index d28a0df8c2..feb4e50ce2 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -254,6 +254,23 @@ Dialog *GuiManager::getTopDialog() const {
return _dialogStack.top();
}
+void GuiManager::addToTrash(GuiObject* object, Dialog* parent) {
+ debug(7, "Adding Gui Object %p to trash", object);
+ GuiObjectTrashItem t;
+ t.object = object;
+ t.parent = 0;
+ // If a dialog was provided, check it is in the dialog stack
+ if (parent != 0) {
+ for (int i = 0 ; i < _dialogStack.size() ; ++i) {
+ if (_dialogStack[i] == parent) {
+ t.parent = parent;
+ break;
+ }
+ }
+ }
+ _guiObjectTrash.push_back(t);
+}
+
void GuiManager::runLoop() {
Dialog * const activeDialog = getTopDialog();
bool didSaveState = false;
@@ -341,6 +358,17 @@ void GuiManager::runLoop() {
}
}
+ // Delete GuiObject that have been added to the trash for a delayed deletion
+ Common::List<GuiObjectTrashItem>::iterator it = _guiObjectTrash.begin();
+ while (it != _guiObjectTrash.end()) {
+ if ((*it).parent == 0 || (*it).parent == activeDialog) {
+ debug(7, "Delayed deletion of Gui Object %p", (*it).object);
+ delete (*it).object;
+ it = _guiObjectTrash.erase(it);
+ } else
+ ++it;
+ }
+
if (_lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) {
Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 4dc9af95fb..82a8aa9cfd 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -27,6 +27,7 @@
#include "common/singleton.h"
#include "common/stack.h"
#include "common/str.h"
+#include "common/list.h"
#include "gui/ThemeEngine.h"
@@ -44,6 +45,7 @@ namespace GUI {
class Dialog;
class ThemeEval;
+class GuiObject;
#define g_gui (GUI::GuiManager::instance())
@@ -99,6 +101,13 @@ public:
*/
bool checkScreenChange();
+ /**
+ * Tell the GuiManager to delete the given GuiObject later. If a parent
+ * dialog is provided and is present in the DialogStack, the object will
+ * only be deleted when that dialog is the top level dialog.
+ */
+ void addToTrash(GuiObject*, Dialog* parent = 0);
+
bool _launched;
protected:
@@ -137,6 +146,13 @@ protected:
int _cursorAnimateTimer;
byte _cursor[2048];
+ // delayed deletion of GuiObject
+ struct GuiObjectTrashItem {
+ GuiObject* object;
+ Dialog* parent;
+ };
+ Common::List<GuiObjectTrashItem> _guiObjectTrash;
+
void initKeymap();
void pushKeymap();
void popKeymap();
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index f96dd17d46..f60fecf509 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -204,7 +204,10 @@ void LauncherDialog::clean() {
while (_firstWidget) {
Widget* w = _firstWidget;
removeWidget(w);
- delete w;
+ // This is called from rebuild() which may result from handleCommand being called by
+ // a child widget sendCommand call. In such a case sendCommand is still being executed
+ // so we should not delete yet the child widget. Thus delay the deletion.
+ g_gui.addToTrash(w, this);
}
delete _browser;
delete _loadDialog;
diff --git a/gui/options.cpp b/gui/options.cpp
index 7a22a9ba3f..179fa65991 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -423,7 +423,10 @@ void OptionsDialog::clean() {
while (_firstWidget) {
Widget* w = _firstWidget;
removeWidget(w);
- delete w;
+ // This is called from rebuild() which may result from handleCommand being called by
+ // a child widget sendCommand call. In such a case sendCommand is still being executed
+ // so we should not delete yet the child widget. Thus delay the deletion.
+ g_gui.addToTrash(w, this);
}
init();
}