Something went wrong. Try again.
A hardware-accelerated GPU terminal emulator focusing to run in desktops and browsers.
Something went wrong. Try again.
29 kB · 751 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752use std::cell::{Cell, RefCell};use std::clone::Clone;use std::collections::vec_deque::IntoIter as VecDequeIter;use std::collections::VecDeque;use std::iter;use std::rc::{Rc, Weak};
use web_sys::Element;
use super::super::monitor::MonitorHandle;use super::super::KeyEventExtra;use super::device::DeviceId;use super::runner::{EventWrapper, Execution};use super::window::WindowId;use super::{backend, runner};use crate::event::{ DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent,};use crate::event_loop::{ControlFlow, DeviceEvents};use crate::keyboard::ModifiersState;use crate::platform::web::{CustomCursorFuture, PollStrategy};use crate::platform_impl::platform::cursor::CustomCursor;use crate::platform_impl::platform::r#async::Waker;use crate::window::{ CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,};
#[derive(Default)]struct ModifiersShared(Rc<Cell<ModifiersState>>);
impl ModifiersShared { fn set(&self, new: ModifiersState) { self.0.set(new) }
fn get(&self) -> ModifiersState { self.0.get() }}
impl Clone for ModifiersShared { fn clone(&self) -> Self { Self(Rc::clone(&self.0)) }}
#[derive(Clone)]pub struct ActiveEventLoop { pub(crate) runner: runner::Shared, modifiers: ModifiersShared,}
impl ActiveEventLoop { pub fn new() -> Self { Self { runner: runner::Shared::new(), modifiers: ModifiersShared::default(), } }
pub fn run( &self, event_handler: Box<runner::EventHandler>, event_loop_recreation: bool, ) { self.runner.event_loop_recreation(event_loop_recreation); self.runner.set_listener(event_handler); }
pub fn generate_id(&self) -> WindowId { WindowId(self.runner.generate_id()) }
pub fn create_custom_cursor(&self, source: CustomCursorSource) -> RootCustomCursor { RootCustomCursor { inner: CustomCursor::new(self, source.inner), } }
pub fn create_custom_cursor_async( &self, source: CustomCursorSource, ) -> CustomCursorFuture { CustomCursorFuture(CustomCursor::new_async(self, source.inner)) }
pub fn register(&self, canvas: &Rc<RefCell<backend::Canvas>>, id: WindowId) { let canvas_clone = canvas.clone(); canvas.on_touch_start();
let runner = self.runner.clone(); let has_focus = canvas.has_focus.clone(); let modifiers = self.modifiers.clone(); canvas.on_blur(move || { has_focus.set(false);
let clear_modifiers = (!modifiers.get().is_empty()).then(|| { modifiers.set(ModifiersState::empty()); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(ModifiersState::empty().into()), } });
runner.send_events(clear_modifiers.into_iter().chain(iter::once( Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Focused(false), }, ))); });
let runner = self.runner.clone(); let has_focus = canvas.has_focus.clone(); canvas.on_focus(move || { if !has_focus.replace(true) { runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Focused(true), }); } });
// It is possible that at this point the canvas has // been focused before the callback can be called. let focused = canvas .document() .active_element() .filter(|element| { let canvas: &Element = canvas.raw(); element == canvas }) .is_some();
if focused { canvas.has_focus.set(true); self.runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Focused(true), }) }
let runner = self.runner.clone(); let modifiers = self.modifiers.clone(); canvas.on_keyboard_press( move |physical_key, logical_key, text, location, repeat, active_modifiers| { let modifiers_changed = (modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
let device_id = RootDeviceId(unsafe { DeviceId::dummy() });
runner.send_events( iter::once(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::KeyboardInput { device_id, event: KeyEvent { physical_key, logical_key, text, location, state: ElementState::Pressed, repeat, platform_specific: KeyEventExtra, }, is_synthetic: false, }, }) .chain(modifiers_changed), ); }, );
let runner = self.runner.clone(); let modifiers = self.modifiers.clone(); canvas.on_keyboard_release( move |physical_key, logical_key, text, location, repeat, active_modifiers| { let modifiers_changed = (modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
let device_id = RootDeviceId(unsafe { DeviceId::dummy() });
runner.send_events( iter::once(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::KeyboardInput { device_id, event: KeyEvent { physical_key, logical_key, text, location, state: ElementState::Released, repeat, platform_specific: KeyEventExtra, }, is_synthetic: false, }, }) .chain(modifiers_changed), ) }, );
let has_focus = canvas.has_focus.clone(); canvas.on_cursor_leave({ let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id| { let focus = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
let pointer = pointer_id.map(|pointer_id| Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorLeft { device_id: RootDeviceId(DeviceId(pointer_id)), }, });
if focus.is_some() || pointer.is_some() { runner.send_events(focus.into_iter().chain(pointer)) } } });
canvas.on_cursor_enter({ let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id| { let focus = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
let pointer = pointer_id.map(|pointer_id| Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorEntered { device_id: RootDeviceId(DeviceId(pointer_id)), }, });
if focus.is_some() || pointer.is_some() { runner.send_events(focus.into_iter().chain(pointer)) } } });
canvas.on_cursor_move( { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers| { if has_focus.get() && modifiers.get() != active_modifiers { modifiers.set(active_modifiers); runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), }) } } }, { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id, events| { let modifiers = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged( active_modifiers.into(), ), } });
runner.send_events(modifiers.into_iter().chain(events.flat_map( |position| { let device_id = RootDeviceId(DeviceId(pointer_id));
iter::once(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorMoved { device_id, position, }, }) }, ))); } }, { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, device_id, events| { let modifiers = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged( active_modifiers.into(), ), } });
runner.send_events(modifiers.into_iter().chain(events.map( |(location, force)| Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Touch(Touch { id: device_id as u64, device_id: RootDeviceId(DeviceId(device_id)), phase: TouchPhase::Moved, force: Some(force), location, }), }, ))); } }, { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id, position: crate::dpi::PhysicalPosition<f64>, buttons, button| { let modifiers = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged( active_modifiers.into(), ), } });
let device_id = RootDeviceId(DeviceId(pointer_id));
let state = if buttons.contains(button.into()) { ElementState::Pressed } else { ElementState::Released };
// A chorded button event may come in without any prior CursorMoved events, // therefore we should send a CursorMoved event to make sure that the // user code has the correct cursor position. runner.send_events(modifiers.into_iter().chain([ Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorMoved { device_id, position, }, }, Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::MouseInput { device_id, state, button, }, }, ])); } }, );
canvas.on_mouse_press( { let runner = self.runner.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers| { if modifiers.get() != active_modifiers { modifiers.set(active_modifiers); runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), }) } } }, { let runner = self.runner.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id, position, button| { let modifiers = (modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
let device_id: RootDeviceId = RootDeviceId(DeviceId(pointer_id));
// A mouse down event may come in without any prior CursorMoved events, // therefore we should send a CursorMoved event to make sure that the // user code has the correct cursor position. runner.send_events(modifiers.into_iter().chain([ Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorMoved { device_id, position, }, }, Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::MouseInput { device_id, state: ElementState::Pressed, button, }, }, ])); } }, { let runner = self.runner.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, device_id, location, force| { let modifiers = (modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
runner.send_events(modifiers.into_iter().chain(iter::once( Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Touch(Touch { id: device_id as u64, device_id: RootDeviceId(DeviceId(device_id)), phase: TouchPhase::Started, force: Some(force), location, }), }, ))) } }, );
canvas.on_mouse_release( { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers| { if has_focus.get() && modifiers.get() != active_modifiers { modifiers.set(active_modifiers); runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), }); } } }, { let runner = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, pointer_id, position, button| { let modifiers = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged( active_modifiers.into(), ), } });
let device_id: RootDeviceId = RootDeviceId(DeviceId(pointer_id));
// A mouse up event may come in without any prior CursorMoved events, // therefore we should send a CursorMoved event to make sure that the // user code has the correct cursor position. runner.send_events(modifiers.into_iter().chain([ Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::CursorMoved { device_id, position, }, }, Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::MouseInput { device_id, state: ElementState::Released, button, }, }, ])); } }, { let runner_touch = self.runner.clone(); let has_focus = has_focus.clone(); let modifiers = self.modifiers.clone();
move |active_modifiers, device_id, location, force| { let modifiers = (has_focus.get() && modifiers.get() != active_modifiers) .then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged( active_modifiers.into(), ), } });
runner_touch.send_events(modifiers.into_iter().chain(iter::once( Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Touch(Touch { id: device_id as u64, device_id: RootDeviceId(DeviceId(device_id)), phase: TouchPhase::Ended, force: Some(force), location, }), }, ))); } }, );
let runner = self.runner.clone(); let modifiers = self.modifiers.clone(); canvas.on_mouse_wheel(move |pointer_id, delta, active_modifiers| { let modifiers_changed = (has_focus.get() && modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers); Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()), } });
runner.send_events(modifiers_changed.into_iter().chain(iter::once( Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::MouseWheel { device_id: RootDeviceId(DeviceId(pointer_id)), delta, phase: TouchPhase::Moved, }, }, ))); });
let runner = self.runner.clone(); canvas.on_touch_cancel(move |device_id, location, force| { runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Touch(Touch { id: device_id as u64, device_id: RootDeviceId(DeviceId(device_id)), phase: TouchPhase::Cancelled, force: Some(force), location, }), }); });
let runner = self.runner.clone(); canvas.on_dark_mode(move |is_dark_mode| { let theme = if is_dark_mode { Theme::Dark } else { Theme::Light }; runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::ThemeChanged(theme), }); });
canvas.on_resize_scale( { let runner = self.runner.clone(); let canvas = canvas_clone.clone();
move |size, scale| { runner.send_event(EventWrapper::ScaleChange { canvas: Rc::downgrade(&canvas), size, scale, }) } }, { let runner = self.runner.clone(); let canvas = canvas_clone.clone();
move |new_size| { let canvas = canvas.borrow(); canvas.set_current_size(new_size); if canvas.old_size() != new_size { canvas.set_old_size(new_size); runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Resized(new_size), }); runner.request_redraw(RootWindowId(id)); } } }, );
let runner = self.runner.clone(); canvas.on_intersection(move |is_intersecting| { // only fire if visible while skipping the first event if it's intersecting if backend::is_visible(runner.document()) && !(is_intersecting && canvas_clone.borrow().is_intersecting.is_none()) { runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Occluded(!is_intersecting), }); }
canvas_clone.borrow_mut().is_intersecting = Some(is_intersecting); });
let runner = self.runner.clone(); canvas.on_animation_frame(move || runner.request_redraw(RootWindowId(id)));
canvas.on_context_menu(); }
pub fn available_monitors(&self) -> VecDequeIter<MonitorHandle> { VecDeque::new().into_iter() }
pub fn primary_monitor(&self) -> Option<MonitorHandle> { None }
#[inline] pub fn raw_display_handle_raw_window_handle( &self, ) -> Result<raw_window_handle::RawDisplayHandle, raw_window_handle::HandleError> { Ok(raw_window_handle::RawDisplayHandle::Web( raw_window_handle::WebDisplayHandle::new(), )) }
pub fn listen_device_events(&self, allowed: DeviceEvents) { self.runner.listen_device_events(allowed) }
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { self.runner.set_control_flow(control_flow) }
pub(crate) fn control_flow(&self) -> ControlFlow { self.runner.control_flow() }
pub(crate) fn exit(&self) { self.runner.exit() }
pub(crate) fn exiting(&self) -> bool { self.runner.exiting() }
pub(crate) fn set_poll_strategy(&self, strategy: PollStrategy) { self.runner.set_poll_strategy(strategy) }
pub(crate) fn poll_strategy(&self) -> PollStrategy { self.runner.poll_strategy() }
pub(crate) fn waker(&self) -> Waker<Weak<Execution>> { self.runner.waker() }
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { OwnedDisplayHandle }}
#[derive(Clone)]pub(crate) struct OwnedDisplayHandle;
impl OwnedDisplayHandle { #[inline] pub fn raw_display_handle_raw_window_handle( &self, ) -> Result<raw_window_handle::RawDisplayHandle, raw_window_handle::HandleError> { Ok(raw_window_handle::WebDisplayHandle::new().into()) }}