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

Event loop run_forever #757

Closed
mickvangelderen opened this issue Jan 12, 2019 · 2 comments
Closed

Event loop run_forever #757

mickvangelderen opened this issue Jan 12, 2019 · 2 comments
Labels
B - bug Dang, that shouldn't have happened C - in progress Implementation is proceeding smoothly DS - x11

Comments

@mickvangelderen
Copy link

I wan't to know when every event occurs so I'm moving my window into another thread, using run_forever on the event loop with a callback that passes every event along with a std::time::Instant to the window thread.

When I call gl_window.make_current the thread blocks until I move my mouse or after I fire a couple of keyboard input events.

I'm on linux and the backend seems to be X.

I have no idea how event loops work internally. I don't know what it means to "wake up the event loop". I know this has been mentioned before like in #239 and #420.

The glutin documentation says the following:

Note that the EventsLoop cannot be shared accross threads (due to platform-dependant logic forbiding it), as such it is neither Send nor Sync. If you need cross-thread access, the Window created from this EventsLoop can be sent to an other thread, and the EventsLoopProxy allows you to wakeup an EventsLoop from an other thread.

The code

use glutin;
use glutin::GlContext;
use std::sync::mpsc;
use std::thread;
use std::time;

mod gl;

fn main() {
    let start = time::Instant::now();

    let window_dims = glutin::dpi::LogicalSize::new(640.0, 480.0);
    let mut event_loop = glutin::EventsLoop::new();
    let gl_window = glutin::GlWindow::new(
        glutin::WindowBuilder::new()
            .with_title("Continuous event loop")
            .with_dimensions(window_dims),
        glutin::ContextBuilder::new()
            .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (4, 5)))
            .with_gl_profile(glutin::GlProfile::Core),
        &event_loop,
    )
    .unwrap();

    #[derive(Debug)]
    struct TimedEvent {
        instant: time::Instant,
        event: glutin::Event,
    };

    let (timed_event_tx, timed_event_rx) = mpsc::channel::<TimedEvent>();

    let _guard = thread::spawn(move || {
        let mut should_keep_running = true;

        println!("{:?}", start.elapsed());

        unsafe {
            gl_window.make_current().unwrap();
        }

        println!("{:?}", start.elapsed());

        let gl = gl::Gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);

        println!("{:?}", start.elapsed());

        while should_keep_running {
            // Process input.
            for timed_event in timed_event_rx.try_iter() {
                let TimedEvent { instant, event } = timed_event;
                println!("{:?} {:?}", instant.elapsed(), event);

                use glutin::Event;
                match event {
                    Event::DeviceEvent { event, .. } => {
                        use glutin::DeviceEvent;
                        match event {
                            DeviceEvent::Key(keyboard_input) => {

                                if let Some(virtual_keycode) = keyboard_input.virtual_keycode {
                                    use glutin::VirtualKeyCode;
                                    match virtual_keycode {
                                        VirtualKeyCode::Escape => {
                                            should_keep_running = false;
                                        }
                                        _ => {}
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                    _ => {}
                }
            }

            // Render.
            unsafe {
                gl.ClearColor(0.7, 0.8, 0.9, 1.0);
                gl.Clear(gl::COLOR_BUFFER_BIT);
            }

            // VSync.
            gl_window.swap_buffers().unwrap();
        }
    });

    event_loop.run_forever(|event| {
        match timed_event_tx.send(TimedEvent {
            instant: time::Instant::now(),
            event,
        }) {
            Ok(_) => glutin::ControlFlow::Continue,
            Err(_) => glutin::ControlFlow::Break,
        }
    })
}

The output (started moving my mouse after ~4 seconds):

45.166266ms
4.461137718s
4.462550974s
4.416836559s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: Resized(LogicalSize { width: 640.0, height: 480.0 }) }
4.41684652s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: Moved(LogicalPosition { x: 63.333333333333336, y: 36.666666666666664 }) }
4.416853051s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: Refresh }
4.416806095s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: CursorEntered { device_id: DeviceId(X(DeviceId(2))) } }
4.416798429s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: CursorMoved { device_id: DeviceId(X(DeviceId(2))), position: LogicalPosition { x: 360.6666666666667, y: 84.66666666666667 }, modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } }
4.416733053s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: Focused(true) }
4.416736955s WindowEvent { window_id: WindowId(X(WindowId(52428805))), event: CursorMoved { device_id: DeviceId(X(DeviceId(2))), position: LogicalPosition { x: 360.6666666666667, y: 84.66666666666667 }, modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } }
34.678495ms DeviceEvent { device_id: DeviceId(X(DeviceId(12))), event: Motion { axis: 0, value: 0.0 } }

Is there a way to make this work?

@rikusalminen
Copy link
Contributor

This is a bug caused by using XNextEvent which is not thread safe. See issue #779, the thread there has a (work in progress) workaround.

@mickvangelderen
Copy link
Author

mickvangelderen commented Jan 30, 2019

Alright, thanks for letting me know. I'll close this issue and follow #779.

@francesca64 francesca64 added B - bug Dang, that shouldn't have happened DS - x11 C - in progress Implementation is proceeding smoothly labels Jan 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened C - in progress Implementation is proceeding smoothly DS - x11
Development

No branches or pull requests

3 participants