From 4d5a9ed45618593af3430bc0db072c705749e4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 7 Oct 2021 17:51:50 +0200 Subject: [PATCH] python: expose viewport and exit event. And also a possibility to make the window resizable on startup, otherwise the viewport event gets never triggered. --- doc/python/pages/changelog.rst | 5 +++ src/python/magnum/platform/application.h | 31 +++++++++++++++-- src/python/magnum/platform/glfw.cpp | 43 +++++++++++++++++++++--- src/python/magnum/platform/sdl2.cpp | 43 +++++++++++++++++++++--- 4 files changed, 111 insertions(+), 11 deletions(-) diff --git a/doc/python/pages/changelog.rst b/doc/python/pages/changelog.rst index b8357c7..168d6ff 100644 --- a/doc/python/pages/changelog.rst +++ b/doc/python/pages/changelog.rst @@ -75,6 +75,11 @@ Changelog - Fixed :ref:`platform.sdl2.Application.InputEvent.Modifier` and :ref:`platform.glfw.Application.InputEvent.Modifier` to behave properly as flags and not just as an enum +- Exposed :ref:`platform.sdl2.Application.viewport_event` and + :ref:`platform.glfw.Application.viewport_event` and a possibility + to make the window resizable on startup +- Exposed :ref:`platform.sdl2.Application.exit_event` and + :ref:`platform.glfw.Application.exit_event` `2020.06`_ ========== diff --git a/src/python/magnum/platform/application.h b/src/python/magnum/platform/application.h index d80d11b..792b7de 100644 --- a/src/python/magnum/platform/application.h +++ b/src/python/magnum/platform/application.h @@ -34,6 +34,12 @@ namespace magnum { namespace platform { template void application(py::class_& c) { py::class_ configuration{c, "Configuration", "Configuration"}; + + py::enum_ configurationWindowFlags{configuration, "WindowFlag", "WindowFlag"}; + configurationWindowFlags + .value("RESIZABLE", T::Configuration::WindowFlag::Resizable); + corrade::enumOperators(configurationWindowFlags); + configuration .def(py::init()) .def_property("title", &T::Configuration::title, @@ -43,7 +49,14 @@ template void application(py::class_::type(self.windowFlags())); + }, + [](typename T::Configuration& self, typename T::Configuration::WindowFlag flags) { + self.setWindowFlags(flags); + }, "Window flags"); /** @todo others */ py::class_ glConfiguration{c, "GLConfiguration", "OpenGL context configuration"}; @@ -67,8 +80,9 @@ template void application(py::class_ void application(py::class_ void exitEvent(py::class_& c) { + c + .def_property("accepted", &T::isAccepted, &T::setAccepted, "Accepted status of the event"); +} + +template void viewportEvent(py::class_& c) { + c + .def_property_readonly("window_size", &T::windowSize, "Window size") + .def_property_readonly("framebuffer_size", &T::framebufferSize, "Framebuffer size") + .def_property_readonly("dpi_scaling", &T::dpiScaling, "DPI scaling"); +} template void inputEvent(py::class_& c) { py::enum_ modifiers{c, "Modifier", "Modifier"}; diff --git a/src/python/magnum/platform/glfw.cpp b/src/python/magnum/platform/glfw.cpp index 3f6044d..4a5324b 100644 --- a/src/python/magnum/platform/glfw.cpp +++ b/src/python/magnum/platform/glfw.cpp @@ -49,6 +49,12 @@ void glfw(py::module_& m) { throw py::error_already_set{}; } + void exitEvent(ExitEvent& event) override { + /* The base implementation does this, otherwise the exit event is + always cancelled. It's private so we can't call it directly. */ + event.setAccepted(); + } + void viewportEvent(ViewportEvent&) override {} void keyPressEvent(KeyEvent&) override {} void keyReleaseEvent(KeyEvent&) override {} void mousePressEvent(MouseEvent&) override {} @@ -64,6 +70,35 @@ void glfw(py::module_& m) { struct PyApplication: PublicizedApplication { using PublicizedApplication::PublicizedApplication; + /* PYBIND11_OVERLOAD_NAME() calls object_api::operator() with implicit + template param, which is return_value_policy::automatic_reference. + That later gets changed to return_value_policy::copy in + type_caster_base::cast() and there's no way to override that. */ + + void exitEvent(ExitEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "exit_event", + exitEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void viewportEvent(ViewportEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "viewport_event", + viewportEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + void drawEvent() override { #ifdef __clang__ /* ugh pybind don't tell me I AM THE FIRST ON EARTH to get a @@ -83,10 +118,6 @@ void glfw(py::module_& m) { #endif } - /* PYBIND11_OVERLOAD_NAME() calls object_api::operator() with implicit - template param, which is return_value_policy::automatic_reference. - That later gets changed to return_value_policy::copy in - type_caster_base::cast() and there's no way to override that */ void keyPressEvent(KeyEvent& event) override { PYBIND11_OVERLOAD_NAME( void, @@ -159,6 +190,8 @@ void glfw(py::module_& m) { py::class_> glfwApplication{m, "Application", "GLFW application"}; /** @todo def_property_writeonly for swap_interval */ + PyNonDestructibleClass exitEvent_{glfwApplication, "ExitEvent", "Exit event"}; + PyNonDestructibleClass viewportEvent_{glfwApplication, "ViewportEvent", "Viewport event"}; PyNonDestructibleClass inputEvent_{glfwApplication, "InputEvent", "Base for input events"}; py::class_ keyEvent_{glfwApplication, "KeyEvent", "Key event"}; py::class_ mouseEvent_{glfwApplication, "MouseEvent", "Mouse event"}; @@ -166,6 +199,8 @@ void glfw(py::module_& m) { py::class_ mouseScrollEvent_{glfwApplication, "MouseScrollEvent", "Mouse scroll event"}; application(glfwApplication); + exitEvent(exitEvent_); + viewportEvent(viewportEvent_); inputEvent(inputEvent_); keyEvent(keyEvent_); mouseEvent(mouseEvent_); diff --git a/src/python/magnum/platform/sdl2.cpp b/src/python/magnum/platform/sdl2.cpp index 70d159b..a9e54c9 100644 --- a/src/python/magnum/platform/sdl2.cpp +++ b/src/python/magnum/platform/sdl2.cpp @@ -49,6 +49,12 @@ void sdl2(py::module_& m) { throw py::error_already_set{}; } + void exitEvent(ExitEvent& event) override { + /* The base implementation does this, otherwise the exit event is + always cancelled. It's private so we can't call it directly. */ + event.setAccepted(); + } + void viewportEvent(ViewportEvent&) override {} void keyPressEvent(KeyEvent&) override {} void keyReleaseEvent(KeyEvent&) override {} void mousePressEvent(MouseEvent&) override {} @@ -64,6 +70,35 @@ void sdl2(py::module_& m) { struct PyApplication: PublicizedApplication { using PublicizedApplication::PublicizedApplication; + /* PYBIND11_OVERLOAD_NAME() calls object_api::operator() with implicit + template param, which is return_value_policy::automatic_reference. + That later gets changed to return_value_policy::copy in + type_caster_base::cast() and there's no way to override that. */ + + void exitEvent(ExitEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "exit_event", + exitEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void viewportEvent(ViewportEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "viewport_event", + viewportEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + void drawEvent() override { #ifdef __clang__ /* ugh pybind don't tell me I AM THE FIRST ON EARTH to get a @@ -83,10 +118,6 @@ void sdl2(py::module_& m) { #endif } - /* PYBIND11_OVERLOAD_NAME() calls object_api::operator() with implicit - template param, which is return_value_policy::automatic_reference. - That later gets changed to return_value_policy::copy in - type_caster_base::cast() and there's no way to override that */ void keyPressEvent(KeyEvent& event) override { PYBIND11_OVERLOAD_NAME( void, @@ -164,6 +195,8 @@ void sdl2(py::module_& m) { }, "Swap interval") .def("main_loop_iteration", &PyApplication::mainLoopIteration, "Run one iteration of application main loop"); + PyNonDestructibleClass exitEvent_{sdl2application, "ExitEvent", "Exit event"}; + PyNonDestructibleClass viewportEvent_{sdl2application, "ViewportEvent", "Viewport event"}; PyNonDestructibleClass inputEvent_{sdl2application, "InputEvent", "Base for input events"}; py::class_ keyEvent_{sdl2application, "KeyEvent", "Key event"}; py::class_ mouseEvent_{sdl2application, "MouseEvent", "Mouse event"}; @@ -171,6 +204,8 @@ void sdl2(py::module_& m) { py::class_ mouseScrollEvent_{sdl2application, "MouseScrollEvent", "Mouse scroll event"}; application(sdl2application); + exitEvent(exitEvent_); + viewportEvent(viewportEvent_); inputEvent(inputEvent_); keyEvent(keyEvent_); mouseEvent(mouseEvent_);