use crate::lang::prog::ffi::js::{JsInstant, JsNumFmt, js_int32, js_number};
use crate::{
EventButton, EventButtonState, EventButtons, EventKind, EventKindTimed, EventPointer,
EventPointerKind, EventTimestamp, KeyMods, Timed, WebEventKind, f32bits_niche,
};
use crate::{impl_trait, is};
#[doc = crate::_tags!(event web)]
#[doc = crate::_doc_meta!{
location("sys/os/browser/web"),
test_size_of(WebEventPointer = 48|384; niche Option),
}]
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct WebEventPointer {
pub x: js_number, pub y: js_number, pub pressure: js_number,
pub id: js_int32, pub tilt_x: i8, pub tilt_y: i8, pub twist: u16,
code: WebPointerCode, pub buttons: u8, pub mods: KeyMods, pub etype: WebEventKind, pub timestamp: JsInstant, }
impl_trait! { fmt::Debug for WebEventPointer |self, f| {
f.debug_struct("WebEventPointer")
.field("x", &JsNumFmt::<2>(self.x))
.field("y", &JsNumFmt::<2>(self.y))
.field("pressure", &JsNumFmt::<3>(self.pressure))
.field("id", &self.id)
.field("tilt_x", &self.tilt_x)
.field("tilt_y", &self.tilt_y)
.field("twist", &self.twist)
.field("kind", &self.kind())
.field("button", &self.button())
.field("buttons", &EventButtons::from_bits(self.buttons))
.field("mods", &self.mods)
.field("etype", &self.etype)
.field("timestamp", &self.timestamp)
.finish()
}}
impl WebEventPointer {
#[allow(clippy::too_many_arguments)] #[rustfmt::skip]
pub const fn new(
x: js_number, y: js_number,
pressure: js_number,
id: js_int32,
tilt_x: i8, tilt_y: i8,
twist: u16,
kind: EventPointerKind,
button: u8, buttons: u8,
mods: KeyMods,
etype: WebEventKind,
timestamp: JsInstant,
) -> Self {
let code = WebPointerCode::new()
.with_kind(kind.to_web())
.with_button(Self::encode_web_button(button));
Self { x, y, pressure, id, tilt_x, tilt_y, twist, code, buttons, mods, etype, timestamp }
}
pub const fn kind(self) -> EventPointerKind {
EventPointerKind::from_web(self.code.get_kind())
}
pub const fn web_kind(self) -> u8 {
self.code.get_kind()
}
pub const fn with_kind(mut self, kind: EventPointerKind) -> Self {
self.code.set_kind(kind.to_web());
self
}
pub const fn button(self) -> Option<EventButton> {
EventButton::from_web(self.web_button())
}
pub const fn web_button(self) -> u8 {
Self::decode_web_button(self.code.get_button())
}
pub const fn with_button(mut self, button: Option<EventButton>) -> Self {
let web_button = match button {
Some(button) => button.to_web(),
None => 255,
};
self.code.set_button(Self::encode_web_button(web_button));
self
}
pub const fn with_web_button(mut self, button: u8) -> Self {
self.code.set_button(Self::encode_web_button(button));
self
}
const WEB_BUTTON_NONE: u8 = 15;
const fn encode_web_button(button: u8) -> u8 {
match button {
255 => Self::WEB_BUTTON_NONE,
0..=14 => button,
_ => Self::WEB_BUTTON_NONE,
}
}
const fn decode_web_button(code: u8) -> u8 {
match code {
Self::WEB_BUTTON_NONE => 255,
n => n,
}
}
}
impl WebEventPointer {
pub const fn to_kind_timed(self) -> EventKindTimed {
let kind = EventKind::Pointer(EventPointer::new(
self.kind(),
self.id as u32,
self.x as i32,
self.y as i32,
0,
0,
f32bits_niche::new(self.pressure as f32),
self.tilt_x,
self.tilt_y,
self.twist,
self.button(),
EventButtonState::from_web(self.etype),
EventButtons::from_bits(self.buttons),
self.mods,
));
let timestamp = Some(EventTimestamp::from_js(self.timestamp));
EventKindTimed::new(kind, timestamp)
}
pub const fn from_event_pointer_timed(
from: Timed<EventPointer, Option<EventTimestamp>>,
) -> WebEventPointer {
let timestamp = is![let Some(t) = from.time, t.to_js(), JsInstant { ms: 0.0 }];
WebEventPointer::new(
from.value.x as js_number,
from.value.y as js_number,
from.value.get_pressure() as js_number,
from.value.id as js_int32,
from.value.tilt_x,
from.value.tilt_y,
from.value.twist,
from.value.kind,
is![let Some(b) = from.value.button, b.to_web(), 255],
from.value.buttons.bits(),
from.value.mods,
from.value.state.to_web_as_pointer(),
timestamp,
)
}
}
impl From<WebEventPointer> for EventKindTimed {
fn from(from: WebEventPointer) -> Self {
from.to_kind_timed()
}
}
impl From<Timed<EventPointer, Option<EventTimestamp>>> for WebEventPointer {
fn from(from: Timed<EventPointer, Option<EventTimestamp>>) -> Self {
Self::from_event_pointer_timed(from)
}
}
impl EventPointerKind {
pub const fn from_web(kind: u8) -> Self {
match kind {
1 => EventPointerKind::Touch,
2 => EventPointerKind::Pen,
_ => EventPointerKind::Mouse,
}
}
pub const fn to_web(self) -> u8 {
match self {
EventPointerKind::Mouse => 0,
EventPointerKind::Touch => 1,
EventPointerKind::Pen => 2,
}
}
}
crate::bitfield! {
struct WebPointerCode(u8) {
KIND = 0..=1;
BUTTON = 2..=5;
RESERVED = 6..=7;
}
}