diff --git a/example/example.collection b/example/example.collection index 06f42ec..5877fc8 100644 --- a/example/example.collection +++ b/example/example.collection @@ -281,6 +281,11 @@ embedded_instances { " type: PROPERTY_TYPE_URL\n" " }\n" " properties {\n" + " id: \"focus_url\"\n" + " value: \"about:/go#about\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" " id: \"preload\"\n" " value: \"true\"\n" " type: PROPERTY_TYPE_BOOLEAN\n" diff --git a/monarch/monarch.lua b/monarch/monarch.lua index 0733ee5..f65ca38 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -67,6 +67,16 @@ local function pcallfn(fn, ...) if not ok then print(err) end end end + +local function cowait(delay) + local co = coroutine.running() + assert(co, "You must run this form within a coroutine") + timer.delay(delay, false, function() + coroutine.resume(co) + end) + coroutine.yield() +end + local function notify_transition_listeners(message_id, message) log("notify_transition_listeners()", message_id) for _,url in pairs(transition_listeners) do @@ -364,6 +374,11 @@ local function focus_lost(screen, next_screen) log("focus_lost()", screen.id) if screen.focus_url then msg.post(screen.focus_url, M.FOCUS.LOST, { id = next_screen and next_screen.id }) + -- if there's no transition on the screen losing focus and it gets + -- unloaded this will happen before the focus_lost message reaches + -- the focus_url + -- we add a delay to ensure the message queue has time to be processed + cowait(0) else log("focus_lost() no focus url - ignoring") end diff --git a/test/data/focus1.collection b/test/data/focus1.collection new file mode 100644 index 0000000..e554ef1 --- /dev/null +++ b/test/data/focus1.collection @@ -0,0 +1,37 @@ +name: "focus1" +scale_along_z: 0 +embedded_instances { + id: "go" + data: "components {\n" + " id: \"focus1\"\n" + " component: \"/test/data/focus1.gui\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + "}\n" + "" + position { + x: 0.0 + y: 0.0 + z: 0.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale3 { + x: 1.0 + y: 1.0 + z: 1.0 + } +} diff --git a/test/data/focus1.gui b/test/data/focus1.gui new file mode 100644 index 0000000..56d3ba5 --- /dev/null +++ b/test/data/focus1.gui @@ -0,0 +1,131 @@ +script: "/test/data/focus1.gui_script" +fonts { + name: "example" + font: "/assets/example.font" +} +background_color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 +} +nodes { + position { + x: 320.0 + y: 568.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 100.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "box" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_AUTO +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 100.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "1" + font: "example" + id: "text" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "box" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 1.0 + shadow_alpha: 1.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT +max_nodes: 512 diff --git a/test/data/focus1.gui_script b/test/data/focus1.gui_script new file mode 100644 index 0000000..027016a --- /dev/null +++ b/test/data/focus1.gui_script @@ -0,0 +1,9 @@ +local monarch = require "monarch.monarch" + +function on_message(self, message_id, message, sender) + if message_id == monarch.FOCUS.GAINED then + _G.focus1_gained = true + elseif message_id == monarch.FOCUS.LOST then + _G.focus1_lost = true + end +end diff --git a/test/data/screen1.gui b/test/data/screen1.gui index d1f1baf..f0f8877 100644 --- a/test/data/screen1.gui +++ b/test/data/screen1.gui @@ -96,7 +96,7 @@ nodes { } type: TYPE_TEXT blend_mode: BLEND_MODE_ALPHA - text: "1" + text: "FOCUS 1" font: "example" id: "text" xanchor: XANCHOR_NONE diff --git a/test/data/screens.collection b/test/data/screens.collection index 4f277e3..a5df750 100644 --- a/test/data/screens.collection +++ b/test/data/screens.collection @@ -471,3 +471,66 @@ embedded_instances { z: 1.0 } } +embedded_instances { + id: "focus1" + data: "components {\n" + " id: \"screen_proxy\"\n" + " component: \"/monarch/screen_proxy.script\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + " properties {\n" + " id: \"screen_id\"\n" + " value: \"focus1\"\n" + " type: PROPERTY_TYPE_HASH\n" + " }\n" + " properties {\n" + " id: \"focus_url\"\n" + " value: \"focus1:/go#focus1\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + "}\n" + "embedded_components {\n" + " id: \"collectionproxy\"\n" + " type: \"collectionproxy\"\n" + " data: \"collection: \\\"/test/data/focus1.collection\\\"\\n" + "exclude: false\\n" + "\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + "}\n" + "" + position { + x: 0.0 + y: 0.0 + z: 0.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale3 { + x: 1.0 + y: 1.0 + z: 1.0 + } +} diff --git a/test/test_monarch.lua b/test/test_monarch.lua index 2b0a213..228446a 100644 --- a/test/test_monarch.lua +++ b/test/test_monarch.lua @@ -7,6 +7,7 @@ local SCREEN1_STR = hash("screen1") local SCREEN1 = hash(SCREEN1_STR) local SCREEN2 = hash("screen2") local SCREEN_PRELOAD = hash("screen_preload") +local FOCUS1 = hash("focus1") local BACKGROUND = hash("background") local POPUP1 = hash("popup1") local POPUP2 = hash("popup2") @@ -405,5 +406,21 @@ return function() -- second time the screen gets shown it will be reloaded and increment the count assert(monarch.data(SCREEN_PRELOAD).count == 2) end) + + + it("should send focus messages", function() + _G.focus1_gained = nil + _G.focus1_lost = nil + + monarch.show(SCREEN1) + assert(wait_until_shown(SCREEN1), "Screen1 was never shown") + monarch.show(FOCUS1) + assert(wait_until_shown(FOCUS1), "Screen1 was never shown") + assert(_G.focus1_gained) + monarch.show(SCREEN1) + assert(wait_until_shown(SCREEN1), "Screen1 was never shown") + assert(wait_until_hidden(FOCUS1), "Focus1 was never hidden") + assert(_G.focus1_lost) + end) end) end