Index: binaries/data/mods/_test.gui/gui/regainFocus/page_regainFocus.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/_test.gui/gui/regainFocus/page_regainFocus.xml
@@ -0,0 +1,5 @@
+
+
+ common/styles.xml
+ regainFocus/regainFocus.xml
+
Index: binaries/data/mods/_test.gui/gui/regainFocus/regainFocus.js
===================================================================
--- /dev/null
+++ binaries/data/mods/_test.gui/gui/regainFocus/regainFocus.js
@@ -0,0 +1,7 @@
+var receivedEvents = 0;
+var obj1 = Engine.GetGUIObjectByName("obj1");
+
+obj1.onPageRegainedFocus = () => { ++receivedEvents; };
+obj1.onTick = () => {
+ Engine.PushGuiPage("regainFocus/page_emptyPage.xml", {}, () => Engine.PushGuiPage("regainFocus/page_emptyPage.xml"));
+};
Index: binaries/data/mods/_test.gui/gui/regainFocus/regainFocus.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/_test.gui/gui/regainFocus/regainFocus.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
Index: binaries/data/mods/public/gui/common/OverlayCounterManager.js
===================================================================
--- binaries/data/mods/public/gui/common/OverlayCounterManager.js
+++ binaries/data/mods/public/gui/common/OverlayCounterManager.js
@@ -15,6 +15,7 @@
this.resizeHandlers = [];
this.lastHeight = undefined;
this.initSize = this.dataCounter.size;
+ this.hideOverlay = false;
for (let name of this.availableCounterNames())
{
@@ -28,6 +29,13 @@
}
this.dataCounter.onTick = this.onTick.bind(this);
+ this.dataCounter.onPageRegainedFocus = () => this.hide(false);
+ }
+
+ hide(hide)
+ {
+ this.hideOverlay = hide;
+ this.rebuildOverlay();
}
/**
@@ -79,6 +87,17 @@
this.lastTick = now;
+ this.rebuildOverlay();
+ }
+
+ rebuildOverlay()
+ {
+ if (this.hideOverlay)
+ {
+ this.dataCounter.hidden = true;
+ return;
+ }
+
let lineCount = 0;
let txt = "";
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/LobbyButton.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/LobbyButton.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/LobbyButton.js
@@ -10,8 +10,11 @@
onPress()
{
- if (Engine.HasXmppClient())
- Engine.PushGuiPage("page_lobby.xml", { "dialog": true });
+ if (!Engine.HasXmppClient())
+ return;
+
+ g_OverlayCounterManager.hide(true);
+ Engine.PushGuiPage("page_lobby.xml", { "dialog": true });
}
}
Index: binaries/data/mods/public/gui/pregame/MainMenuItems.js
===================================================================
--- binaries/data/mods/public/gui/pregame/MainMenuItems.js
+++ binaries/data/mods/public/gui/pregame/MainMenuItems.js
@@ -7,6 +7,7 @@
"caption": translate("Manual"),
"tooltip": translate("Open the 0 A.D. Game Manual."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_manual.xml");
}
},
@@ -176,8 +177,10 @@
"enabled": () => !!Engine.StartXmppClient,
"hotkey": "lobby",
"onPress": () => {
- if (Engine.StartXmppClient)
- Engine.PushGuiPage("page_prelobby_entrance.xml");
+ if (!Engine.StartXmppClient)
+ return;
+ g_OverlayCounterManager.hide(true);
+ Engine.PushGuiPage("page_prelobby_entrance.xml");
}
},
{
@@ -203,6 +206,7 @@
"caption": translate("Options"),
"tooltip": translate("Adjust game settings."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage(
"page_options.xml",
{},
@@ -213,6 +217,7 @@
"caption": translate("Hotkeys"),
"tooltip": translate("Adjust hotkeys."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("hotkeys/page_hotkeys.xml");
}
},
@@ -220,6 +225,7 @@
"caption": translate("Language"),
"tooltip": translate("Choose the language of the game."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_locale.xml");
}
},
@@ -234,6 +240,7 @@
"caption": translate("Welcome Screen"),
"tooltip": translate("Show the Welcome Screen again. Useful if you hid it by mistake."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_splashscreen.xml");
}
}
@@ -261,6 +268,7 @@
"caption": translate("Credits"),
"tooltip": translate("Show the 0 A.D. credits."),
"onPress": () => {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_credits.xml");
}
},
Index: binaries/data/mods/public/gui/pregame/SplashscreenHandler.js
===================================================================
--- binaries/data/mods/public/gui/pregame/SplashscreenHandler.js
+++ binaries/data/mods/public/gui/pregame/SplashscreenHandler.js
@@ -32,6 +32,9 @@
if (Engine.ConfigDB_GetValue("user", "gui.splashscreen.enable") === "true" ||
Engine.ConfigDB_GetValue("user", "gui.splashscreen.version") < Engine.GetFileMTime("gui/splashscreen/splashscreen.txt"))
+ {
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_splashscreen.xml", {});
+ }
}
}
Index: binaries/data/mods/public/gui/prelobby/entrance/entrance.js
===================================================================
--- binaries/data/mods/public/gui/prelobby/entrance/entrance.js
+++ binaries/data/mods/public/gui/prelobby/entrance/entrance.js
@@ -6,11 +6,13 @@
function loginButton()
{
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_prelobby_login.xml");
}
function registerButton()
{
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_prelobby_register.xml");
}
Index: binaries/data/mods/public/gui/session/MenuButtons.js
===================================================================
--- binaries/data/mods/public/gui/session/MenuButtons.js
+++ binaries/data/mods/public/gui/session/MenuButtons.js
@@ -20,6 +20,7 @@
{
closeOpenDialogs();
this.pauseControl.implicitPause();
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_manual.xml", {}, resumeGame);
}
};
@@ -99,7 +100,8 @@
closeOpenDialogs();
this.pauseControl.implicitPause();
- // Allows players to see their own summary.
+ g_OverlayCounterManager.hide(true);
+ // Allows players to see their own summary.
// If they have shared ally vision researched, they are able to see the summary of there allies too.
let simState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
Engine.PushGuiPage(
@@ -149,6 +151,7 @@
if (!Engine.HasXmppClient())
return;
closeOpenDialogs();
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage("page_lobby.xml", { "dialog": true });
}
};
@@ -166,6 +169,7 @@
{
closeOpenDialogs();
this.pauseControl.implicitPause();
+ g_OverlayCounterManager.hide(true);
Engine.PushGuiPage(
"page_options.xml",
@@ -190,11 +194,9 @@
{
closeOpenDialogs();
this.pauseControl.implicitPause();
+ g_OverlayCounterManager.hide(true);
- Engine.PushGuiPage(
- "hotkeys/page_hotkeys.xml",
- {},
- () => { resumeGame(); });
+ Engine.PushGuiPage( "hotkeys/page_hotkeys.xml", {}, resumeGame);
}
};
Index: source/gui/GUIManager.h
===================================================================
--- source/gui/GUIManager.h
+++ source/gui/GUIManager.h
@@ -162,6 +162,7 @@
};
const static CStr EventNameWindowResized;
+ const static CStr EventNamePageRegainedFocus;
std::shared_ptr top() const;
Index: source/gui/GUIManager.cpp
===================================================================
--- source/gui/GUIManager.cpp
+++ source/gui/GUIManager.cpp
@@ -34,6 +34,7 @@
CGUIManager* g_GUI = nullptr;
const CStr CGUIManager::EventNameWindowResized = "WindowResized";
+const CStr CGUIManager::EventNamePageRegainedFocus = "PageRegainedFocus";
// General TODOs:
@@ -123,7 +124,14 @@
}
m_PageStack.pop_back();
+ // Save an immutable copy so page isn't invalidated by anything that happens in the callback function.
+ SGUIPage page = m_PageStack.back();
m_PageStack.back().PerformCallbackFunction(args);
+
+ // Only send the regained focus event if the page is still on the top.
+ // We can assume that pages are identifiable by their gui pointer.
+ if (page.gui == m_PageStack.back().gui)
+ m_PageStack.back().gui->SendEventToAll(EventNamePageRegainedFocus);
}
CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const Script::StructuredClone initData)
Index: source/gui/tests/test_GuiManager.h
===================================================================
--- source/gui/tests/test_GuiManager.h
+++ source/gui/tests/test_GuiManager.h
@@ -197,7 +197,6 @@
UnloadHotkeys();
}
-
void test_PageRegainedFocusEvent()
{
// Load up a test page.
@@ -207,19 +206,49 @@
Script::CreateObject(rq, &val);
Script::StructuredClone data = Script::WriteStructuredClone(rq, JS::NullHandleValue);
- g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", data, JS::UndefinedHandleValue);
+ g_GUI->PushPage(L"regainFocus/page_regainFocus.xml", data, JS::UndefinedHandleValue);
const ScriptInterface& pageScriptInterface = *(g_GUI->GetActiveGUI()->GetScriptInterface());
ScriptRequest prq(pageScriptInterface);
JS::RootedValue global(prq.cx, prq.globalValue());
+ int receivedEvents = 0;
+ JS::RootedValue jsReceivedEvents(prq.cx);
+
+ // Just check if the initial values are correct.
+ Script::GetProperty(prq, global, "receivedEvents", &jsReceivedEvents);
+ Script::FromJSVal(prq, jsReceivedEvents, receivedEvents);
+ TS_ASSERT_EQUALS(receivedEvents, 0);
+
g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", data, JS::UndefinedHandleValue);
g_GUI->PopPage(data);
+ // Regained focus once.
+ Script::GetProperty(prq, global, "receivedEvents", &jsReceivedEvents);
+ Script::FromJSVal(prq, jsReceivedEvents, receivedEvents);
+ TS_ASSERT_EQUALS(receivedEvents, 1);
+
// This page instantly pushes an empty page with a callback that pops another page again.
g_GUI->PushPage(L"regainFocus/page_pushWithPopOnInit.xml", data, JS::UndefinedHandleValue);
- // Pop the empty page and trigger the callback (effectively pops twice).
+ // Pop the empty page and trigger the callback.
g_GUI->PopPage(data);
+
+ // We are now back at the initial page and the event should have been triggered only once.
+ Script::GetProperty(prq, global, "receivedEvents", &jsReceivedEvents);
+ Script::FromJSVal(prq, jsReceivedEvents, receivedEvents);
+ TS_ASSERT_EQUALS(receivedEvents, 2);
+
+ // This triggers obj1 that will push an empty page with a callback that also pushes an empty page.
+ g_GUI->TickObjects();
+ // Pop the empty page and trigger the callback that pushes another empty page.
+ g_GUI->PopPage(data);
+ // Pop the newly pushed empty page.
+ g_GUI->PopPage(data);
+
+ // We are now back at the initial page and the callback should have been triggered only once.
+ Script::GetProperty(prq, global, "receivedEvents", &jsReceivedEvents);
+ Script::FromJSVal(prq, jsReceivedEvents, receivedEvents);
+ TS_ASSERT_EQUALS(receivedEvents, 3);
}
};