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

Awakened event doesn't always work #462

Closed
yokljo opened this issue Apr 14, 2018 · 5 comments
Closed

Awakened event doesn't always work #462

yokljo opened this issue Apr 14, 2018 · 5 comments

Comments

@yokljo
Copy link

yokljo commented Apr 14, 2018

See the comment at the top of this code block:

//! This demonstrates a situation where the the Awakened event doesn't make it from the proxy to the
//! event loop (at least with the X11 backend). If you remove the `run_forever` call, the Awakened
//! event starts to work again. Maybe waiting for events invalidates the Awakened event.
//! Click the window that appears to call the proxy wakeup() method.

extern crate glutin;

fn main() {
    let window_builder = glutin::WindowBuilder::new()
		.with_title("A window")
		.with_dimensions(800, 600);
	
	let mut events_loop = glutin::EventsLoop::new();
	
	let context_builder = glutin::ContextBuilder::new();
	let _gl_window = glutin::GlWindow::new(window_builder, context_builder, &events_loop).unwrap();
	
	let events_proxy = events_loop.create_proxy();
	
	loop {
		let mut events = vec![];
		
		// Wait for events.
		events_loop.run_forever(|event| {
			println!("event: {:?}", event);
			events.push(event);
			glutin::ControlFlow::Break
		});
		
		// Just poll events without waiting.
		events_loop.poll_events(|event| {
			println!("event: {:?}", event);
			events.push(event);
		});
		
		for event in &events {
			match *event {
				glutin::Event::WindowEvent{event: glutin::WindowEvent::MouseInput{state, ..}, ..} => {
					match state {
						glutin::ElementState::Pressed => {
							println!("wakeup()");
							events_proxy.wakeup().unwrap();
						}
						_ => {}
					}
				}
				_ => {}
			}
		}
	}
}

When it works, it should print wakeup() then event: Awakened to the console when the window is clicked. When it does not, it will only print wakeup().

@b-r-u
Copy link
Contributor

b-r-u commented Apr 27, 2018

I could reproduce this issue and tried to look at older commits (up until the introduction of the EventsLoop::wakeup method), but could not find any with the expected behavior.

Here is the code without the glutin dependency:

extern crate winit;

fn main() {
    let mut events_loop = winit::EventsLoop::new();
    let events_proxy = events_loop.create_proxy();

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

    'outer: loop {
        let mut events = vec![];

        // Wait for events.
        events_loop.run_forever(|event| {
            println!("event: {:?}", event);
            events.push(event);
            winit::ControlFlow::Break
        });

        // Just poll events without waiting.
        events_loop.poll_events(|event| {
            println!("event: {:?}", event);
            events.push(event);
        });

        for event in &events {
            match *event {
                winit::Event::WindowEvent {
                    event: winit::WindowEvent::MouseInput {
                        state: winit::ElementState::Pressed, ..
                    }, ..
                } => {
                    println!("wakeup()");
                    events_proxy.wakeup().unwrap();
                },
                winit::Event::WindowEvent {
                    event: winit::WindowEvent::CloseRequested,
                    ..
                } => break 'outer,
                _ => {},
            }
        }
    }
}

@francesca64
Copy link
Member

What's expected here? I must confess that I don't really understand what EventsLoopProxy is used for, which precludes me being able to fix anything with it.

@b-r-u
Copy link
Contributor

b-r-u commented Apr 27, 2018

It is expected that each click pushes an Awakened event to the queue of unhandled events, but with run_forever (in this setup) the event gets lost somehow.
An EventsLoopProxy can be send to another thread to inject Awakened events to the event loop. This seems to be the one way to react to asynchronous events from outside of winit.

There is a historical issue with some background information: #175

And there is also an example:
https://github.com/tomaka/winit/blob/master/examples/proxy.rs

b-r-u added a commit to b-r-u/winit that referenced this issue Apr 28, 2018
Do not reset the pending_wakeup boolean at the start of run_forever so
that each call to EventsLoopProxy::wakeup results in an Awakened event.

Fixes rust-windowing#462
@francesca64
Copy link
Member

@b-r-u thanks! I think I understand now, particularly from #187 (comment).

So, it enables this pattern, right?

do stuff on other thread (send awakened when wants to render)
loop
  run forever until awakened
  render

@b-r-u
Copy link
Contributor

b-r-u commented Apr 28, 2018

@francesca64 Yes, exactly!

francesca64 pushed a commit that referenced this issue Apr 28, 2018
* x11: Always receive Awakened event in run_forever

Do not reset the pending_wakeup boolean at the start of run_forever so
that each call to EventsLoopProxy::wakeup results in an Awakened event.

Fixes #462

* Update CHANGELOG.md
tmfink pushed a commit to tmfink/winit that referenced this issue Jan 5, 2022
Update lexical-core for nightly changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants