summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Pokorny <andreas.pokorny@canonical.com>2015-06-24 19:17:08 +0200
committerAndreas Pokorny <andreas.pokorny@canonical.com>2015-06-24 19:17:08 +0200
commitaee914d643adf4994c655cce06998d1dd06d98d6 (patch)
treea32b2891baabc5b60f689341c7520485a9696550 /src
parenta36d99e78c2407aa540a04abb07352dec8e90a04 (diff)
parentec03118336af538ce0af198adb9cdc571150ae16 (diff)
merge trunk
Diffstat (limited to 'src')
-rw-r--r--src/modules/Unity/Application/CMakeLists.txt1
-rw-r--r--src/modules/Unity/Application/application.cpp16
-rw-r--r--src/modules/Unity/Application/application.h19
-rw-r--r--src/modules/Unity/Application/application_manager.cpp34
-rw-r--r--src/modules/Unity/Application/desktopfilereader.cpp96
-rw-r--r--src/modules/Unity/Application/desktopfilereader.h5
-rw-r--r--src/modules/Unity/Application/mirsurfaceitem.cpp43
-rw-r--r--src/modules/Unity/Application/mirsurfaceitem.h26
-rw-r--r--src/platforms/mirserver/CMakeLists.txt1
-rw-r--r--src/platforms/mirserver/display.cpp7
-rw-r--r--src/platforms/mirserver/display.h12
-rw-r--r--src/platforms/mirserver/miropenglcontext.cpp5
-rw-r--r--src/platforms/mirserver/miropenglcontext.h1
-rw-r--r--src/platforms/mirserver/mirserverintegration.cpp59
-rw-r--r--src/platforms/mirserver/mirserverintegration.h7
-rw-r--r--src/platforms/mirserver/nativeinterface.cpp23
-rw-r--r--src/platforms/mirserver/nativeinterface.h6
-rw-r--r--src/platforms/mirserver/qmirserver.cpp101
-rw-r--r--src/platforms/mirserver/qmirserver.h60
-rw-r--r--src/platforms/mirserver/qmirserver_p.cpp53
-rw-r--r--src/platforms/mirserver/qmirserver_p.h67
21 files changed, 390 insertions, 252 deletions
diff --git a/src/modules/Unity/Application/CMakeLists.txt b/src/modules/Unity/Application/CMakeLists.txt
index 7a0154a..8c437e6 100644
--- a/src/modules/Unity/Application/CMakeLists.txt
+++ b/src/modules/Unity/Application/CMakeLists.txt
@@ -1,5 +1,4 @@
include_directories(
- ${APPLICATION_API_INCLUDE_DIRS}
${GLIB_INCLUDE_DIRS}
${GIO_INCLUDE_DIRS}
${GIO_UNIX_INCLUDE_DIRS}
diff --git a/src/modules/Unity/Application/application.cpp b/src/modules/Unity/Application/application.cpp
index 4714c22..cf37c92 100644
--- a/src/modules/Unity/Application/application.cpp
+++ b/src/modules/Unity/Application/application.cpp
@@ -60,12 +60,9 @@ Application::Application(const QSharedPointer<TaskController>& taskController,
// FIXME(greyback) need to save long appId internally until ubuntu-app-launch can hide it from us
m_longAppId = desktopFileReader->file().remove(QRegExp(".desktop$")).split('/').last();
- // FIXME: This is a hack. Remove once we have a real implementation for knowing the supported
- // orientations of an app
- m_supportedOrientations = PortraitOrientation
- | LandscapeOrientation
- | InvertedPortraitOrientation
- | InvertedLandscapeOrientation;
+ m_supportedOrientations = m_desktopData->supportedOrientations();
+
+ m_rotatesWindowContents = m_desktopData->rotatesWindowContents();
}
Application::~Application()
@@ -355,11 +352,16 @@ QString Application::longAppId() const
return m_longAppId;
}
-Application::SupportedOrientations Application::supportedOrientations() const
+Qt::ScreenOrientations Application::supportedOrientations() const
{
return m_supportedOrientations;
}
+bool Application::rotatesWindowContents() const
+{
+ return m_rotatesWindowContents;
+}
+
Session* Application::session() const
{
return m_session;
diff --git a/src/modules/Unity/Application/application.h b/src/modules/Unity/Application/application.h
index a80f852..dff36cd 100644
--- a/src/modules/Unity/Application/application.h
+++ b/src/modules/Unity/Application/application.h
@@ -47,27 +47,15 @@ class Application : public unity::shell::application::ApplicationInfoInterface
{
Q_OBJECT
- Q_FLAGS(Orientation SupportedOrientations)
-
Q_PROPERTY(QString desktopFile READ desktopFile CONSTANT)
Q_PROPERTY(QString exec READ exec CONSTANT)
Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged)
Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
- Q_PROPERTY(SupportedOrientations supportedOrientations READ supportedOrientations CONSTANT)
Q_PROPERTY(Session* session READ session NOTIFY sessionChanged DESIGNABLE false)
public:
Q_DECLARE_FLAGS(Stages, Stage)
- // Matching Qt::ScreenOrientation values for convenience
- enum Orientation {
- PortraitOrientation = 0x1,
- LandscapeOrientation = 0x2,
- InvertedPortraitOrientation = 0x4,
- InvertedLandscapeOrientation = 0x8
- };
- Q_DECLARE_FLAGS(SupportedOrientations, Orientation)
-
Application(const QSharedPointer<TaskController>& taskController,
const QSharedPointer<SharedWakelock>& sharedWakelock,
DesktopFileReader *desktopFileReader,
@@ -90,6 +78,8 @@ public:
QColor splashColor() const override;
QColor splashColorHeader() const override;
QColor splashColorFooter() const override;
+ Qt::ScreenOrientations supportedOrientations() const override;
+ bool rotatesWindowContents() const override;
void setStage(Stage stage);
void setState(State state);
@@ -105,7 +95,6 @@ public:
bool fullscreen() const;
Stages supportedStages() const;
- SupportedOrientations supportedOrientations() const;
pid_t pid() const;
@@ -140,7 +129,8 @@ private:
bool m_focused;
bool m_canBeResumed;
QStringList m_arguments;
- SupportedOrientations m_supportedOrientations;
+ Qt::ScreenOrientations m_supportedOrientations;
+ bool m_rotatesWindowContents;
Session *m_session;
friend class ApplicationManager;
@@ -151,6 +141,5 @@ private:
} // namespace qtmir
Q_DECLARE_METATYPE(qtmir::Application*)
-Q_DECLARE_OPERATORS_FOR_FLAGS(qtmir::Application::SupportedOrientations)
#endif // APPLICATION_H
diff --git a/src/modules/Unity/Application/application_manager.cpp b/src/modules/Unity/Application/application_manager.cpp
index 6f6e5a6..ea316e7 100644
--- a/src/modules/Unity/Application/application_manager.cpp
+++ b/src/modules/Unity/Application/application_manager.cpp
@@ -62,36 +62,6 @@ namespace qtmir
namespace {
-// FIXME: AppManager should not implement policy based on display geometry, shell should do that
-bool forceAllAppsIntoMainStage(const QSharedPointer<MirServer> &mirServer)
-{
- const int tabletModeMinimimWithGU = 100;
-
- // Obtain display size
- //TODO: should use mir::graphics::Display::configuration
- mir::geometry::Rectangles view_area;
- mirServer->the_display()->for_each_display_sync_group(
- [&view_area](mir::graphics::DisplaySyncGroup &group) {
- group.for_each_display_buffer(
- [&view_area](const mir::graphics::DisplayBuffer &db) {
- view_area.add(db.view_area());
- });
- });
-
- // Get current Grid Unit value
- int gridUnitPx = 8;
- QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
- if (!gridUnitString.isEmpty()) {
- bool ok;
- int value = gridUnitString.toInt(&ok);
- if (ok) {
- gridUnitPx = value;
- }
- }
-
- return (view_area.bounding_rectangle().size.width.as_int() < tabletModeMinimimWithGU * gridUnitPx);
-}
-
// FIXME: To be removed once shell has fully adopted short appIds!!
QString toShortAppIdIfPossible(const QString &appId) {
QRegExp longAppIdMask("[a-z0-9][a-z0-9+.-]+_[a-zA-Z0-9+.-]+_[0-9][a-zA-Z0-9.+:~-]*");
@@ -556,10 +526,6 @@ void ApplicationManager::onProcessStarting(const QString &appId)
return;
}
- // override stage if necessary (i.e. side stage invalid on phone)
- if (application->stage() == Application::SideStage && forceAllAppsIntoMainStage(m_mirServer))
- application->setStage(Application::MainStage);
-
add(application);
Q_EMIT focusRequested(appId);
}
diff --git a/src/modules/Unity/Application/desktopfilereader.cpp b/src/modules/Unity/Application/desktopfilereader.cpp
index 303e55f..2c2963a 100644
--- a/src/modules/Unity/Application/desktopfilereader.cpp
+++ b/src/modules/Unity/Application/desktopfilereader.cpp
@@ -68,6 +68,8 @@ DesktopFileReader::DesktopFileReader(const QString &appId, const QFileInfo &desk
: d_ptr(new DesktopFileReaderPrivate(this))
{
Q_D(DesktopFileReader);
+ qCDebug(QTMIR_APPLICATIONS) << "Loading desktop file" << desktopFile.absoluteFilePath()
+ << "for appId" << appId;
d->appId = appId;
d->file = desktopFile.absoluteFilePath();
@@ -202,6 +204,100 @@ QString DesktopFileReader::splashColorFooter() const
return d->getKey("X-Ubuntu-Splash-Color-Footer");
}
+Qt::ScreenOrientations DesktopFileReader::supportedOrientations() const
+{
+ Q_D(const DesktopFileReader);
+ Qt::ScreenOrientations result;
+
+ if (!parseOrientations(d->getKey("X-Ubuntu-Supported-Orientations"), result)) {
+ qCWarning(QTMIR_APPLICATIONS) << d->file << "has an invalid X-Ubuntu-Supported-Orientations entry.";
+ }
+
+ return result;
+}
+
+bool DesktopFileReader::rotatesWindowContents() const
+{
+ Q_D(const DesktopFileReader);
+ bool result;
+
+ if (!parseBoolean(d->getKey("X-Ubuntu-Rotates-Window-Contents"), result)) {
+ qCWarning(QTMIR_APPLICATIONS) << d->file << "has an invalid X-Ubuntu-Rotates-Window-Contents entry.";
+ }
+
+ return result;
+}
+
+bool DesktopFileReader::parseOrientations(const QString &rawString, Qt::ScreenOrientations &result)
+{
+ // Default to all orientations
+ result = Qt::PortraitOrientation | Qt::LandscapeOrientation
+ | Qt::InvertedPortraitOrientation | Qt::InvertedLandscapeOrientation;
+
+ if (rawString.isEmpty()) {
+ return true;
+ }
+
+ Qt::ScreenOrientations parsedOrientations = 0;
+ bool ok = true;
+
+ QStringList orientationsList = rawString
+ .simplified()
+ .replace(QChar(','), ";")
+ .remove(QChar(' '))
+ .remove(QChar('-'))
+ .remove(QChar('_'))
+ .toLower()
+ .split(";");
+
+ for (int i = 0; i < orientationsList.count() && ok; ++i) {
+ const QString &orientationString = orientationsList.at(i);
+ if (orientationString.isEmpty()) {
+ // skip it
+ continue;
+ }
+
+ if (orientationString == "portrait") {
+ parsedOrientations |= Qt::PortraitOrientation;
+ } else if (orientationString == "landscape") {
+ parsedOrientations |= Qt::LandscapeOrientation;
+ } else if (orientationString == "invertedportrait") {
+ parsedOrientations |= Qt::InvertedPortraitOrientation;
+ } else if (orientationString == "invertedlandscape") {
+ parsedOrientations |= Qt::InvertedLandscapeOrientation;
+ } else if (orientationsList.count() == 1 && orientationString == "primary") {
+ // Special case: primary orientation must be alone
+ // There's no sense in supporting primary orientation + other orientations
+ // like "primary,landscape"
+ parsedOrientations = Qt::PrimaryOrientation;
+ } else {
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ result = parsedOrientations;
+ }
+
+ return ok;
+}
+
+bool DesktopFileReader::parseBoolean(const QString &rawString, bool &result)
+{
+ QString cookedString = rawString.trimmed().toLower();
+
+ result = cookedString == "y"
+ || cookedString == "1"
+ || cookedString == "yes"
+ || cookedString == "true";
+
+ return result || rawString.isEmpty()
+ || cookedString == "n"
+ || cookedString == "0"
+ || cookedString == "no"
+ || cookedString == "false";
+}
+
bool DesktopFileReader::loaded() const
{
Q_D(const DesktopFileReader);
diff --git a/src/modules/Unity/Application/desktopfilereader.h b/src/modules/Unity/Application/desktopfilereader.h
index 3670469..771855b 100644
--- a/src/modules/Unity/Application/desktopfilereader.h
+++ b/src/modules/Unity/Application/desktopfilereader.h
@@ -55,8 +55,13 @@ public:
virtual QString splashColor() const;
virtual QString splashColorHeader() const;
virtual QString splashColorFooter() const;
+ virtual Qt::ScreenOrientations supportedOrientations() const;
+ virtual bool rotatesWindowContents() const;
virtual bool loaded() const;
+ static bool parseOrientations(const QString &rawString, Qt::ScreenOrientations &result);
+ static bool parseBoolean(const QString &rawString, bool &result);
+
protected:
DesktopFileReader(const QString &appId, const QFileInfo &desktopFile);
diff --git a/src/modules/Unity/Application/mirsurfaceitem.cpp b/src/modules/Unity/Application/mirsurfaceitem.cpp
index b816f65..c8d895a 100644
--- a/src/modules/Unity/Application/mirsurfaceitem.cpp
+++ b/src/modules/Unity/Application/mirsurfaceitem.cpp
@@ -196,7 +196,7 @@ MirSurfaceItem::MirSurfaceItem(std::shared_ptr<mir::scene::Surface> surface,
, m_shell(shell)
, m_firstFrameDrawn(false)
, m_live(true)
- , m_orientation(Qt::PortraitOrientation)
+ , m_orientationAngle(Angle0)
, m_textureProvider(nullptr)
, m_lastTouchEvent(nullptr)
{
@@ -306,49 +306,42 @@ MirSurfaceItem::State MirSurfaceItem::state() const
return static_cast<MirSurfaceItem::State>(m_surface->state());
}
-Qt::ScreenOrientation MirSurfaceItem::orientation() const
+MirSurfaceItem::OrientationAngle MirSurfaceItem::orientationAngle() const
{
- return m_orientation;
+ return m_orientationAngle;
}
-void MirSurfaceItem::setOrientation(const Qt::ScreenOrientation orientation)
+void MirSurfaceItem::setOrientationAngle(MirSurfaceItem::OrientationAngle angle)
{
- qCDebug(QTMIR_SURFACES) << "MirSurfaceItem::setOrientation - orientation=" << orientation;
+ qCDebug(QTMIR_SURFACES, "MirSurfaceItem::setOrientationAngle(%d)", angle);
- if (m_orientation == orientation)
+ if (m_orientationAngle == angle)
return;
MirOrientation mirOrientation;
- Qt::ScreenOrientation nativeOrientation = QGuiApplication::primaryScreen()->nativeOrientation();
- const bool landscapeNativeOrientation = (nativeOrientation == Qt::LandscapeOrientation);
- Qt::ScreenOrientation requestedOrientation = orientation;
- if (orientation == Qt::PrimaryOrientation) { // means orientation equals native orientation, set it as such
- requestedOrientation = nativeOrientation;
- }
-
- switch(requestedOrientation) {
- case Qt::PortraitOrientation:
- mirOrientation = (landscapeNativeOrientation) ? mir_orientation_right : mir_orientation_normal;
+ switch (angle) {
+ case Angle0:
+ mirOrientation = mir_orientation_normal;
break;
- case Qt::LandscapeOrientation:
- mirOrientation = (landscapeNativeOrientation) ? mir_orientation_normal : mir_orientation_left;
+ case Angle90:
+ mirOrientation = mir_orientation_right;
break;
- case Qt::InvertedPortraitOrientation:
- mirOrientation = (landscapeNativeOrientation) ? mir_orientation_left : mir_orientation_inverted;
+ case Angle180:
+ mirOrientation = mir_orientation_inverted;
break;
- case Qt::InvertedLandscapeOrientation:
- mirOrientation = (landscapeNativeOrientation) ? mir_orientation_inverted : mir_orientation_right;
+ case Angle270:
+ mirOrientation = mir_orientation_left;
break;
default:
- qWarning("Unrecognized Qt::ScreenOrientation!");
+ qCWarning(QTMIR_SURFACES, "Unsupported orientation angle: %d", angle);
return;
}
m_surface->set_orientation(mirOrientation);
- m_orientation = orientation;
- Q_EMIT orientationChanged();
+ m_orientationAngle = angle;
+ Q_EMIT orientationAngleChanged(angle);
}
QString MirSurfaceItem::name() const
diff --git a/src/modules/Unity/Application/mirsurfaceitem.h b/src/modules/Unity/Application/mirsurfaceitem.h
index 769f4bb..fd3ab45 100644
--- a/src/modules/Unity/Application/mirsurfaceitem.h
+++ b/src/modules/Unity/Application/mirsurfaceitem.h
@@ -48,12 +48,17 @@ class MirSurfaceItem : public QQuickItem
Q_OBJECT
Q_ENUMS(Type)
Q_ENUMS(State)
+ Q_ENUMS(OrientationAngle)
Q_PROPERTY(Type type READ type NOTIFY typeChanged)
Q_PROPERTY(State state READ state NOTIFY stateChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(bool live READ live NOTIFY liveChanged)
- Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged DESIGNABLE false)
+
+ // How many degrees, clockwise, the UI in the surface has to rotate to match with the
+ // shell UI orientation
+ Q_PROPERTY(OrientationAngle orientationAngle READ orientationAngle WRITE setOrientationAngle
+ NOTIFY orientationAngleChanged DESIGNABLE false)
public:
explicit MirSurfaceItem(std::shared_ptr<mir::scene::Surface> surface,
@@ -83,12 +88,18 @@ public:
Fullscreen = mir_surface_state_fullscreen,
};
+ enum OrientationAngle {
+ Angle0 = 0,
+ Angle90 = 90,
+ Angle180 = 180,
+ Angle270 = 270
+ };
+
//getters
Type type() const;
State state() const;
QString name() const;
bool live() const;
- Qt::ScreenOrientation orientation() const;
SessionInterface *session() const;
Q_INVOKABLE void release();
@@ -102,7 +113,9 @@ public:
bool isFirstFrameDrawn() const { return m_firstFrameDrawn; }
- void setOrientation(const Qt::ScreenOrientation orientation);
+ OrientationAngle orientationAngle() const;
+ void setOrientationAngle(OrientationAngle angle);
+
void setSession(SessionInterface *app);
// to allow easy touch event injection from tests
@@ -116,7 +129,7 @@ Q_SIGNALS:
void typeChanged();
void stateChanged();
void nameChanged();
- void orientationChanged();
+ void orientationAngleChanged(OrientationAngle angle);
void liveChanged(bool live);
void firstFrameDrawn(MirSurfaceItem *item);
@@ -182,7 +195,9 @@ private:
MirShell *const m_shell;
bool m_firstFrameDrawn;
bool m_live;
- Qt::ScreenOrientation m_orientation; //FIXME - have to save the state as Mir has no getter for it (bug:1357429)
+
+ //FIXME - have to save the state as Mir has no getter for it (bug:1357429)
+ OrientationAngle m_orientationAngle;
QMirSurfaceTextureProvider *m_textureProvider;
@@ -218,5 +233,6 @@ private:
} // namespace qtmir
Q_DECLARE_METATYPE(qtmir::MirSurfaceItem*)
+Q_DECLARE_METATYPE(qtmir::MirSurfaceItem::OrientationAngle)
#endif // MIRSURFACEITEM_H
diff --git a/src/platforms/mirserver/CMakeLists.txt b/src/platforms/mirserver/CMakeLists.txt
index a47cb1a..60abe20 100644
--- a/src/platforms/mirserver/CMakeLists.txt
+++ b/src/platforms/mirserver/CMakeLists.txt
@@ -44,6 +44,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