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

winit::event::Event extensions and time enhancements. #1055

Open
cheako opened this issue Jul 21, 2019 · 12 comments
Open

winit::event::Event extensions and time enhancements. #1055

cheako opened this issue Jul 21, 2019 · 12 comments
Labels
C - needs discussion Direction must be ironed out S - api Design and usability S - meta Project governance

Comments

@cheako
Copy link

cheako commented Jul 21, 2019

#459 (comment)

winit::event::Event would logically have:

  1. Something to emit when polling: Update
  2. Something to emit when a timer expires and obviously this needs to contain a handle to the timer that's expiring: Timer(T)

Consider redoing winit::event_loop::ControlFlow as a trait instance that has callbacks for fn set_timer(&mut self, T, Instant) -> RunningTimerAPI;, fn set_sleeping(&mut self);, fn set_polling(&mut self);, and fn set_exiting(self);.
#1018

@cheako
Copy link
Author

cheako commented Jul 21, 2019

...Also a fn create_tick(&mut self, T, Duration) -> Rc<TickAPI>;, you know your average JavaScript timer. Emits an event every Duration until told to stop.... also it would be nice to provide the TickAPI when emitting winit::event::Event::Tick(Rc<TickAPI>, T).

@cheako
Copy link
Author

cheako commented Jul 21, 2019

Ohh, I forgot. winit::event::Event::Update(Duration) Since the last update, an inverse Tick. It should be simple to measure this oneself, but providing it would be nice.

Sarcasticly, of course Real Time applications are going to need an estimate as to how long until the next Update, so if you could provide that as well, that would be great. The app will provide how long you can take in calculating the estimated next Update time, obviously.

@goddessfreya goddessfreya added C - needs discussion Direction must be ironed out S - api Design and usability S - meta Project governance labels Jul 21, 2019
@goddessfreya
Copy link
Contributor

#459 (comment)

winit::event::Event would logically have:

1. Something to emit when polling: Update

2. Something to emit when a timer expires and obviously this needs to contain a handle to the timer that's expiring: Timer(T)

Are these two cases not covered by https://docs.rs/winit/0.20.0-alpha2/winit/event/enum.Event.html#variant.NewEvents ?

I'm basically at loss to what you want.

@cheako
Copy link
Author

cheako commented Jul 21, 2019

I was asked to open a new issue for this so you can ignore the implied want for anything.

Ohhhhh "NewEvents"... but um don't call them that, what would you do the next time you go to add events. I mean sure there's still "NewerEvents" but you'll just have to trust me you'll soon run out of names with that scheme.

@cheako
Copy link
Author

cheako commented Jul 21, 2019

I thought NewEvents was the event sent to indicate that there is a collection of events that are in the pipeline to be followed up with an EventsCleared. I was going to use EventsCleared as my Update event because that's typically what you want, get all your input events and then calculate an image then present it. Sleeping till there are new events is kinda the opposite of what app developers are after with ControlFlow::Poll.

@cheako
Copy link
Author

cheako commented Jul 21, 2019

The problem here, if you'r sure that you want to go with NewEvents, is the documentation for Poll:

When the current loop iteration finishes, immediately begin a new iteration regardless of whether or not new events are available to process.

See the indication that it'll trigger when there are NOT new events. This stems from a wider issue #1054, the documentation for ControlFlow::Poll must indicate what event it will cause to be emitted.

Also might I request that NewEvents indicate approximately how many events will be being emitted, this could assist in things like allocating vectors.

@Osspial
Copy link
Contributor

Osspial commented Jul 23, 2019

I'm not entirely sure what you're suggesting here. This sounds like it's mostly a documentation issue, but you're also suggesting major changes to the ControlFlow API that will substantially increase our internal and external complexity, when you're already complaining about our API being too complex!

About timers - the reason we designed ControlFlow::WaitUntil as we did is because it's a small, simple building block upon which more complex timer APIs, including the one you've described here and in #459 (comment), can be built.

@dhardy
Copy link
Contributor

dhardy commented Oct 25, 2019

Related question: when setting control_flow = ControlFlow::WaitUntil(instant), is there a guarantee that an event will be received with Event::NewEvents(StartCause::ResumeTimeReached { requested_resume: instant, .. })?

@Osspial
Copy link
Contributor

Osspial commented Oct 26, 2019

@dhardy What exactly do you mean by that? If you're asking whether or a WindowEvent or DeviceEvent is guaranteed to be delivered after NewEvents, the answer is no. If you're asking whether or not you're guaranteed to receive NewEvents(ResumeTimeReached{..}), the answer is also no; if the OS dispatched an event before the specified resume time was reached, you'll receive NewEvents(WaitCancelled).

@dhardy
Copy link
Contributor

dhardy commented Oct 26, 2019

Ah, so I can't set up a repeating timer which is incremented only when the corresponding NewEvents is received. Thanks.

@Osspial
Copy link
Contributor

Osspial commented Oct 26, 2019

@dhardy Wait, I didn't entirely understood what you originally meant there. You'll receive a NewEvents(ResumeTimeReached{..}) eventually as long as you don't modify control_flow, but it may not be the first NewEvents event you receive. Winit's control_flow is sticky, so if you leave it alone after processing NewEvents(WaitCancelled) it should go back to waiting for the original time you asked, and notify you when the time has been reached. Sorry about the confusion!

EDIT: that'll always happen even if the requested time passes during the event loop iteration that's handling NewEvents(WaitCancelled). You can verify that that's true with the following code, which asks Winit to wait until one second before the current time - that should dispatch ResumeTimeReached continuously, since the requested time will always have been reached by the time the event loop is checking to see if it should start another iteration or go to sleep.

use instant::Instant;
use std::time::Duration;
use winit::{
    event::{Event, StartCause, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};

fn main() {
    let event_loop = EventLoop::new();

    let _window = WindowBuilder::new()
        .with_title("A fantastic window!")
        .build(&event_loop)
        .unwrap();

    let timer_length = Duration::new(1, 0);

    event_loop.run(move |event, _, control_flow| {
        println!("{:?}", event);

        match event {
            Event::NewEvents(StartCause::Init) => {
                *control_flow = ControlFlow::WaitUntil(Instant::now() - timer_length)
            }
            Event::NewEvents(StartCause::ResumeTimeReached { .. }) => {
                *control_flow = ControlFlow::WaitUntil(Instant::now() - timer_length);
                println!("\nTimer\n");
            }
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => *control_flow = ControlFlow::Exit,
            _ => (),
        }
    });
}

@dhardy
Copy link
Contributor

dhardy commented Oct 28, 2019

Aha, thanks @Osspial! (I didn't test, assuming it may be platform specific.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C - needs discussion Direction must be ironed out S - api Design and usability S - meta Project governance
Development

No branches or pull requests

4 participants