diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index fe59e22f3..309b06820 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -126,55 +126,59 @@ int AbstractXApplication::exec() { /* Show window */ XMapWindow(_display, _window); - while(!(_flags & Flag::Exit)) { - XEvent event; + while(mainLoopIteration()) {} - /* Closed window */ - if(XCheckTypedWindowEvent(_display, _window, ClientMessage, &event) && - Atom(event.xclient.data.l[0]) == _deleteWindow) { - return 0; - } + return 0; +} - while(XCheckWindowEvent(_display, _window, INPUT_MASK, &event)) { - switch(event.type) { - /* Window resizing */ - case ConfigureNotify: { - Vector2i size(event.xconfigure.width, event.xconfigure.height); - if(size != _windowSize) { - _windowSize = size; - ViewportEvent e{size}; - viewportEvent(e); - _flags |= Flag::Redraw; - } - } break; - - /* Key/mouse events */ - case KeyPress: - case KeyRelease: { - KeyEvent e(static_cast(XLookupKeysym(&event.xkey, 0)), static_cast(event.xkey.state), {event.xkey.x, event.xkey.y}); - event.type == KeyPress ? keyPressEvent(e) : keyReleaseEvent(e); - } break; - case ButtonPress: - case ButtonRelease: { - MouseEvent e(static_cast(event.xbutton.button), static_cast(event.xkey.state), {event.xbutton.x, event.xbutton.y}); - event.type == ButtonPress ? mousePressEvent(e) : mouseReleaseEvent(e); - } break; - - /* Mouse move events */ - case MotionNotify: { - MouseMoveEvent e(static_cast(event.xmotion.state), {event.xmotion.x, event.xmotion.y}); - mouseMoveEvent(e); - } break; - } - } +bool AbstractXApplication::mainLoopIteration() { + XEvent event; - if(_flags & Flag::Redraw) { - _flags &= ~Flag::Redraw; - drawEvent(); - } else Utility::System::sleep(5); + /* Closed window */ + if(XCheckTypedWindowEvent(_display, _window, ClientMessage, &event) && + Atom(event.xclient.data.l[0]) == _deleteWindow) { + return 0; } - return 0; + while(XCheckWindowEvent(_display, _window, INPUT_MASK, &event)) { + switch(event.type) { + /* Window resizing */ + case ConfigureNotify: { + Vector2i size(event.xconfigure.width, event.xconfigure.height); + if(size != _windowSize) { + _windowSize = size; + ViewportEvent e{size}; + viewportEvent(e); + _flags |= Flag::Redraw; + } + } break; + + /* Key/mouse events */ + case KeyPress: + case KeyRelease: { + KeyEvent e(static_cast(XLookupKeysym(&event.xkey, 0)), static_cast(event.xkey.state), {event.xkey.x, event.xkey.y}); + event.type == KeyPress ? keyPressEvent(e) : keyReleaseEvent(e); + } break; + case ButtonPress: + case ButtonRelease: { + MouseEvent e(static_cast(event.xbutton.button), static_cast(event.xkey.state), {event.xbutton.x, event.xbutton.y}); + event.type == ButtonPress ? mousePressEvent(e) : mouseReleaseEvent(e); + } break; + + /* Mouse move events */ + case MotionNotify: { + MouseMoveEvent e(static_cast(event.xmotion.state), {event.xmotion.x, event.xmotion.y}); + mouseMoveEvent(e); + } break; + } + } + + if(_flags & Flag::Redraw) { + _flags &= ~Flag::Redraw; + drawEvent(); + } else Utility::System::sleep(5); + + return !(_flags & Flag::Exit); } void AbstractXApplication::viewportEvent(ViewportEvent& event) { diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index b2a7df849..2c6e155e3 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -109,6 +109,18 @@ class AbstractXApplication { */ int exec(); + /** + * @brief Run one iteration of application main loop + * @return @cpp false @ce if @ref exit() was called and the application + * should exit, @cpp true @ce otherwise + * + * Called internally from @ref exec(). If you want to have better + * control over how the main loop behaves, you can call this function + * yourself from your own `main()` function instead of it being called + * automatically from @ref exec(). + */ + bool mainLoopIteration(); + /** @brief Exit application main loop */ void exit() { _flags |= Flag::Exit; }