diff --git a/lib/bds/desktop/shutdown.ex b/lib/bds/desktop/shutdown.ex index 41275ad..a22fc9f 100644 --- a/lib/bds/desktop/shutdown.ex +++ b/lib/bds/desktop/shutdown.ex @@ -2,19 +2,29 @@ defmodule BDS.Desktop.Shutdown do @moduledoc false alias BDS.Desktop.MainWindow + alias Desktop.Wx alias Desktop.Window + require Record + + Record.defrecordp(:wx, Record.extract(:wx, from_lib: "wx/include/wx.hrl")) + @spec install_handlers(term()) :: :ok def install_handlers(frame) do :wx.set_env(Desktop.Env.wx_env()) _ = :wxFrame.disconnect(frame, :close_window) + _ = :wxFrame.disconnect(frame, :command_menu_selected) :wxFrame.connect(frame, :close_window, callback: &__MODULE__.close_window/2, userData: self() ) + :wxFrame.connect(frame, :command_menu_selected, + callback: &__MODULE__.command_menu_selected/2 + ) + :ok rescue _error -> :ok @@ -42,6 +52,17 @@ defmodule BDS.Desktop.Shutdown do request_quit() end + @spec command_menu_selected(tuple(), term()) :: :ok + def command_menu_selected(wx(id: id), _command_event) do + if id == Wx.wxID_EXIT() do + request_quit() + end + + :ok + end + + def command_menu_selected(_event, _command_event), do: :ok + defp start_shutdown_task do Task.start(fn -> MainWindow.persist_now() diff --git a/test/bds/desktop_test.exs b/test/bds/desktop_test.exs index 613867c..c20f1bb 100644 --- a/test/bds/desktop_test.exs +++ b/test/bds/desktop_test.exs @@ -3,6 +3,12 @@ defmodule BDS.DesktopTest do import Plug.Test + alias Desktop.Wx + + require Record + + Record.defrecordp(:wx, Record.extract(:wx, from_lib: "wx/include/wx.hrl")) + defmodule FakeShutdown do def request_quit do send(Application.fetch_env!(:bds, :desktop_shutdown_test_pid), :quit_requested) @@ -145,8 +151,25 @@ defmodule BDS.DesktopTest do assert_receive :quit_requested end - test "cmd-q remains handled by the desktop window quit handler" do - refute function_exported?(BDS.Desktop.Shutdown, :command_menu_selected, 2) + test "cmd-q is handled by the app-owned shutdown handler" do + assert {:module, BDS.Desktop.Shutdown} = Code.ensure_loaded(BDS.Desktop.Shutdown) + assert function_exported?(BDS.Desktop.Shutdown, :command_menu_selected, 2) + end + + test "cmd-q callback requests app-owned shutdown" do + previous_module = Application.get_env(:bds, :desktop_shutdown_module) + previous_pid = Application.get_env(:bds, :desktop_shutdown_test_pid) + + Application.put_env(:bds, :desktop_shutdown_module, FakeShutdown) + Application.put_env(:bds, :desktop_shutdown_test_pid, self()) + + on_exit(fn -> + restore_env(:desktop_shutdown_module, previous_module) + restore_env(:desktop_shutdown_test_pid, previous_pid) + end) + + assert :ok = BDS.Desktop.Shutdown.command_menu_selected(wx(id: Wx.wxID_EXIT()), nil) + assert_receive :quit_requested end test "app-owned shutdown delegates final termination to the desktop hard quit path" do