wip: most of the input types can be sent from rust -> beam.
This commit is contained in:
parent
fc46908151
commit
4451c2e887
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -26,3 +26,4 @@ scenic_driver_renderling-*.tar
|
|||
/tmp/
|
||||
|
||||
priv/__scenic
|
||||
priv/native
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
defmodule Scenic.Driver.Renderling.Window.Config do
|
||||
defstruct name: nil,
|
||||
limit_ms: nil,
|
||||
layer: nil,
|
||||
opacity: nil,
|
||||
debug: false,
|
||||
debugger: "",
|
||||
debug_fps: 0,
|
||||
antialias: true,
|
||||
position: nil,
|
||||
window: nil,
|
||||
|
@ -41,19 +35,14 @@ defmodule Scenic.Driver.Renderling.Window.Config do
|
|||
|
||||
@type t :: %__MODULE__{
|
||||
name: atom | String.t(),
|
||||
limit_ms: non_neg_integer(),
|
||||
layer: integer,
|
||||
opacity: integer,
|
||||
debug: boolean,
|
||||
debugger: String.t(),
|
||||
debug_fps: integer,
|
||||
antialias: boolean,
|
||||
position: Position.t(),
|
||||
window: Window.t(),
|
||||
cursor: boolean,
|
||||
key_map: module,
|
||||
on_close: :restart | :stop_driver | :stop_viewport | :stop_system | :halt_system,
|
||||
input_blacklist: [String.t()]
|
||||
input_blacklist: [String.t()],
|
||||
server_path: Path.t()
|
||||
}
|
||||
|
||||
def init(opts) do
|
||||
|
|
|
@ -9,10 +9,6 @@ defmodule Scenic.Driver.Renderling.Window do
|
|||
use Scenic.Driver
|
||||
require Logger
|
||||
|
||||
@default_limit 29
|
||||
@default_layer 0
|
||||
@default_opacity 255
|
||||
|
||||
@position_schema [
|
||||
scaled: [type: :boolean, default: false],
|
||||
centered: [type: :boolean, default: false],
|
||||
|
@ -26,12 +22,6 @@ defmodule Scenic.Driver.Renderling.Window do
|
|||
|
||||
@opts_schema [
|
||||
name: [type: {:or, [:atom, :string]}],
|
||||
limit_ms: [type: :non_neg_integer, default: @default_limit],
|
||||
layer: [type: :integer, default: @default_layer],
|
||||
opacity: [type: :integer, default: @default_opacity],
|
||||
debug: [type: :boolean, default: false],
|
||||
debugger: [type: :string, default: ""],
|
||||
debug_fps: [type: :integer, default: 0],
|
||||
antialias: [type: :boolean, default: true],
|
||||
position: [type: :keyword_list, keys: @position_schema, default: []],
|
||||
window: [type: :keyword_list, keys: @window_schema, default: []],
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"Rect",
|
||||
"Renderling",
|
||||
"Rrect",
|
||||
"Stdio"
|
||||
"Stdio",
|
||||
"winit"
|
||||
]
|
||||
}
|
||||
|
|
7
native/renderling_window/Cargo.lock
generated
7
native/renderling_window/Cargo.lock
generated
|
@ -634,6 +634,9 @@ name = "cursor-icon"
|
|||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
|
@ -716,6 +719,9 @@ name = "dpi"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
|
@ -3315,6 +3321,7 @@ dependencies = [
|
|||
"redox_syscall 0.4.1",
|
||||
"rustix",
|
||||
"sctk-adwaita 0.9.0",
|
||||
"serde",
|
||||
"smithay-client-toolkit",
|
||||
"smol_str",
|
||||
"tracing",
|
||||
|
|
|
@ -17,7 +17,7 @@ renderling = "0.4.1"
|
|||
rustler = {version = "0.32.1", features = ["serde", "nif_version_2_16"]}
|
||||
serde = {version = "1", features = ["derive"]}
|
||||
wgpu = "0.20.0"
|
||||
winit = "0.30.0"
|
||||
winit = {version = "0.30.0", features = ["serde"]}
|
||||
|
||||
[[bin]]
|
||||
name = "renderling_window_server"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::message;
|
||||
use rustler::{NifStruct, NifTaggedEnum, NifTuple, NifUnitEnum, NifUntaggedEnum, Term};
|
||||
use rustler::{NifStruct, NifTaggedEnum, NifTuple, NifUnitEnum};
|
||||
|
||||
/// Structures received from BEAM.
|
||||
|
||||
|
@ -40,12 +40,6 @@ pub enum OnCloseAction {
|
|||
#[derive(NifStruct, Debug, Clone)]
|
||||
#[module = "Scenic.Driver.Renderling.Window.Config"]
|
||||
pub struct DriverConfig {
|
||||
pub limit_ms: u32,
|
||||
pub layer: u32,
|
||||
pub opacity: u32,
|
||||
pub debug: bool,
|
||||
pub debugger: String,
|
||||
pub debug_fps: u32,
|
||||
pub antialias: bool,
|
||||
pub position: WindowPosition,
|
||||
pub window: WindowConfig,
|
||||
|
@ -458,11 +452,339 @@ impl From<message::ViewPortEvent> for ViewPortEvent {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(NifUnitEnum, Debug, Clone)]
|
||||
pub enum ElementState {
|
||||
Pressed,
|
||||
Released,
|
||||
}
|
||||
|
||||
impl From<message::ElementState> for ElementState {
|
||||
fn from(state: message::ElementState) -> Self {
|
||||
match state {
|
||||
message::ElementState::Pressed => ElementState::Pressed,
|
||||
message::ElementState::Released => ElementState::Released,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(NifUnitEnum, Debug, Clone)]
|
||||
pub enum Key {
|
||||
KeySpace,
|
||||
KeyApostrophe,
|
||||
KeyComma,
|
||||
KeyMinus,
|
||||
KeyDot,
|
||||
KeySlash,
|
||||
Key0,
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
KeySemicolon,
|
||||
KeyEqual,
|
||||
KeyA,
|
||||
KeyB,
|
||||
KeyC,
|
||||
KeyD,
|
||||
KeyE,
|
||||
KeyF,
|
||||
KeyG,
|
||||
KeyH,
|
||||
KeyI,
|
||||
KeyJ,
|
||||
KeyK,
|
||||
KeyL,
|
||||
KeyM,
|
||||
KeyN,
|
||||
KeyO,
|
||||
KeyP,
|
||||
KeyQ,
|
||||
KeyR,
|
||||
KeyS,
|
||||
KeyT,
|
||||
KeyU,
|
||||
KeyV,
|
||||
KeyW,
|
||||
KeyX,
|
||||
KeyY,
|
||||
KeyZ,
|
||||
KeyLeftbrace,
|
||||
KeyBlackslash,
|
||||
KeyRightbrace,
|
||||
KeyGrave,
|
||||
KeyEsc,
|
||||
KeyEnter,
|
||||
KeyTab,
|
||||
KeyBackspace,
|
||||
KeyInsert,
|
||||
KeyDelete,
|
||||
KeyRight,
|
||||
KeyLeft,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
KeyPageup,
|
||||
KeyPagedown,
|
||||
KeyHome,
|
||||
KeyEnd,
|
||||
KeyCapslock,
|
||||
KeyScrolllock,
|
||||
KeyNumlock,
|
||||
KeyScreen,
|
||||
KeyPause,
|
||||
KeyF1,
|
||||
KeyF2,
|
||||
KeyF3,
|
||||
KeyF4,
|
||||
KeyF5,
|
||||
KeyF6,
|
||||
KeyF7,
|
||||
KeyF8,
|
||||
KeyF9,
|
||||
KeyF10,
|
||||
KeyF11,
|
||||
KeyF12,
|
||||
KeyF13,
|
||||
KeyF14,
|
||||
KeyF15,
|
||||
KeyF16,
|
||||
KeyF17,
|
||||
KeyF18,
|
||||
KeyF19,
|
||||
KeyF20,
|
||||
KeyF21,
|
||||
KeyF22,
|
||||
KeyF23,
|
||||
KeyF24,
|
||||
KeyF25,
|
||||
KeyKp0,
|
||||
KeyKp1,
|
||||
KeyKp2,
|
||||
KeyKp3,
|
||||
KeyKp4,
|
||||
KeyKp5,
|
||||
KeyKp6,
|
||||
KeyKp7,
|
||||
KeyKp8,
|
||||
KeyKp9,
|
||||
KeyKpdot,
|
||||
KeyKpslash,
|
||||
KeyKpasterisk,
|
||||
KeyKpminus,
|
||||
KeyKpplus,
|
||||
KeyKpenter,
|
||||
KeyKpequal,
|
||||
KeyLeftshift,
|
||||
KeyLeftctrl,
|
||||
KeyLeftalt,
|
||||
KeyLeftsuper,
|
||||
KeyRightshift,
|
||||
KeyRightctrl,
|
||||
KeyRightalt,
|
||||
KeyRightsuper,
|
||||
KeyMenu,
|
||||
|
||||
// Added specifically because `From<_>` can't fail, so we can handle up in BEAM land.
|
||||
KeyUnsupported,
|
||||
|
||||
// Added because I felt bad Scenic didn't know about them:
|
||||
KeyPrintscreen,
|
||||
KeyBrback,
|
||||
KeyBrfavs,
|
||||
KeyBrfwd,
|
||||
KeyBrhome,
|
||||
KeyBrrefresh,
|
||||
KeyBrsearch,
|
||||
KeyBrstop,
|
||||
KeyEject,
|
||||
KeyMedplay,
|
||||
KeyMedsel,
|
||||
KeyMedstop,
|
||||
KeyMednext,
|
||||
KeyMedprev,
|
||||
KeyMedvolup,
|
||||
KeyMedmute,
|
||||
KeyMedvoldown,
|
||||
}
|
||||
|
||||
impl From<winit::keyboard::KeyCode> for Key {
|
||||
fn from(key: winit::keyboard::KeyCode) -> Self {
|
||||
match key {
|
||||
winit::keyboard::KeyCode::Backquote => Key::KeyGrave,
|
||||
winit::keyboard::KeyCode::Backslash => Key::KeyBlackslash,
|
||||
winit::keyboard::KeyCode::BracketLeft => Key::KeyLeftbrace,
|
||||
winit::keyboard::KeyCode::BracketRight => Key::KeyRightbrace,
|
||||
winit::keyboard::KeyCode::Comma => Key::KeyComma,
|
||||
winit::keyboard::KeyCode::Digit0 => Key::Key0,
|
||||
winit::keyboard::KeyCode::Digit1 => Key::Key1,
|
||||
winit::keyboard::KeyCode::Digit2 => Key::Key2,
|
||||
winit::keyboard::KeyCode::Digit3 => Key::Key3,
|
||||
winit::keyboard::KeyCode::Digit4 => Key::Key4,
|
||||
winit::keyboard::KeyCode::Digit5 => Key::Key5,
|
||||
winit::keyboard::KeyCode::Digit6 => Key::Key6,
|
||||
winit::keyboard::KeyCode::Digit7 => Key::Key7,
|
||||
winit::keyboard::KeyCode::Digit8 => Key::Key8,
|
||||
winit::keyboard::KeyCode::Digit9 => Key::Key9,
|
||||
winit::keyboard::KeyCode::Equal => Key::KeyEqual,
|
||||
winit::keyboard::KeyCode::IntlBackslash => Key::KeyBlackslash,
|
||||
winit::keyboard::KeyCode::IntlRo => Key::KeyBlackslash,
|
||||
winit::keyboard::KeyCode::KeyA => Key::KeyA,
|
||||
winit::keyboard::KeyCode::KeyB => Key::KeyB,
|
||||
winit::keyboard::KeyCode::KeyC => Key::KeyC,
|
||||
winit::keyboard::KeyCode::KeyD => Key::KeyD,
|
||||
winit::keyboard::KeyCode::KeyE => Key::KeyE,
|
||||
winit::keyboard::KeyCode::KeyF => Key::KeyF,
|
||||
winit::keyboard::KeyCode::KeyG => Key::KeyG,
|
||||
winit::keyboard::KeyCode::KeyH => Key::KeyH,
|
||||
winit::keyboard::KeyCode::KeyI => Key::KeyI,
|
||||
winit::keyboard::KeyCode::KeyJ => Key::KeyJ,
|
||||
winit::keyboard::KeyCode::KeyK => Key::KeyK,
|
||||
winit::keyboard::KeyCode::KeyL => Key::KeyL,
|
||||
winit::keyboard::KeyCode::KeyM => Key::KeyM,
|
||||
winit::keyboard::KeyCode::KeyN => Key::KeyN,
|
||||
winit::keyboard::KeyCode::KeyO => Key::KeyO,
|
||||
winit::keyboard::KeyCode::KeyP => Key::KeyP,
|
||||
winit::keyboard::KeyCode::KeyQ => Key::KeyQ,
|
||||
winit::keyboard::KeyCode::KeyR => Key::KeyR,
|
||||
winit::keyboard::KeyCode::KeyS => Key::KeyS,
|
||||
winit::keyboard::KeyCode::KeyT => Key::KeyT,
|
||||
winit::keyboard::KeyCode::KeyU => Key::KeyU,
|
||||
winit::keyboard::KeyCode::KeyV => Key::KeyV,
|
||||
winit::keyboard::KeyCode::KeyW => Key::KeyW,
|
||||
winit::keyboard::KeyCode::KeyX => Key::KeyX,
|
||||
winit::keyboard::KeyCode::KeyY => Key::KeyY,
|
||||
winit::keyboard::KeyCode::KeyZ => Key::KeyZ,
|
||||
winit::keyboard::KeyCode::Minus => Key::KeyMinus,
|
||||
winit::keyboard::KeyCode::Period => Key::KeyDot,
|
||||
winit::keyboard::KeyCode::Quote => Key::KeyApostrophe,
|
||||
winit::keyboard::KeyCode::Semicolon => Key::KeySemicolon,
|
||||
winit::keyboard::KeyCode::Slash => Key::KeySlash,
|
||||
winit::keyboard::KeyCode::AltLeft => Key::KeyLeftalt,
|
||||
winit::keyboard::KeyCode::AltRight => Key::KeyRightalt,
|
||||
winit::keyboard::KeyCode::Backspace => Key::KeyBackspace,
|
||||
winit::keyboard::KeyCode::CapsLock => Key::KeyCapslock,
|
||||
winit::keyboard::KeyCode::ContextMenu => Key::KeyMenu,
|
||||
winit::keyboard::KeyCode::ControlLeft => Key::KeyLeftctrl,
|
||||
winit::keyboard::KeyCode::ControlRight => Key::KeyRightctrl,
|
||||
winit::keyboard::KeyCode::Enter => Key::KeyEnter,
|
||||
winit::keyboard::KeyCode::SuperLeft => Key::KeyLeftsuper,
|
||||
winit::keyboard::KeyCode::SuperRight => Key::KeyRightsuper,
|
||||
winit::keyboard::KeyCode::ShiftLeft => Key::KeyLeftshift,
|
||||
winit::keyboard::KeyCode::ShiftRight => Key::KeyRightshift,
|
||||
winit::keyboard::KeyCode::Space => Key::KeySpace,
|
||||
winit::keyboard::KeyCode::Tab => Key::KeyTab,
|
||||
winit::keyboard::KeyCode::Delete => Key::KeyDelete,
|
||||
winit::keyboard::KeyCode::End => Key::KeyEnd,
|
||||
winit::keyboard::KeyCode::Insert => Key::KeyInsert,
|
||||
winit::keyboard::KeyCode::PageDown => Key::KeyPagedown,
|
||||
winit::keyboard::KeyCode::PageUp => Key::KeyPageup,
|
||||
winit::keyboard::KeyCode::ArrowDown => Key::KeyDown,
|
||||
winit::keyboard::KeyCode::ArrowLeft => Key::KeyLeft,
|
||||
winit::keyboard::KeyCode::ArrowRight => Key::KeyRight,
|
||||
winit::keyboard::KeyCode::ArrowUp => Key::KeyUp,
|
||||
winit::keyboard::KeyCode::NumLock => Key::KeyNumlock,
|
||||
winit::keyboard::KeyCode::Numpad0 => Key::KeyKp0,
|
||||
winit::keyboard::KeyCode::Numpad1 => Key::KeyKp1,
|
||||
winit::keyboard::KeyCode::Numpad2 => Key::KeyKp2,
|
||||
winit::keyboard::KeyCode::Numpad3 => Key::KeyKp3,
|
||||
winit::keyboard::KeyCode::Numpad4 => Key::KeyKp4,
|
||||
winit::keyboard::KeyCode::Numpad5 => Key::KeyKp5,
|
||||
winit::keyboard::KeyCode::Numpad6 => Key::KeyKp6,
|
||||
winit::keyboard::KeyCode::Numpad7 => Key::KeyKp7,
|
||||
winit::keyboard::KeyCode::Numpad8 => Key::KeyKp8,
|
||||
winit::keyboard::KeyCode::Numpad9 => Key::KeyKp9,
|
||||
winit::keyboard::KeyCode::NumpadAdd => Key::KeyKpplus,
|
||||
winit::keyboard::KeyCode::NumpadBackspace => Key::KeyBackspace,
|
||||
winit::keyboard::KeyCode::NumpadComma => Key::KeyComma,
|
||||
winit::keyboard::KeyCode::NumpadDecimal => Key::KeyKpdot,
|
||||
winit::keyboard::KeyCode::NumpadDivide => Key::KeyKpslash,
|
||||
winit::keyboard::KeyCode::NumpadEqual => Key::KeyKpequal,
|
||||
winit::keyboard::KeyCode::NumpadMultiply => Key::KeyKpasterisk,
|
||||
winit::keyboard::KeyCode::NumpadStar => Key::KeyKpasterisk,
|
||||
winit::keyboard::KeyCode::NumpadSubtract => Key::KeyKpminus,
|
||||
winit::keyboard::KeyCode::Escape => Key::KeyEsc,
|
||||
winit::keyboard::KeyCode::PrintScreen => Key::KeyPrintscreen,
|
||||
winit::keyboard::KeyCode::ScrollLock => Key::KeyScrolllock,
|
||||
winit::keyboard::KeyCode::Pause => Key::KeyPause,
|
||||
winit::keyboard::KeyCode::BrowserBack => Key::KeyBrback,
|
||||
winit::keyboard::KeyCode::BrowserFavorites => Key::KeyBrfavs,
|
||||
winit::keyboard::KeyCode::BrowserForward => Key::KeyBrfwd,
|
||||
winit::keyboard::KeyCode::BrowserHome => Key::KeyBrhome,
|
||||
winit::keyboard::KeyCode::BrowserRefresh => Key::KeyBrrefresh,
|
||||
winit::keyboard::KeyCode::BrowserSearch => Key::KeyBrsearch,
|
||||
winit::keyboard::KeyCode::BrowserStop => Key::KeyBrstop,
|
||||
winit::keyboard::KeyCode::Eject => Key::KeyEject,
|
||||
winit::keyboard::KeyCode::MediaPlayPause => Key::KeyMedplay,
|
||||
winit::keyboard::KeyCode::MediaSelect => Key::KeyMedsel,
|
||||
winit::keyboard::KeyCode::MediaStop => Key::KeyMedstop,
|
||||
winit::keyboard::KeyCode::MediaTrackNext => Key::KeyMednext,
|
||||
winit::keyboard::KeyCode::MediaTrackPrevious => Key::KeyMedprev,
|
||||
winit::keyboard::KeyCode::AudioVolumeUp => Key::KeyMedvolup,
|
||||
winit::keyboard::KeyCode::AudioVolumeMute => Key::KeyMedmute,
|
||||
winit::keyboard::KeyCode::AudioVolumeDown => Key::KeyMedvoldown,
|
||||
winit::keyboard::KeyCode::F1 => Key::KeyF1,
|
||||
winit::keyboard::KeyCode::F2 => Key::KeyF2,
|
||||
winit::keyboard::KeyCode::F3 => Key::KeyF3,
|
||||
winit::keyboard::KeyCode::F4 => Key::KeyF4,
|
||||
winit::keyboard::KeyCode::F5 => Key::KeyF5,
|
||||
winit::keyboard::KeyCode::F6 => Key::KeyF6,
|
||||
winit::keyboard::KeyCode::F7 => Key::KeyF7,
|
||||
winit::keyboard::KeyCode::F8 => Key::KeyF8,
|
||||
winit::keyboard::KeyCode::F9 => Key::KeyF9,
|
||||
winit::keyboard::KeyCode::F10 => Key::KeyF10,
|
||||
winit::keyboard::KeyCode::F11 => Key::KeyF11,
|
||||
winit::keyboard::KeyCode::F12 => Key::KeyF12,
|
||||
winit::keyboard::KeyCode::F13 => Key::KeyF13,
|
||||
winit::keyboard::KeyCode::F14 => Key::KeyF14,
|
||||
winit::keyboard::KeyCode::F15 => Key::KeyF15,
|
||||
winit::keyboard::KeyCode::F16 => Key::KeyF16,
|
||||
winit::keyboard::KeyCode::F17 => Key::KeyF17,
|
||||
winit::keyboard::KeyCode::F18 => Key::KeyF18,
|
||||
winit::keyboard::KeyCode::F19 => Key::KeyF19,
|
||||
winit::keyboard::KeyCode::F20 => Key::KeyF20,
|
||||
winit::keyboard::KeyCode::F21 => Key::KeyF21,
|
||||
winit::keyboard::KeyCode::F22 => Key::KeyF22,
|
||||
winit::keyboard::KeyCode::F23 => Key::KeyF23,
|
||||
winit::keyboard::KeyCode::F24 => Key::KeyF24,
|
||||
winit::keyboard::KeyCode::F25 => Key::KeyF25,
|
||||
|
||||
_ => Key::KeyUnsupported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(NifUnitEnum, Debug, Clone)]
|
||||
pub enum MouseButton {
|
||||
BtnLeft,
|
||||
BtnRight,
|
||||
BtnMiddle,
|
||||
BtnBack,
|
||||
BtnForward,
|
||||
BtnOther,
|
||||
}
|
||||
|
||||
impl From<winit::event::MouseButton> for MouseButton {
|
||||
fn from(btn: winit::event::MouseButton) -> Self {
|
||||
match btn {
|
||||
winit::event::MouseButton::Left => MouseButton::BtnLeft,
|
||||
winit::event::MouseButton::Right => MouseButton::BtnRight,
|
||||
winit::event::MouseButton::Middle => MouseButton::BtnMiddle,
|
||||
winit::event::MouseButton::Back => MouseButton::BtnBack,
|
||||
winit::event::MouseButton::Forward => MouseButton::BtnForward,
|
||||
winit::event::MouseButton::Other(_) => MouseButton::BtnOther,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(NifTaggedEnum, Debug, Clone)]
|
||||
pub enum InputEvent {
|
||||
CodePoint(String, Vec<ModifierKey>),
|
||||
Key(String, u8, Vec<ModifierKey>),
|
||||
CursorButton(String, u8, Vec<ModifierKey>, Point),
|
||||
CodePoint(u32, Vec<ModifierKey>),
|
||||
Key(Key, ElementState, Vec<ModifierKey>),
|
||||
CursorButton(MouseButton, ElementState, Vec<ModifierKey>, Point),
|
||||
CursorScroll(Point, Point),
|
||||
CursorPos(Point),
|
||||
ViewPort(ViewPortEvent, Point),
|
||||
|
@ -483,21 +805,21 @@ impl From<message::InputEvent> for InputEvent {
|
|||
),
|
||||
message::InputEvent::Key {
|
||||
key,
|
||||
value,
|
||||
state,
|
||||
modifiers,
|
||||
} => InputEvent::Key(
|
||||
key,
|
||||
value,
|
||||
key.into(),
|
||||
state.into(),
|
||||
modifiers.iter().map(|x| x.clone().into()).collect(),
|
||||
),
|
||||
message::InputEvent::CursorButton {
|
||||
button,
|
||||
value,
|
||||
state,
|
||||
modifiers,
|
||||
position,
|
||||
} => InputEvent::CursorButton(
|
||||
button,
|
||||
value,
|
||||
button.into(),
|
||||
state.into(),
|
||||
modifiers.iter().map(|x| x.clone().into()).collect(),
|
||||
position.into(),
|
||||
),
|
||||
|
@ -514,3 +836,39 @@ impl From<message::InputEvent> for InputEvent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(NifUnitEnum, Debug, Clone)]
|
||||
pub enum ShutdownAtom {
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
#[derive(NifUnitEnum, Debug, Clone)]
|
||||
pub enum ShutdownReason {
|
||||
Normal,
|
||||
Terminate,
|
||||
}
|
||||
|
||||
#[derive(NifTuple, Debug, Clone)]
|
||||
pub struct ShutdownMessage(ShutdownAtom, ShutdownReason);
|
||||
|
||||
impl ShutdownMessage {
|
||||
pub fn normal() -> Self {
|
||||
ShutdownMessage(ShutdownAtom::Shutdown, ShutdownReason::Normal)
|
||||
}
|
||||
pub fn terminate() -> Self {
|
||||
ShutdownMessage(ShutdownAtom::Shutdown, ShutdownReason::Terminate)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<message::ShutdownReason> for ShutdownMessage {
|
||||
fn from(reason: message::ShutdownReason) -> Self {
|
||||
match reason {
|
||||
message::ShutdownReason::Normal => {
|
||||
ShutdownMessage(ShutdownAtom::Shutdown, ShutdownReason::Normal)
|
||||
}
|
||||
message::ShutdownReason::Terminate => {
|
||||
ShutdownMessage(ShutdownAtom::Shutdown, ShutdownReason::Terminate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
mod elixir_types;
|
||||
mod message;
|
||||
|
||||
use crate::elixir_types::{Color, DriverConfig, InputClass, InputEvent, ScriptItem};
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
|
||||
use rustler::{Encoder, Env, LocalPid, NifResult, OwnedEnv, ResourceArc, Term};
|
||||
use crate::elixir_types::{
|
||||
Color, DriverConfig, InputClass, InputEvent, ScriptItem, ShutdownMessage,
|
||||
};
|
||||
use ipc_channel::ipc::{IpcOneShotServer, IpcSender};
|
||||
use rustler::{Encoder, Env, NifResult, OwnedEnv, ResourceArc, Term};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::sync::Mutex;
|
||||
use std::thread::sleep;
|
||||
|
@ -33,21 +35,32 @@ fn init(env: Env<'_>, cfg: DriverConfig) -> ResourceArc<IpcResource> {
|
|||
let pid = env.pid();
|
||||
|
||||
std::thread::spawn(move || loop {
|
||||
let event = receiver.recv().unwrap();
|
||||
let mut msg_env = OwnedEnv::new();
|
||||
match event {
|
||||
message::Message::InputEvent(input_event) => {
|
||||
let _ = msg_env.send_and_clear(&pid, |env| {
|
||||
let input_event: InputEvent = input_event.into();
|
||||
input_event.encode(env)
|
||||
});
|
||||
if let Ok(event) = receiver.recv() {
|
||||
let mut msg_env = OwnedEnv::new();
|
||||
match event {
|
||||
message::Message::InputEvent(input_event) => {
|
||||
msg_env
|
||||
.send_and_clear(&pid, |env| {
|
||||
let input_event: InputEvent = input_event.into();
|
||||
input_event.encode(env)
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
message::Message::Shutdown(reason) => {
|
||||
msg_env
|
||||
.send_and_clear(&pid, |env| {
|
||||
let msg: ShutdownMessage = reason.into();
|
||||
msg.encode(env)
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
message::Message::Shutdown => {
|
||||
let _ = msg_env.send_and_clear(&pid, |env| {
|
||||
rustler::Atom::from_str(env, "shutdown").unwrap()
|
||||
});
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
} else {
|
||||
let mut msg_env = OwnedEnv::new();
|
||||
msg_env
|
||||
.send_and_clear(&pid, |env| ShutdownMessage::terminate().encode(env))
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -128,7 +141,10 @@ fn terminate(resource: ResourceArc<IpcResource>) {
|
|||
println!("Shutting down server.");
|
||||
let mut mutex = resource.0.lock().unwrap();
|
||||
if let None = mutex.handle.try_wait().unwrap() {
|
||||
mutex.sender.send(message::Message::Shutdown).unwrap();
|
||||
mutex
|
||||
.sender
|
||||
.send(message::Message::Shutdown(message::ShutdownReason::Normal))
|
||||
.unwrap();
|
||||
drop(mutex);
|
||||
std::thread::spawn(move || {
|
||||
// We give the server 100 millis to shut down and then we just kill
|
||||
|
|
|
@ -611,7 +611,7 @@ impl From<elixir_types::ScriptItem> for ScriptItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum ModifierKey {
|
||||
Meta,
|
||||
Alt,
|
||||
|
@ -628,6 +628,24 @@ pub struct Point {
|
|||
pub y: u32,
|
||||
}
|
||||
|
||||
impl From<winit::dpi::PhysicalPosition<f64>> for Point {
|
||||
fn from(pos: winit::dpi::PhysicalPosition<f64>) -> Self {
|
||||
Point {
|
||||
x: pos.x.round() as u32,
|
||||
y: pos.y.round() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<winit::dpi::PhysicalSize<u32>> for Point {
|
||||
fn from(pos: winit::dpi::PhysicalSize<u32>) -> Self {
|
||||
Point {
|
||||
x: pos.width,
|
||||
y: pos.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum ViewPortEvent {
|
||||
Enter,
|
||||
|
@ -635,20 +653,35 @@ pub enum ViewPortEvent {
|
|||
Reshape,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum ElementState {
|
||||
Pressed,
|
||||
Released,
|
||||
}
|
||||
|
||||
impl From<winit::event::ElementState> for ElementState {
|
||||
fn from(state: winit::event::ElementState) -> Self {
|
||||
match state {
|
||||
winit::event::ElementState::Pressed => ElementState::Pressed,
|
||||
winit::event::ElementState::Released => ElementState::Released,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum InputEvent {
|
||||
CodePoint {
|
||||
codepoint: String,
|
||||
codepoint: u32,
|
||||
modifiers: Vec<ModifierKey>,
|
||||
},
|
||||
Key {
|
||||
key: String,
|
||||
value: u8,
|
||||
key: winit::keyboard::KeyCode,
|
||||
state: ElementState,
|
||||
modifiers: Vec<ModifierKey>,
|
||||
},
|
||||
CursorButton {
|
||||
button: String,
|
||||
value: u8,
|
||||
button: winit::event::MouseButton,
|
||||
state: ElementState,
|
||||
modifiers: Vec<ModifierKey>,
|
||||
position: Point,
|
||||
},
|
||||
|
@ -676,13 +709,17 @@ pub enum InputEvent {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum ShutdownReason {
|
||||
Normal,
|
||||
Terminate,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum Message {
|
||||
Shutdown,
|
||||
Shutdown(ShutdownReason),
|
||||
ResetScene,
|
||||
Init {
|
||||
opacity: u32,
|
||||
debug: bool,
|
||||
antialias: bool,
|
||||
centered: bool,
|
||||
scaled: bool,
|
||||
|
@ -703,8 +740,6 @@ pub enum Message {
|
|||
impl From<elixir_types::DriverConfig> for Message {
|
||||
fn from(driver_config: elixir_types::DriverConfig) -> Self {
|
||||
Message::Init {
|
||||
opacity: driver_config.opacity,
|
||||
debug: driver_config.debug,
|
||||
antialias: driver_config.antialias,
|
||||
centered: driver_config.position.centered,
|
||||
scaled: driver_config.position.scaled,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod elixir_types;
|
||||
mod message;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::process::exit;
|
||||
|
||||
use crate::message::{IpcExchange, Message};
|
||||
|
@ -8,12 +9,12 @@ use clap::Parser;
|
|||
use ipc_channel::ipc;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
|
||||
use message::{InputClass, OnClose, Orientation};
|
||||
use message::{InputClass, ModifierKey, OnClose, Orientation};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event::{ElementState, KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::keyboard::{Key, ModifiersState};
|
||||
use winit::keyboard::{Key, NamedKey, PhysicalKey};
|
||||
use winit::window::{Window, WindowId};
|
||||
|
||||
#[cfg(macos_platform)]
|
||||
|
@ -54,7 +55,8 @@ fn main() -> anyhow::Result<()> {
|
|||
let event = c2s_recv.recv().unwrap();
|
||||
|
||||
match event {
|
||||
Message::Shutdown => exit(0),
|
||||
Message::Shutdown(message::ShutdownReason::Normal) => exit(0),
|
||||
Message::Shutdown(message::ShutdownReason::Terminate) => exit(1),
|
||||
Message::Init { .. } => unreachable!(),
|
||||
_ => event_loop_proxy.send_event(event).unwrap(),
|
||||
};
|
||||
|
@ -68,8 +70,6 @@ fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
struct Application {
|
||||
opacity: u32,
|
||||
debug: bool,
|
||||
antialias: bool,
|
||||
centered: bool,
|
||||
scaled: bool,
|
||||
|
@ -82,14 +82,14 @@ struct Application {
|
|||
window: Option<Window>,
|
||||
input_classes: Vec<InputClass>,
|
||||
sender: IpcSender<Message>,
|
||||
current_modifier_keys: HashSet<message::ModifierKey>,
|
||||
last_cursor_pos: message::Point,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
fn new(event: Message, sender: IpcSender<Message>) -> Self {
|
||||
match event {
|
||||
Message::Init {
|
||||
opacity,
|
||||
debug,
|
||||
antialias,
|
||||
centered,
|
||||
scaled,
|
||||
|
@ -100,8 +100,6 @@ impl Application {
|
|||
height,
|
||||
on_close,
|
||||
} => Application {
|
||||
opacity,
|
||||
debug,
|
||||
antialias,
|
||||
centered,
|
||||
scaled,
|
||||
|
@ -124,6 +122,8 @@ impl Application {
|
|||
InputClass::Switch,
|
||||
],
|
||||
sender,
|
||||
current_modifier_keys: HashSet::default(),
|
||||
last_cursor_pos: message::Point { x: 0, y: 0 },
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -142,42 +142,199 @@ impl ApplicationHandler<Message> for Application {
|
|||
event: WindowEvent,
|
||||
) {
|
||||
match event {
|
||||
// Keep a record of which modifier keys are pressed at any given time.
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
// From cairo driver:
|
||||
//
|
||||
// int action = (event->type == GDK_KEY_PRESS) ? 1 : 0;
|
||||
// uint32_t unicode = gdk_keyval_to_unicode(event->keyval);
|
||||
// send_key(KEYMAP_GDK, event->keyval, event->hardware_keycode, action, event->state);
|
||||
// if (!(event->keyval & 0xF000) && event->type == GDK_KEY_PRESS) {
|
||||
// send_codepoint(KEYMAP_GDK, unicode, event->state);
|
||||
// }
|
||||
// return TRUE;
|
||||
//
|
||||
// Basically, always send a Key event and sometimes a Codepoint event.
|
||||
match event {
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Meta),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::Meta),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Meta),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::Meta),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Alt),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::Alt),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Alt),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::Alt),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Control),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::Ctrl),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Control),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::Ctrl),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Shift),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::Shift),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::Shift),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::Shift),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::CapsLock),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::CapsLock),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::CapsLock),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::CapsLock),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::NumLock),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::NumLock),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::NumLock),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::NumLock),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::ScrollLock),
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => self.current_modifier_keys.insert(ModifierKey::ScrollLock),
|
||||
KeyEvent {
|
||||
logical_key: Key::Named(NamedKey::ScrollLock),
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => self.current_modifier_keys.remove(&ModifierKey::ScrollLock),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if let PhysicalKey::Code(keycode) = event.physical_key {
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::Key {
|
||||
key: keycode,
|
||||
state: event.state.into(),
|
||||
modifiers: self
|
||||
.current_modifier_keys
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<ModifierKey>>(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if let Some(text) = event.text {
|
||||
let codepoint = text.chars().next().unwrap();
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::CodePoint {
|
||||
codepoint: codepoint as u32,
|
||||
modifiers: self
|
||||
.current_modifier_keys
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<ModifierKey>>(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
WindowEvent::CloseRequested => {
|
||||
self.sender.send(Message::Shutdown).unwrap();
|
||||
self.sender
|
||||
.send(Message::Shutdown(message::ShutdownReason::Normal))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
self.sender.send(Message::Shutdown).unwrap();
|
||||
self.sender
|
||||
.send(Message::Shutdown(message::ShutdownReason::Terminate))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
// Send an CursorPos event.
|
||||
let pos: message::Point = position.into();
|
||||
self.last_cursor_pos = pos.clone();
|
||||
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::CursorPos {
|
||||
position: pos,
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
// Send a CursorButton event.
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::CursorButton {
|
||||
button: button,
|
||||
state: state.into(),
|
||||
modifiers: self
|
||||
.current_modifier_keys
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<ModifierKey>>(),
|
||||
position: self.last_cursor_pos.clone(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::AxisMotion { axis, value, .. } => {
|
||||
// Send a CursorScroll event.
|
||||
WindowEvent::Touch(touch) => match touch.phase {
|
||||
winit::event::TouchPhase::Started => {
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::CursorButton {
|
||||
button: winit::event::MouseButton::Left,
|
||||
state: message::ElementState::Pressed,
|
||||
modifiers: self
|
||||
.current_modifier_keys
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<ModifierKey>>(),
|
||||
position: self.last_cursor_pos.clone(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
winit::event::TouchPhase::Ended => {
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::CursorButton {
|
||||
button: winit::event::MouseButton::Left,
|
||||
state: message::ElementState::Released,
|
||||
modifiers: self
|
||||
.current_modifier_keys
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<ModifierKey>>(),
|
||||
position: self.last_cursor_pos.clone(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
WindowEvent::CursorEntered { .. } => {
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::ViewPort {
|
||||
event: message::ViewPortEvent::Enter,
|
||||
position: self.last_cursor_pos.clone(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::CursorEntered { device_id } => {
|
||||
// Send a ViewPort { event: ViewPortEvent::Enter, position: ?? }
|
||||
}
|
||||
WindowEvent::CursorLeft { device_id } => {
|
||||
// Send a ViewPort { event: ViewPortEvent::Exit, position: ?? }
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::ViewPort {
|
||||
event: message::ViewPortEvent::Exit,
|
||||
position: self.last_cursor_pos.clone(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
// Send a ViewPort { event: ViewPortEvent::Reshape, position: Point(size.x, size.y) }
|
||||
self.sender
|
||||
.send(Message::InputEvent(message::InputEvent::ViewPort {
|
||||
event: message::ViewPortEvent::Reshape,
|
||||
position: size.into(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
_ => println!("unhandled window event {:?}", event),
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -7,7 +7,7 @@ defmodule Example do
|
|||
[
|
||||
module: Scenic.Driver.Renderling.Window,
|
||||
name: :window,
|
||||
window: [resizeable: false, title: "Example Window"]
|
||||
window: [resizeable: true, title: "Example Window"]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue