Fl4m3Ph03n1x

Fl4m3Ph03n1x

Background

I have a basic Desktop app with the following config:

application.ex

defmodule WebInterface.Application do
  use Application

  alias Desktop
  alias Manager
  alias WebInterface.{Endpoint, PubSub, Telemetry}

  @impl true
  def start(_type, _args) do
    children = [
      Telemetry,
      {Phoenix.PubSub, name: PubSub},
      Endpoint,
      Manager,
      {Desktop.Window,
       [
         app: :web_interface,
         id: WebInterface,
         title: "Market Manager",
         size: {900, 900},
         icon: "static/images/resized_logo_5_32x32.png",
         url: &WebInterface.Endpoint.url/0
       ]}
    ]

    opts = [strategy: :one_for_one, name: WebInterface.Supervisor]
    Supervisor.start_link(children, opts)
  end

  @impl true
  def config_change(changed, _new, removed) do
    WebInterface.Endpoint.config_change(changed, removed)
    :ok
  end
end

This is basically the default configuration. You will notice the desktop app does not have a MenuBar. This is on purpose, as I don’t want one.

Problem

The issue here is that no matter what, the application won’t close:

ezgif.com-gif-maker

It always reopens.
After checking the code of Desktop, I believe the issue could be in Desktop.Window:

def init(options) do
    window_title = options[:title] || Atom.to_string(options[:id])
    size = options[:size] || {600, 500}
    min_size = options[:min_size]
    app = options[:app]
    icon = options[:icon]
    taskbar_icon = options[:taskbar_icon]
    # not supported on mobile atm
    menubar = unless OS.mobile?(), do: options[:menubar]

Namely, I am lead to believe there is a difference for Mobile apps and normal apps.

Funnily enough, if add a MenuBar, then the application does eventually close, even though it takes forever for the process behind it to terminate:

{Desktop.Window,
       [
         app: :web_interface,
         id: WebInterface,
         title: "Market Manager",
         size: WindowUtils.calculate_window_size(0.4, 0.7),
         menubar: MenuBar,
         icon: "static/images/resized_logo_5_32x32.png",
         url: &WebInterface.Endpoint.url/0
       ]}

Cliking on the Menubar Quit option also closes the application.

Questions

Am I forced to have a Menubar, if my I have a Desktop app?
How can this be fixed?

Showing Posts 1 to 3

al2o3cr

al2o3cr

The “close window” icon and the “Quit” menu item do quite different things:

  • the “Quit” menu item ends up calling Window.quit/0, which ultimately kill -9s the BEAM from outside (!!).

  • the “close window” icon ends up calling Window.close_window/2 which returns {:stop, :normal, ui} - which will result in the parent Supervisor restarting the Window process.

    Setting the Desktop.Window process to restart: :transient would be prevent this restart.

Not sure how the menu bar ties into this, tho… :thinking:

Fl4m3Ph03n1x

Fl4m3Ph03n1x OP

I see that it spawns a process which eventually calls System.halt. This is curious to me, as it raises a couple of questions:

  1. Why do we need to spawn a new process for this? The new process will kill everything (including the parent) so why not have the parent just do it?

  2. Why not use System.stop instead? I know it eventually ends up calling System.halt, but it also does a lot of cleanup on the background before that.

Here I am confused. Both Window.quit and Window.close_window should eventually call OS.shutdown which would in theory kill the BEAM process, thus preventing a restart.

I am guessing the :wxFrame.isShown(frame) is preventing this from happening, but I am not sure if this is intended behavior or not.

Am I missing something in my interpretation of the code?
Also, huge thanks for helping !

al2o3cr

al2o3cr

I’m definitely at the edge of my understanding regarding what’s happening on shutdown, but the main conclusion I draw from the code + issues is that “application shutdown” is a complicated mess when the app is coordinating Erlang / C++ / native entities all at once.

More examples:

Researching about the other “close” event mentioned in that last ticket turns up this note in the wxWidgets docs:

The EVT_END_SESSION event is slightly different as it is sent by the system when the user session is ending (e.g. because of log out or shutdown) and so all windows are being forcefully closed. At least under MSW, after the handler for this event is executed the program is simply killed by the system. Because of this, the default handler for this event provided by wxWidgets calls all the usual cleanup code (including wxApp::OnExit()) so that it could still be executed and exit()s the process itself, without waiting for being killed. If this behaviour is for some reason undesirable, make sure that you define a handler for this event in your wxApp-derived class and do not call event.Skip() in it (but be aware that the system will still kill your application).

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews