diff options
author | Daniel d'Andrada <daniel.dandrada@canonical.com> | 2015-07-24 19:00:22 -0300 |
---|---|---|
committer | Daniel d'Andrada <daniel.dandrada@canonical.com> | 2015-07-24 19:00:22 -0300 |
commit | 038c0514e8d12fa5f067f336a0e26a5d3417b29b (patch) | |
tree | 2b0ec28271424825b1adde3db9de84e66a1b4dc9 /src | |
parent | 0669f32d7b6112561458df8888845a4e26eb9167 (diff) | |
parent | 5435c2d8e18affc57d03d0742029edadba6f48fa (diff) |
Merge trunk
[ Andreas Pokorny ]
* Release in step with Mir 0.14.0
[ CI Train Bot ]
* New rebuild forced.
[ Gerry Boland ]
* [qpa] refactor QMirServer to clean up its API, and fix strange
thread design.
[ MichaĆ Sawicz ]
* Depend on same-version qtmir-{desktop,android}
* No-change rebuild against Qt 5.4.2.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/debughelpers.h | 2 | ||||
-rw-r--r-- | src/modules/Unity/Application/mirsurfaceitem.cpp | 30 | ||||
-rw-r--r-- | src/platforms/mirserver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/platforms/mirserver/display.cpp | 7 | ||||
-rw-r--r-- | src/platforms/mirserver/display.h | 12 | ||||
-rw-r--r-- | src/platforms/mirserver/miropenglcontext.cpp | 5 | ||||
-rw-r--r-- | src/platforms/mirserver/miropenglcontext.h | 1 | ||||
-rw-r--r-- | src/platforms/mirserver/mirserverintegration.cpp | 59 | ||||
-rw-r--r-- | src/platforms/mirserver/mirserverintegration.h | 7 | ||||
-rw-r--r-- | src/platforms/mirserver/nativeinterface.cpp | 23 | ||||
-rw-r--r-- | src/platforms/mirserver/nativeinterface.h | 6 | ||||
-rw-r--r-- | src/platforms/mirserver/qmirserver.cpp | 101 | ||||
-rw-r--r-- | src/platforms/mirserver/qmirserver.h | 60 | ||||
-rw-r--r-- | src/platforms/mirserver/qmirserver_p.cpp | 53 | ||||
-rw-r--r-- | src/platforms/mirserver/qmirserver_p.h | 67 | ||||
-rw-r--r-- | src/platforms/mirserver/qteventfeeder.cpp | 17 | ||||
-rw-r--r-- | src/platforms/mirserver/qteventfeeder.h | 4 |
17 files changed, 258 insertions, 197 deletions
diff --git a/src/common/debughelpers.h b/src/common/debughelpers.h index 7990598..d4e5253 100644 --- a/src/common/debughelpers.h +++ b/src/common/debughelpers.h @@ -20,7 +20,7 @@ #include <QString> #include <mir_toolkit/common.h> -#include <mir_toolkit/events/input/input_event.h> +#include <mir_toolkit/event.h> class QTouchEvent; diff --git a/src/modules/Unity/Application/mirsurfaceitem.cpp b/src/modules/Unity/Application/mirsurfaceitem.cpp index d140f7e..3c98329 100644 --- a/src/modules/Unity/Application/mirsurfaceitem.cpp +++ b/src/modules/Unity/Application/mirsurfaceitem.cpp @@ -73,16 +73,16 @@ getMirModifiersFromQt(Qt::KeyboardModifiers mods) mir::EventUPtr makeMirEvent(QMouseEvent *qtEvent, MirPointerAction action) { - auto timestamp = qtEvent->timestamp() * 1000000; + auto timestamp = std::chrono::milliseconds(qtEvent->timestamp()); auto modifiers = getMirModifiersFromQt(qtEvent->modifiers()); - std::vector<MirPointerButton> buttons; + MirPointerButtons buttons = 0; if (qtEvent->buttons() & Qt::LeftButton) - buttons.push_back(mir_pointer_button_primary); + buttons |= mir_pointer_button_primary; if (qtEvent->buttons() & Qt::RightButton) - buttons.push_back(mir_pointer_button_secondary); + buttons |= mir_pointer_button_secondary; if (qtEvent->buttons() & Qt::MidButton) - buttons.push_back(mir_pointer_button_tertiary); + buttons |= mir_pointer_button_tertiary; return mir::events::make_event(0 /*DeviceID */, timestamp, modifiers, action, buttons, qtEvent->x(), qtEvent->y(), 0, 0); @@ -90,9 +90,9 @@ mir::EventUPtr makeMirEvent(QMouseEvent *qtEvent, MirPointerAction action) mir::EventUPtr makeMirEvent(QHoverEvent *qtEvent, MirPointerAction action) { - auto timestamp = qtEvent->timestamp() * 1000000; + auto timestamp = std::chrono::milliseconds(qtEvent->timestamp()); - std::vector<MirPointerButton> buttons; + MirPointerButtons buttons = 0; return mir::events::make_event(0 /*DeviceID */, timestamp, mir_input_event_modifier_none, action, buttons, qtEvent->posF().x(), qtEvent->posF().y(), 0, 0); @@ -115,7 +115,7 @@ mir::EventUPtr makeMirEvent(QKeyEvent *qtEvent) if (qtEvent->isAutoRepeat()) action = mir_keyboard_action_repeat; - return mir::events::make_event(0 /* DeviceID */, qtEvent->timestamp() * 1000000, + return mir::events::make_event(0 /* DeviceID */, std::chrono::milliseconds(qtEvent->timestamp()), action, qtEvent->nativeVirtualKey(), qtEvent->nativeScanCode(), qtEvent->nativeModifiers()); @@ -127,7 +127,7 @@ mir::EventUPtr makeMirEvent(Qt::KeyboardModifiers qmods, ulong qtTimestamp) { auto modifiers = getMirModifiersFromQt(qmods); - auto ev = mir::events::make_event(0, static_cast<int64_t>(qtTimestamp) * 1000000, + auto ev = mir::events::make_event(0, std::chrono::milliseconds(qtTimestamp), modifiers); for (int i = 0; i < qtTouchPoints.count(); ++i) { @@ -388,17 +388,16 @@ bool MirSurfaceItem::updateTexture() // called by rendering thread (scene gra bool textureUpdated = false; const void* const userId = (void*)123; - std::unique_ptr<mg::Renderable> renderable = - m_surface->compositor_snapshot(userId); + auto renderables = m_surface->generate_renderables(userId); - if (m_surface->buffers_ready_for_compositor(userId) > 0) { + if (m_surface->buffers_ready_for_compositor(userId) > 0 && renderables.size() > 0) { if (!m_textureProvider->t) { - m_textureProvider->t = new MirBufferSGTexture(renderable->buffer()); + m_textureProvider->t = new MirBufferSGTexture(renderables[0]->buffer()); } else { // Avoid holding two buffers for the compositor at the same time. Thus free the current // before acquiring the next m_textureProvider->t->freeBuffer(); - m_textureProvider->t->setBuffer(renderable->buffer()); + m_textureProvider->t->setBuffer(renderables[0]->buffer()); } textureUpdated = true; } @@ -746,7 +745,8 @@ void MirSurfaceItem::dropPendingBuffers() // The line below looks like an innocent, effect-less, getter. But as this // method returns a unique_pointer, not holding its reference causes the // buffer to be destroyed/released straight away. - m_surface->compositor_snapshot(userId)->buffer(); + for (auto const & item : m_surface->generate_renderables(userId)) + item->buffer(); qCDebug(QTMIR_SURFACES) << "MirSurfaceItem::dropPendingBuffers()" << "surface =" << this << "buffer dropped." diff --git a/src/platforms/mirserver/CMakeLists.txt b/src/platforms/mirserver/CMakeLists.txt index 13c643a..7397ad1 100644 --- a/src/platforms/mirserver/CMakeLists.txt +++ b/src/platforms/mirserver/CMakeLists.txt @@ -46,6 +46,7 @@ set(MIRSERVER_QPA_PLUGIN_SRC qteventfeeder.cpp plugin.cpp qmirserver.cpp + qmirserver_p.cpp sessionauthorizer.cpp sessionlistener.cpp surfaceobserver.cpp diff --git a/src/platforms/mirserver/display.cpp b/src/platforms/mirserver/display.cpp index 70a6b15..7228f6e 100644 --- a/src/platforms/mirserver/display.cpp +++ b/src/platforms/mirserver/display.cpp @@ -23,18 +23,13 @@ #include <mir/graphics/display.h> #include <mir/graphics/display_configuration.h> -#include <QDebug> namespace mg = mir::graphics; // TODO: Listen for display changes and update the list accordingly -Display::Display(const QSharedPointer<MirServer> &server, QObject *parent) - : QObject(parent) - , m_mirServer(server) +Display::Display(const std::shared_ptr<mir::graphics::DisplayConfiguration> &displayConfig) { - std::shared_ptr<mir::graphics::DisplayConfiguration> displayConfig = m_mirServer->the_display()->configuration(); - displayConfig->for_each_output([this](mg::DisplayConfigurationOutput const& output) { if (output.used) { auto screen = new Screen(output); diff --git a/src/platforms/mirserver/display.h b/src/platforms/mirserver/display.h index 21c7767..bc77381 100644 --- a/src/platforms/mirserver/display.h +++ b/src/platforms/mirserver/display.h @@ -19,23 +19,21 @@ #ifndef DISPLAY_H #define DISPLAY_H -#include <QObject> #include <qpa/qplatformscreen.h> +#include <memory> -class MirServer; +namespace mir { namespace graphics { class DisplayConfiguration; }} -class Display : public QObject +class Display { - Q_OBJECT public: - Display(const QSharedPointer<MirServer> &server, QObject *parent = 0); - ~Display(); + Display(const std::shared_ptr<mir::graphics::DisplayConfiguration> &displayConfig); + virtual ~Display(); QList<QPlatformScreen *> screens() const { return m_screens; } private: QList<QPlatformScreen *> m_screens; - const QSharedPointer<MirServer> m_mirServer; }; #endif // DISPLAY_H diff --git a/src/platforms/mirserver/miropenglcontext.cpp b/src/platforms/mirserver/miropenglcontext.cpp index cf5ef9d..cb84666 100644 --- a/src/platforms/mirserver/miropenglcontext.cpp +++ b/src/platforms/mirserver/miropenglcontext.cpp @@ -36,12 +36,11 @@ // (i.e. individual display output buffers) to use as a common base context. MirOpenGLContext::MirOpenGLContext(const QSharedPointer<MirServer> &server, const QSurfaceFormat &format) - : m_mirServer(server) #if GL_DEBUG - , m_logger(new QOpenGLDebugLogger(this)) + : m_logger(new QOpenGLDebugLogger(this)) #endif { - std::shared_ptr<mir::graphics::Display> display = m_mirServer->the_display(); + std::shared_ptr<mir::graphics::Display> display = server->the_display(); // create a temporary GL context to fetch the EGL display and config, so Qt can determine the surface format std::unique_ptr<mir::graphics::GLContext> mirContext = display->create_gl_context(); diff --git a/src/platforms/mirserver/miropenglcontext.h b/src/platforms/mirserver/miropenglcontext.h index e09a992..de3ec9c 100644 --- a/src/platforms/mirserver/miropenglcontext.h +++ b/src/platforms/mirserver/miropenglcontext.h @@ -52,7 +52,6 @@ public: #endif private: - const QSharedPointer<MirServer> m_mirServer; QSurfaceFormat m_format; #if GL_DEBUG QOpenGLDebugLogger *m_logger; diff --git a/src/platforms/mirserver/mirserverintegration.cpp b/src/platforms/mirserver/mirserverintegration.cpp index 2292831..ad33caa 100644 --- a/src/platforms/mirserver/mirserverintegration.cpp +++ b/src/platforms/mirserver/mirserverintegration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -30,7 +30,6 @@ #include <qpa/qwindowsysteminterface.h> #include <QCoreApplication> -#include <QStringList> #include <QOpenGLContext> #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) @@ -41,10 +40,7 @@ // Mir #include <mir/graphics/display.h> -#include <mir/graphics/display_buffer.h> - -// std -#include <csignal> +#include <mir/graphics/display_configuration.h> // local #include "clipboard.h" @@ -66,36 +62,25 @@ MirServerIntegration::MirServerIntegration() #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) , m_eventDispatcher(createUnixEventDispatcher()) #endif + , m_mirServer(new QMirServer(QCoreApplication::arguments())) , m_display(nullptr) - , m_qmirServer(nullptr) , m_nativeInterface(nullptr) , m_clipboard(new Clipboard) { - // Start Mir server only once Qt has initialized its event dispatcher, see initialize() - - QStringList args = QCoreApplication::arguments(); - // convert arguments back into argc-argv form that Mir wants - char **argv; - argv = new char*[args.size() + 1]; - for (int i = 0; i < args.size(); i++) { - argv[i] = new char[strlen(args.at(i).toStdString().c_str())+1]; - memcpy(argv[i], args.at(i).toStdString().c_str(), strlen(args.at(i).toStdString().c_str())+1); - } - argv[args.size()] = '\0'; - // For access to sensors, qtmir uses qtubuntu-sensors. qtubuntu-sensors reads the // UBUNTU_PLATFORM_API_BACKEND variable to decide if to load a valid sensor backend or not. // For it to function we need to ensure a valid backend has been specified if (qEnvironmentVariableIsEmpty("UBUNTU_PLATFORM_API_BACKEND")) { - if (qgetenv("DESKTOP_SESSION").contains("mir")) { + if (qgetenv("DESKTOP_SESSION").contains("mir") || !qEnvironmentVariableIsSet("ANDROID_DATA")) { qputenv("UBUNTU_PLATFORM_API_BACKEND", "desktop_mirclient"); } else { qputenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient"); } } - m_mirServer = QSharedPointer<MirServer>( - new MirServer(args.length(), const_cast<const char**>(argv))); + // If Mir shuts down, quit. + QObject::connect(m_mirServer.data(), &QMirServer::stopped, + QCoreApplication::instance(), &QCoreApplication::quit); #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) QGuiApplicationPrivate::instance()->setEventDispatcher(eventDispatcher_); @@ -109,7 +94,6 @@ MirServerIntegration::~MirServerIntegration() { delete m_nativeInterface; delete m_display; - delete m_qmirServer; } bool MirServerIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -135,18 +119,21 @@ QPlatformWindow *MirServerIntegration::createPlatformWindow(QWindow *window) con DisplayWindow* displayWindow = nullptr; + auto const mirServer = m_mirServer->mirServer().lock(); mg::DisplayBuffer* first_buffer{nullptr}; mg::DisplaySyncGroup* first_group{nullptr}; - m_mirServer->the_display()->for_each_display_sync_group([&](mg::DisplaySyncGroup &group) { - if (!first_group) { - first_group = &group; - } - group.for_each_display_buffer([&](mg::DisplayBuffer &buffer) { - if (!first_buffer) { - first_buffer = &buffer; + if (mirServer) { + mirServer->the_display()->for_each_display_sync_group([&](mg::DisplaySyncGroup &group) { + if (!first_group) { + first_group = &group; } + group.for_each_display_buffer([&](mg::DisplayBuffer &buffer) { + if (!first_buffer) { + first_buffer = &buffer; + } + }); }); - }); + } // FIXME(gerry) this will go very bad for >1 display buffer if (first_group && first_buffer) @@ -168,7 +155,7 @@ QPlatformBackingStore *MirServerIntegration::createPlatformBackingStore(QWindow QPlatformOpenGLContext *MirServerIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { qDebug() << "createPlatformOpenGLContext" << context; - return new MirOpenGLContext(m_mirServer, context->format()); + return new MirOpenGLContext(m_mirServer->mirServer(), context->format()); } #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) @@ -181,10 +168,12 @@ QAbstractEventDispatcher *MirServerIntegration::createEventDispatcher() const void MirServerIntegration::initialize() { // Creates instance of and start the Mir server in a separate thread - m_qmirServer = new QMirServer(m_mirServer); + if (!m_mirServer->start()) { + exit(2); + } - m_display = new Display(m_mirServer); - m_nativeInterface = new NativeInterface(m_mirServer); + m_display = new Display(m_mirServer->mirServer().data()->the_display()->configuration()); + m_nativeInterface = new NativeInterface(m_mirServer->mirServer()); for (QPlatformScreen *screen : m_display->screens()) screenAdded(screen); diff --git a/src/platforms/mirserver/mirserverintegration.h b/src/platforms/mirserver/mirserverintegration.h index 37e0dc0..a02405e 100644 --- a/src/platforms/mirserver/mirserverintegration.h +++ b/src/platforms/mirserver/mirserverintegration.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -69,8 +69,6 @@ public: QPlatformNativeInterface *nativeInterface() const override; private: - QSharedPointer<MirServer> m_mirServer; - QScopedPointer<QPlatformAccessibility> m_accessibility; QScopedPointer<QPlatformFontDatabase> m_fontDb; QScopedPointer<QPlatformServices> m_services; @@ -78,8 +76,9 @@ private: QScopedPointer<QAbstractEventDispatcher> m_eventDispatcher; #endif + QScopedPointer<QMirServer> m_mirServer; + Display *m_display; - QMirServer *m_qmirServer; NativeInterface *m_nativeInterface; QPlatformInputContext* m_inputContext; QScopedPointer<qtmir::Clipboard> m_clipboard; diff --git a/src/platforms/mirserver/nativeinterface.cpp b/src/platforms/mirserver/nativeinterface.cpp index b013345..6cc4c0d 100644 --- a/src/platforms/mirserver/nativeinterface.cpp +++ b/src/platforms/mirserver/nativeinterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -18,7 +18,7 @@ #include "nativeinterface.h" -NativeInterface::NativeInterface(const QSharedPointer<MirServer> &server) +NativeInterface::NativeInterface(const QWeakPointer<MirServer> &server) : m_mirServer(server) { } @@ -27,14 +27,17 @@ void *NativeInterface::nativeResourceForIntegration(const QByteArray &resource) { void *result = nullptr; - if (resource == "SessionAuthorizer") - result = m_mirServer->sessionAuthorizer(); - else if (resource == "Shell") - result = m_mirServer->shell(); - else if (resource == "SessionListener") - result = m_mirServer->sessionListener(); - else if (resource == "PromptSessionListener") - result = m_mirServer->promptSessionListener(); + auto const server = m_mirServer.lock(); + if (server) { + if (resource == "SessionAuthorizer") + result = server->sessionAuthorizer(); + else if (resource == "Shell") + result = server->shell(); + else if (resource == "SessionListener") + result = server->sessionListener(); + else if (resource == "PromptSessionListener") + result = server->promptSessionListener(); + } return result; } diff --git a/src/platforms/mirserver/nativeinterface.h b/src/platforms/mirserver/nativeinterface.h index 5a5c377..da97663 100644 --- a/src/platforms/mirserver/nativeinterface.h +++ b/src/platforms/mirserver/nativeinterface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -29,11 +29,11 @@ class NativeInterface : public QPlatformNativeInterface { public: - NativeInterface(const QSharedPointer<MirServer> &); + NativeInterface(const QWeakPointer<MirServer> &); virtual void *nativeResourceForIntegration(const QByteArray &resource); - QSharedPointer<MirServer> m_mirServer; + QWeakPointer<MirServer> m_mirServer; }; #endif // NATIVEINTEGRATION_H diff --git a/src/platforms/mirserver/qmirserver.cpp b/src/platforms/mirserver/qmirserver.cpp index f28393a..c7dc580 100644 --- a/src/platforms/mirserver/qmirserver.cpp +++ b/src/platforms/mirserver/qmirserver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -19,80 +19,77 @@ #include <QCoreApplication> #include <QDebug> -#include <mir/main_loop.h> - // local +#include "mirserver.h" #include "qmirserver.h" +#include "qmirserver_p.h" -void MirServerWorker::run() +QMirServer::QMirServer(const QStringList &arguments, QObject *parent) + : QObject(parent) + , d_ptr(new QMirServerPrivate()) { - auto const main_loop = server->the_main_loop(); - // By enqueuing the notification code in the main loop, we are - // ensuring that the server has really and fully started before - // leaving wait_for_startup(). - main_loop->enqueue( - this, - [&] - { - std::lock_guard<std::mutex> lock(mutex); - mir_running = true; - started_cv.notify_one(); - }); - - server->run(); - Q_EMIT stopped(); + Q_D(QMirServer); + + // convert arguments back into argc-argv form that Mir wants + int argc = arguments.size(); + char **argv = new char*[argc + 1]; + for (int i = 0; i < argc; i++) { + argv[i] = new char[strlen(arguments.at(i).toStdString().c_str())+1]; + memcpy(argv[i], arguments.at(i).toStdString().c_str(), strlen(arguments.at(i).toStdString().c_str())+1); + } + argv[argc] = '\0'; + + d->server = QSharedPointer<MirServer>(new MirServer(argc, const_cast<const char**>(argv))); + + d->serverThread = new MirServerThread(d->server); + + connect(d->serverThread, &MirServerThread::stopped, this, &QMirServer::stopped); } -bool MirServerWorker::wait_for_mir_startup() +QMirServer::~QMirServer() { - std::unique_lock<decltype(mutex)> lock(mutex); - started_cv.wait_for(lock, std::chrono::seconds{10}, [&]{ return mir_running; }); - return mir_running; + stop(); } -QMirServer::QMirServer(const QSharedPointer<MirServer> &server, QObject *parent) - : QObject(parent) - , m_mirServer(new MirServerWorker(server)) +bool QMirServer::start() { - m_mirServer->moveToThread(&m_mirThread); + Q_D(QMirServer); - connect(this, &QMirServer::run, m_mirServer, &MirServerWorker::run); - connect(this, &QMirServer::stop, m_mirServer, &MirServerWorker::stop); + d->serverThread->start(QThread::TimeCriticalPriority); - connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QMirServer::shutDownMirServer); - connect(m_mirServer, &MirServerWorker::stopped, this, &QMirServer::shutDownQApplication, Qt::DirectConnection); // since no event loop - - m_mirThread.start(QThread::TimeCriticalPriority); - Q_EMIT run(); - - if (!m_mirServer->wait_for_mir_startup()) + if (!d->serverThread->waitForMirStartup()) { qCritical() << "ERROR: QMirServer - Mir failed to start"; - exit(2); + return false; } -} -QMirServer::~QMirServer() -{ - shutDownMirServer(); + Q_EMIT started(); + return true; } -void QMirServer::shutDownMirServer() +void QMirServer::stop() { - if (m_mirThread.isRunning()) { - m_mirServer->stop(); - m_mirThread.wait(); + Q_D(QMirServer); + + if (d->serverThread->isRunning()) { + d->serverThread->stop(); + if (!d->serverThread->wait(10000)) { + // do something to indicate fail during shutdown + qCritical() << "ERROR: QMirServer - Mir failed to shut down correctly, terminating it"; + d->serverThread->terminate(); + } } } -void QMirServer::shutDownQApplication() +bool QMirServer::isRunning() const { - if (m_mirThread.isRunning()) - m_mirThread.quit(); + Q_D(const QMirServer); + return d->serverThread->isRunning(); +} - // if unexpected mir server stop, better quit the QApplication - if (!QCoreApplication::closingDown()) { - QCoreApplication::quit(); - } +QWeakPointer<MirServer> QMirServer::mirServer() const +{ + Q_D(const QMirServer); + return d->server.toWeakRef(); } diff --git a/src/platforms/mirserver/qmirserver.h b/src/platforms/mirserver/qmirserver.h index be74149..ecb943b 100644 --- a/src/platforms/mirserver/qmirserver.h +++ b/src/platforms/mirserver/qmirserver.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical, Ltd. + * Copyright (C) 2013-2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by @@ -19,63 +19,35 @@ // Qt #include <QObject> -#include <QThread> -#include <QSharedPointer> +#include <QWeakPointer> -// local -#include "mirserver.h" +class QMirServerPrivate; +class MirServer; -#include <condition_variable> -#include <mutex> - -// Wrap mir::Server with QObject, so it can be controlled via QThread -class MirServerWorker : public QObject +class QMirServer: public QObject { Q_OBJECT public: - MirServerWorker(const QSharedPointer<MirServer> &server) - : server(server) - {} - - bool wait_for_mir_startup(); + QMirServer(const QStringList &arguments, QObject* parent=0); + virtual ~QMirServer(); -Q_SIGNALS: - void stopped(); + bool start(); + Q_SLOT void stop(); + bool isRunning() const; -public Q_SLOTS: - void run(); - void stop() { server->stop(); } - -private: - std::mutex mutex; - std::condition_variable started_cv; - bool mir_running{false}; - - const QSharedPointer<MirServer> server; -}; - - -class QMirServer: public QObject -{ - Q_OBJECT - -public: - QMirServer(const QSharedPointer<MirServer> &config, QObject* parent=0); - ~QMirServer(); + QWeakPointer<MirServer> mirServer() const; Q_SIGNALS: - void run(); - void stop(); + void started(); + void stopped(); -protected Q_SLOTS: - void shutDownMirServer(); - void shutDownQApplication(); +protected: + QMirServerPrivate * const d_ptr; private: - QThread m_mirThread; - MirServerWorker *m_mirServer; Q_DISABLE_COPY(QMirServer) + Q_DECLARE_PRIVATE(QMirServer) }; #endif // QMIRSERVER_H diff --git a/src/platforms/mirserver/qmirserver_p.cpp b/src/platforms/mirserver/qmirserver_p.cpp new file mode 100644 index 0000000..d784a46 --- /dev/null +++ b/src/platforms/mirserver/qmirserver_p.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// Mir +#include <mir/main_loop.h> + +// local +#include "qmirserver_p.h" + + +void MirServerThread::run() +{ + auto const main_loop = server->the_main_loop(); + // By enqueuing the notification code in the main loop, we are + // ensuring that the server has really and fully started before + // leaving wait_for_startup(). + main_loop->enqueue( + this, + [&] + { + std::lock_guard<std::mutex> lock(mutex); + mir_running = true; + started_cv.notify_one(); + }); + + server->run(); // blocks until Mir server stopped + Q_EMIT stopped(); +} + +void MirServerThread::stop() +{ + server->stop(); +} + +bool MirServerThread::waitForMirStartup() +{ + std::unique_lock<decltype(mutex)> lock(mutex); + started_cv.wait_for(lock, std::chrono::seconds{10}, [&]{ return mir_running; }); + return mir_running; +} diff --git a/src/platforms/mirserver/qmirserver_p.h b/src/platforms/mirserver/qmirserver_p.h new file mode 100644 index 0000000..6e86d8d --- /dev/null +++ b/src/platforms/mirserver/qmirserver_p.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2015 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QMIRSERVER_P_H +#define QMIRSERVER_P_H + +// Qt +#include <QThread> +#include <QSharedPointer> + +// std +#include <condition_variable> +#include <mutex> + +// local +#include "mirserver.h" + +class QMirServer; +class MirServerThread; + +struct QMirServerPrivate +{ + QSharedPointer<MirServer> server; + MirServerThread *serverThread; +}; + + +class MirServerThread : public QThread +{ + Q_OBJECT + +public: + MirServerThread(const QSharedPointer<MirServer> &server) + : server(server) + {} + + bool waitForMirStartup(); + +Q_SIGNALS: + void stopped(); + +public Q_SLOTS: + void run() override; + void stop(); + +private: + std::mutex mutex; + std::condition_variable started_cv; + bool mir_running{false}; + + const QSharedPointer<MirServer> server; +}; + +#endif // QMIRSERVER_P_H diff --git a/src/platforms/mirserver/qteventfeeder.cpp b/src/platforms/mirserver/qteventfeeder.cpp index 6c6dfa6..5490096 100644 --- a/src/platforms/mirserver/qteventfeeder.cpp +++ b/src/platforms/mirserver/qteventfeeder.cpp @@ -219,11 +219,11 @@ QtEventFeeder::~QtEventFeeder() delete mQtWindowSystem; } -void QtEventFeeder::dispatch(MirEvent const& event) +bool QtEventFeeder::dispatch(MirEvent const& event) { auto type = mir_event_get_type(&event); if (type != mir_event_type_input) - return; + return false; auto iev = mir_event_get_input_event(&event); switch (mir_input_event_get_type(iev)) { @@ -238,6 +238,8 @@ void QtEventFeeder::dispatch(MirEvent const& event) default: break; } + + return true; } namespace @@ -423,17 +425,6 @@ void QtEventFeeder::stop() // not used } -void QtEventFeeder::configuration_changed(std::chrono::nanoseconds when) -{ - Q_UNUSED(when); -} - -void QtEventFeeder::device_reset(int32_t device_id, std::chrono::nanoseconds when) -{ - Q_UNUSED(device_id); - Q_UNUSED(when); -} - void QtEventFeeder::validateTouches(ulong timestamp, QList<QWindowSystemInterface::TouchPoint> &touchPoints) { diff --git a/src/platforms/mirserver/qteventfeeder.h b/src/platforms/mirserver/qteventfeeder.h index 48113bf..d786715 100644 --- a/src/platforms/mirserver/qteventfeeder.h +++ b/src/platforms/mirserver/qteventfeeder.h @@ -61,9 +61,7 @@ public: static const int MirEventActionPointerIndexMask; static const int MirEventActionPointerIndexShift; - void configuration_changed(std::chrono::nanoseconds when) override; - void device_reset(int32_t device_id, std::chrono::nanoseconds when) override; - void dispatch(MirEvent const& event) override; + bool dispatch(MirEvent const& event) override; void start() override; void stop() override; |