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

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews