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

Views on top of inputs don't fire on_clicks #295

Closed
dominikwilkowski opened this issue Jan 27, 2024 · 11 comments · Fixed by #379
Closed

Views on top of inputs don't fire on_clicks #295

dominikwilkowski opened this issue Jan 27, 2024 · 11 comments · Fixed by #379

Comments

@dominikwilkowski
Copy link
Contributor

When I have a view that is positioned absolute over an input field the on_clicks on that view won't fire.
Consider this code:

use floem::{
    reactive::create_rw_signal,
    style::Position,
    view::View,
    views::{container, label, stack, Decorators},
    widgets::text_input,
};

fn app_view() -> impl View {
    let value = create_rw_signal(String::from(""));
    stack((
        container(text_input(value)),
        label(move || "Label on top")
            .style(|s| {
                s.position(Position::Absolute)
                    .inset_top(8.5)
                    .inset_left(7)
                    .background(floem::peniko::Color::rgba8(255, 0, 0, 150))
            })
            .on_click_cont(|_| {
                println!("Click continue");
            })
            .on_click_stop(|_| {
                println!("Click stop");
            }),
    ))
    .style(|s| {
        s.position(Position::Relative)
            .margin(10)
            .height(30)
            .items_center()
            .justify_center()
    })
}

fn main() {
    floem::launch(app_view);
}

This will render something like this:
image

A label with a red background is positioned on top of an input field.
this is what happens when you try to click on the label:
input

Note there is no print output in stdout in the terminal below. Neither for on_click_cont nor for on_click_stop.

@jrmoulton
Copy link
Collaborator

Found what is happening

This is something specific to the click listener. Click is registered and marked as handled after both pointer down and pointer up. But before the pointer up is handled the input gets the pointer down event and requests to be active which means that it will receive prioritized events so the label never gets the pointer up.

If you use on_event_stop pointer down with the on_click then both fire because the label marks the event as handled after the pointer down and the input doesn't see the event.

I'm not sure this is really a bug so much as a specific weird case.

@habics
Copy link
Contributor

habics commented Mar 8, 2024

Run into the same issue using a dropdown widget:

Untitled

  1. Can't select "Two" from the list.
  2. When selecting "Four" from the list, the button underneath the list registers a click.

@jrmoulton
Copy link
Collaborator

@habics the issue with the dropdown is fixed in #376

@habics
Copy link
Contributor

habics commented Mar 15, 2024

@jrmoulton

Still the same issue unfortunately, here is the example that shows it:

use floem::reactive::{create_rw_signal, create_signal};
use strum::IntoEnumIterator;

use floem::view::View;
use floem::views::{h_stack, label, v_stack, Decorators};
use floem::widgets::dropdown::dropdown;
use floem::widgets::{button, checkbox};

fn main() {
    floem::launch(app_view);
}

fn app_view() -> impl View {
    let (counter, set_counter) = create_signal(0);
    let input_name = create_rw_signal("input".to_string());

    v_stack((
        dropdown_view(),
        checkbox_view(),
        input_text(input_name),
        label(move || format!("Value: {}", counter.get())),
        h_stack((
            button(|| "Increment").on_click_stop(move |_| {
                set_counter.update(|value| *value += 1);
            }),
            button(|| "Decrement").on_click_stop(move |_| {
                set_counter.update(|value| *value -= 1);
            }),
        )),
    ))
    .style(|s| s.padding(20.0))
    .style(|s| s.items_center())
    .style(|s| s.width_full())
    .style(|s| s.height_full())
}

pub fn input_text(buffer: floem::reactive::RwSignal<String>) -> impl View {
    floem::widgets::text_input(buffer)
}

#[derive(strum::EnumIter, Debug, PartialEq, Clone, Copy)]
enum Values {
    One,
    Two,
    Three,
    Four,
    Five,
}
impl std::fmt::Display for Values {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("{:?}", self))
    }
}

pub fn dropdown_view() -> impl View {
    let show_dropdown = create_rw_signal(false);

    dropdown(
        move || Values::One,
        move |item| label(move || item).any(),
        Values::iter(),
        |item| label(move || item).any(),
    )
    .show_list(move || show_dropdown.get())
    .on_accept(move |_val| show_dropdown.set(false))
}

pub fn checkbox_view() -> impl View {
    let (is_checked, set_is_checked) = create_signal(true);
    checkbox(move || is_checked.get())
        .on_update(move |checked| {
            set_is_checked.set(checked);
        })
        .style(|s| s.margin(5.0))
}
[dependencies]
floem = { git = "https://github.com/lapce/floem.git", rev = "77a3bae" }
strum = { version = "0.26", features = ["derive"] }

@jrmoulton
Copy link
Collaborator

@habics I tested this specifically in #379 and this has been fixed

@dzhou121
Copy link
Contributor

@jrmoulton Now looking at this issue again, I feel like #379 might not be the right solution for it. on_click intercepts the PointerDown event bubbling by default actually caused an issue with dragging.

For @dominikwilkowski, it can be fixed by adding .on_event_stop(EventListener::PointerDown, |_| {}) on the label. The reason is that without stopping PointerDown bubbling from the label to the text_input, the text_input will make itself active and the next pointer events will only be sent to the text_input.

For @habics It's the same issue and it can be fixed by adding on_event_stop to the list in the dropdown widget.

@dominikwilkowski
Copy link
Contributor Author

Ok I checked this out and indeed this code works and fires the events:

use floem::{
    event::EventListener,
    reactive::create_rw_signal,
    style::Position,
    view::View,
    views::{container, label, stack, Decorators},
    widgets::text_input,
};

fn app_view() -> impl View {
    let value = create_rw_signal(String::from(""));
    stack((
        container(text_input(value)),
        label(move || "Label on top")
            .style(|s| {
                s.position(Position::Absolute)
                    .inset_top(8.5)
                    .inset_left(7)
                    .background(floem::peniko::Color::rgba8(255, 0, 0, 150))
            })
            .on_click_cont(|_| {
                println!("Click continue");
            })
            .on_click_stop(|_| {
                println!("Click stop");
            })
            .on_event_stop(EventListener::PointerDown, |_| {}),
    ))
    .style(|s| {
        s.position(Position::Relative)
            .margin(10)
            .height(30)
            .items_center()
            .justify_center()
    })
}

fn main() {
    floem::launch(app_view);
}

I don't see how that makes sense though. Why am I adding an on_event_stop event onto the label to make the other events work? That's neither obvious nor intuitive and I can't see any docs about this. Still feels like a bug or something we should fix @dzhou121

@jrmoulton
Copy link
Collaborator

I also feel that simply reverting isn't a sufficient fix.

@jrmoulton
Copy link
Collaborator

Maybe the simplest fix would be to have on-click require eventpropagation specifically for the pointer down.

@dzhou121
Copy link
Contributor

If you put on_click on top of another on_click, it works as intended that only the top on_click will fire.

The actual issue here is the text_input makes itself active when receiving PointerDown. So a fix would be only making it active after it starts to drag.

@panekj panekj reopened this Apr 29, 2024
@jrmoulton
Copy link
Collaborator

All of these issues should be fixed more robustly in #648

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants