input: Add InputBackend::set_mouse_cursor. Change cursor on buttons
It doesn't feel like Flash without having the hand cursor display when hovering over buttons. First pass at implementing this; core communicates which mouse cursor to use via `InputBackend::set_mouse_cursor`. TODO: Hand cursor only displayed for Button display objects currently. Movie clips should also display this when they are in "button mode" (when a button mouse event is set on them in AVM1, or `buttonMode` property in AVM2).
This commit is contained in:
parent
a917fa4028
commit
86ec2c6cb8
|
@ -11,6 +11,9 @@ pub trait InputBackend: Downcast {
|
||||||
fn hide_mouse(&mut self);
|
fn hide_mouse(&mut self);
|
||||||
|
|
||||||
fn show_mouse(&mut self);
|
fn show_mouse(&mut self);
|
||||||
|
|
||||||
|
/// Changes the mouse cursor image.
|
||||||
|
fn set_mouse_cursor(&mut self, cursor: MouseCursor);
|
||||||
}
|
}
|
||||||
impl_downcast!(InputBackend);
|
impl_downcast!(InputBackend);
|
||||||
|
|
||||||
|
@ -39,6 +42,8 @@ impl InputBackend for NullInputBackend {
|
||||||
fn hide_mouse(&mut self) {}
|
fn hide_mouse(&mut self) {}
|
||||||
|
|
||||||
fn show_mouse(&mut self) {}
|
fn show_mouse(&mut self) {}
|
||||||
|
|
||||||
|
fn set_mouse_cursor(&mut self, _cursor: MouseCursor) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NullInputBackend {
|
impl Default for NullInputBackend {
|
||||||
|
@ -46,3 +51,24 @@ impl Default for NullInputBackend {
|
||||||
NullInputBackend::new()
|
NullInputBackend::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A mouse cursor icon displayed by the Flash Player.
|
||||||
|
/// Communicated from the core to the input backend via `InputBackend::set_mouse_cursor`.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum MouseCursor {
|
||||||
|
/// The default arrow icon.
|
||||||
|
/// Equivalent to AS3 `MouseCursor.ARROW`.
|
||||||
|
Arrow,
|
||||||
|
|
||||||
|
/// The hand icon incdicating a button or link.
|
||||||
|
/// Equivalent to AS3 `MouseCursor.BUTTON`.
|
||||||
|
Hand,
|
||||||
|
|
||||||
|
/// The text I-beam.
|
||||||
|
/// Equivalent to AS3 `MouseCursor.IBEAM`.
|
||||||
|
IBeam,
|
||||||
|
|
||||||
|
/// The grabby-dragging hand icon.
|
||||||
|
/// Equivalent to AS3 `MouseCursor.HAND`.
|
||||||
|
Grab,
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::avm1::listeners::SystemListener;
|
use crate::avm1::listeners::SystemListener;
|
||||||
use crate::avm1::Avm1;
|
use crate::avm1::Avm1;
|
||||||
use crate::backend::input::InputBackend;
|
use crate::backend::input::{InputBackend, MouseCursor};
|
||||||
use crate::backend::{
|
use crate::backend::{
|
||||||
audio::AudioBackend, navigator::NavigatorBackend, render::Letterbox, render::RenderBackend,
|
audio::AudioBackend, navigator::NavigatorBackend, render::Letterbox, render::RenderBackend,
|
||||||
};
|
};
|
||||||
|
@ -130,6 +130,9 @@ pub struct Player {
|
||||||
mouse_pos: (Twips, Twips),
|
mouse_pos: (Twips, Twips),
|
||||||
is_mouse_down: bool,
|
is_mouse_down: bool,
|
||||||
|
|
||||||
|
/// The current mouse cursor icon.
|
||||||
|
mouse_cursor: MouseCursor,
|
||||||
|
|
||||||
/// Self-reference to ourselves.
|
/// Self-reference to ourselves.
|
||||||
///
|
///
|
||||||
/// This is a weak reference that is upgraded and handed out in various
|
/// This is a weak reference that is upgraded and handed out in various
|
||||||
|
@ -224,6 +227,7 @@ impl Player {
|
||||||
|
|
||||||
mouse_pos: (Twips::new(0), Twips::new(0)),
|
mouse_pos: (Twips::new(0), Twips::new(0)),
|
||||||
is_mouse_down: false,
|
is_mouse_down: false,
|
||||||
|
mouse_cursor: MouseCursor::Arrow,
|
||||||
|
|
||||||
renderer,
|
renderer,
|
||||||
audio,
|
audio,
|
||||||
|
@ -485,7 +489,8 @@ impl Player {
|
||||||
}
|
}
|
||||||
let mouse_pos = self.mouse_pos;
|
let mouse_pos = self.mouse_pos;
|
||||||
|
|
||||||
self.mutate_with_update_context(|avm, context| {
|
let mut new_cursor = self.mouse_cursor;
|
||||||
|
let hover_changed = self.mutate_with_update_context(|avm, context| {
|
||||||
// Check hovered object.
|
// Check hovered object.
|
||||||
let mut new_hovered = None;
|
let mut new_hovered = None;
|
||||||
for (_depth, level) in context.levels.iter().rev() {
|
for (_depth, level) in context.levels.iter().rev() {
|
||||||
|
@ -507,9 +512,11 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RollOver on new node.
|
// RollOver on new node.
|
||||||
|
new_cursor = MouseCursor::Arrow;
|
||||||
if let Some(node) = new_hovered {
|
if let Some(node) = new_hovered {
|
||||||
if let Some(mut button) = node.as_button() {
|
if let Some(mut button) = node.as_button() {
|
||||||
button.handle_button_event(context, ButtonEvent::RollOver);
|
button.handle_button_event(context, ButtonEvent::RollOver);
|
||||||
|
new_cursor = MouseCursor::Hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +527,15 @@ impl Player {
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
// Update mouse cursor if it has changed.
|
||||||
|
if new_cursor != self.mouse_cursor {
|
||||||
|
self.mouse_cursor = new_cursor;
|
||||||
|
self.input.set_mouse_cursor(new_cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
hover_changed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Preload the first movie in the player.
|
/// Preload the first movie in the player.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use glium::Display;
|
use glium::Display;
|
||||||
use ruffle_core::backend::input::InputBackend;
|
use ruffle_core::backend::input::{InputBackend, MouseCursor};
|
||||||
use ruffle_core::events::{KeyCode, PlayerEvent};
|
use ruffle_core::events::{KeyCode, PlayerEvent};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use winit::event::{ElementState, VirtualKeyCode, WindowEvent};
|
use winit::event::{ElementState, VirtualKeyCode, WindowEvent};
|
||||||
|
@ -178,6 +178,17 @@ impl InputBackend for WinitInputBackend {
|
||||||
self.display.gl_window().window().set_cursor_visible(true);
|
self.display.gl_window().window().set_cursor_visible(true);
|
||||||
self.cursor_visible = true;
|
self.cursor_visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
|
||||||
|
use winit::window::CursorIcon;
|
||||||
|
let icon = match cursor {
|
||||||
|
MouseCursor::Arrow => CursorIcon::Arrow,
|
||||||
|
MouseCursor::Hand => CursorIcon::Hand,
|
||||||
|
MouseCursor::IBeam => CursorIcon::Text,
|
||||||
|
MouseCursor::Grab => CursorIcon::Grab,
|
||||||
|
};
|
||||||
|
self.display.gl_window().window().set_cursor_icon(icon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a winit `VirtualKeyCode` into a Ruffle `KeyCode`.
|
/// Converts a winit `VirtualKeyCode` into a Ruffle `KeyCode`.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::utils::JsResult;
|
use crate::utils::JsResult;
|
||||||
use ruffle_core::backend::input::InputBackend;
|
use ruffle_core::backend::input::{InputBackend, MouseCursor};
|
||||||
use ruffle_core::events::KeyCode;
|
use ruffle_core::events::KeyCode;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use web_sys::HtmlCanvasElement;
|
use web_sys::HtmlCanvasElement;
|
||||||
|
@ -10,6 +10,7 @@ pub struct WebInputBackend {
|
||||||
keys_down: HashSet<String>,
|
keys_down: HashSet<String>,
|
||||||
canvas: HtmlCanvasElement,
|
canvas: HtmlCanvasElement,
|
||||||
cursor_visible: bool,
|
cursor_visible: bool,
|
||||||
|
cursor: MouseCursor,
|
||||||
last_key: KeyCode,
|
last_key: KeyCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ impl WebInputBackend {
|
||||||
keys_down: HashSet::new(),
|
keys_down: HashSet::new(),
|
||||||
canvas: canvas.clone(),
|
canvas: canvas.clone(),
|
||||||
cursor_visible: true,
|
cursor_visible: true,
|
||||||
|
cursor: MouseCursor::Arrow,
|
||||||
last_key: KeyCode::Unknown,
|
last_key: KeyCode::Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +35,23 @@ impl WebInputBackend {
|
||||||
pub fn keyup(&mut self, code: String) {
|
pub fn keyup(&mut self, code: String) {
|
||||||
self.keys_down.remove(&code);
|
self.keys_down.remove(&code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_mouse_cursor(&self) {
|
||||||
|
let cursor = if self.cursor_visible {
|
||||||
|
"none"
|
||||||
|
} else {
|
||||||
|
match self.cursor {
|
||||||
|
MouseCursor::Arrow => "auto",
|
||||||
|
MouseCursor::Hand => "pointer",
|
||||||
|
MouseCursor::IBeam => "text",
|
||||||
|
MouseCursor::Grab => "grab",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.canvas
|
||||||
|
.style()
|
||||||
|
.set_property("cursor", cursor)
|
||||||
|
.warn_on_error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputBackend for WebInputBackend {
|
impl InputBackend for WebInputBackend {
|
||||||
|
@ -151,19 +170,18 @@ impl InputBackend for WebInputBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide_mouse(&mut self) {
|
fn hide_mouse(&mut self) {
|
||||||
self.canvas
|
|
||||||
.style()
|
|
||||||
.set_property("cursor", "none")
|
|
||||||
.warn_on_error();
|
|
||||||
self.cursor_visible = false;
|
self.cursor_visible = false;
|
||||||
|
self.update_mouse_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_mouse(&mut self) {
|
fn show_mouse(&mut self) {
|
||||||
self.canvas
|
|
||||||
.style()
|
|
||||||
.set_property("cursor", "auto")
|
|
||||||
.warn_on_error();
|
|
||||||
self.cursor_visible = true;
|
self.cursor_visible = true;
|
||||||
|
self.update_mouse_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
|
||||||
|
self.cursor = cursor;
|
||||||
|
self.update_mouse_cursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue