In my specific use case, I cannot use :wx.set_env(Desktop.Env.wx_env())
as the Desktop application has not yet started:
See my application.ex
:
def start(_type, _args) do
children = [
Telemetry,
{Phoenix.PubSub, name: PubSub},
Endpoint,
Manager,
%{
id: Desktop.Window,
start: {Desktop.Window, :start_link, [[
app: :web_interface,
id: WebInterface,
title: "Market Manager",
size: calculate_window_size(0.4, 0.8),
menubar: MenuBar,
icon: "static/images/resized_logo_5_32x32.png",
url: fn -> "#{WebInterface.Endpoint.url()}/#{@landing_page}" end
]]},
restart: :transient,
shutdown: 5_000
}
]
opts = [strategy: :one_for_one, name: WebInterface.Supervisor]
Supervisor.start_link(children, opts)
end
@doc """
Calculates the width and height for the window. Fetches the display
information using :wx. Because we create a :wx server every time we call this
function this is a heavy operation and should be used cautiously.
Both percentages given must be > 0 and <= 1.
"""
@spec calculate_window_size(float, float) :: {pos_integer, pos_integer}
def calculate_window_size(width_percentage, height_percentage)
when is_float(width_percentage) and width_percentage > 0 and width_percentage <= 1 and
is_float(height_percentage) and height_percentage > 0 and height_percentage <= 1 do
# Since Desktop has not yet started its wx server, we need to create one
# to get the screen size first
_wx_object = :wx.new()
display = :wxDisplay.new()
{_x, _y, total_width, total_height} = :wxDisplay.getClientArea(display)
width_pixels = ceil(width_percentage * total_width)
height_pixels = ceil(height_percentage * total_height)
# we destroy the previously created wx server to save resources and avoid
# a conflict with Desktop library
:wx.destroy()
{width_pixels, height_pixels}
end
If I replace _wx_object = :wx.new()
with :wx.set_env(Desktop.Env.wx_env())
then the application crashes on startup:
07:24:00.603 [notice] Application wx exited: :stopped
07:24:00.606 [notice] Application runtime_tools exited: :stopped
** (Mix) Could not start application web_interface: WebInterface.Application.start(:normal, []) returned an error: shutdown: failed to start child: Desktop.Window
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:noproc, {:gen_server, :call, [#PID<0.717.0>, :register_me, :infinity]}}}
(desktop 1.5.1) lib/desktop/window.ex:109: Desktop.Window.start_link/1
(stdlib 4.1.1) supervisor.erl:414: :supervisor.do_start_child_i/3
(stdlib 4.1.1) supervisor.erl:400: :supervisor.do_start_child/2
(stdlib 4.1.1) supervisor.erl:384: anonymous fn/3 in :supervisor.start_children/2
(stdlib 4.1.1) supervisor.erl:1250: :supervisor.children_map/4
(stdlib 4.1.1) supervisor.erl:350: :supervisor.init_children/2
(stdlib 4.1.1) gen_server.erl:851: :gen_server.init_it/2
(stdlib 4.1.1) gen_server.erl:814: :gen_server.init_it/6
Therefore, the solution I found (and works for me) is to create a temporary wx_object and then kill it, to avoid conflicts with Desktop, just like in the code snippet I shared above.
This also reminds me of one question:
-
@dominicletz what do you think aboud adding a function that takes in percentages for the windows size instead of absolute pixel values, like the function I created?