Skip to content

Commit

Permalink
Fix tooltip behaviour (#414)
Browse files Browse the repository at this point in the history
* Fix tooltip behaviour

* Fix formatting issues

* Fix tooltip shown while dragging

* Fix rounded corner rendering (#410)

still won't work if border_radius < border_width / 2,
since the radius is limited by the stroke width

* Simplify boolean expression

* Remove tooltip on pointer wheel

* Replace add/remove tooltip functions to the possibility to listen keyboard without the view being focused

* Add keyboard listenable example

* Add keyboard listenable documentation

* Revert tooltip field

---------

Co-authored-by: Long0x0 <[email protected]>
Co-authored-by: Ferran Alcaina <[email protected]>
  • Loading branch information
3 people authored May 8, 2024
1 parent d87a6a1 commit b1b6bf4
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 3 deletions.
10 changes: 10 additions & 0 deletions examples/keyboard_listener/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "keyboard_listener"
edition = "2021"
license.workspace = true
version.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
floem = { path = "../.." }
31 changes: 31 additions & 0 deletions examples/keyboard_listener/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use floem::event::{Event, EventListener};
use floem::reactive::create_rw_signal;
use floem::views::label;
use floem::{
view::View,
views::{v_stack, Decorators},
widgets::text_input,
EventPropagation,
};

fn app_view() -> impl View {
let text = create_rw_signal("".to_string());
let keyboard_signal = create_rw_signal("".to_string());
v_stack((
text_input(text)
.placeholder("Write here")
.keyboard_navigatable(),
label(move || format!("Key Pressed: {}", keyboard_signal.get()))
.keyboard_listenable()
.on_event(EventListener::KeyDown, move |e| {
if let Event::KeyDown(e) = e {
keyboard_signal.set(e.key.logical_key.to_text().unwrap().to_string());
}
EventPropagation::Continue
}),
))
}

fn main() {
floem::launch(app_view);
}
2 changes: 2 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub struct AppState {
pub(crate) request_paint: bool,
pub(crate) disabled: HashSet<Id>,
pub(crate) keyboard_navigable: HashSet<Id>,
pub(crate) keyboard_listenable: HashSet<Id>,
pub(crate) draggable: HashSet<Id>,
pub(crate) dragging: Option<DragState>,
pub(crate) drag_start: Option<(Id, Point)>,
Expand Down Expand Up @@ -145,6 +146,7 @@ impl AppState {
request_compute_layout: false,
disabled: HashSet::new(),
keyboard_navigable: HashSet::new(),
keyboard_listenable: HashSet::new(),
draggable: HashSet::new(),
dragging: None,
drag_start: None,
Expand Down
4 changes: 4 additions & 0 deletions src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ impl Id {
self.add_update_message(UpdateMessage::KeyboardNavigable { id: *self });
}

pub fn keyboard_listenable(&self) {
self.add_update_message(UpdateMessage::KeyboardListenable { id: *self });
}

pub fn draggable(&self) {
self.add_update_message(UpdateMessage::Draggable { id: *self });
}
Expand Down
3 changes: 3 additions & 0 deletions src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ pub(crate) enum UpdateMessage {
KeyboardNavigable {
id: Id,
},
KeyboardListenable {
id: Id,
},
Draggable {
id: Id,
},
Expand Down
7 changes: 7 additions & 0 deletions src/views/decorator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ pub trait Decorators: View + Sized {
self
}

/// Allows the elements to receive keyboard events without being navigable and without being focused.
fn keyboard_listenable(self) -> Self {
let id = self.id();
id.keyboard_listenable();
self
}

fn draggable(self) -> Self {
let id = self.id();
id.draggable();
Expand Down
13 changes: 10 additions & 3 deletions src/views/tooltip.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use kurbo::Point;
use std::{rc::Rc, time::Duration};

use crate::views::Decorators;
use crate::{
action::{add_overlay, exec_after, remove_overlay, TimerToken},
context::{EventCx, UpdateCx},
Expand Down Expand Up @@ -44,6 +45,7 @@ pub fn tooltip<V: View + 'static, T: Widget + 'static>(
style: Default::default(),
window_origin: None,
}
.keyboard_listenable()
}

impl View for Tooltip {
Expand Down Expand Up @@ -110,7 +112,7 @@ impl Widget for Tooltip {
) -> EventPropagation {
match &event {
Event::PointerMove(e) => {
if self.overlay.is_none() {
if self.overlay.is_none() && cx.app_state.dragging.is_none() {
let id = self.id();
let token =
exec_after(Duration::from_secs_f64(self.style.delay()), move |token| {
Expand All @@ -119,7 +121,12 @@ impl Widget for Tooltip {
self.hover = Some((e.pos, token));
}
}
Event::PointerLeave => {
Event::PointerLeave
| Event::PointerDown(_)
| Event::PointerUp(_)
| Event::PointerWheel(_)
| Event::KeyUp(_)
| Event::KeyDown(_) => {
self.hover = None;
if let Some(id) = self.overlay {
remove_overlay(id);
Expand All @@ -141,7 +148,7 @@ impl Widget for Tooltip {
impl Drop for Tooltip {
fn drop(&mut self) {
if let Some(id) = self.overlay {
remove_overlay(id)
remove_overlay(id);
}
}
}
18 changes: 18 additions & 0 deletions src/window_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,21 @@ impl WindowHandle {
cx.app_state.focus
};

if matches!(event, Event::KeyUp(_)) || matches!(event, Event::KeyDown(_)) {
for id in cx.app_state.keyboard_listenable.clone().iter() {
let id_path = ID_PATHS.with(|paths| paths.borrow().get(id).cloned());
if let Some(id_path) = id_path {
cx.unconditional_view_event(
&mut self.view,
Some(id_path.dispatch()),
event.clone(),
);
} else {
cx.app_state.focus = None;
}
}
}

if event.needs_focus() {
let mut processed = false;

Expand Down Expand Up @@ -835,6 +850,9 @@ impl WindowHandle {
UpdateMessage::KeyboardNavigable { id } => {
cx.app_state.keyboard_navigable.insert(id);
}
UpdateMessage::KeyboardListenable { id } => {
cx.app_state.keyboard_listenable.insert(id);
}
UpdateMessage::Draggable { id } => {
cx.app_state.draggable.insert(id);
}
Expand Down

0 comments on commit b1b6bf4

Please sign in to comment.