Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hover Implementation #180

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
17 changes: 17 additions & 0 deletions examples/hover.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use dioxus::prelude::*;

fn main() {
dioxus_native::launch(app);
}

fn app() -> Element {
let mut hover_count = use_signal(|| 0);

rsx! {
div {
style: "padding: 20px; background: #eee; cursor: pointer;",
onmouseenter: move |_| hover_count += 1,
"Hover count: {hover_count}"
}
}
}
12 changes: 12 additions & 0 deletions packages/blitz-dom/src/events/hover.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::BaseDocument;

pub(crate) fn handle_hover(doc: &mut BaseDocument, _target: usize, x: f32, y: f32) {
if let Some(node) = doc.get_node_mut(_target) {
// Toggle hover state on the node
node.hover();

doc.set_focus_to(_target);

doc.set_hover_to(x, y);
}
}
6 changes: 5 additions & 1 deletion packages/blitz-dom/src/events/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod hover;
mod ime;
mod keyboard;
mod mouse;

use blitz_traits::{DomEvent, DomEventData};
pub(crate) use hover::handle_hover;
pub(crate) use ime::handle_ime_event;
pub(crate) use keyboard::handle_keypress;
pub(crate) use mouse::handle_click;
Expand All @@ -15,7 +17,9 @@ pub(crate) fn handle_event(doc: &mut BaseDocument, event: DomEvent) {
match event.data {
DomEventData::MouseDown(_) => {}
DomEventData::MouseUp(_) => {}
DomEventData::Hover => {}
DomEventData::Hover(event) => {
handle_hover(doc, target_node_id, event.x, event.y);
}
wheregmis marked this conversation as resolved.
Show resolved Hide resolved
DomEventData::Click(event) => {
handle_click(doc, target_node_id, event.x, event.y);
}
Expand Down
32 changes: 28 additions & 4 deletions packages/blitz-shell/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::convert_events::{
};
use crate::event::{create_waker, BlitzShellEvent};
use blitz_dom::BaseDocument;
use blitz_traits::{BlitzMouseButtonEvent, ColorScheme, Devtools, Viewport};
use blitz_traits::{BlitzHoverEvent, BlitzMouseButtonEvent, ColorScheme, Devtools, Viewport};
use blitz_traits::{Document, DocumentRenderer, DomEvent, DomEventData};
use winit::keyboard::PhysicalKey;

Expand Down Expand Up @@ -249,12 +249,36 @@ impl<Doc: Document<Doc = D>, Rend: DocumentRenderer<Doc = D>> View<Doc, Rend> {
let dom_x = x + viewport_scroll.x as f32 / self.viewport.zoom();
let dom_y = y + viewport_scroll.y as f32 / self.viewport.zoom();

// println!("Mouse move: ({}, {})", x, y);
// println!("Unscaled: ({}, {})",);
//println!("Mouse move: ({}, {})", x, y);
//println!("Unscaled: ({}, {})",);

self.mouse_pos = (x, y);
self.dom_mouse_pos = (dom_x, dom_y);
self.doc.as_mut().set_hover_to(dom_x, dom_y)

// Get previous and new hover nodes
let previous_hover_node = self.doc.as_ref().get_hover_node_id();
let hover_changed = self.doc.as_mut().set_hover_to(dom_x, dom_y);
let current_hover_node = self.doc.as_ref().get_hover_node_id();

if previous_hover_node != current_hover_node {
// ! No Idea how Handle mouseleave for previous node
wheregmis marked this conversation as resolved.
Show resolved Hide resolved
// if let Some(prev_node) = previous_hover_node {
// self.doc.handle_event(DomEvent {
// target: prev_node,
// data: DomEventData::Hover(BlitzHoverEvent { x: dom_x, y: dom_y }),
// });
// }

// Handle mouseenter for new node
if let Some(curr_node) = current_hover_node {
self.doc.handle_event(DomEvent {
target: curr_node,
data: DomEventData::Hover(BlitzHoverEvent { x: dom_x, y: dom_y }),
});
}
}

hover_changed
}

pub fn mouse_down(&mut self, _button: &str) {
Expand Down
10 changes: 8 additions & 2 deletions packages/blitz-traits/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub enum DomEventData {
Click(BlitzMouseButtonEvent),
KeyPress(BlitzKeyEvent),
Ime(BlitzImeEvent),
Hover,
Hover(BlitzHoverEvent),
}

impl DomEventData {
Expand All @@ -36,11 +36,17 @@ impl DomEventData {
DomEventData::Click { .. } => "click",
DomEventData::KeyPress { .. } => "keypress",
DomEventData::Ime { .. } => "input",
DomEventData::Hover => "mouseover",
DomEventData::Hover { .. } => "mouseover",
}
}
}

#[derive(Clone, Debug)]
pub struct BlitzHoverEvent {
pub x: f32,
pub y: f32,
}

#[derive(Debug, Clone, Copy)]
pub struct HitResult {
/// The node_id of the node identified as the hit target
Expand Down
4 changes: 2 additions & 2 deletions packages/blitz-traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pub mod navigation;

mod events;
pub use events::{
BlitzImeEvent, BlitzKeyEvent, BlitzMouseButtonEvent, DomEvent, DomEventData, EventListener,
HitResult, KeyState,
BlitzHoverEvent, BlitzImeEvent, BlitzKeyEvent, BlitzMouseButtonEvent, DomEvent, DomEventData,
EventListener, HitResult, KeyState,
};

mod document;
Expand Down
40 changes: 39 additions & 1 deletion packages/dioxus-native/src/dioxus_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,45 @@ impl Document for DioxusDocument {
}
// TODO: Implement IME and Hover events handling
DomEventData::Ime(_) => {}
DomEventData::Hover => {}
DomEventData::Hover { .. } => {
let hover_event_data = wrap_event_data(NativeClickData);
println!("HOVER EVENT");

for &DxNodeIds { node_id, dioxus_id } in chain.iter() {
if let Some(id) = dioxus_id {
// Dispatch both mouseenter and mouseover events
let events = ["mouseenter", "mouseover"];
for event_name in events {
let hover_event = Event::new(hover_event_data.clone(), true);
self.vdom
.runtime()
.handle_event(event_name, hover_event.clone(), id);
prevent_default |= !hover_event.default_action_enabled();
stop_propagation |= !hover_event.propagates();
}

// Also dispatch mouseleave when hover ends
if !prevent_default {
let default_event = DomEvent {
target: node_id,
data: renderer_event.data.clone(),
};
self.inner.as_mut().handle_event(default_event.clone());

// Explicit mouseleave event
self.vdom.runtime().handle_event(
"mouseleave",
Event::new(hover_event_data.clone(), true),
id,
);
}
}

if stop_propagation {
break;
}
}
}
}

if !prevent_default {
Expand Down