fix: issue #9 moved windows menu

This commit is contained in:
2026-07-05 18:13:07 +02:00
parent ae1c8703e7
commit ae2e534fdb
13 changed files with 577 additions and 346 deletions

View File

@@ -65,6 +65,8 @@ defmodule BDS.Application do
if desktop_automation?() do
[]
else
disable_auto_window_menu()
window_opts =
BDS.Desktop.MainWindow.window_options(
menubar: BDS.Desktop.MenuBar,
@@ -80,6 +82,17 @@ defmodule BDS.Application do
end
end
# wxOSX injects an untracked "Window" menu into the menubar at install time,
# which races elixir-desktop's async menu populate and ends up at an
# unstable position. We disable it and ship our own :window menu group
# (BDS.UI.MenuBar) placed between Blog and Help.
defp disable_auto_window_menu do
if :os.type() == {:unix, :darwin} do
:wx.set_env(Desktop.Env.wx_env())
:wxMenuBar.setAutoWindowMenu(false)
end
end
defp desktop_automation? do
System.get_env("BDS_DESKTOP_AUTOMATION") in ["1", "true", "TRUE"]
end

View File

@@ -61,7 +61,7 @@ defmodule BDS.BoundedAtoms do
:api_documentation,
:close_tab
]
@menu_actions MenuBar.default_groups(dev_mode?: true)
@menu_actions MenuBar.default_groups(dev_mode?: true, window_menu?: true)
|> Enum.flat_map(fn group ->
Enum.flat_map(group.items, fn
%{separator: true} -> []

View File

@@ -25,12 +25,7 @@ defmodule BDS.Desktop.MenuBar do
def mount(menu) do
UILocale.put(ShellData.ui_language())
{:ok,
Desktop.Menu.assign(
menu,
:groups,
groups(dev_mode?: Application.get_env(:bds, :dev_routes, false))
)}
{:ok, Desktop.Menu.assign(menu, :groups, groups(native_menu_opts()))}
end
@impl true
@@ -82,6 +77,24 @@ defmodule BDS.Desktop.MenuBar do
{:noreply, menu}
end
def handle_event("minimize", menu) do
with_frame(&:wxTopLevelWindow.iconize(&1, iconize: true))
{:noreply, menu}
end
def handle_event("zoom", menu) do
with_frame(fn frame ->
:wxTopLevelWindow.maximize(frame, maximize: not :wxTopLevelWindow.isMaximized(frame))
end)
{:noreply, menu}
end
def handle_event("bring_all_to_front", menu) do
with_frame(&:wxWindow.raise/1)
{:noreply, menu}
end
def handle_event(command, menu) do
dispatch_shell_menu_action(command)
{:noreply, menu}
@@ -91,12 +104,7 @@ defmodule BDS.Desktop.MenuBar do
def handle_info({:set_ui_locale, locale}, menu) do
UILocale.put(locale)
{:noreply,
Desktop.Menu.assign(
menu,
:groups,
groups(dev_mode?: Application.get_env(:bds, :dev_routes, false))
)}
{:noreply, Desktop.Menu.assign(menu, :groups, groups(native_menu_opts()))}
end
def handle_info(_, menu) do
@@ -123,6 +131,32 @@ defmodule BDS.Desktop.MenuBar do
end
end
defp native_menu_opts do
[
dev_mode?: Application.get_env(:bds, :dev_routes, false),
window_menu?: OS.type() == MacOS
]
end
defp with_frame(fun) do
case frame() do
nil ->
:ok
frame ->
:wx.set_env(Desktop.Env.wx_env())
fun.(frame)
end
end
defp frame do
try do
Window.frame(BDS.Desktop.MainWindow.window_id())
catch
:exit, _ -> nil
end
end
defp normalize_item(%{separator: true}), do: %{separator: true}
defp normalize_item(item) do
@@ -145,6 +179,7 @@ defmodule BDS.Desktop.MenuBar do
defp group_label(:edit), do: dgettext("ui", "Edit")
defp group_label(:view), do: dgettext("ui", "View")
defp group_label(:blog), do: dgettext("ui", "Blog")
defp group_label(:window), do: dgettext("ui", "Window")
defp group_label(:help), do: dgettext("ui", "Help")
defp item_label(:new_post), do: dgettext("ui", "New Post")
@@ -191,6 +226,9 @@ defmodule BDS.Desktop.MenuBar do
defp item_label(:force_render_site), do: dgettext("ui", "Force Render Site")
defp item_label(:validate_site), do: dgettext("ui", "Validate Site")
defp item_label(:upload_site), do: dgettext("ui", "Upload Site")
defp item_label(:minimize), do: dgettext("ui", "Minimize")
defp item_label(:zoom), do: dgettext("ui", "Zoom")
defp item_label(:bring_all_to_front), do: dgettext("ui", "Bring All to Front")
defp item_label(:about), do: dgettext("ui", "About")
defp item_label(:documentation), do: dgettext("ui", "Documentation")
defp item_label(:api_documentation), do: dgettext("ui", "API Documentation")

View File

@@ -8,6 +8,7 @@ defmodule BDS.UI.Commands do
%{id: :import_media, accelerator: "CTRL+I"},
%{id: :save, accelerator: "CTRL+S"},
%{id: :close_tab, accelerator: "CTRL+W", key: "w", primary: true},
%{id: :minimize, accelerator: "CTRL+M"},
%{id: :quit, accelerator: "CTRL+Q"},
%{id: :undo, accelerator: "CTRL+Z"},
%{id: :redo, accelerator: "CTRL+Y"},

View File

@@ -7,6 +7,7 @@ defmodule BDS.UI.MenuBar do
@spec default_groups(keyword()) :: [map()]
def default_groups(opts \\ []) do
dev_mode? = Keyword.get(opts, :dev_mode?, false)
window_menu? = Keyword.get(opts, :window_menu?, false)
[
%{
@@ -67,16 +68,38 @@ defmodule BDS.UI.MenuBar do
%{id: :validate_site},
%{id: :upload_site}
]
},
}
] ++
window_group(window_menu?) ++
[
%{
id: :help,
items: [
%{id: :about},
%{id: :documentation},
%{id: :api_documentation},
%{separator: true},
%{id: :view_on_github},
%{id: :report_issue}
]
}
]
end
# The native macOS menu enables this group; wx's automatic Window menu is
# disabled because it races the async menubar populate and lands in the
# wrong position (see BDS.Application.disable_auto_window_menu/0).
defp window_group(false), do: []
defp window_group(true) do
[
%{
id: :help,
id: :window,
items: [
%{id: :about},
%{id: :documentation},
%{id: :api_documentation},
%{id: :minimize},
%{id: :zoom},
%{separator: true},
%{id: :view_on_github},
%{id: :report_issue}
%{id: :bring_all_to_front}
]
}
]