Fl4m3Ph03n1x

Fl4m3Ph03n1x

How to get Screen size in elixir?

Background

I am working on an Elixir desktop application, and I need it to adapt to the monitor/screen size of the user.
Using Elixir Desktop (GitHub - elixir-desktop/desktop: Building Local-First apps for Windows, MacOS, Linux, iOS and Android using Phoenix LiveView & Elixir! · GitHub), I would normally do something like this:

      {Desktop.Window,
       [
         # simplified for the sake of brevity
         title: "Market Manager",
         size: {940, 980},
         icon: "static/images/resized_logo_5_32x32.png"
       ]}

Where size will be the size (in pixels) of the window of the application.
This is all fine if all my users have monitors of the same size. However, this is not the case.

Problem

So I need to know the dimensions of the screen size of the user in order to create a Window that is, lets say, 60% width and 70% height.

Since the underlying library (Desktop) does not support relative sizes for the window afaik, I need to calculate them myself.

To this effect I found no library that gives me this.

Question

How can I find the screen dimensions ?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

From the docs (wxDisplay — OTP 29.0.2 (wx 2.6)) I understand I need to:

_wx = :wx.new()
display = :wxDisplay.new()
{x, y, w, h} = :wxDisplay.getClientArea(display)

Being the first time I am using this library, do I really need the first line _wx = :wx.new()?
Am I missing something?

Also Liked

dominicletz

dominicletz

Creator of Elixir Desktop

Yes, you’re right. you can typically also get the same effect by using :wx.set_env(env) using an existing wx_env for this there is a helper in Desktop.Env: Desktop.Env — Desktop v1.5.3

:wx.set_env(Desktop.Env.wx_env())
display = :wxDisplay.new()
{x, y, w, h} = :wxDisplay.getClientArea(display)
Fl4m3Ph03n1x

Fl4m3Ph03n1x

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?

Where Next?

Popular in Discussions Top

andre1sk
A big advantage to Elixir is all the distributed goodness but for many applications running on multiple nodes having integrated Etcd, Zoo...
New
Jayshua
I recently came across the javascript library htmx. It reminded me a lot of liveview so I thought the community here might be interested....
New
blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
WolfDan
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
sashaafm
Piggy backing a bit on @dvcrn topic BEAM optimization for functions with static return type?, I’ve been trying to understand in a deeper ...
New
pillaiindu
I want to convert a Phoenix LiveView CRUD website to a CRUD mobile app. What do you think is the easiest way to do so?
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New

Other popular topics Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

We're in Beta

About us Mission Statement