From 3bf050ed306ef75387b3d7a90948a51e3be8f775 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Mon, 21 Sep 2015 15:07:36 +0200 Subject: [PATCH] qt5: use signal handler for input processing Fixes #1707 --- repos/libports/lib/mk/qt5_qpa_nitpicker.mk | 4 +- .../nitpicker/qnitpickerintegration.cpp | 21 ++- .../nitpicker/qnitpickerintegration.h | 23 ++- .../nitpicker/qnitpickerplatformwindow.cpp | 134 +++++++++--------- .../nitpicker/qnitpickerplatformwindow.h | 55 +++---- .../nitpicker/qsignalhandlerthread.cpp | 22 +++ .../nitpicker/qsignalhandlerthread.h | 39 +++++ 7 files changed, 189 insertions(+), 109 deletions(-) create mode 100644 repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.cpp create mode 100644 repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.h diff --git a/repos/libports/lib/mk/qt5_qpa_nitpicker.mk b/repos/libports/lib/mk/qt5_qpa_nitpicker.mk index c58d9117de..e20a9eeefe 100644 --- a/repos/libports/lib/mk/qt5_qpa_nitpicker.mk +++ b/repos/libports/lib/mk/qt5_qpa_nitpicker.mk @@ -14,12 +14,14 @@ SRC_CC += main.cpp \ qnitpickerintegration.cpp \ qnitpickerplatformwindow.cpp \ qnitpickerwindowsurface.cpp \ + qsignalhandlerthread.cpp \ moc_qnitpickerplatformwindow.cpp \ moc_qnitpickerwindowsurface.cpp \ moc_qnitpickerintegrationplugin.cpp \ qevdevkeyboardhandler.cpp \ moc_qunixeventdispatcher_qpa_p.cpp \ - moc_qevdevkeyboardhandler_p.cpp + moc_qevdevkeyboardhandler_p.cpp \ + moc_qsignalhandlerthread.cpp INC_DIR += $(QT5_CONTRIB_DIR)/qtbase/src/platformsupport/eventdispatchers \ $(QT5_CONTRIB_DIR)/qtbase/src/platformsupport/fontdatabases/basic \ diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.cpp index 5c58cbfab4..d5367873f4 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.cpp @@ -11,11 +11,6 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode includes */ - -#include -#include - /* Qt includes */ #include #include "qnitpickerglcontext.h" @@ -30,21 +25,20 @@ QT_BEGIN_NAMESPACE static const bool verbose = false; -static Genode::Rpc_entrypoint &_entrypoint() +Genode::Signal_receiver &QNitpickerIntegration::_signal_receiver() { - enum { STACK_SIZE = 2*1024*sizeof(Genode::addr_t) }; - static Genode::Cap_connection cap; - static Genode::Rpc_entrypoint entrypoint(&cap, STACK_SIZE, "qt_window_ep"); - return entrypoint; + static Genode::Signal_receiver _inst; + return _inst; } - QNitpickerIntegration::QNitpickerIntegration() -: _nitpicker_screen(new QNitpickerScreen()), +: _signal_handler_thread(_signal_receiver()), + _nitpicker_screen(new QNitpickerScreen()), _event_dispatcher(createUnixEventDispatcher()) { QGuiApplicationPrivate::instance()->setEventDispatcher(_event_dispatcher); screenAdded(_nitpicker_screen); + _signal_handler_thread.start(); } @@ -63,7 +57,8 @@ QPlatformWindow *QNitpickerIntegration::createPlatformWindow(QWindow *window) co qDebug() << "QNitpickerIntegration::createPlatformWindow(" << window << ")"; QRect screen_geometry = _nitpicker_screen->geometry(); - return new QNitpickerPlatformWindow(window, _entrypoint(), + return new QNitpickerPlatformWindow(window, + _signal_receiver(), screen_geometry.width(), screen_geometry.height()); } diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.h index ceeb5e73c9..9e5f0be3b6 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerintegration.h @@ -21,6 +21,7 @@ #include #include "qnitpickerscreen.h" +#include "qsignalhandlerthread.h" QT_BEGIN_NAMESPACE @@ -28,22 +29,32 @@ class QNitpickerIntegration : public QPlatformIntegration { private: + QSignalHandlerThread _signal_handler_thread; + QNitpickerScreen *_nitpicker_screen; QAbstractEventDispatcher *_event_dispatcher; + /* + * A reference to the signal receiver gets passed to newly created + * objects, for example in 'createPlatformWindow()'. Since this is + * a const member function, the signal receiver cannot be a member + * variable of QNitpickerIntegration. + */ + static Genode::Signal_receiver &_signal_receiver(); + public: QNitpickerIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const override; - QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; - QAbstractEventDispatcher *guiThreadEventDispatcher() const; + QPlatformWindow *createPlatformWindow(QWindow *window) const override; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; + QAbstractEventDispatcher *guiThreadEventDispatcher() const override; - QPlatformFontDatabase *fontDatabase() const; + QPlatformFontDatabase *fontDatabase() const override; - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; }; QT_END_NAMESPACE diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp index 763b2247c8..f63fe8d085 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp @@ -111,6 +111,7 @@ void QNitpickerPlatformWindow::_process_mouse_event(Input::Event *ev) _mouse_button_state); } + void QNitpickerPlatformWindow::_process_key_event(Input::Event *ev) { const bool pressed = (ev->type() == Input::Event::PRESS); @@ -118,6 +119,55 @@ void QNitpickerPlatformWindow::_process_key_event(Input::Event *ev) _keyboard_handler.processKeycode(keycode, pressed, false); } + +void QNitpickerPlatformWindow::_handle_input(unsigned int) +{ + for (int i = 0, num_ev = _input_session.flush(); i < num_ev; i++) { + + Input::Event *ev = &_ev_buf[i]; + + bool const is_key_event = ev->type() == Input::Event::PRESS || + ev->type() == Input::Event::RELEASE; + + bool const is_mouse_button_event = + is_key_event && (ev->code() == Input::BTN_LEFT || + ev->code() == Input::BTN_MIDDLE || + ev->code() == Input::BTN_RIGHT); + + if (ev->type() == Input::Event::MOTION || + ev->type() == Input::Event::WHEEL || + is_mouse_button_event) { + + _process_mouse_event(ev); + + } else if (is_key_event && (ev->code() < 128)) { + + _process_key_event(ev); + + } + } +} + + +void QNitpickerPlatformWindow::_handle_mode_changed(unsigned int) +{ + Framebuffer::Mode mode(_nitpicker_session.mode()); + + if ((mode.width() != _current_mode.width()) || + (mode.height() != _current_mode.height()) || + (mode.format() != _current_mode.format())) { + + QRect geo(geometry()); + geo.setWidth(mode.width()); + geo.setHeight(mode.height()); + + QWindowSystemInterface::handleGeometryChange(window(), geo); + + setGeometry(geo); + } +} + + Nitpicker::Session::View_handle QNitpickerPlatformWindow::_create_view() { if (window()->type() == Qt::Desktop) @@ -176,27 +226,33 @@ void QNitpickerPlatformWindow::_adjust_and_set_geometry(const QRect &rect) emit framebuffer_changed(); } -QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_entrypoint &ep, - int screen_width, int screen_height) +QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, + Genode::Signal_receiver &signal_receiver, + int screen_width, int screen_height) : QPlatformWindow(window), _framebuffer_session(_nitpicker_session.framebuffer_session()), _framebuffer(0), _framebuffer_changed(false), _geometry_changed(false), + _signal_receiver(signal_receiver), _view_handle(_create_view()), _input_session(_nitpicker_session.input_session()), - _timer(this), _keyboard_handler("", -1, false, false, ""), _resize_handle(!window->flags().testFlag(Qt::Popup)), _decoration(!window->flags().testFlag(Qt::Popup)), - _egl_surface(EGL_NO_SURFACE) + _egl_surface(EGL_NO_SURFACE), + _input_signal_dispatcher(_signal_receiver, *this, + &QNitpickerPlatformWindow::_input), + _mode_changed_signal_dispatcher(_signal_receiver, *this, + &QNitpickerPlatformWindow::_mode_changed) { if (qnpw_verbose) if (window->transientParent()) qDebug() << "QNitpickerPlatformWindow(): child window of" << window->transientParent(); - _mode_changed_signal_context_capability = _signal_receiver.manage(&_mode_changed_signal_context); - _nitpicker_session.mode_sigh(_mode_changed_signal_context_capability); + _input_session.sigh(_input_signal_dispatcher); + + _nitpicker_session.mode_sigh(_mode_changed_signal_dispatcher); _adjust_and_set_geometry(geometry()); @@ -211,8 +267,13 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_ _nitpicker_session.execute(); } - connect(_timer, SIGNAL(timeout()), this, SLOT(handle_events())); - _timer->start(10); + connect(this, SIGNAL(_input(unsigned int)), + this, SLOT(_handle_input(unsigned int)), + Qt::QueuedConnection); + + connect(this, SIGNAL(_mode_changed(unsigned int)), + this, SLOT(_handle_mode_changed(unsigned int)), + Qt::QueuedConnection); } QWindow *QNitpickerPlatformWindow::window() const @@ -584,61 +645,4 @@ Nitpicker::View_capability QNitpickerPlatformWindow::view_cap() const return npw->_nitpicker_session.view_capability(_view_handle); } -void QNitpickerPlatformWindow::handle_events() -{ - /* handle resize events */ - - if (_signal_receiver.pending()) { - - _signal_receiver.wait_for_signal(); - - Framebuffer::Mode mode(_nitpicker_session.mode()); - - if ((mode.width() != _current_mode.width()) || - (mode.height() != _current_mode.height()) || - (mode.format() != _current_mode.format())) { - - QRect geo(geometry()); - geo.setWidth(mode.width()); - geo.setHeight(mode.height()); - - QWindowSystemInterface::handleGeometryChange(window(), geo); - - setGeometry(geo); - } - } - - /* handle input events */ - - if (_input_session.is_pending()) { - for (int i = 0, num_ev = _input_session.flush(); i < num_ev; i++) { - - Input::Event *ev = &_ev_buf[i]; - - bool const is_key_event = ev->type() == Input::Event::PRESS || - ev->type() == Input::Event::RELEASE; - - bool const is_mouse_button_event = - is_key_event && (ev->code() == Input::BTN_LEFT || - ev->code() == Input::BTN_MIDDLE || - ev->code() == Input::BTN_RIGHT); - - if (ev->type() == Input::Event::MOTION || - ev->type() == Input::Event::WHEEL || - is_mouse_button_event) { - - _process_mouse_event(ev); - - } else if (is_key_event && (ev->code() < 128)) { - - _process_key_event(ev); - - } - } - - } - -} - QT_END_NAMESPACE - diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h index d6e3c6009a..5bdda72d43 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h @@ -37,25 +37,25 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow private: - Nitpicker::Connection _nitpicker_session; - Framebuffer::Session_client _framebuffer_session; - unsigned char *_framebuffer; - bool _framebuffer_changed; - bool _geometry_changed; - Framebuffer::Mode _current_mode; - Genode::Signal_context _mode_changed_signal_context; - Genode::Signal_context_capability _mode_changed_signal_context_capability; - Genode::Signal_receiver _signal_receiver; - Nitpicker::Session::View_handle _view_handle; - Input::Session_client _input_session; - Input::Event *_ev_buf; - QMember _timer; - Qt::MouseButtons _mouse_button_state; - QEvdevKeyboardHandler _keyboard_handler; - QByteArray _title; - bool _resize_handle; - bool _decoration; - EGLSurface _egl_surface; + Nitpicker::Connection _nitpicker_session; + Framebuffer::Session_client _framebuffer_session; + unsigned char *_framebuffer; + bool _framebuffer_changed; + bool _geometry_changed; + Framebuffer::Mode _current_mode; + Genode::Signal_receiver &_signal_receiver; + Nitpicker::Session::View_handle _view_handle; + Input::Session_client _input_session; + Input::Event *_ev_buf; + Qt::MouseButtons _mouse_button_state; + QEvdevKeyboardHandler _keyboard_handler; + QByteArray _title; + bool _resize_handle; + bool _decoration; + EGLSurface _egl_surface; + + Genode::Signal_dispatcher _input_signal_dispatcher; + Genode::Signal_dispatcher _mode_changed_signal_dispatcher; void _process_mouse_event(Input::Event *ev); void _process_key_event(Input::Event *ev); @@ -63,9 +63,20 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow Nitpicker::Session::View_handle _create_view(); void _adjust_and_set_geometry(const QRect &rect); + private Q_SLOTS: + + void _handle_input(unsigned int); + void _handle_mode_changed(unsigned int); + + Q_SIGNALS: + + void _input(unsigned int); + void _mode_changed(unsigned int); + public: - QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_entrypoint &ep, + QNitpickerPlatformWindow(QWindow *window, + Genode::Signal_receiver &signal_receiver, int screen_width, int screen_height); QWindow *window() const; @@ -162,10 +173,6 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow void framebuffer_changed(); - private slots: - - void handle_events(); - }; QT_END_NAMESPACE diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.cpp new file mode 100644 index 0000000000..3a9f5c2aab --- /dev/null +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.cpp @@ -0,0 +1,22 @@ +/* + * \brief QPA signal handler thread + * \author Christian Prochaska + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include "qsignalhandlerthread.h" + +void QSignalHandlerThread::run() +{ + for (;;) { + Genode::Signal s = _signal_receiver.wait_for_signal(); + static_cast(s.context())->dispatch(s.num()); + } +} diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.h new file mode 100644 index 0000000000..3fa95f94c2 --- /dev/null +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qsignalhandlerthread.h @@ -0,0 +1,39 @@ +/* + * \brief QPA signal handler thread + * \author Christian Prochaska + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _QSIGNALHANDLERTHREAD_H_ +#define _QSIGNALHANDLERTHREAD_H_ + +/* Genode includes */ +#include + +/* Qt includes */ +#include + +class QSignalHandlerThread : public QThread +{ + Q_OBJECT + + private: + + Genode::Signal_receiver &_signal_receiver; + + public: + + QSignalHandlerThread(Genode::Signal_receiver &signal_receiver) + : _signal_receiver(signal_receiver) { } + + void run() override; +}; + +#endif /* _QSIGNALHANDLERTHREAD_H_ */