From d8de338a465066a9b9ff1bb6d20b5476e78d6359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ritzl?= Date: Wed, 29 Mar 2023 10:40:38 +0200 Subject: [PATCH] Added focus and post listener setup functions --- example/slidingwindow/window1.gui_script | 12 ++- example/slidingwindow/window2.gui_script | 7 +- monarch/monarch.lua | 113 +++++++++++++++++++---- 3 files changed, 106 insertions(+), 26 deletions(-) diff --git a/example/slidingwindow/window1.gui_script b/example/slidingwindow/window1.gui_script index 73c12b0..fef770b 100644 --- a/example/slidingwindow/window1.gui_script +++ b/example/slidingwindow/window1.gui_script @@ -2,9 +2,9 @@ local monarch = require "monarch.monarch" local transitions = require "monarch.transitions.gui" function init(self) - print("window1", msg.url()) + msg.post(".", "acquire_input_focus") - local DURATION = 1 + local DURATION = 0.3 local transition = transitions.create(gui.get_node("bg")) .show_in(transitions.slide_in_right, gui.EASING_LINEAR, DURATION, 0) .show_out(transitions.slide_out_left, gui.EASING_LINEAR, DURATION, 0) @@ -13,7 +13,13 @@ function init(self) monarch.on_transition("window1", transition) - msg.post(".", "acquire_input_focus") + monarch.on_focus_changed("window1", function(message_id, message) + if message_id == monarch.FOCUS.GAINED then + print("window1 gained focus") + elseif message_id == monarch.FOCUS.LOST then + print("window1 lost focus") + end + end) end function on_input(self, action_id, action) diff --git a/example/slidingwindow/window2.gui_script b/example/slidingwindow/window2.gui_script index f81fbb2..15bd842 100644 --- a/example/slidingwindow/window2.gui_script +++ b/example/slidingwindow/window2.gui_script @@ -2,9 +2,9 @@ local monarch = require "monarch.monarch" local transitions = require "monarch.transitions.gui" function init(self) - print("window2", msg.url()) + msg.post(".", "acquire_input_focus") - local DURATION = 1 + local DURATION = 0.3 local transition = transitions.create(gui.get_node("bg")) .show_in(transitions.slide_in_right, gui.EASING_LINEAR, DURATION, 0) .show_out(transitions.slide_out_left, gui.EASING_LINEAR, DURATION, 0) @@ -12,8 +12,6 @@ function init(self) .back_out(transitions.slide_out_right, gui.EASING_LINEAR, DURATION, 0) monarch.on_transition("window2", transition) - - msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) @@ -25,5 +23,6 @@ function on_input(self, action_id, action) end function on_message(self, message_id, message, sender) + print("window2", message_id, message, sender) monarch.on_message(message_id, message, sender) end \ No newline at end of file diff --git a/monarch/monarch.lua b/monarch/monarch.lua index ff5aac8..ee1e79f 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -135,27 +135,49 @@ local function notify_transition_listeners(message_id, message) end end -local function find_screen(url) - local current_url = msg.url() - for _,screen in pairs(screens) do - if screen.transition_url == current_url - or screen.script == current_url - or screen.proxy == current_url - then - return screen - end - end - - for _,screen in pairs(screens) do - if screen.transition_url == url - or screen.script == url - or screen.proxy == url - then - return screen +local function find_screen(url_to_find) + local function find(url) + for _,screen in pairs(screens) do + if screen.script == url or screen.proxy == url then + return screen + end end end + return find(msg.url()) or find(url_to_find) end +local function find_transition_screen(url_to_find) + local function find(url) + for _,screen in pairs(screens) do + if screen.transition_url == url or screen.script == url or screen.proxy == url then + return screen + end + end + end + return find(msg.url()) or find(url_to_find) +end + +local function find_focus_screen(url_to_find) + local function find(url) + for _,screen in pairs(screens) do + if screen.focus_url == url or screen.script == url or screen.proxy == url then + return screen + end + end + end + return find(msg.url()) or find(url_to_find) +end + +local function find_post_receiver_screen(url_to_find) + local function find(url) + for _,screen in pairs(screens) do + if screen.receiver_url == url or screen.script == url or screen.proxy == url then + return screen + end + end + end + return find(msg.url()) or find(url_to_find) +end --- Check if a screen exists in the current screen stack -- @param id (string|hash) @@ -1152,7 +1174,7 @@ function M.on_message(message_id, message, sender) assert(coroutine.resume(screen.co)) end elseif message_id == M.TRANSITION.DONE then - local screen = find_screen(sender) + local screen = find_transition_screen(sender) assert(screen, "Unable to find screen for transition") if screen.wait_for == M.TRANSITION.DONE then assert(coroutine.resume(screen.co)) @@ -1162,7 +1184,7 @@ function M.on_message(message_id, message, sender) or message_id == M.TRANSITION.BACK_IN or message_id == M.TRANSITION.BACK_OUT then - local screen = find_screen(sender) + local screen = find_transition_screen(sender) assert(screen, "Unable to find screen for transition") if screen.transition_fn then screen.transition_fn(message_id, message, sender) @@ -1172,6 +1194,19 @@ function M.on_message(message_id, message, sender) if screen and screen.transition_fn then screen.transition_fn(message_id, message, sender) end + elseif message_id == M.FOCUS.GAINED + or message_id == M.FOCUS.LOST + then + local screen = find_focus_screen(sender) + assert(screen, "Unable to find screen for focus change") + if screen.focus_fn then + screen.focus_fn(message_id, message, sender) + end + else + local screen = find_post_receiver_screen(sender) + if screen and screen.receiver_fn then + screen.receiver_fn(message_id, message, sender) + end end end @@ -1218,6 +1253,13 @@ function M.set_timestep_below_popup(id, timestep) end +--- +-- Set a function to call when a transition should be started +-- The function will receive (message_id, message, sender) +-- IMPORTANT! You must call monarch.on_message() from the same script as +-- this function was called +-- @param id Screen id to associate transition with +-- @param fn Transition handler function function M.on_transition(id, fn) assert(id, "You must provide a screen id") assert(fn, "You must provide a transition function") @@ -1228,6 +1270,39 @@ function M.on_transition(id, fn) screen.transition_fn = fn end +--- +-- Set a function to call when a screen gains or loses focus +-- The function will receive (message_id, message, sender) +-- IMPORTANT! You must call monarch.on_message() from the same script as +-- this function was called +-- @param id Screen id to associate focus listener function with +-- @param fn Focus listener function +function M.on_focus_changed(id, fn) + assert(id, "You must provide a screen id") + assert(fn, "You must provide a focus change function") + id = tohash(id) + assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id))) + local screen = screens[id] + screen.focus_url = msg.url() + screen.focus_fn = fn +end + +--- +-- Set a function to call when a screen is sent a message using monarch.post() +-- The function will receive (message_id, message, sender) +-- IMPORTANT! You must call monarch.on_message() from the same script as +-- this function was called +-- @param id Screen id to associate the message listener function with +-- @param fn Message listener function +function M.on_post(id, fn) + assert(id, "You must provide a screen id") + assert(fn, "You must provide a post receiver function") + id = tohash(id) + assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id))) + local screen = screens[id] + screen.receiver_url = msg.url() + screen.receiver_fn = fn +end local function url_to_key(url) return (url.socket or hash("")) .. (url.path or hash("")) .. (url.fragment or hash(""))