146 lines
3.5 KiB
Elixir
146 lines
3.5 KiB
Elixir
defmodule Scenic.Driver.Renderling.Window do
|
|
@moduledoc """
|
|
The Scenic for windowed applications.
|
|
"""
|
|
|
|
alias Scenic.ViewPort
|
|
alias Scenic.Driver.Renderling.Window.{Config, Nif}
|
|
|
|
use Scenic.Driver
|
|
require Logger
|
|
|
|
@position_schema [
|
|
centered: [type: :boolean, default: false],
|
|
full_screen: [type: :boolean, default: false],
|
|
maximized: [type: :boolean, default: false],
|
|
orientation: [type: {:in, [:normal, :left, :right, :upside_down]}, default: :normal],
|
|
scaled: [type: :boolean, default: false]
|
|
]
|
|
|
|
@window_schema [
|
|
title: [type: :string, default: "Scenic Window"],
|
|
resizeable: [type: :boolean, default: false]
|
|
]
|
|
|
|
@opts_schema [
|
|
name: [type: {:or, [:atom, :string]}],
|
|
position: [type: :keyword_list, keys: @position_schema, default: []],
|
|
window: [type: :keyword_list, keys: @window_schema, default: []],
|
|
cursor: [type: :boolean, default: false],
|
|
key_map: [type: :atom, default: Scenic.KeyMap.USEnglish],
|
|
on_close: [
|
|
type:
|
|
{:or, [:mfa, {:in, [:restart, :stop_driver, :stop_viewport, :stop_system, :halt_system]}]},
|
|
default: :restart
|
|
],
|
|
input_blacklist: [type: {:list, :string}, default: []]
|
|
]
|
|
|
|
@doc false
|
|
@impl Scenic.Driver
|
|
def validate_opts(opts), do: NimbleOptions.validate(opts, @opts_schema)
|
|
|
|
@doc false
|
|
@impl true
|
|
def init(driver, opts) do
|
|
{width, height} = driver.viewport.size
|
|
|
|
config =
|
|
opts
|
|
|> Keyword.update(
|
|
:window,
|
|
[width: width, height: height],
|
|
&Keyword.merge(&1, width: width, height: height)
|
|
)
|
|
|> Config.init()
|
|
|
|
driver = assign(driver, config: config, server: Nif.init(config))
|
|
|
|
Process.flag(:trap_exit, true)
|
|
Logger.info("#{inspect(__MODULE__)}: start #{inspect(opts)}, pid: #{inspect(self())}")
|
|
|
|
{:ok, driver}
|
|
end
|
|
|
|
@doc false
|
|
@impl true
|
|
def update_scene(ids, driver) do
|
|
Enum.reduce_while(ids, {:ok, driver}, fn id, {:ok, driver} ->
|
|
case ViewPort.get_script(driver.viewport, id) do
|
|
{:ok, script} ->
|
|
Nif.update_scene(script, id, driver.assigns.server)
|
|
|
|
{:cont, {:ok, driver}}
|
|
|
|
{:error, reason} ->
|
|
{:halt, {:error, reason}}
|
|
end
|
|
end)
|
|
end
|
|
|
|
@doc false
|
|
@impl true
|
|
def reset_scene(driver) do
|
|
Nif.reset_scene(driver.assigns.server)
|
|
{:ok, driver}
|
|
end
|
|
|
|
@doc false
|
|
@impl true
|
|
def del_scripts(ids, driver) do
|
|
Nif.del_scripts(ids, driver.assigns.server)
|
|
{:ok, driver}
|
|
end
|
|
|
|
@doc false
|
|
@impl true
|
|
def clear_color(color, driver) do
|
|
Nif.clear_color(color, driver.assigns.server)
|
|
{:ok, driver}
|
|
end
|
|
|
|
@doc false
|
|
@impl GenServer
|
|
def terminate(_, driver) do
|
|
Nif.terminate(driver.assigns.server)
|
|
end
|
|
|
|
@doc false
|
|
@impl GenServer
|
|
def handle_info({:shutdown, reason}, driver) do
|
|
Logger.debug(fn -> "Received shutdown from `scenic_window_server`: #{inspect(reason)}" end)
|
|
|
|
case driver.assigns.config.on_close do
|
|
:restart ->
|
|
{:stop, :normal, driver}
|
|
|
|
:stop_driver ->
|
|
ViewPort.stop_driver(driver.viewport, self())
|
|
{:stop, :normal, driver}
|
|
|
|
:stop_viewport ->
|
|
ViewPort.stop(driver.viewport)
|
|
{:stop, :normal, driver}
|
|
|
|
:stop_system ->
|
|
System.stop(0)
|
|
{:stop, :normal, driver}
|
|
|
|
:halt_system ->
|
|
System.halt(0)
|
|
{:stop, :normal, driver}
|
|
|
|
{module, _fun, 1} ->
|
|
module.fun(:shutdown)
|
|
{:stop, :normal, driver}
|
|
end
|
|
end
|
|
|
|
def handle_info(msg, driver) do
|
|
Logger.debug(fn ->
|
|
"Unhandled message #{inspect(msg)}"
|
|
end)
|
|
|
|
{:noreply, driver}
|
|
end
|
|
end
|