Skip to content
This repository has been archived by the owner on Feb 15, 2024. It is now read-only.

[Help wanted] Events on iced_web? #3

Open
vicky5124 opened this issue Jun 18, 2020 · 8 comments
Open

[Help wanted] Events on iced_web? #3

vicky5124 opened this issue Jun 18, 2020 · 8 comments

Comments

@vicky5124
Copy link

I can't find any way with iced to catch mouse and keyboard events, is this possible, or will a different library be needed for me to do this?
If the later is the case, which one would be recommended that is able to interface with iced, and modify various fields with those events, while making the events not trigger when on an input box, in the case of keyboard events.

@vicky5124
Copy link
Author

wasm-bindgen with web-sys works for events, I'm also able to use lazy static with Mutex to share data between the event and iced.

Now the issue is, how do i make that event call the update method of the sandbox?
I've noticed that I'm able to start iced before the event, i think this may be key to make this work, but i can't think of any way or design to do so.

Here's the event code.

    let window = web_sys::window().unwrap();

    let closure = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| {
        // ...
    }) as Box<dyn FnMut(_)>);

    window.add_event_listener_with_callback(
        "mousedown",
        closure.as_ref().unchecked_ref()
    ).expect("what happened?");
    closure.forget();

@hecrj
Copy link
Member

hecrj commented Jun 18, 2020

You may be able to listen to mouse clicks by implementing your own event subscription (see iced-rs/iced#122).

Basically, you need to implement the Recipe trait by turning your logic into a Stream. You should be able to do this by creating an mpsc channel, moving the Sender inside the Closure, and returning the Receiver in Recipe::stream.

I think we should include subscriptions like this one in iced_web. If you end up succeeding, feel free to open a PR with the implementation!

@vicky5124
Copy link
Author

Using a cut down version of this example https://github.com/hecrj/iced/blob/master/examples/download_progress/src/download.rs
i've gotten stuck with the stream method of the Recipe trait

        fn stream(self: Box<Self>, _input: futures::stream::BoxStream<'static, I>)
            -> futures::stream::BoxStream<'static, Self::Output> {

            Box::pin(futures::stream::unfold(
                State::Ready(self.url),
                |_state| async move {
                    None
                },
            ))
        }

This looks to compile fine natively, but when the target is wasm32 it's unable to satisfy types because it expects a non-Send, but it's obtaining something that is Send
https://5124.16-b.it/ss/19:34:59_26-06-2020.png

Fixed: had to use iced_futures::BoxStream instead

@vicky5124
Copy link
Author

New issue, there's no subscription() method for the Sandbox trait, and i don't see any way to subscribe the sandbox to the Recipe stream.

@hecrj
Copy link
Member

hecrj commented Jun 26, 2020

This looks to compile fine natively, but when the target is wasm32 it's unable to satisfy types because it expects a non-Send, but it's obtaining something that is Send

This was fixed recently in iced-rs/iced#322. I recommend you to depend on master for the time being.

New issue, there's no subscription() method for the Sandbox trait, and i don't see any way to subscribe the sandbox to the Recipe stream.

Yes, Sandbox is meant to be an Application with no support for async actions. As the documentation says:

A sandboxed Application.

If you are a just getting started with the library, this trait offers a simpler interface than Application.

Unlike an Application, a Sandbox cannot run any asynchronous actions or be initialized with some external flags. However, both traits are very similar and upgrading from a Sandbox is very straightforward.

Therefore, it is recommended to always start by implementing this trait and upgrade only once necessary.

@vicky5124
Copy link
Author

https://pastebin.com/9NMLs5qd
This is how far i got today, i think I'm close, but I've been stuck with an issue for a while.
Every time i do an interaction with the iced interface, the whole site freezes until it times out;
this stops happening if line 171 returns None, which means that the issue is probably some kind of infinite loop between the updater and the subscriber.
https://5124.16-b.it/ss/22:34:55_26-06-2020.png this is the timeout error.
Maybe i shouldn't be using Message, but i ran out of time today to do this, if anyone thinks the issue is something else, tell me and ill attempt to fix it tomorrow.

iced = { git = "https://github.com/hecrj/iced", features = ["canvas", "debug", "image"] }
iced_futures = { git = "https://github.com/hecrj/iced"}
async-std = { version = "1.0", features = ["unstable"] }
wasm-bindgen = "0.2.63"
js-sys = "*"
lazy_static = "1.4.0"

[dependencies.web-sys]
version = "0.3.4"
# TODO: remove unused features
features = [
  'CanvasRenderingContext2d',
  'CssStyleDeclaration',
  'Document',
  'Element',
  'EventTarget',
  'HtmlCanvasElement',
  'HtmlElement',
  'MouseEvent',
  'Node',
  'Window',
]

@sum-elier
Copy link

This looks to compile fine natively, but when the target is wasm32 it's unable to satisfy types because it expects a non-Send, but it's obtaining something that is Send

This was fixed recently in iced-rs/iced#322. I recommend you to depend on master for the time being.

New issue, there's no subscription() method for the Sandbox trait, and i don't see any way to subscribe the sandbox to the Recipe stream.

Yes, Sandbox is meant to be an Application with no support for async actions. As the documentation says:

A sandboxed Application.
If you are a just getting started with the library, this trait offers a simpler interface than Application.
Unlike an Application, a Sandbox cannot run any asynchronous actions or be initialized with some external flags. However, both traits are very similar and upgrading from a Sandbox is very straightforward.
Therefore, it is recommended to always start by implementing this trait and upgrade only once necessary.

@hecrj Using master and still having the same problem, even though I can see the fix in the repo:

#[cfg(target_arch = "wasm32")]
pub type BoxStream<T> = futures::stream::LocalBoxStream<'static, T>;

cargo build --package download_progress --target wasm32-unknown-unknown yields the following error:

error[E0053]: method `stream` has an incompatible type for trait
  --> native\src\subscription\events.rs:18:5
   |
18 | /     fn stream(
19 | |         self: Box<Self>,
20 | |         event_stream: EventStream,
21 | |     ) -> BoxStream<Self::Output> {
22 | |         event_stream
23 | |     }
   | |_____^ expected trait `Stream<Item = event::Event>`, found trait `Stream<Item = event::Event> + std::marker::Send`
   |
   = note: expected fn pointer `fn(Box<_>, Pin<Box<(dyn Stream<Item = event::Event> + 'static)>>) -> Pin<_>`
              found fn pointer `fn(Box<_>, Pin<Box<(dyn Stream<Item = event::Event> + std::marker::Send + 'static)>>) -> Pin<_>`

error: aborting due to previous error

@jgrussell
Copy link

@hecrj

I am seeing the same behavior documented by @sum-elier when I attempt to build the pane_grid example.

cargo run --package "pane_grid" works exactly as expected.

cargo build --package "pane_grid" --target wasm32-unknown-unknown produces the same error @sum-elier is seeing when trying to build download_progress:

error[E0053]: method stream has an incompatible type for trait
--> native\src\subscription\events.rs:18:5
|
18 | / fn stream(
19 | | self: Box,
20 | | event_stream: EventStream,
21 | | ) -> BoxStreamSelf::Output {
22 | | event_stream
23 | | }
| |_____^ expected trait Stream<Item = event::Event>, found trait Stream<Item = event::Event> + std::marker::Send
|
= note: expected fn pointer fn(Box<_>, Pin<Box<(dyn Stream<Item = event::Event> + 'static)>>) -> Pin<_>
found fn pointer fn(Box<_>, Pin<Box<(dyn Stream<Item = event::Event> + std::marker::Send + 'static)>>) -> Pin<_>

error: aborting due to previous error

Note: Not that I think it would have any bearing; but, I do have to override the iced dependency in Cargo.toml as follows since my current laptop does not support Vulkan:
iced = { path = "../..", features = ["glow"] }.

Any insight, guidance, etc. would be appreciated.

Thank you for all of the work you are doing here. I am actually hoping to offer assistance once I become more familiar with both Rust and this framework.

@hecrj hecrj transferred this issue from iced-rs/iced Jan 31, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants