Merge lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064 into lp:qtmir

Proposed by Michał Sawicz
Status: Merged
Merged at revision: 462
Proposed branch: lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064
Merge into: lp:qtmir
Diff against target: 4345 lines (+3483/-201)
42 files modified
debian/changelog (+30/-0)
debian/tests/control (+0/-5)
debian/tests/run-tests (+0/-10)
src/modules/Unity/Application/mirsurface.cpp (+5/-0)
src/modules/Unity/Application/mirsurfacemanager.cpp (+15/-0)
src/modules/Unity/Application/mirsurfacemanager.h (+5/-1)
src/platforms/mirserver/CMakeLists.txt (+2/-0)
src/platforms/mirserver/argvHelper.h (+52/-0)
src/platforms/mirserver/miropenglcontext.cpp (+7/-2)
src/platforms/mirserver/miropenglcontext.h (+2/-0)
src/platforms/mirserver/mirserver.cpp (+24/-11)
src/platforms/mirserver/mirserver.h (+1/-1)
src/platforms/mirserver/mirserverintegration.cpp (+2/-2)
src/platforms/mirserver/mirserverintegration.h (+1/-1)
src/platforms/mirserver/plugin.cpp (+4/-8)
src/platforms/mirserver/plugin.h (+1/-2)
src/platforms/mirserver/qmirserver.cpp (+2/-11)
src/platforms/mirserver/qmirserver.h (+1/-1)
src/platforms/mirserver/screen.cpp (+24/-4)
src/platforms/mirserver/screen.h (+3/-1)
src/platforms/mirserver/screenwindow.cpp (+1/-1)
src/platforms/mirserver/wm-wip/CMakeLists.txt (+22/-0)
src/platforms/mirserver/wm-wip/README (+5/-0)
src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp (+312/-0)
src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h (+252/-0)
src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp (+946/-0)
src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h (+132/-0)
src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp (+640/-0)
src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h (+124/-0)
src/platforms/mirserver/wm-wip/server_example_window_management.cpp (+155/-0)
src/platforms/mirserver/wm-wip/server_example_window_management.h (+33/-0)
src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp (+406/-0)
src/platforms/mirserver/wm-wip/server_example_window_management_info.h (+103/-0)
tests/framework/mock_proc_info.cpp (+2/-0)
tests/framework/mock_session.cpp (+1/-0)
tests/framework/mock_task_controller.cpp (+4/-4)
tests/framework/qtmir_test.cpp (+2/-2)
tests/mirserver/ArgvHelper/CMakeLists.txt (+18/-0)
tests/mirserver/ArgvHelper/argvHelper_test.cpp (+72/-0)
tests/mirserver/CMakeLists.txt (+1/-0)
tests/mirserver/Screen/screen_test.cpp (+17/-3)
tests/modules/ApplicationManager/application_manager_test.cpp (+54/-131)
To merge this branch: bzr merge lp:~ci-train-bot/qtmir/qtmir-ubuntu-xenial-landing-064
Reviewer Review Type Date Requested Status
Mir development team Pending
Review via email: mp+288756@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2016-02-19 10:41:19 +0000
+++ debian/changelog 2016-03-11 11:36:44 +0000
@@ -1,3 +1,33 @@
1qtmir (0.4.7+16.04.20160310.1-0ubuntu1) xenial; urgency=medium
2
3 [ Alan Griffiths ]
4 * Copy the Window Management work-in-progress from Mir examples.
5
6 [ Alberto Aguirre ]
7 * Hook MirOpenGLContext::doneCurrent to Screen::doneCurrent
8
9 [ Daniel d'Andrada ]
10 * Ensure QmlEngine doesn't delete our MirSurfaces
11
12 [ Gerry Boland ]
13 * Allow Mir remove command line arguments it understands, before
14 letting Qt process them.
15 * Ensure ScreenWindow geometry correctly set and used after moving
16 Screen (LP: #1545286)
17 * Screen: only enable orientation sensor for internal display. (LP:
18 #1545286)
19
20 [ Michael Terry ]
21 * Fix some mocks to use more realistic code paths.
22
23 [ Michael Zanetti ]
24 * Add a dedicated property for the inputMethodSurface (LP: #1545286)
25
26 [ Michał Sawicz ]
27 * Drop dummy autopkgtest
28
29 -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 10 Mar 2016 09:29:49 +0000
30
1qtmir (0.4.7+16.04.20160219-0ubuntu1) xenial; urgency=medium31qtmir (0.4.7+16.04.20160219-0ubuntu1) xenial; urgency=medium
232
3 * Mir 0.20 Release33 * Mir 0.20 Release
434
=== removed directory 'debian/tests'
=== removed file 'debian/tests/control'
--- debian/tests/control 2015-10-27 15:53:28 +0000
+++ debian/tests/control 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1Tests: run-tests
2Restrictions: build-needed
3Depends: qtdeclarative5-qtmir-plugin,
4 qtmir-desktop,
5 qtmir-tests,
60
=== removed file 'debian/tests/run-tests'
--- debian/tests/run-tests 2015-06-15 15:57:04 +0000
+++ debian/tests/run-tests 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
1#!/bin/sh
2
3set -ex
4
5# Do nothing here. We don't need to run the tests multiple times, and they
6# are already being run during the build phase of the autopkgtest, as we
7# require a built tree to run them, and the tests are run as part of the
8# normal package build process. We do want to test that things install, though
9# and at least one test is actually required, for autopkgtest to work.
10
110
=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
--- src/modules/Unity/Application/mirsurface.cpp 2016-02-11 11:58:16 +0000
+++ src/modules/Unity/Application/mirsurface.cpp 2016-03-11 11:36:44 +0000
@@ -32,6 +32,9 @@
32// mirserver32// mirserver
33#include <logging.h>33#include <logging.h>
3434
35// Qt
36#include <QQmlEngine>
37
35using namespace qtmir;38using namespace qtmir;
3639
37#define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__40#define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__
@@ -223,6 +226,8 @@
223 // in practice rarely happen.226 // in practice rarely happen.
224 m_frameDropperTimer.setInterval(200);227 m_frameDropperTimer.setInterval(200);
225 m_frameDropperTimer.setSingleShot(false);228 m_frameDropperTimer.setSingleShot(false);
229
230 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
226}231}
227232
228MirSurface::~MirSurface()233MirSurface::~MirSurface()
229234
=== modified file 'src/modules/Unity/Application/mirsurfacemanager.cpp'
--- src/modules/Unity/Application/mirsurfacemanager.cpp 2016-02-11 11:58:16 +0000
+++ src/modules/Unity/Application/mirsurfacemanager.cpp 2016-03-11 11:36:44 +0000
@@ -114,6 +114,11 @@
114 if (session)114 if (session)
115 session->registerSurface(qmlSurface);115 session->registerSurface(qmlSurface);
116116
117 if (qmlSurface->type() == Mir::InputMethodType) {
118 m_inputMethodSurface = qmlSurface;
119 Q_EMIT inputMethodSurfaceChanged();
120 }
121
117 // Only notify QML of surface creation once it has drawn its first frame.122 // Only notify QML of surface creation once it has drawn its first frame.
118 connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {123 connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {
119 tracepoint(qtmir, firstFrameDrawn);124 tracepoint(qtmir, firstFrameDrawn);
@@ -155,8 +160,18 @@
155 }160 }
156 }161 }
157162
163 if (qmlSurface->type() == Mir::InputMethodType) {
164 m_inputMethodSurface = nullptr;
165 Q_EMIT inputMethodSurfaceChanged();
166 }
167
158 qmlSurface->setLive(false);168 qmlSurface->setLive(false);
159 Q_EMIT surfaceDestroyed(qmlSurface);169 Q_EMIT surfaceDestroyed(qmlSurface);
160}170}
161171
172MirSurfaceInterface* MirSurfaceManager::inputMethodSurface() const
173{
174 return m_inputMethodSurface;
175}
176
162} // namespace qtmir177} // namespace qtmir
163178
=== modified file 'src/modules/Unity/Application/mirsurfacemanager.h'
--- src/modules/Unity/Application/mirsurfacemanager.h 2016-02-11 11:58:16 +0000
+++ src/modules/Unity/Application/mirsurfacemanager.h 2016-03-11 11:36:44 +0000
@@ -54,7 +54,7 @@
54class MirSurfaceManager : public QObject54class MirSurfaceManager : public QObject
55{55{
56 Q_OBJECT56 Q_OBJECT
5757 Q_PROPERTY(MirSurfaceInterface* inputMethodSurface READ inputMethodSurface NOTIFY inputMethodSurfaceChanged)
58public:58public:
59 explicit MirSurfaceManager(59 explicit MirSurfaceManager(
60 const QSharedPointer<MirServer>& mirServer,60 const QSharedPointer<MirServer>& mirServer,
@@ -66,7 +66,10 @@
6666
67 static MirSurfaceManager* singleton();67 static MirSurfaceManager* singleton();
6868
69 MirSurfaceInterface* inputMethodSurface() const;
70
69Q_SIGNALS:71Q_SIGNALS:
72 void inputMethodSurfaceChanged();
70 void surfaceCreated(MirSurfaceInterface* surface);73 void surfaceCreated(MirSurfaceInterface* surface);
71 void surfaceDestroyed(MirSurfaceInterface* surface);74 void surfaceDestroyed(MirSurfaceInterface* surface);
7275
@@ -86,6 +89,7 @@
86 mir::shell::Shell *const m_shell;89 mir::shell::Shell *const m_shell;
87 SessionManager* m_sessionManager;90 SessionManager* m_sessionManager;
88 static MirSurfaceManager *instance;91 static MirSurfaceManager *instance;
92 MirSurfaceInterface* m_inputMethodSurface = nullptr;
89};93};
9094
91} // namespace qtmir95} // namespace qtmir
9296
=== modified file 'src/platforms/mirserver/CMakeLists.txt'
--- src/platforms/mirserver/CMakeLists.txt 2016-02-11 11:58:16 +0000
+++ src/platforms/mirserver/CMakeLists.txt 2016-03-11 11:36:44 +0000
@@ -36,6 +36,8 @@
36 ${APPLICATION_API_INCLUDE_DIRS}36 ${APPLICATION_API_INCLUDE_DIRS}
37)37)
3838
39add_subdirectory(wm-wip)
40
39# We have to remove -pedantic for tracepoints.c41# We have to remove -pedantic for tracepoints.c
40string (REPLACE " -pedantic " " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS})42string (REPLACE " -pedantic " " " CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
41# Needed to compile tracepoints in C99 mode.43# Needed to compile tracepoints in C99 mode.
4244
=== added file 'src/platforms/mirserver/argvHelper.h'
--- src/platforms/mirserver/argvHelper.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/argvHelper.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,52 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef ARGVHELPER_P_H
18#define ARGVHELPER_P_H
19
20#include <cassert>
21
22namespace qtmir {
23
24// Function to edit argv to strip out unmatched entries of targetArray, so both arrays have identical contents
25// Note: Mir parses out arguments that it understands, but it also removes argv[0] (bug pad.lv/1511509)
26// so need to ensure argv[0] is the binary name as usual.
27void editArgvToMatch(int &argcToEdit, char** argvToEdit, int targetCount, const char* const targetArray[])
28{
29 // Make copy of the argv array of pointers, as we will be editing the original
30 const size_t arraySize = (argcToEdit + 1) * sizeof(char*);
31 char** argvCopy = static_cast<char**>(malloc(arraySize));
32 memcpy(argvCopy, argvToEdit, arraySize);
33
34 int k=1; // index of argv we want to edit - note we'll leave argv[0] alone
35 for (int i=0; i<targetCount; i++) { // taking each argument Mir did not parse out
36 for (int j=1; j<argcToEdit; j++) { // find pointer to same argument in argvCopy (leave arg[0] out)
37 if (strcmp(targetArray[i], argvCopy[j]) == 0) {
38 argvToEdit[k] = const_cast<char*>(argvCopy[j]); // edit argv to position that argument to match argv2.
39 k++;
40 break;
41 }
42 }
43 }
44 assert(k == targetCount+1);
45 argvToEdit[k] = nullptr;
46 free(argvCopy);
47 argcToEdit = targetCount+1; // now argv and targetArray should have list the same strings.
48}
49
50} // namespace qtmir
51
52#endif // ARGVHELPER_P_H
053
=== modified file 'src/platforms/mirserver/miropenglcontext.cpp'
--- src/platforms/mirserver/miropenglcontext.cpp 2015-09-14 22:38:20 +0000
+++ src/platforms/mirserver/miropenglcontext.cpp 2016-03-11 11:36:44 +0000
@@ -36,8 +36,9 @@
36// (i.e. individual display output buffers) to use as a common base context.36// (i.e. individual display output buffers) to use as a common base context.
3737
38MirOpenGLContext::MirOpenGLContext(const QSharedPointer<MirServer> &server, const QSurfaceFormat &format)38MirOpenGLContext::MirOpenGLContext(const QSharedPointer<MirServer> &server, const QSurfaceFormat &format)
39 : m_currentWindow(nullptr)
39#ifndef QT_NO_DEBUG40#ifndef QT_NO_DEBUG
40 : m_logger(new QOpenGLDebugLogger(this))41 , m_logger(new QOpenGLDebugLogger(this))
41#endif42#endif
42{43{
43 auto display = server->the_display();44 auto display = server->the_display();
@@ -131,6 +132,7 @@
131 // ultimately calls Mir's DisplayBuffer::make_current()132 // ultimately calls Mir's DisplayBuffer::make_current()
132 ScreenWindow *screenWindow = static_cast<ScreenWindow*>(surface);133 ScreenWindow *screenWindow = static_cast<ScreenWindow*>(surface);
133 if (screenWindow) {134 if (screenWindow) {
135 m_currentWindow = screenWindow;
134 screenWindow->makeCurrent();136 screenWindow->makeCurrent();
135137
136#ifndef QT_NO_DEBUG138#ifndef QT_NO_DEBUG
@@ -148,7 +150,10 @@
148150
149void MirOpenGLContext::doneCurrent()151void MirOpenGLContext::doneCurrent()
150{152{
151 // FIXME: create a temporary GL context just to release? Would be better to get existing one.153 if (m_currentWindow) {
154 m_currentWindow->doneCurrent();
155 m_currentWindow = nullptr;
156 }
152}157}
153158
154QFunctionPointer MirOpenGLContext::getProcAddress(const QByteArray &procName)159QFunctionPointer MirOpenGLContext::getProcAddress(const QByteArray &procName)
155160
=== modified file 'src/platforms/mirserver/miropenglcontext.h'
--- src/platforms/mirserver/miropenglcontext.h 2015-09-14 22:38:20 +0000
+++ src/platforms/mirserver/miropenglcontext.h 2016-03-11 11:36:44 +0000
@@ -25,6 +25,7 @@
2525
2626
27class MirServer;27class MirServer;
28class ScreenWindow;
2829
29class MirOpenGLContext : public QObject, public QPlatformOpenGLContext30class MirOpenGLContext : public QObject, public QPlatformOpenGLContext
30{31{
@@ -49,6 +50,7 @@
4950
50private:51private:
51 QSurfaceFormat m_format;52 QSurfaceFormat m_format;
53 ScreenWindow *m_currentWindow;
52#ifndef QT_NO_DEBUG54#ifndef QT_NO_DEBUG
53 QOpenGLDebugLogger *m_logger;55 QOpenGLDebugLogger *m_logger;
54#endif56#endif
5557
=== modified file 'src/platforms/mirserver/mirserver.cpp'
--- src/platforms/mirserver/mirserver.cpp 2016-02-11 11:58:16 +0000
+++ src/platforms/mirserver/mirserver.cpp 2016-03-11 11:36:44 +0000
@@ -19,6 +19,7 @@
19#include "mirserver.h"19#include "mirserver.h"
2020
21// local21// local
22#include "argvHelper.h"
22#include "mircursorimages.h"23#include "mircursorimages.h"
23#include "mirwindowmanager.h"24#include "mirwindowmanager.h"
24#include "mirglconfig.h"25#include "mirglconfig.h"
@@ -47,22 +48,24 @@
47namespace msh = mir::shell;48namespace msh = mir::shell;
48namespace ms = mir::scene;49namespace ms = mir::scene;
4950
50namespace
51{
52void ignore_unparsed_arguments(int /*argc*/, char const* const/*argv*/[])
53{
54}
55}
56
57Q_LOGGING_CATEGORY(QTMIR_MIR_MESSAGES, "qtmir.mir")51Q_LOGGING_CATEGORY(QTMIR_MIR_MESSAGES, "qtmir.mir")
5852
59MirServer::MirServer(int argc, char const* argv[],53
54MirServer::MirServer(int &argc, char **argv,
60 const QSharedPointer<ScreenController> &screenController, QObject* parent)55 const QSharedPointer<ScreenController> &screenController, QObject* parent)
61 : QObject(parent)56 : QObject(parent)
62 , m_screenController(screenController)57 , m_screenController(screenController)
63{58{
64 set_command_line_handler(&ignore_unparsed_arguments);59 bool unknownArgsFound = false;
65 set_command_line(argc, argv);60 set_command_line_handler([&argc, &argv, &unknownArgsFound](int filteredCount, const char* const filteredArgv[]) {
61 unknownArgsFound = true;
62 // Want to edit argv to match that which Mir returns, as those are for to Qt alone to process. Edit existing
63 // argc as filteredArgv only defined in this scope.
64 qtmir::editArgvToMatch(argc, argv, filteredCount, filteredArgv);
65 });
66
67 // Casting char** to be a const char** safe as Mir won't change it, nor will we
68 set_command_line(argc, const_cast<const char **>(argv));
6669
67 override_the_session_listener([]70 override_the_session_listener([]
68 {71 {
@@ -130,7 +133,16 @@
130 screenController->init(the_display(), the_compositor());133 screenController->init(the_display(), the_compositor());
131 });134 });
132135
133 apply_settings();136 try {
137 apply_settings();
138 } catch (const std::exception &ex) {
139 qCritical() << ex.what();
140 exit(1);
141 }
142
143 if (!unknownArgsFound) { // mir parsed all the arguments, so edit argv to pretend to have just argv[0]
144 argc = 1;
145 }
134146
135 // We will draw our own cursor.147 // We will draw our own cursor.
136 // FIXME: Call override_the_cusor() instead once this method becomes available in a148 // FIXME: Call override_the_cusor() instead once this method becomes available in a
@@ -142,6 +154,7 @@
142 });154 });
143155
144 qCDebug(QTMIR_MIR_MESSAGES) << "MirServer created";156 qCDebug(QTMIR_MIR_MESSAGES) << "MirServer created";
157 qCDebug(QTMIR_MIR_MESSAGES) << "Command line arguments passed to Qt:" << QCoreApplication::arguments();
145}158}
146159
147// Override default implementation to ensure we terminate the ScreenController first.160// Override default implementation to ensure we terminate the ScreenController first.
148161
=== modified file 'src/platforms/mirserver/mirserver.h'
--- src/platforms/mirserver/mirserver.h 2016-02-11 11:54:59 +0000
+++ src/platforms/mirserver/mirserver.h 2016-03-11 11:36:44 +0000
@@ -41,7 +41,7 @@
41 Q_PROPERTY(PromptSessionListener* promptSessionListener READ promptSessionListener CONSTANT)41 Q_PROPERTY(PromptSessionListener* promptSessionListener READ promptSessionListener CONSTANT)
4242
43public:43public:
44 MirServer(int argc, char const* argv[], const QSharedPointer<ScreenController> &, QObject* parent = 0);44 MirServer(int &argc, char **argv, const QSharedPointer<ScreenController> &, QObject* parent = 0);
45 ~MirServer() = default;45 ~MirServer() = default;
4646
47 /* mir specific */47 /* mir specific */
4848
=== modified file 'src/platforms/mirserver/mirserverintegration.cpp'
--- src/platforms/mirserver/mirserverintegration.cpp 2015-10-21 11:46:33 +0000
+++ src/platforms/mirserver/mirserverintegration.cpp 2016-03-11 11:36:44 +0000
@@ -51,11 +51,11 @@
51namespace mg = mir::graphics;51namespace mg = mir::graphics;
52using qtmir::Clipboard;52using qtmir::Clipboard;
5353
54MirServerIntegration::MirServerIntegration()54MirServerIntegration::MirServerIntegration(int &argc, char **argv)
55 : m_accessibility(new QPlatformAccessibility())55 : m_accessibility(new QPlatformAccessibility())
56 , m_fontDb(new QGenericUnixFontDatabase())56 , m_fontDb(new QGenericUnixFontDatabase())
57 , m_services(new Services)57 , m_services(new Services)
58 , m_mirServer(new QMirServer(QCoreApplication::arguments()))58 , m_mirServer(new QMirServer(argc, argv))
59 , m_nativeInterface(nullptr)59 , m_nativeInterface(nullptr)
60 , m_clipboard(new Clipboard)60 , m_clipboard(new Clipboard)
61{61{
6262
=== modified file 'src/platforms/mirserver/mirserverintegration.h'
--- src/platforms/mirserver/mirserverintegration.h 2015-08-20 10:16:54 +0000
+++ src/platforms/mirserver/mirserverintegration.h 2016-03-11 11:36:44 +0000
@@ -31,7 +31,7 @@
31class MirServerIntegration : public QPlatformIntegration31class MirServerIntegration : public QPlatformIntegration
32{32{
33public:33public:
34 MirServerIntegration();34 MirServerIntegration(int &argc, char **argv);
35 ~MirServerIntegration();35 ~MirServerIntegration();
3636
37 bool hasCapability(QPlatformIntegration::Capability cap) const override;37 bool hasCapability(QPlatformIntegration::Capability cap) const override;
3838
=== modified file 'src/platforms/mirserver/plugin.cpp'
--- src/platforms/mirserver/plugin.cpp 2015-08-11 12:08:32 +0000
+++ src/platforms/mirserver/plugin.cpp 2016-03-11 11:36:44 +0000
@@ -17,14 +17,10 @@
17#include "plugin.h"17#include "plugin.h"
18#include "mirserverintegration.h"18#include "mirserverintegration.h"
1919
20QStringList MirServerIntegrationPlugin::keys() const {20QPlatformIntegration *MirServerIntegrationPlugin::create(const QString &system, const QStringList &/*paramList*/,
21 QStringList list;21 int &argc, char **argv)
22 list << "mirserver";22{
23 return list;
24}
25
26QPlatformIntegration* MirServerIntegrationPlugin::create(const QString &system, const QStringList &) {
27 if (system.toLower() == "mirserver")23 if (system.toLower() == "mirserver")
28 return new MirServerIntegration;24 return new MirServerIntegration(argc, argv);
29 return 0;25 return 0;
30}26}
3127
=== modified file 'src/platforms/mirserver/plugin.h'
--- src/platforms/mirserver/plugin.h 2015-08-11 12:08:32 +0000
+++ src/platforms/mirserver/plugin.h 2016-03-11 11:36:44 +0000
@@ -25,8 +25,7 @@
25 Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirserver.json")25 Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirserver.json")
2626
27public:27public:
28 QStringList keys() const;28 QPlatformIntegration *create(const QString &system, const QStringList &paramList, int &argc, char **argv) override;
29 QPlatformIntegration* create(const QString&, const QStringList&);
30};29};
3130
32#endif // PLUGIN_H31#endif // PLUGIN_H
3332
=== modified file 'src/platforms/mirserver/qmirserver.cpp'
--- src/platforms/mirserver/qmirserver.cpp 2015-11-19 12:55:57 +0000
+++ src/platforms/mirserver/qmirserver.cpp 2016-03-11 11:36:44 +0000
@@ -26,24 +26,15 @@
26#include "screencontroller.h"26#include "screencontroller.h"
27#include "screen.h"27#include "screen.h"
2828
29QMirServer::QMirServer(const QStringList &arguments, QObject *parent)29QMirServer::QMirServer(int &argc, char **argv, QObject *parent)
30 : QObject(parent)30 : QObject(parent)
31 , d_ptr(new QMirServerPrivate())31 , d_ptr(new QMirServerPrivate())
32{32{
33 Q_D(QMirServer);33 Q_D(QMirServer);
3434
35 // convert arguments back into argc-argv form that Mir wants
36 int argc = arguments.size();
37 char **argv = new char*[argc + 1];
38 for (int i = 0; i < argc; i++) {
39 argv[i] = new char[strlen(arguments.at(i).toStdString().c_str())+1];
40 memcpy(argv[i], arguments.at(i).toStdString().c_str(), strlen(arguments.at(i).toStdString().c_str())+1);
41 }
42 argv[argc] = nullptr;
43
44 d->screenController = QSharedPointer<ScreenController>(new ScreenController());35 d->screenController = QSharedPointer<ScreenController>(new ScreenController());
4536
46 d->server = QSharedPointer<MirServer>(new MirServer(argc, const_cast<const char**>(argv), d->screenController));37 d->server = QSharedPointer<MirServer>(new MirServer(argc, argv, d->screenController));
4738
48 d->serverThread = new MirServerThread(d->server);39 d->serverThread = new MirServerThread(d->server);
4940
5041
=== modified file 'src/platforms/mirserver/qmirserver.h'
--- src/platforms/mirserver/qmirserver.h 2015-08-20 10:16:54 +0000
+++ src/platforms/mirserver/qmirserver.h 2016-03-11 11:36:44 +0000
@@ -30,7 +30,7 @@
30 Q_OBJECT30 Q_OBJECT
3131
32public:32public:
33 QMirServer(const QStringList &arguments, QObject* parent=0);33 QMirServer(int &argc, char **argv, QObject* parent=0);
34 virtual ~QMirServer();34 virtual ~QMirServer();
3535
36 bool start();36 bool start();
3737
=== modified file 'src/platforms/mirserver/screen.cpp'
--- src/platforms/mirserver/screen.cpp 2015-10-14 22:59:04 +0000
+++ src/platforms/mirserver/screen.cpp 2016-03-11 11:36:44 +0000
@@ -135,9 +135,11 @@
135 ? Qt::LandscapeOrientation : Qt::PortraitOrientation;135 ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
136 qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen - initial currentOrientation is:" << m_currentOrientation;136 qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen - initial currentOrientation is:" << m_currentOrientation;
137137
138 QObject::connect(m_orientationSensor, &QOrientationSensor::readingChanged,138 if (internalDisplay()) { // only enable orientation sensor for device-internal display
139 this, &Screen::onOrientationReadingChanged);139 QObject::connect(m_orientationSensor, &QOrientationSensor::readingChanged,
140 m_orientationSensor->start();140 this, &Screen::onOrientationReadingChanged);
141 m_orientationSensor->start();
142 }
141143
142 if (!skipDBusRegistration) {144 if (!skipDBusRegistration) {
143 // FIXME This is a unity8 specific dbus call and shouldn't be in qtmir145 // FIXME This is a unity8 specific dbus call and shouldn't be in qtmir
@@ -171,7 +173,9 @@
171void Screen::onDisplayPowerStateChanged(int status, int reason)173void Screen::onDisplayPowerStateChanged(int status, int reason)
172{174{
173 Q_UNUSED(reason);175 Q_UNUSED(reason);
174 toggleSensors(status);176 if (internalDisplay()) {
177 toggleSensors(status);
178 }
175}179}
176180
177void Screen::setMirDisplayConfiguration(const mir::graphics::DisplayConfigurationOutput &screen)181void Screen::setMirDisplayConfiguration(const mir::graphics::DisplayConfigurationOutput &screen)
@@ -297,6 +301,13 @@
297 qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen::setWindow - overwriting existing ScreenWindow";301 qCDebug(QTMIR_SENSOR_MESSAGES) << "Screen::setWindow - overwriting existing ScreenWindow";
298 }302 }
299 m_screenWindow = window;303 m_screenWindow = window;
304
305 if (m_screenWindow) {
306 if (m_screenWindow->geometry() != geometry()) {
307 qCDebug(QTMIR_SCREENS) << "Screen::setWindow - new geometry for shell surface" << window->window() << geometry();
308 m_screenWindow->setGeometry(geometry());
309 }
310 }
300}311}
301312
302void Screen::setMirDisplayBuffer(mir::graphics::DisplayBuffer *buffer, mir::graphics::DisplaySyncGroup *group)313void Screen::setMirDisplayBuffer(mir::graphics::DisplayBuffer *buffer, mir::graphics::DisplaySyncGroup *group)
@@ -334,3 +345,12 @@
334{345{
335 m_renderTarget->release_current();346 m_renderTarget->release_current();
336}347}
348
349bool Screen::internalDisplay() const
350{
351 using namespace mir::graphics;
352 if (m_type == DisplayConfigurationOutputType::lvds || m_type == DisplayConfigurationOutputType::edp) {
353 return true;
354 }
355 return false;
356}
337357
=== modified file 'src/platforms/mirserver/screen.h'
--- src/platforms/mirserver/screen.h 2015-10-14 22:59:04 +0000
+++ src/platforms/mirserver/screen.h 2016-03-11 11:36:44 +0000
@@ -53,7 +53,6 @@
53 Qt::ScreenOrientation orientation() const override { return m_currentOrientation; }53 Qt::ScreenOrientation orientation() const override { return m_currentOrientation; }
54 QPlatformCursor *cursor() const override;54 QPlatformCursor *cursor() const override;
5555
56 void toggleSensors(const bool enable) const;
57 mir::graphics::DisplayConfigurationOutputType outputType() const { return m_type; }56 mir::graphics::DisplayConfigurationOutputType outputType() const { return m_type; }
5857
59 ScreenWindow* window() const;58 ScreenWindow* window() const;
@@ -79,6 +78,9 @@
79 void doneCurrent();78 void doneCurrent();
8079
81private:80private:
81 void toggleSensors(const bool enable) const;
82 bool internalDisplay() const;
83
82 QRect m_geometry;84 QRect m_geometry;
83 int m_depth;85 int m_depth;
84 QImage::Format m_format;86 QImage::Format m_format;
8587
=== modified file 'src/platforms/mirserver/screenwindow.cpp'
--- src/platforms/mirserver/screenwindow.cpp 2015-10-15 07:05:16 +0000
+++ src/platforms/mirserver/screenwindow.cpp 2016-03-11 11:36:44 +0000
@@ -89,7 +89,7 @@
89 auto renderer = QSGRenderLoop::instance();89 auto renderer = QSGRenderLoop::instance();
90 if (exposed) {90 if (exposed) {
91 renderer->show(quickWindow);91 renderer->show(quickWindow);
92 QWindowSystemInterface::handleExposeEvent(window(), QRegion()); // else it won't redraw92 QWindowSystemInterface::handleExposeEvent(window(), geometry()); // else it won't redraw
93 } else {93 } else {
94 quickWindow->setPersistentOpenGLContext(false);94 quickWindow->setPersistentOpenGLContext(false);
95 quickWindow->setPersistentSceneGraph(false);95 quickWindow->setPersistentSceneGraph(false);
9696
=== added directory 'src/platforms/mirserver/wm-wip'
=== added file 'src/platforms/mirserver/wm-wip/CMakeLists.txt'
--- src/platforms/mirserver/wm-wip/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/CMakeLists.txt 2016-03-11 11:36:44 +0000
@@ -0,0 +1,22 @@
1set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fPIC")
2
3add_library(experimentalwindowmanager STATIC
4 server_example_basic_window_manager.cpp
5 server_example_basic_window_manager.h
6 server_example_window_management_info.cpp
7 server_example_window_management_info.h
8)
9
10
11if (EXAMPLE_MIR_WINDOW_MANAGERS)
12
13add_library(examplewindowmanager STATIC
14 server_example_canonical_window_manager.h
15 server_example_tiling_window_manager.h
16 server_example_window_management.h
17 server_example_canonical_window_manager.cpp
18 server_example_tiling_window_manager.cpp
19 server_example_window_management.cpp
20)
21
22endif()
023
=== added file 'src/platforms/mirserver/wm-wip/README'
--- src/platforms/mirserver/wm-wip/README 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/README 2016-03-11 11:36:44 +0000
@@ -0,0 +1,5 @@
1examples for mir clients. you should have package 'libmirclient-dev' installed
2
3you can compile with a command like:
4 g++ -std=c++0x -o mir_demo_client_scroll `pkg-config --libs --cflags mirclient` demo_client_scroll.cpp graphics_utils.cpp
5 gcc -o mir_demo_client_flicker `pkg-config --libs --cflags mirclient` demo_client_flicker.c
06
=== added file 'src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp'
--- src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_basic_window_manager.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,312 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "server_example_basic_window_manager.h"
20
21#include "mir/scene/session.h"
22#include "mir/scene/surface.h"
23#include "mir/scene/surface_creation_parameters.h"
24
25namespace me = mir::examples;
26
27me::BasicWindowManager::BasicWindowManager(
28 shell::FocusController* focus_controller,
29 std::unique_ptr<WindowManagementPolicy> policy) :
30 focus_controller(focus_controller),
31 policy(std::move(policy))
32{
33}
34
35void me::BasicWindowManager::add_session(std::shared_ptr<scene::Session> const& session)
36{
37 std::lock_guard<decltype(mutex)> lock(mutex);
38 session_info[session] = SessionInfo();
39 policy->handle_session_info_updated(session_info, displays);
40}
41
42void me::BasicWindowManager::remove_session(std::shared_ptr<scene::Session> const& session)
43{
44 std::lock_guard<decltype(mutex)> lock(mutex);
45 session_info.erase(session);
46 policy->handle_session_info_updated(session_info, displays);
47}
48
49auto me::BasicWindowManager::add_surface(
50 std::shared_ptr<scene::Session> const& session,
51 scene::SurfaceCreationParameters const& params,
52 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build)
53-> frontend::SurfaceId
54{
55 std::lock_guard<decltype(mutex)> lock(mutex);
56 scene::SurfaceCreationParameters const placed_params = policy->handle_place_new_surface(session, params);
57 auto const result = build(session, placed_params);
58 auto const surface = session->surface(result);
59 surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params});
60 policy->handle_new_surface(session, surface);
61 policy->generate_decorations_for(session, surface, surface_info, build);
62 return result;
63}
64
65void me::BasicWindowManager::modify_surface(
66 std::shared_ptr<scene::Session> const& session,
67 std::shared_ptr<scene::Surface> const& surface,
68 shell::SurfaceSpecification const& modifications)
69{
70 std::lock_guard<decltype(mutex)> lock(mutex);
71 policy->handle_modify_surface(session, surface, modifications);
72}
73
74void me::BasicWindowManager::remove_surface(
75 std::shared_ptr<scene::Session> const& session,
76 std::weak_ptr<scene::Surface> const& surface)
77{
78 std::lock_guard<decltype(mutex)> lock(mutex);
79 policy->handle_delete_surface(session, surface);
80
81 surface_info.erase(surface);
82}
83
84void me::BasicWindowManager::forget(std::weak_ptr<scene::Surface> const& surface)
85{
86 surface_info.erase(surface);
87}
88
89void me::BasicWindowManager::add_display(geometry::Rectangle const& area)
90{
91 std::lock_guard<decltype(mutex)> lock(mutex);
92 displays.add(area);
93 policy->handle_displays_updated(session_info, displays);
94}
95
96void me::BasicWindowManager::remove_display(geometry::Rectangle const& area)
97{
98 std::lock_guard<decltype(mutex)> lock(mutex);
99 displays.remove(area);
100 policy->handle_displays_updated(session_info, displays);
101}
102
103bool me::BasicWindowManager::handle_keyboard_event(MirKeyboardEvent const* event)
104{
105 std::lock_guard<decltype(mutex)> lock(mutex);
106 update_event_timestamp(event);
107 return policy->handle_keyboard_event(event);
108}
109
110bool me::BasicWindowManager::handle_touch_event(MirTouchEvent const* event)
111{
112 std::lock_guard<decltype(mutex)> lock(mutex);
113 update_event_timestamp(event);
114 return policy->handle_touch_event(event);
115}
116
117bool me::BasicWindowManager::handle_pointer_event(MirPointerEvent const* event)
118{
119 std::lock_guard<decltype(mutex)> lock(mutex);
120 update_event_timestamp(event);
121
122 cursor = {
123 mir_pointer_event_axis_value(event, mir_pointer_axis_x),
124 mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
125
126 return policy->handle_pointer_event(event);
127}
128
129void me::BasicWindowManager::handle_raise_surface(
130 std::shared_ptr<scene::Session> const& session,
131 std::shared_ptr<scene::Surface> const& surface,
132 uint64_t timestamp)
133{
134 std::lock_guard<decltype(mutex)> lock(mutex);
135 if (timestamp >= last_input_event_timestamp)
136 policy->handle_raise_surface(session, surface);
137}
138
139int me::BasicWindowManager::set_surface_attribute(
140 std::shared_ptr<scene::Session> const& /*session*/,
141 std::shared_ptr<scene::Surface> const& surface,
142 MirSurfaceAttrib attrib,
143 int value)
144{
145 std::lock_guard<decltype(mutex)> lock(mutex);
146 switch (attrib)
147 {
148 case mir_surface_attrib_state:
149 {
150 auto const state = policy->handle_set_state(surface, MirSurfaceState(value));
151 return surface->configure(attrib, state);
152 }
153 default:
154 return surface->configure(attrib, value);
155 }
156}
157
158auto me::BasicWindowManager::find_session(std::function<bool(SessionInfo const& info)> const& predicate)
159-> std::shared_ptr<scene::Session>
160 {
161 for(auto& info : session_info)
162 {
163 if (predicate(info.second))
164 {
165 return info.first.lock();
166 }
167 }
168
169 return std::shared_ptr<scene::Session>{};
170 }
171
172auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Session> const& session) const
173-> SessionInfo&
174{
175 return const_cast<SessionInfo&>(session_info.at(session));
176}
177
178auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Surface> const& surface) const
179-> SurfaceInfo&
180{
181 return const_cast<SurfaceInfo&>(surface_info.at(surface));
182}
183
184auto me::BasicWindowManager::focused_session() const
185-> std::shared_ptr<scene::Session>
186{
187 return focus_controller->focused_session();
188}
189
190auto me::BasicWindowManager::focused_surface() const
191->std::shared_ptr<scene::Surface>
192{
193 return focus_controller->focused_surface();
194}
195
196void me::BasicWindowManager::focus_next_session()
197{
198 focus_controller->focus_next_session();
199}
200
201void me::BasicWindowManager::set_focus_to(
202 std::shared_ptr<scene::Session> const& focus,
203 std::shared_ptr<scene::Surface> const& surface)
204{
205 focus_controller->set_focus_to(focus, surface);
206}
207
208auto me::BasicWindowManager::surface_at(geometry::Point cursor) const
209-> std::shared_ptr<scene::Surface>
210{
211 return focus_controller->surface_at(cursor);
212}
213
214auto me::BasicWindowManager::active_display()
215-> geometry::Rectangle const
216{
217 geometry::Rectangle result;
218
219 // 1. If a window has input focus, whichever display contains the largest
220 // proportion of the area of that window.
221 if (auto const surface = focused_surface())
222 {
223 auto const surface_rect = surface->input_bounds();
224 int max_overlap_area = -1;
225
226 for (auto const& display : displays)
227 {
228 auto const intersection = surface_rect.intersection_with(display).size;
229 if (intersection.width.as_int()*intersection.height.as_int() > max_overlap_area)
230 {
231 max_overlap_area = intersection.width.as_int()*intersection.height.as_int();
232 result = display;
233 }
234 }
235 return result;
236 }
237
238 // 2. Otherwise, if any window previously had input focus, for the window that had
239 // it most recently, the display that contained the largest proportion of the
240 // area of that window at the moment it closed, as long as that display is still
241 // available.
242
243 // 3. Otherwise, the display that contains the pointer, if there is one.
244 for (auto const& display : displays)
245 {
246 if (display.contains(cursor))
247 {
248 // Ignore the (unspecified) possiblity of overlapping displays
249 return display;
250 }
251 }
252
253 // 4. Otherwise, the primary display, if there is one (for example, the laptop display).
254
255 // 5. Otherwise, the first display.
256 if (displays.size())
257 result = *displays.begin();
258
259 return result;
260}
261
262void me::BasicWindowManager::raise_tree(std::shared_ptr<scene::Surface> const& root)
263{
264 SurfaceSet surfaces;
265 std::function<void(std::weak_ptr<scene::Surface> const& surface)> const add_children =
266 [&,this](std::weak_ptr<scene::Surface> const& surface)
267 {
268 auto const& info = info_for(surface);
269 surfaces.insert(begin(info.children), end(info.children));
270 for (auto const& child : info.children)
271 add_children(child);
272 };
273
274 surfaces.insert(root);
275 add_children(root);
276
277 focus_controller->raise(surfaces);
278}
279
280void me::BasicWindowManager::update_event_timestamp(MirKeyboardEvent const* kev)
281{
282 auto iev = mir_keyboard_event_input_event(kev);
283 last_input_event_timestamp = mir_input_event_get_event_time(iev);
284}
285
286void me::BasicWindowManager::update_event_timestamp(MirPointerEvent const* pev)
287{
288 auto iev = mir_pointer_event_input_event(pev);
289 auto pointer_action = mir_pointer_event_action(pev);
290
291 if (pointer_action == mir_pointer_action_button_up ||
292 pointer_action == mir_pointer_action_button_down)
293 {
294 last_input_event_timestamp = mir_input_event_get_event_time(iev);
295 }
296}
297
298void me::BasicWindowManager::update_event_timestamp(MirTouchEvent const* tev)
299{
300 auto iev = mir_touch_event_input_event(tev);
301 auto touch_count = mir_touch_event_point_count(tev);
302 for (unsigned i = 0; i < touch_count; i++)
303 {
304 auto touch_action = mir_touch_event_action(tev, i);
305 if (touch_action == mir_touch_action_up ||
306 touch_action == mir_touch_action_down)
307 {
308 last_input_event_timestamp = mir_input_event_get_event_time(iev);
309 break;
310 }
311 }
312}
0313
=== added file 'src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h'
--- src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_basic_window_manager.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,252 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_
20#define MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_
21
22#include "server_example_window_management_info.h"
23
24#include "mir/geometry/rectangles.h"
25#include "mir/shell/abstract_shell.h"
26#include "mir/shell/window_manager.h"
27
28#include <map>
29#include <mutex>
30
31///\example server_example_basic_window_manager.h
32/// A generic policy-based window manager implementation
33
34namespace mir
35{
36namespace examples
37{
38using shell::SurfaceSet;
39
40/// The interface through which the policy instructs the controller.
41/// These functions assume that the BasicWindowManager data structures can be accessed freely.
42/// I.e. should only be invoked by the policy handle_... methods (where any necessary locks are held).
43class WindowManagerTools
44{
45public:
46 using SurfaceInfoMap = std::map<std::weak_ptr<scene::Surface>, SurfaceInfo, std::owner_less<std::weak_ptr<scene::Surface>>>;
47 using SessionInfoMap = std::map<std::weak_ptr<scene::Session>, SessionInfo, std::owner_less<std::weak_ptr<scene::Session>>>;
48
49 virtual auto find_session(std::function<bool(SessionInfo const& info)> const& predicate)
50 -> std::shared_ptr<scene::Session> = 0;
51
52 virtual auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& = 0;
53
54 virtual auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& = 0;
55
56 virtual std::shared_ptr<scene::Session> focused_session() const = 0;
57
58 virtual std::shared_ptr<scene::Surface> focused_surface() const = 0;
59
60 virtual void focus_next_session() = 0;
61
62 virtual void set_focus_to(
63 std::shared_ptr<scene::Session> const& focus,
64 std::shared_ptr<scene::Surface> const& surface) = 0;
65
66 virtual auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> = 0;
67
68 virtual auto active_display() -> geometry::Rectangle const = 0;
69
70 virtual void forget(std::weak_ptr<scene::Surface> const& surface) = 0;
71
72 virtual void raise_tree(std::shared_ptr<scene::Surface> const& root) = 0;
73
74 virtual ~WindowManagerTools() = default;
75 WindowManagerTools() = default;
76 WindowManagerTools(WindowManagerTools const&) = delete;
77 WindowManagerTools& operator=(WindowManagerTools const&) = delete;
78};
79
80class WindowManagementPolicy
81{
82public:
83 using SessionInfoMap = typename WindowManagerTools::SessionInfoMap;
84 using SurfaceInfoMap = typename WindowManagerTools::SurfaceInfoMap;
85
86 virtual void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0;
87
88 virtual void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0;
89
90 virtual auto handle_place_new_surface(
91 std::shared_ptr<scene::Session> const& session,
92 scene::SurfaceCreationParameters const& request_parameters)
93 -> scene::SurfaceCreationParameters = 0;
94
95 virtual void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) = 0;
96
97 virtual void handle_modify_surface(
98 std::shared_ptr<scene::Session> const& session,
99 std::shared_ptr<scene::Surface> const& surface,
100 shell::SurfaceSpecification const& modifications) = 0;
101
102 virtual void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface) = 0;
103
104 virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value) = 0;
105
106 virtual void generate_decorations_for(
107 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface,
108 SurfaceInfoMap& surface_info,
109 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build) = 0;
110
111 virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0;
112
113 virtual bool handle_touch_event(MirTouchEvent const* event) = 0;
114
115 virtual bool handle_pointer_event(MirPointerEvent const* event) = 0;
116
117 virtual void handle_raise_surface(
118 std::shared_ptr<scene::Session> const& session,
119 std::shared_ptr<scene::Surface> const& surface) = 0;
120
121 virtual ~WindowManagementPolicy() = default;
122 WindowManagementPolicy() = default;
123 WindowManagementPolicy(WindowManagementPolicy const&) = delete;
124 WindowManagementPolicy& operator=(WindowManagementPolicy const&) = delete;
125};
126
127/// A policy based window manager.
128/// This takes care of the management of any meta implementation held for the sessions and surfaces.
129class BasicWindowManager : public virtual shell::WindowManager,
130 protected WindowManagerTools
131{
132protected:
133 BasicWindowManager(
134 shell::FocusController* focus_controller,
135 std::unique_ptr<WindowManagementPolicy> policy);
136
137public:
138 using typename WindowManagerTools::SurfaceInfoMap;
139 using typename WindowManagerTools::SessionInfoMap;
140
141 void add_session(std::shared_ptr<scene::Session> const& session) override;
142
143 void remove_session(std::shared_ptr<scene::Session> const& session) override;
144
145 auto add_surface(
146 std::shared_ptr<scene::Session> const& session,
147 scene::SurfaceCreationParameters const& params,
148 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build)
149 -> frontend::SurfaceId override;
150
151 void modify_surface(
152 std::shared_ptr<scene::Session> const& session,
153 std::shared_ptr<scene::Surface> const& surface,
154 shell::SurfaceSpecification const& modifications) override;
155
156 void remove_surface(
157 std::shared_ptr<scene::Session> const& session,
158 std::weak_ptr<scene::Surface> const& surface) override;
159
160 void forget(std::weak_ptr<scene::Surface> const& surface) override;
161
162 void add_display(geometry::Rectangle const& area) override;
163
164 void remove_display(geometry::Rectangle const& area) override;
165
166 bool handle_keyboard_event(MirKeyboardEvent const* event) override;
167
168 bool handle_touch_event(MirTouchEvent const* event) override;
169
170 bool handle_pointer_event(MirPointerEvent const* event) override;
171
172 void handle_raise_surface(
173 std::shared_ptr<scene::Session> const& session,
174 std::shared_ptr<scene::Surface> const& surface,
175 uint64_t timestamp) override;
176
177 int set_surface_attribute(
178 std::shared_ptr<scene::Session> const& /*session*/,
179 std::shared_ptr<scene::Surface> const& surface,
180 MirSurfaceAttrib attrib,
181 int value) override;
182
183 auto find_session(std::function<bool(SessionInfo const& info)> const& predicate)
184 -> std::shared_ptr<scene::Session> override;
185
186 auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& override;
187
188 auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& override;
189
190 std::shared_ptr<scene::Session> focused_session() const override;
191
192 std::shared_ptr<scene::Surface> focused_surface() const override;
193
194 void focus_next_session() override;
195
196 void set_focus_to(
197 std::shared_ptr<scene::Session> const& focus,
198 std::shared_ptr<scene::Surface> const& surface) override;
199
200 auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> override;
201
202 auto active_display() -> geometry::Rectangle const override;
203
204 void raise_tree(std::shared_ptr<scene::Surface> const& root) override;
205
206private:
207 shell::FocusController* const focus_controller;
208 std::unique_ptr<WindowManagementPolicy> const policy;
209
210 std::mutex mutex;
211 SessionInfoMap session_info;
212 SurfaceInfoMap surface_info;
213 geometry::Rectangles displays;
214 geometry::Point cursor;
215 uint64_t last_input_event_timestamp{0};
216
217 void update_event_timestamp(MirKeyboardEvent const* kev);
218 void update_event_timestamp(MirPointerEvent const* pev);
219 void update_event_timestamp(MirTouchEvent const* tev);
220};
221
222/// A policy based window manager. This exists to initialize BasicWindowManager and
223/// the WMPolicy (in an awkward manner).
224/// TODO revisit this initialization sequence.
225template<typename WMPolicy>
226class WindowManagerBuilder : public BasicWindowManager
227{
228public:
229
230 template <typename... PolicyArgs>
231 WindowManagerBuilder(
232 shell::FocusController* focus_controller,
233 PolicyArgs&&... policy_args) :
234 BasicWindowManager(
235 focus_controller,
236 build_policy(std::forward<PolicyArgs>(policy_args)...))
237 {
238 }
239
240private:
241 template <typename... PolicyArgs>
242 auto build_policy(PolicyArgs&&... policy_args)
243 -> std::unique_ptr<WMPolicy>
244 {
245 return std::unique_ptr<WMPolicy>(
246 new WMPolicy(this, std::forward<PolicyArgs>(policy_args)...));
247 }
248};
249}
250}
251
252#endif /* MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ */
0253
=== added file 'src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp'
--- src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,946 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "server_example_canonical_window_manager.h"
20
21#include "mir/scene/session.h"
22#include "mir/scene/surface.h"
23#include "mir/scene/surface_creation_parameters.h"
24#include "mir/shell/surface_ready_observer.h"
25#include "mir/shell/display_layout.h"
26
27#include <linux/input.h>
28#include <csignal>
29#include <algorithm>
30
31namespace me = mir::examples;
32namespace ms = mir::scene;
33using namespace mir::geometry;
34
35///\example server_example_canonical_window_manager.cpp
36// Based on "Mir and Unity: Surfaces, input, and displays (v0.3)"
37
38namespace
39{
40int const title_bar_height = 10;
41Size titlebar_size_for_window(Size window_size)
42{
43 return {window_size.width, Height{title_bar_height}};
44}
45
46Point titlebar_position_for_window(Point window_position)
47{
48 return {
49 window_position.x,
50 window_position.y - DeltaY(title_bar_height)
51 };
52}
53}
54
55me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy(
56 WindowManagerTools* const tools,
57 std::shared_ptr<shell::DisplayLayout> const& display_layout) :
58 tools{tools},
59 display_layout{display_layout}
60{
61}
62
63void me::CanonicalWindowManagerPolicyCopy::click(Point cursor)
64{
65 if (auto const surface = tools->surface_at(cursor))
66 select_active_surface(surface);
67}
68
69void me::CanonicalWindowManagerPolicyCopy::handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/)
70{
71}
72
73void me::CanonicalWindowManagerPolicyCopy::handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& displays)
74{
75 display_area = displays.bounding_rectangle();
76
77 for (auto const weak_surface : fullscreen_surfaces)
78 {
79 if (auto const surface = weak_surface.lock())
80 {
81 auto const& info = tools->info_for(weak_surface);
82 Rectangle rect{surface->top_left(), surface->size()};
83
84 display_layout->place_in_output(info.output_id.value(), rect);
85 surface->move_to(rect.top_left);
86 surface->resize(rect.size);
87 }
88 }
89}
90
91void me::CanonicalWindowManagerPolicyCopy::resize(Point cursor)
92{
93 select_active_surface(tools->surface_at(old_cursor));
94 resize(active_surface(), cursor, old_cursor, display_area);
95}
96
97auto me::CanonicalWindowManagerPolicyCopy::handle_place_new_surface(
98 std::shared_ptr<ms::Session> const& session,
99 ms::SurfaceCreationParameters const& request_parameters)
100-> ms::SurfaceCreationParameters
101{
102 auto parameters = request_parameters;
103 auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_surface_type_normal;
104 bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type);
105
106 if (needs_titlebar)
107 parameters.size.height = parameters.size.height + DeltaY{title_bar_height};
108
109 if (!parameters.state.is_set())
110 parameters.state = mir_surface_state_restored;
111
112 auto const active_display = tools->active_display();
113
114 auto const width = parameters.size.width.as_int();
115 auto const height = parameters.size.height.as_int();
116
117 bool positioned = false;
118
119 auto const parent = parameters.parent.lock();
120
121 if (parameters.output_id != mir::graphics::DisplayConfigurationOutputId{0})
122 {
123 Rectangle rect{parameters.top_left, parameters.size};
124 display_layout->place_in_output(parameters.output_id, rect);
125 parameters.top_left = rect.top_left;
126 parameters.size = rect.size;
127 parameters.state = mir_surface_state_fullscreen;
128 positioned = true;
129 }
130 else if (!parent) // No parent => client can't suggest positioning
131 {
132 if (auto const default_surface = session->default_surface())
133 {
134 static Displacement const offset{title_bar_height, title_bar_height};
135
136 parameters.top_left = default_surface->top_left() + offset;
137
138 geometry::Rectangle display_for_app{default_surface->top_left(), default_surface->size()};
139
140 display_layout->size_to_output(display_for_app);
141
142 positioned = display_for_app.overlaps(Rectangle{parameters.top_left, parameters.size});
143 }
144 }
145
146 if (parent && parameters.aux_rect.is_set() && parameters.edge_attachment.is_set())
147 {
148 auto const edge_attachment = parameters.edge_attachment.value();
149 auto const aux_rect = parameters.aux_rect.value();
150 auto const parent_top_left = parent->top_left();
151 auto const top_left = aux_rect.top_left -Point{} + parent_top_left;
152 auto const top_right= aux_rect.top_right() -Point{} + parent_top_left;
153 auto const bot_left = aux_rect.bottom_left()-Point{} + parent_top_left;
154
155 if (edge_attachment & mir_edge_attachment_vertical)
156 {
157 if (active_display.contains(top_right + Displacement{width, height}))
158 {
159 parameters.top_left = top_right;
160 positioned = true;
161 }
162 else if (active_display.contains(top_left + Displacement{-width, height}))
163 {
164 parameters.top_left = top_left + Displacement{-width, 0};
165 positioned = true;
166 }
167 }
168
169 if (edge_attachment & mir_edge_attachment_horizontal)
170 {
171 if (active_display.contains(bot_left + Displacement{width, height}))
172 {
173 parameters.top_left = bot_left;
174 positioned = true;
175 }
176 else if (active_display.contains(top_left + Displacement{width, -height}))
177 {
178 parameters.top_left = top_left + Displacement{0, -height};
179 positioned = true;
180 }
181 }
182 }
183 else if (parent)
184 {
185 // o Otherwise, if the dialog is not the same as any previous dialog for the
186 // same parent window, and/or it does not have user-customized position:
187 // o It should be optically centered relative to its parent, unless this
188 // would overlap or cover the title bar of the parent.
189 // o Otherwise, it should be cascaded vertically (but not horizontally)
190 // relative to its parent, unless, this would cause at least part of
191 // it to extend into shell space.
192 auto const parent_top_left = parent->top_left();
193 auto const centred = parent_top_left
194 + 0.5*(as_displacement(parent->size()) - as_displacement(parameters.size))
195 - DeltaY{(parent->size().height.as_int()-height)/6};
196
197 parameters.top_left = centred;
198 positioned = true;
199 }
200
201 if (!positioned)
202 {
203 auto const centred = active_display.top_left
204 + 0.5*(as_displacement(active_display.size) - as_displacement(parameters.size))
205 - DeltaY{(active_display.size.height.as_int()-height)/6};
206
207 switch (parameters.state.value())
208 {
209 case mir_surface_state_fullscreen:
210 case mir_surface_state_maximized:
211 parameters.top_left = active_display.top_left;
212 parameters.size = active_display.size;
213 break;
214
215 case mir_surface_state_vertmaximized:
216 parameters.top_left = centred;
217 parameters.top_left.y = active_display.top_left.y;
218 parameters.size.height = active_display.size.height;
219 break;
220
221 case mir_surface_state_horizmaximized:
222 parameters.top_left = centred;
223 parameters.top_left.x = active_display.top_left.x;
224 parameters.size.width = active_display.size.width;
225 break;
226
227 default:
228 parameters.top_left = centred;
229 }
230
231 if (parameters.top_left.y < display_area.top_left.y)
232 parameters.top_left.y = display_area.top_left.y;
233 }
234
235 if (parameters.state != mir_surface_state_fullscreen && needs_titlebar)
236 {
237 parameters.top_left.y = parameters.top_left.y + DeltaY{title_bar_height};
238 parameters.size.height = parameters.size.height - DeltaY{title_bar_height};
239 }
240
241 return parameters;
242}
243
244void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for(
245 std::shared_ptr<scene::Session> const& session,
246 std::shared_ptr<scene::Surface> const& surface,
247 SurfaceInfoMap& surface_map,
248 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build)
249{
250 if (!SurfaceInfo::needs_titlebar(surface->type()))
251 return;
252
253 auto format = mir_pixel_format_xrgb_8888;
254 ms::SurfaceCreationParameters params;
255 params.of_size(titlebar_size_for_window(surface->size()))
256 .of_name("decoration")
257 .of_pixel_format(format)
258 .of_buffer_usage(mir::graphics::BufferUsage::software)
259 .of_position(titlebar_position_for_window(surface->top_left()))
260 .of_type(mir_surface_type_gloss);
261 auto id = build(session, params);
262 auto titlebar = session->surface(id);
263 titlebar->set_alpha(0.9);
264
265 auto& surface_info = tools->info_for(surface);
266 surface_info.titlebar = titlebar;
267 surface_info.titlebar_id = id;
268 surface_info.children.push_back(titlebar);
269
270 SurfaceInfo& titlebar_info =
271 surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second;
272 titlebar_info.is_titlebar = true;
273 titlebar_info.parent = surface;
274 titlebar_info.init_titlebar(titlebar);
275}
276
277void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface)
278{
279 auto& surface_info = tools->info_for(surface);
280 if (auto const parent = surface_info.parent.lock())
281 {
282 tools->info_for(parent).children.push_back(surface);
283 }
284
285 tools->info_for(session).surfaces.push_back(surface);
286
287 if (surface_info.can_be_active())
288 {
289 surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>(
290 [this](std::shared_ptr<scene::Session> const& /*session*/,
291 std::shared_ptr<scene::Surface> const& surface)
292 {
293 select_active_surface(surface);
294 },
295 session,
296 surface));
297 }
298
299 if (surface_info.state == mir_surface_state_fullscreen)
300 fullscreen_surfaces.insert(surface);
301}
302
303void me::CanonicalWindowManagerPolicyCopy::handle_modify_surface(
304 std::shared_ptr<scene::Session> const& session,
305 std::shared_ptr<scene::Surface> const& surface,
306 shell::SurfaceSpecification const& modifications)
307{
308 auto& surface_info_old = tools->info_for(surface);
309
310 auto surface_info = surface_info_old;
311
312 if (modifications.parent.is_set())
313 surface_info.parent = modifications.parent.value();
314
315 if (modifications.type.is_set() &&
316 surface_info.type != modifications.type.value())
317 {
318 auto const new_type = modifications.type.value();
319
320 if (!surface_info.can_morph_to(new_type))
321 {
322 throw std::runtime_error("Unsupported surface type change");
323 }
324
325 surface_info.type = new_type;
326
327 if (surface_info.must_not_have_parent())
328 {
329 if (modifications.parent.is_set())
330 throw std::runtime_error("Target surface type does not support parent");
331
332 surface_info.parent.reset();
333 }
334 else if (surface_info.must_have_parent())
335 {
336 if (!surface_info.parent.lock())
337 throw std::runtime_error("Target surface type requires parent");
338 }
339
340 surface->configure(mir_surface_attrib_type, new_type);
341 }
342
343 #define COPY_IF_SET(field)\
344 if (modifications.field.is_set())\
345 surface_info.field = modifications.field.value()
346
347 COPY_IF_SET(min_width);
348 COPY_IF_SET(min_height);
349 COPY_IF_SET(max_width);
350 COPY_IF_SET(max_height);
351 COPY_IF_SET(min_width);
352 COPY_IF_SET(width_inc);
353 COPY_IF_SET(height_inc);
354 COPY_IF_SET(min_aspect);
355 COPY_IF_SET(max_aspect);
356 COPY_IF_SET(output_id);
357
358 #undef COPY_IF_SET
359
360 std::swap(surface_info, surface_info_old);
361
362 if (modifications.name.is_set())
363 surface->rename(modifications.name.value());
364
365 if (modifications.streams.is_set())
366 {
367 auto v = modifications.streams.value();
368 std::vector<shell::StreamSpecification> l (v.begin(), v.end());
369 session->configure_streams(*surface, l);
370 }
371
372 if (modifications.input_shape.is_set())
373 {
374 surface->set_input_region(modifications.input_shape.value());
375 }
376
377 if (modifications.width.is_set() || modifications.height.is_set())
378 {
379 auto new_size = surface->size();
380
381 if (modifications.width.is_set())
382 new_size.width = modifications.width.value();
383
384 if (modifications.height.is_set())
385 new_size.height = modifications.height.value();
386
387 auto top_left = surface->top_left();
388
389 surface_info.constrain_resize(
390 surface,
391 top_left,
392 new_size,
393 false,
394 false,
395 display_area);
396
397 apply_resize(surface, surface_info.titlebar, top_left, new_size);
398 }
399
400 if (modifications.state.is_set())
401 {
402 auto const state = handle_set_state(surface, modifications.state.value());
403 surface->configure(mir_surface_attrib_state, state);
404 }
405}
406
407void me::CanonicalWindowManagerPolicyCopy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface)
408{
409 fullscreen_surfaces.erase(surface);
410
411 auto& info = tools->info_for(surface);
412
413 if (auto const parent = info.parent.lock())
414 {
415 auto& siblings = tools->info_for(parent).children;
416
417 for (auto i = begin(siblings); i != end(siblings); ++i)
418 {
419 if (surface.lock() == i->lock())
420 {
421 siblings.erase(i);
422 break;
423 }
424 }
425 }
426
427 session->destroy_surface(surface);
428 if (info.titlebar)
429 {
430 session->destroy_surface(info.titlebar_id);
431 tools->forget(info.titlebar);
432 }
433
434 auto& surfaces = tools->info_for(session).surfaces;
435
436 for (auto i = begin(surfaces); i != end(surfaces); ++i)
437 {
438 if (surface.lock() == i->lock())
439 {
440 surfaces.erase(i);
441 break;
442 }
443 }
444
445 if (surfaces.empty() && session == tools->focused_session())
446 {
447 active_surface_.reset();
448 tools->focus_next_session();
449 select_active_surface(tools->focused_surface());
450 }
451}
452
453int me::CanonicalWindowManagerPolicyCopy::handle_set_state(std::shared_ptr<ms::Surface> const& surface, MirSurfaceState value)
454{
455 auto& info = tools->info_for(surface);
456
457 switch (value)
458 {
459 case mir_surface_state_restored:
460 case mir_surface_state_maximized:
461 case mir_surface_state_vertmaximized:
462 case mir_surface_state_horizmaximized:
463 case mir_surface_state_fullscreen:
464 case mir_surface_state_hidden:
465 case mir_surface_state_minimized:
466 break;
467
468 default:
469 return info.state;
470 }
471
472 if (info.state == mir_surface_state_restored)
473 {
474 info.restore_rect = {surface->top_left(), surface->size()};
475 }
476
477 if (info.state != mir_surface_state_fullscreen)
478 {
479 info.output_id = decltype(info.output_id){};
480 fullscreen_surfaces.erase(surface);
481 }
482 else
483 {
484 fullscreen_surfaces.insert(surface);
485 }
486
487 if (info.state == value)
488 {
489 return info.state;
490 }
491
492 auto const old_pos = surface->top_left();
493 Displacement movement;
494
495 switch (value)
496 {
497 case mir_surface_state_restored:
498 movement = info.restore_rect.top_left - old_pos;
499 surface->resize(info.restore_rect.size);
500 if (info.titlebar)
501 {
502 info.titlebar->resize(titlebar_size_for_window(info.restore_rect.size));
503 info.titlebar->show();
504 }
505 break;
506
507 case mir_surface_state_maximized:
508 movement = display_area.top_left - old_pos;
509 surface->resize(display_area.size);
510 if (info.titlebar)
511 info.titlebar->hide();
512 break;
513
514 case mir_surface_state_horizmaximized:
515 movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos;
516 surface->resize({display_area.size.width, info.restore_rect.size.height});
517 if (info.titlebar)
518 {
519 info.titlebar->resize(titlebar_size_for_window({display_area.size.width, info.restore_rect.size.height}));
520 info.titlebar->show();
521 }
522 break;
523
524 case mir_surface_state_vertmaximized:
525 movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos;
526 surface->resize({info.restore_rect.size.width, display_area.size.height});
527 if (info.titlebar)
528 info.titlebar->hide();
529 break;
530
531 case mir_surface_state_fullscreen:
532 {
533 Rectangle rect{old_pos, surface->size()};
534
535 if (info.output_id.is_set())
536 {
537 display_layout->place_in_output(info.output_id.value(), rect);
538 }
539 else
540 {
541 display_layout->size_to_output(rect);
542 }
543
544 movement = rect.top_left - old_pos;
545 surface->resize(rect.size);
546 break;
547 }
548
549 case mir_surface_state_hidden:
550 case mir_surface_state_minimized:
551 if (info.titlebar)
552 info.titlebar->hide();
553 surface->hide();
554 return info.state = value;
555
556 default:
557 break;
558 }
559
560 // TODO It is rather simplistic to move a tree WRT the top_left of the root
561 // TODO when resizing. But for more sophistication we would need to encode
562 // TODO some sensible layout rules.
563 move_tree(surface, movement);
564
565 info.state = value;
566
567 if (info.is_visible())
568 surface->show();
569
570 return info.state;
571}
572
573void me::CanonicalWindowManagerPolicyCopy::drag(Point cursor)
574{
575 select_active_surface(tools->surface_at(old_cursor));
576 drag(active_surface(), cursor, old_cursor, display_area);
577}
578
579void me::CanonicalWindowManagerPolicyCopy::handle_raise_surface(
580 std::shared_ptr<ms::Session> const& /*session*/,
581 std::shared_ptr<ms::Surface> const& surface)
582{
583 select_active_surface(surface);
584}
585
586bool me::CanonicalWindowManagerPolicyCopy::handle_keyboard_event(MirKeyboardEvent const* event)
587{
588 auto const action = mir_keyboard_event_action(event);
589 auto const scan_code = mir_keyboard_event_scan_code(event);
590 auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
591
592 if (action == mir_keyboard_action_down && scan_code == KEY_F11)
593 {
594 switch (modifiers)
595 {
596 case mir_input_event_modifier_alt:
597 toggle(mir_surface_state_maximized);
598 return true;
599
600 case mir_input_event_modifier_shift:
601 toggle(mir_surface_state_vertmaximized);
602 return true;
603
604 case mir_input_event_modifier_ctrl:
605 toggle(mir_surface_state_horizmaximized);
606 return true;
607
608 default:
609 break;
610 }
611 }
612 else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
613 {
614 if (auto const session = tools->focused_session())
615 {
616 switch (modifiers)
617 {
618 case mir_input_event_modifier_alt:
619 kill(session->process_id(), SIGTERM);
620 return true;
621
622 case mir_input_event_modifier_ctrl:
623 if (auto const surf = session->default_surface())
624 {
625 surf->request_client_surface_close();
626 return true;
627 }
628
629 default:
630 break;
631 }
632 }
633 }
634 else if (action == mir_keyboard_action_down &&
635 modifiers == mir_input_event_modifier_alt &&
636 scan_code == KEY_TAB)
637 {
638 tools->focus_next_session();
639 if (auto const surface = tools->focused_surface())
640 select_active_surface(surface);
641
642 return true;
643 }
644 else if (action == mir_keyboard_action_down &&
645 modifiers == mir_input_event_modifier_alt &&
646 scan_code == KEY_GRAVE)
647 {
648 if (auto const prev = tools->focused_surface())
649 {
650 if (auto const app = tools->focused_session())
651 select_active_surface(app->surface_after(prev));
652 }
653
654 return true;
655 }
656
657 return false;
658}
659
660bool me::CanonicalWindowManagerPolicyCopy::handle_touch_event(MirTouchEvent const* event)
661{
662 auto const count = mir_touch_event_point_count(event);
663
664 long total_x = 0;
665 long total_y = 0;
666
667 for (auto i = 0U; i != count; ++i)
668 {
669 total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x);
670 total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y);
671 }
672
673 Point const cursor{total_x/count, total_y/count};
674
675 bool is_drag = true;
676 for (auto i = 0U; i != count; ++i)
677 {
678 switch (mir_touch_event_action(event, i))
679 {
680 case mir_touch_action_up:
681 return false;
682
683 case mir_touch_action_down:
684 is_drag = false;
685
686 case mir_touch_action_change:
687 continue;
688 }
689 }
690
691 bool consumes_event = false;
692 if (is_drag)
693 {
694 switch (count)
695 {
696 case 2:
697 resize(cursor);
698 consumes_event = true;
699 break;
700
701 case 3:
702 drag(cursor);
703 consumes_event = true;
704 break;
705 }
706 }
707
708 old_cursor = cursor;
709 return consumes_event;
710}
711
712bool me::CanonicalWindowManagerPolicyCopy::handle_pointer_event(MirPointerEvent const* event)
713{
714 auto const action = mir_pointer_event_action(event);
715 auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask;
716 Point const cursor{
717 mir_pointer_event_axis_value(event, mir_pointer_axis_x),
718 mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
719
720 bool consumes_event = false;
721
722 if (action == mir_pointer_action_button_down)
723 {
724 click(cursor);
725 }
726 else if (action == mir_pointer_action_motion &&
727 modifiers == mir_input_event_modifier_alt)
728 {
729 if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
730 {
731 drag(cursor);
732 consumes_event = true;
733 }
734
735 if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary))
736 {
737 resize(cursor);
738 consumes_event = true;
739 }
740 }
741 else if (action == mir_pointer_action_motion && !modifiers)
742 {
743 if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
744 {
745 if (auto const possible_titlebar = tools->surface_at(old_cursor))
746 {
747 if (tools->info_for(possible_titlebar).is_titlebar)
748 {
749 drag(cursor);
750 consumes_event = true;
751 }
752 }
753 }
754 }
755
756 old_cursor = cursor;
757 return consumes_event;
758}
759
760void me::CanonicalWindowManagerPolicyCopy::toggle(MirSurfaceState state)
761{
762 if (auto const surface = active_surface())
763 {
764 auto& info = tools->info_for(surface);
765
766 if (info.state == state)
767 state = mir_surface_state_restored;
768
769 auto const value = handle_set_state(surface, MirSurfaceState(state));
770 surface->configure(mir_surface_attrib_state, value);
771 }
772}
773
774void me::CanonicalWindowManagerPolicyCopy::select_active_surface(std::shared_ptr<ms::Surface> const& surface)
775{
776 if (surface == active_surface_.lock())
777 return;
778
779 if (!surface)
780 {
781 if (auto const active_surface = active_surface_.lock())
782 {
783 if (auto const titlebar = tools->info_for(active_surface).titlebar)
784 {
785 tools->info_for(titlebar).paint_titlebar(0x3F);
786 }
787 }
788
789 if (active_surface_.lock())
790 tools->set_focus_to({}, {});
791
792 active_surface_.reset();
793 return;
794 }
795
796 auto const& info_for = tools->info_for(surface);
797
798 if (info_for.can_be_active())
799 {
800 if (auto const active_surface = active_surface_.lock())
801 {
802 if (auto const titlebar = tools->info_for(active_surface).titlebar)
803 {
804 tools->info_for(titlebar).paint_titlebar(0x3F);
805 }
806 }
807 if (auto const titlebar = tools->info_for(surface).titlebar)
808 {
809 tools->info_for(titlebar).paint_titlebar(0xFF);
810 }
811 tools->set_focus_to(info_for.session.lock(), surface);
812 tools->raise_tree(surface);
813 active_surface_ = surface;
814 }
815 else
816 {
817 // Cannot have input focus - try the parent
818 if (auto const parent = info_for.parent.lock())
819 select_active_surface(parent);
820 }
821}
822
823auto me::CanonicalWindowManagerPolicyCopy::active_surface() const
824-> std::shared_ptr<ms::Surface>
825{
826 if (auto const surface = active_surface_.lock())
827 return surface;
828
829 if (auto const session = tools->focused_session())
830 {
831 if (auto const surface = session->default_surface())
832 return surface;
833 }
834
835 return std::shared_ptr<ms::Surface>{};
836}
837
838bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds)
839{
840 if (!surface || !surface->input_area_contains(old_cursor))
841 return false;
842
843 auto const top_left = surface->top_left();
844 Rectangle const old_pos{top_left, surface->size()};
845
846 auto anchor = top_left;
847
848 for (auto const& corner : {
849 old_pos.top_right(),
850 old_pos.bottom_left(),
851 old_pos.bottom_right()})
852 {
853 if ((old_cursor - anchor).length_squared() <
854 (old_cursor - corner).length_squared())
855 {
856 anchor = corner;
857 }
858 }
859
860 bool const left_resize = anchor.x != top_left.x;
861 bool const top_resize = anchor.y != top_left.y;
862 int const x_sign = left_resize? -1 : 1;
863 int const y_sign = top_resize? -1 : 1;
864
865 auto const delta = cursor-old_cursor;
866
867 Size new_size{old_pos.size.width + x_sign*delta.dx, old_pos.size.height + y_sign*delta.dy};
868
869 Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy;
870
871
872 auto const& surface_info = tools->info_for(surface);
873
874 surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds);
875
876 apply_resize(surface, surface_info.titlebar, new_pos, new_size);
877
878 return true;
879}
880
881void me::CanonicalWindowManagerPolicyCopy::apply_resize(
882 std::shared_ptr<ms::Surface> const& surface,
883 std::shared_ptr<ms::Surface> const& titlebar,
884 Point const& new_pos,
885 Size const& new_size) const
886{
887 if (titlebar)
888 titlebar->resize({new_size.width, Height{title_bar_height}});
889
890 surface->resize(new_size);
891
892 move_tree(surface, new_pos-surface->top_left());
893}
894
895bool me::CanonicalWindowManagerPolicyCopy::drag(std::shared_ptr<ms::Surface> surface, Point to, Point from, Rectangle /*bounds*/)
896{
897 if (!surface)
898 return false;
899
900 if (!surface->input_area_contains(from) && !tools->info_for(surface).titlebar)
901 return false;
902
903 auto movement = to - from;
904
905 // placeholder - constrain onscreen
906
907 switch (tools->info_for(surface).state)
908 {
909 case mir_surface_state_restored:
910 break;
911
912 // "A vertically maximised surface is anchored to the top and bottom of
913 // the available workspace and can have any width."
914 case mir_surface_state_vertmaximized:
915 movement.dy = DeltaY(0);
916 break;
917
918 // "A horizontally maximised surface is anchored to the left and right of
919 // the available workspace and can have any height"
920 case mir_surface_state_horizmaximized:
921 movement.dx = DeltaX(0);
922 break;
923
924 // "A maximised surface is anchored to the top, bottom, left and right of the
925 // available workspace. For example, if the launcher is always-visible then
926 // the left-edge of the surface is anchored to the right-edge of the launcher."
927 case mir_surface_state_maximized:
928 case mir_surface_state_fullscreen:
929 default:
930 return true;
931 }
932
933 move_tree(surface, movement);
934
935 return true;
936}
937
938void me::CanonicalWindowManagerPolicyCopy::move_tree(std::shared_ptr<ms::Surface> const& root, Displacement movement) const
939{
940 root->move_to(root->top_left() + movement);
941
942 for (auto const& child: tools->info_for(root).children)
943 {
944 move_tree(child.lock(), movement);
945 }
946}
0947
=== added file 'src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h'
--- src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_canonical_window_manager.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,132 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_
20#define MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_
21
22#include "server_example_basic_window_manager.h"
23
24#include "mir/geometry/displacement.h"
25
26#include <atomic>
27#include <set>
28
29///\example server_example_canonical_window_manager.h
30// Based on "Mir and Unity: Surfaces, input, and displays (v0.3)"
31
32namespace mir
33{
34namespace shell { class DisplayLayout; }
35namespace examples
36{
37// standard window management algorithm:
38// o Switch apps: tap or click on the corresponding tile
39// o Move window: Alt-leftmousebutton drag (three finger drag)
40// o Resize window: Alt-middle_button drag (two finger drag)
41// o Maximize/restore current window (to display size): Alt-F11
42// o Maximize/restore current window (to display height): Shift-F11
43// o Maximize/restore current window (to display width): Ctrl-F11
44// o client requests to maximize, vertically maximize & restore
45class CanonicalWindowManagerPolicyCopy : public WindowManagementPolicy
46{
47public:
48
49 explicit CanonicalWindowManagerPolicyCopy(
50 WindowManagerTools* const tools,
51 std::shared_ptr<shell::DisplayLayout> const& display_layout);
52
53 void click(geometry::Point cursor);
54
55 void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays);
56
57 void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays);
58
59 void resize(geometry::Point cursor);
60
61 auto handle_place_new_surface(
62 std::shared_ptr<scene::Session> const& session,
63 scene::SurfaceCreationParameters const& request_parameters)
64 -> scene::SurfaceCreationParameters;
65
66 void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface);
67
68 void handle_modify_surface(
69 std::shared_ptr<scene::Session> const& session,
70 std::shared_ptr<scene::Surface> const& surface,
71 shell::SurfaceSpecification const& modifications);
72
73 void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface);
74
75 int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value);
76
77 void drag(geometry::Point cursor);
78
79 bool handle_keyboard_event(MirKeyboardEvent const* event);
80
81 bool handle_touch_event(MirTouchEvent const* event);
82
83 bool handle_pointer_event(MirPointerEvent const* event);
84
85 void handle_raise_surface(
86 std::shared_ptr<scene::Session> const& session,
87 std::shared_ptr<scene::Surface> const& surface);
88
89 void generate_decorations_for(
90 std::shared_ptr<scene::Session> const& session,
91 std::shared_ptr<scene::Surface> const& surface,
92 SurfaceInfoMap& surface_map,
93 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build);
94
95private:
96 static const int modifier_mask =
97 mir_input_event_modifier_alt |
98 mir_input_event_modifier_shift |
99 mir_input_event_modifier_sym |
100 mir_input_event_modifier_ctrl |
101 mir_input_event_modifier_meta;
102
103 void toggle(MirSurfaceState state);
104
105 // "Mir and Unity: Surfaces, input, and displays (v0.3)" talks about active
106 // *window*,but Mir really only understands surfaces
107 void select_active_surface(std::shared_ptr<scene::Surface> const& surface);
108 auto active_surface() const -> std::shared_ptr<scene::Surface>;
109
110 bool resize(std::shared_ptr<scene::Surface> const& surface, geometry::Point cursor, geometry::Point old_cursor, geometry::Rectangle bounds);
111 bool drag(std::shared_ptr<scene::Surface> surface, geometry::Point to, geometry::Point from, geometry::Rectangle bounds);
112 void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const;
113 void apply_resize(
114 std::shared_ptr<mir::scene::Surface> const& surface,
115 std::shared_ptr<mir::scene::Surface> const& titlebar,
116 geometry::Point const& new_pos,
117 geometry::Size const& new_size) const;
118
119 WindowManagerTools* const tools;
120 std::shared_ptr<shell::DisplayLayout> const display_layout;
121
122 geometry::Rectangle display_area;
123 geometry::Point old_cursor{};
124 std::weak_ptr<scene::Surface> active_surface_;
125 using FullscreenSurfaces = std::set<std::weak_ptr<scene::Surface>, std::owner_less<std::weak_ptr<scene::Surface>>>;
126
127 FullscreenSurfaces fullscreen_surfaces;
128};
129}
130}
131
132#endif /* MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ */
0133
=== added file 'src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp'
--- src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,640 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "server_example_tiling_window_manager.h"
20
21#include "mir/scene/session.h"
22#include "mir/scene/surface.h"
23#include "mir/scene/surface_creation_parameters.h"
24#include "mir/shell/surface_specification.h"
25#include "mir/shell/surface_stack.h"
26#include "mir/shell/surface_ready_observer.h"
27#include "mir/geometry/displacement.h"
28
29#include <linux/input.h>
30#include <csignal>
31
32namespace me = mir::examples;
33namespace ms = mir::scene;
34namespace mf = mir::frontend;
35using namespace mir::geometry;
36
37///\example server_example_tiling_window_manager.cpp
38/// Demonstrate implementing a simple tiling algorithm
39
40me::TilingWindowManagerPolicy::TilingWindowManagerPolicy(WindowManagerTools* const tools) :
41 tools{tools}
42{
43}
44
45void me::TilingWindowManagerPolicy::click(Point cursor)
46{
47 auto const session = session_under(cursor);
48 auto const surface = tools->surface_at(cursor);
49 select_active_surface(session, surface);
50}
51
52void me::TilingWindowManagerPolicy::handle_session_info_updated(SessionInfoMap& session_info, Rectangles const& displays)
53{
54 update_tiles(session_info, displays);
55}
56
57void me::TilingWindowManagerPolicy::handle_displays_updated(SessionInfoMap& session_info, Rectangles const& displays)
58{
59 update_tiles(session_info, displays);
60}
61
62void me::TilingWindowManagerPolicy::resize(Point cursor)
63{
64 if (auto const session = session_under(cursor))
65 {
66 if (session == session_under(old_cursor))
67 {
68 if (auto const surface = select_active_surface(session, tools->surface_at(old_cursor)))
69 {
70 resize(surface, cursor, old_cursor, tools->info_for(session).tile);
71 }
72 }
73 }
74}
75
76auto me::TilingWindowManagerPolicy::handle_place_new_surface(
77 std::shared_ptr<ms::Session> const& session,
78 ms::SurfaceCreationParameters const& request_parameters)
79-> ms::SurfaceCreationParameters
80{
81 auto parameters = request_parameters;
82
83 Rectangle const& tile = tools->info_for(session).tile;
84 parameters.top_left = parameters.top_left + (tile.top_left - Point{0, 0});
85
86 if (auto const parent = parameters.parent.lock())
87 {
88 auto const width = parameters.size.width.as_int();
89 auto const height = parameters.size.height.as_int();
90
91 if (parameters.aux_rect.is_set() && parameters.edge_attachment.is_set())
92 {
93 auto const edge_attachment = parameters.edge_attachment.value();
94 auto const aux_rect = parameters.aux_rect.value();
95 auto const parent_top_left = parent->top_left();
96 auto const top_left = aux_rect.top_left -Point{} + parent_top_left;
97 auto const top_right= aux_rect.top_right() -Point{} + parent_top_left;
98 auto const bot_left = aux_rect.bottom_left()-Point{} + parent_top_left;
99
100 if (edge_attachment & mir_edge_attachment_vertical)
101 {
102 if (tile.contains(top_right + Displacement{width, height}))
103 {
104 parameters.top_left = top_right;
105 }
106 else if (tile.contains(top_left + Displacement{-width, height}))
107 {
108 parameters.top_left = top_left + Displacement{-width, 0};
109 }
110 }
111
112 if (edge_attachment & mir_edge_attachment_horizontal)
113 {
114 if (tile.contains(bot_left + Displacement{width, height}))
115 {
116 parameters.top_left = bot_left;
117 }
118 else if (tile.contains(top_left + Displacement{width, -height}))
119 {
120 parameters.top_left = top_left + Displacement{0, -height};
121 }
122 }
123 }
124 else
125 {
126 auto const parent_top_left = parent->top_left();
127 auto const centred = parent_top_left
128 + 0.5*(as_displacement(parent->size()) - as_displacement(parameters.size))
129 - DeltaY{(parent->size().height.as_int()-height)/6};
130
131 parameters.top_left = centred;
132 }
133 }
134
135 clip_to_tile(parameters, tile);
136 return parameters;
137}
138
139void me::TilingWindowManagerPolicy::generate_decorations_for(
140 std::shared_ptr<ms::Session> const&,
141 std::shared_ptr<ms::Surface> const&,
142 SurfaceInfoMap&,
143 std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&)
144{
145}
146
147void me::TilingWindowManagerPolicy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface)
148{
149 tools->info_for(session).surfaces.push_back(surface);
150
151 auto& surface_info = tools->info_for(surface);
152 if (auto const parent = surface_info.parent.lock())
153 {
154 tools->info_for(parent).children.push_back(surface);
155 }
156
157 if (surface_info.can_be_active())
158 {
159 surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>(
160 [this](std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface)
161 { select_active_surface(session, surface); },
162 session,
163 surface));
164 }
165}
166
167void me::TilingWindowManagerPolicy::handle_modify_surface(
168 std::shared_ptr<scene::Session> const& /*session*/,
169 std::shared_ptr<scene::Surface> const& surface,
170 shell::SurfaceSpecification const& modifications)
171{
172 if (modifications.name.is_set())
173 surface->rename(modifications.name.value());
174}
175
176void me::TilingWindowManagerPolicy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface)
177{
178 auto& info = tools->info_for(surface);
179
180 if (auto const parent = info.parent.lock())
181 {
182 auto& siblings = tools->info_for(parent).children;
183
184 for (auto i = begin(siblings); i != end(siblings); ++i)
185 {
186 if (surface.lock() == i->lock())
187 {
188 siblings.erase(i);
189 break;
190 }
191 }
192 }
193
194 auto& surfaces = tools->info_for(session).surfaces;
195
196 for (auto i = begin(surfaces); i != end(surfaces); ++i)
197 {
198 if (surface.lock() == i->lock())
199 {
200 surfaces.erase(i);
201 break;
202 }
203 }
204
205 session->destroy_surface(surface);
206
207 if (surfaces.empty() && session == tools->focused_session())
208 {
209 tools->focus_next_session();
210 select_active_surface(tools->focused_session(), tools->focused_surface());
211 }
212}
213
214int me::TilingWindowManagerPolicy::handle_set_state(std::shared_ptr<ms::Surface> const& surface, MirSurfaceState value)
215{
216 auto& info = tools->info_for(surface);
217
218 switch (value)
219 {
220 case mir_surface_state_restored:
221 case mir_surface_state_maximized:
222 case mir_surface_state_vertmaximized:
223 case mir_surface_state_horizmaximized:
224 break;
225
226 default:
227 return info.state;
228 }
229
230 if (info.state == mir_surface_state_restored)
231 {
232 info.restore_rect = {surface->top_left(), surface->size()};
233 }
234
235 if (info.state == value)
236 {
237 return info.state;
238 }
239
240 auto const& tile = tools->info_for(info.session).tile;
241
242 switch (value)
243 {
244 case mir_surface_state_restored:
245 surface->resize(info.restore_rect.size);
246 drag(surface, info.restore_rect.top_left, surface->top_left(), tile);
247 break;
248
249 case mir_surface_state_maximized:
250 surface->resize(tile.size);
251 drag(surface, tile.top_left, surface->top_left(), tile);
252 break;
253
254 case mir_surface_state_horizmaximized:
255 surface->resize({tile.size.width, info.restore_rect.size.height});
256 drag(surface, {tile.top_left.x, info.restore_rect.top_left.y}, surface->top_left(), tile);
257 break;
258
259 case mir_surface_state_vertmaximized:
260 surface->resize({info.restore_rect.size.width, tile.size.height});
261 drag(surface, {info.restore_rect.top_left.x, tile.top_left.y}, surface->top_left(), tile);
262 break;
263
264 default:
265 break;
266 }
267
268 return info.state = value;
269}
270
271void me::TilingWindowManagerPolicy::drag(Point cursor)
272{
273 if (auto const session = session_under(cursor))
274 {
275 if (session == session_under(old_cursor))
276 {
277 if (auto const surface = select_active_surface(session, tools->surface_at(old_cursor)))
278 {
279 drag(surface, cursor, old_cursor, tools->info_for(session).tile);
280 }
281 }
282 }
283}
284
285void me::TilingWindowManagerPolicy::handle_raise_surface(
286 std::shared_ptr<ms::Session> const& session,
287 std::shared_ptr<ms::Surface> const& surface)
288{
289 select_active_surface(session, surface);
290}
291
292bool me::TilingWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event)
293{
294 auto const action = mir_keyboard_event_action(event);
295 auto const scan_code = mir_keyboard_event_scan_code(event);
296 auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
297
298 if (action == mir_keyboard_action_down && scan_code == KEY_F11)
299 {
300 switch (modifiers & modifier_mask)
301 {
302 case mir_input_event_modifier_alt:
303 toggle(mir_surface_state_maximized);
304 return true;
305
306 case mir_input_event_modifier_shift:
307 toggle(mir_surface_state_vertmaximized);
308 return true;
309
310 case mir_input_event_modifier_ctrl:
311 toggle(mir_surface_state_horizmaximized);
312 return true;
313
314 default:
315 break;
316 }
317 }
318 else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
319 {
320 if (auto const session = tools->focused_session())
321 {
322 switch (modifiers & modifier_mask)
323 {
324 case mir_input_event_modifier_alt:
325 kill(session->process_id(), SIGTERM);
326 return true;
327
328 case mir_input_event_modifier_ctrl:
329 if (auto const surf = session->default_surface())
330 {
331 surf->request_client_surface_close();
332 return true;
333 }
334
335 default:
336 break;
337 }
338 }
339 }
340 else if (action == mir_keyboard_action_down &&
341 modifiers == mir_input_event_modifier_alt &&
342 scan_code == KEY_TAB)
343 {
344 tools->focus_next_session();
345 select_active_surface(tools->focused_session(), tools->focused_surface());
346
347 return true;
348 }
349 else if (action == mir_keyboard_action_down &&
350 modifiers == mir_input_event_modifier_alt &&
351 scan_code == KEY_GRAVE)
352 {
353 if (auto const prev = tools->focused_surface())
354 {
355 if (auto const app = tools->focused_session())
356 if (auto const surface = app->surface_after(prev))
357 {
358 select_active_surface(app, surface);
359 }
360 }
361
362 return true;
363 }
364
365 return false;
366}
367
368bool me::TilingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event)
369{
370 auto const count = mir_touch_event_point_count(event);
371
372 long total_x = 0;
373 long total_y = 0;
374
375 for (auto i = 0U; i != count; ++i)
376 {
377 total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x);
378 total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y);
379 }
380
381 Point const cursor{total_x/count, total_y/count};
382
383 bool is_drag = true;
384 for (auto i = 0U; i != count; ++i)
385 {
386 switch (mir_touch_event_action(event, i))
387 {
388 case mir_touch_action_up:
389 return false;
390
391 case mir_touch_action_down:
392 is_drag = false;
393
394 case mir_touch_action_change:
395 continue;
396 }
397 }
398
399 bool consumes_event = false;
400 if (is_drag)
401 {
402 switch (count)
403 {
404 case 2:
405 resize(cursor);
406 consumes_event = true;
407 break;
408
409 case 3:
410 drag(cursor);
411 consumes_event = true;
412 break;
413 }
414 }
415
416 old_cursor = cursor;
417 return consumes_event;
418}
419
420bool me::TilingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event)
421{
422 auto const action = mir_pointer_event_action(event);
423 auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask;
424 Point const cursor{
425 mir_pointer_event_axis_value(event, mir_pointer_axis_x),
426 mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
427
428 bool consumes_event = false;
429
430 if (action == mir_pointer_action_button_down)
431 {
432 click(cursor);
433 }
434 else if (action == mir_pointer_action_motion &&
435 modifiers == mir_input_event_modifier_alt)
436 {
437 if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
438 {
439 drag(cursor);
440 consumes_event = true;
441 }
442 else if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary))
443 {
444 resize(cursor);
445 consumes_event = true;
446 }
447 }
448
449 old_cursor = cursor;
450 return consumes_event;
451}
452
453void me::TilingWindowManagerPolicy::toggle(MirSurfaceState state)
454{
455 if (auto const session = tools->focused_session())
456 {
457 if (auto const surface = session->default_surface())
458 {
459 if (surface->state() == state)
460 state = mir_surface_state_restored;
461
462 auto const value = handle_set_state(surface, MirSurfaceState(state));
463 surface->configure(mir_surface_attrib_state, value);
464 }
465 }
466}
467
468std::shared_ptr<ms::Session> me::TilingWindowManagerPolicy::session_under(Point position)
469{
470 return tools->find_session([&](SessionInfo const& info) { return info.tile.contains(position);});
471}
472
473void me::TilingWindowManagerPolicy::update_tiles(
474 SessionInfoMap& session_info,
475 Rectangles const& displays)
476{
477 if (session_info.size() < 1 || displays.size() < 1) return;
478
479 auto const sessions = session_info.size();
480
481 auto const bounding_rect = displays.bounding_rectangle();
482
483 auto const total_width = bounding_rect.size.width.as_int();
484 auto const total_height = bounding_rect.size.height.as_int();
485
486 auto index = 0;
487
488 for (auto& info : session_info)
489 {
490 auto const x = (total_width*index)/sessions;
491 ++index;
492 auto const dx = (total_width*index)/sessions - x;
493
494 auto const old_tile = info.second.tile;
495 Rectangle const new_tile{{x, 0}, {dx, total_height}};
496
497 update_surfaces(info.first, old_tile, new_tile);
498
499 info.second.tile = new_tile;
500 }
501}
502
503void me::TilingWindowManagerPolicy::update_surfaces(std::weak_ptr<ms::Session> const& session, Rectangle const& old_tile, Rectangle const& new_tile)
504{
505 auto displacement = new_tile.top_left - old_tile.top_left;
506 auto& info = tools->info_for(session);
507
508 for (auto const& ps : info.surfaces)
509 {
510 if (auto const surface = ps.lock())
511 {
512 auto const old_pos = surface->top_left();
513 surface->move_to(old_pos + displacement);
514
515 fit_to_new_tile(*surface, old_tile, new_tile);
516 }
517 }
518}
519
520void me::TilingWindowManagerPolicy::clip_to_tile(ms::SurfaceCreationParameters& parameters, Rectangle const& tile)
521{
522 auto const displacement = parameters.top_left - tile.top_left;
523
524 auto width = std::min(tile.size.width.as_int()-displacement.dx.as_int(), parameters.size.width.as_int());
525 auto height = std::min(tile.size.height.as_int()-displacement.dy.as_int(), parameters.size.height.as_int());
526
527 parameters.size = Size{width, height};
528}
529
530void me::TilingWindowManagerPolicy::fit_to_new_tile(ms::Surface& surface, Rectangle const& old_tile, Rectangle const& new_tile)
531{
532 auto const displacement = surface.top_left() - new_tile.top_left;
533
534 // For now just scale if was filling width/height of tile
535 auto const old_size = surface.size();
536 auto const scaled_width = old_size.width == old_tile.size.width ? new_tile.size.width : old_size.width;
537 auto const scaled_height = old_size.height == old_tile.size.height ? new_tile.size.height : old_size.height;
538
539 auto width = std::min(new_tile.size.width.as_int()-displacement.dx.as_int(), scaled_width.as_int());
540 auto height = std::min(new_tile.size.height.as_int()-displacement.dy.as_int(), scaled_height.as_int());
541
542 surface.resize({width, height});
543}
544
545void me::TilingWindowManagerPolicy::drag(std::shared_ptr<ms::Surface> surface, Point to, Point from, Rectangle bounds)
546{
547 if (surface && surface->input_area_contains(from))
548 {
549 auto movement = to - from;
550
551 constrained_move(surface, movement, bounds);
552
553 for (auto const& child: tools->info_for(surface).children)
554 {
555 auto move = movement;
556 constrained_move(child.lock(), move, bounds);
557 }
558 }
559}
560
561void me::TilingWindowManagerPolicy::constrained_move(
562 std::shared_ptr<scene::Surface> const& surface,
563 Displacement& movement,
564 Rectangle const& bounds)
565{
566 auto const top_left = surface->top_left();
567 auto const surface_size = surface->size();
568 auto const bottom_right = top_left + as_displacement(surface_size);
569
570 if (movement.dx < DeltaX{0})
571 movement.dx = std::max(movement.dx, (bounds.top_left - top_left).dx);
572
573 if (movement.dy < DeltaY{0})
574 movement.dy = std::max(movement.dy, (bounds.top_left - top_left).dy);
575
576 if (movement.dx > DeltaX{0})
577 movement.dx = std::min(movement.dx, (bounds.bottom_right() - bottom_right).dx);
578
579 if (movement.dy > DeltaY{0})
580 movement.dy = std::min(movement.dy, (bounds.bottom_right() - bottom_right).dy);
581
582 auto new_pos = surface->top_left() + movement;
583
584 surface->move_to(new_pos);
585}
586
587void me::TilingWindowManagerPolicy::resize(std::shared_ptr<ms::Surface> surface, Point cursor, Point old_cursor, Rectangle bounds)
588{
589 if (surface && surface->input_area_contains(old_cursor))
590 {
591 auto const top_left = surface->top_left();
592
593 auto const old_displacement = old_cursor - top_left;
594 auto const new_displacement = cursor - top_left;
595
596 auto const scale_x = new_displacement.dx.as_float()/std::max(1.0f, old_displacement.dx.as_float());
597 auto const scale_y = new_displacement.dy.as_float()/std::max(1.0f, old_displacement.dy.as_float());
598
599 if (scale_x <= 0.0f || scale_y <= 0.0f) return;
600
601 auto const old_size = surface->size();
602 Size new_size{scale_x*old_size.width, scale_y*old_size.height};
603
604 auto const size_limits = as_size(bounds.bottom_right() - top_left);
605
606 if (new_size.width > size_limits.width)
607 new_size.width = size_limits.width;
608
609 if (new_size.height > size_limits.height)
610 new_size.height = size_limits.height;
611
612 surface->resize(new_size);
613 }
614}
615
616std::shared_ptr<ms::Surface> me::TilingWindowManagerPolicy::select_active_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<scene::Surface> const& surface)
617{
618 if (!surface)
619 {
620 tools->set_focus_to({}, {});
621 return surface;
622 }
623
624 auto const& info_for = tools->info_for(surface);
625
626 if (info_for.can_be_active())
627 {
628 tools->set_focus_to(session, surface);
629 tools->raise_tree(surface);
630 return surface;
631 }
632 else
633 {
634 // Cannot have input focus - try the parent
635 if (auto const parent = info_for.parent.lock())
636 return select_active_surface(session, parent);
637
638 return {};
639 }
640}
0641
=== added file 'src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h'
--- src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_tiling_window_manager.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,124 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_
20#define MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_
21
22#include "server_example_basic_window_manager.h"
23
24///\example server_example_tiling_window_manager.h
25/// Demonstrate implementing a simple tiling algorithm
26
27namespace mir
28{
29namespace examples
30{
31// simple tiling algorithm:
32// o Switch apps: tap or click on the corresponding tile
33// o Move window: Alt-leftmousebutton drag (three finger drag)
34// o Resize window: Alt-middle_button drag (two finger drag)
35// o Maximize/restore current window (to tile size): Alt-F11
36// o Maximize/restore current window (to tile height): Shift-F11
37// o Maximize/restore current window (to tile width): Ctrl-F11
38// o client requests to maximize, vertically maximize & restore
39class TilingWindowManagerPolicy : public WindowManagementPolicy
40{
41public:
42 explicit TilingWindowManagerPolicy(WindowManagerTools* const tools);
43
44 void click(geometry::Point cursor);
45
46 void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays);
47
48 void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays);
49
50 void resize(geometry::Point cursor);
51
52 auto handle_place_new_surface(
53 std::shared_ptr<scene::Session> const& session,
54 scene::SurfaceCreationParameters const& request_parameters)
55 -> scene::SurfaceCreationParameters;
56
57 void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface);
58
59 void handle_modify_surface(
60 std::shared_ptr<scene::Session> const& session,
61 std::shared_ptr<scene::Surface> const& surface,
62 shell::SurfaceSpecification const& modifications);
63
64 void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface);
65
66 int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value);
67
68 void drag(geometry::Point cursor);
69
70 bool handle_keyboard_event(MirKeyboardEvent const* event);
71
72 bool handle_touch_event(MirTouchEvent const* event);
73
74 bool handle_pointer_event(MirPointerEvent const* event);
75
76 void handle_raise_surface(
77 std::shared_ptr<scene::Session> const& session,
78 std::shared_ptr<scene::Surface> const& surface);
79
80 void generate_decorations_for(
81 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface,
82 SurfaceInfoMap& surface_info,
83 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build);
84
85private:
86 static const int modifier_mask =
87 mir_input_event_modifier_alt |
88 mir_input_event_modifier_shift |
89 mir_input_event_modifier_sym |
90 mir_input_event_modifier_ctrl |
91 mir_input_event_modifier_meta;
92
93 void toggle(MirSurfaceState state);
94
95 std::shared_ptr<scene::Session> session_under(geometry::Point position);
96
97 void update_tiles(
98 SessionInfoMap& session_info,
99 geometry::Rectangles const& displays);
100
101 void update_surfaces(std::weak_ptr<scene::Session> const& session, geometry::Rectangle const& old_tile, geometry::Rectangle const& new_tile);
102
103 static void clip_to_tile(scene::SurfaceCreationParameters& parameters, geometry::Rectangle const& tile);
104
105 static void fit_to_new_tile(scene::Surface& surface, geometry::Rectangle const& old_tile, geometry::Rectangle const& new_tile);
106
107 void drag(std::shared_ptr<scene::Surface> surface, geometry::Point to, geometry::Point from, geometry::Rectangle bounds);
108
109 static void resize(std::shared_ptr<scene::Surface> surface, geometry::Point cursor, geometry::Point old_cursor, geometry::Rectangle bounds);
110
111 static void constrained_move(std::shared_ptr<scene::Surface> const& surface, geometry::Displacement& movement, geometry::Rectangle const& bounds);
112
113 std::shared_ptr<scene::Surface> select_active_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface);
114
115 WindowManagerTools* const tools;
116
117 geometry::Point old_cursor{};
118};
119
120using TilingWindowManager = WindowManagerBuilder<TilingWindowManagerPolicy>;
121}
122}
123
124#endif /* MIR_EXAMPLE_TILING_WINDOW_MANAGER_H_ */
0125
=== added file 'src/platforms/mirserver/wm-wip/server_example_window_management.cpp'
--- src/platforms/mirserver/wm-wip/server_example_window_management.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_window_management.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,155 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "server_example_window_management.h"
20
21#include "server_example_tiling_window_manager.h"
22#include "server_example_canonical_window_manager.h"
23
24#include "mir/abnormal_exit.h"
25#include "mir/server.h"
26#include "mir/input/composite_event_filter.h"
27#include "mir/options/option.h"
28#include "mir/scene/session.h"
29#include "mir/scene/surface_creation_parameters.h"
30#include "mir/shell/display_layout.h"
31#include "mir/shell/system_compositor_window_manager.h"
32
33namespace me = mir::examples;
34namespace mf = mir::frontend;
35namespace mg = mir::graphics;
36namespace mi = mir::input;
37namespace ms = mir::scene;
38namespace msh = mir::shell;
39using namespace mir::geometry;
40
41///\example server_example_window_management.cpp
42/// Demonstrate introducing a window management strategy
43
44namespace
45{
46char const* const wm_option = "window-manager";
47char const* const wm_description = "window management strategy [{tiling|fullscreen|canonical|system-compositor}]";
48
49char const* const wm_tiling = "tiling";
50char const* const wm_fullscreen = "fullscreen";
51char const* const wm_canonical = "canonical";
52char const* const wm_system_compositor = "system-compositor";
53
54// Very simple - make every surface fullscreen
55class FullscreenWindowManagerPolicy : public me::WindowManagementPolicy
56{
57public:
58 FullscreenWindowManagerPolicy(me::WindowManagerTools* const /*tools*/, std::shared_ptr<msh::DisplayLayout> const& display_layout) :
59 display_layout{display_layout} {}
60
61 void handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) {}
62
63 void handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) {}
64
65 auto handle_place_new_surface(
66 std::shared_ptr<ms::Session> const& /*session*/,
67 ms::SurfaceCreationParameters const& request_parameters)
68 -> ms::SurfaceCreationParameters
69 {
70 auto placed_parameters = request_parameters;
71
72 Rectangle rect{request_parameters.top_left, request_parameters.size};
73 display_layout->size_to_output(rect);
74 placed_parameters.size = rect.size;
75
76 return placed_parameters;
77 }
78 void handle_modify_surface(
79 std::shared_ptr<ms::Session> const& /*session*/,
80 std::shared_ptr<ms::Surface> const& /*surface*/,
81 msh::SurfaceSpecification const& /*modifications*/)
82 {
83 }
84
85 void handle_new_surface(std::shared_ptr<ms::Session> const& /*session*/, std::shared_ptr<ms::Surface> const& /*surface*/)
86 {
87 }
88
89 void handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface)
90 { session->destroy_surface(surface); }
91
92 int handle_set_state(std::shared_ptr<ms::Surface> const& /*surface*/, MirSurfaceState value)
93 { return value; }
94
95 bool handle_keyboard_event(MirKeyboardEvent const* /*event*/) { return false; }
96
97 bool handle_touch_event(MirTouchEvent const* /*event*/) { return false; }
98
99 bool handle_pointer_event(MirPointerEvent const* /*event*/) { return false; }
100
101 void handle_raise_surface(
102 std::shared_ptr<ms::Session> const& /*session*/,
103 std::shared_ptr<ms::Surface> const& /*surface*/)
104 {
105 }
106
107 void generate_decorations_for(
108 std::shared_ptr<ms::Session> const&,
109 std::shared_ptr<ms::Surface> const&,
110 SurfaceInfoMap&,
111 std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&)
112 {
113 }
114private:
115 std::shared_ptr<msh::DisplayLayout> const display_layout;
116};
117
118}
119
120using FullscreenWindowManager = me::WindowManagerBuilder<FullscreenWindowManagerPolicy>;
121using CanonicalWindowManager = me::WindowManagerBuilder<me::CanonicalWindowManagerPolicyCopy>;
122
123void me::add_window_manager_option_to(Server& server)
124{
125 server.add_configuration_option(wm_option, wm_description, wm_canonical);
126
127 server.override_the_window_manager_builder([&server](msh::FocusController* focus_controller)
128 -> std::shared_ptr<msh::WindowManager>
129 {
130 auto const options = server.get_options();
131 auto const selection = options->get<std::string>(wm_option);
132
133 if (selection == wm_tiling)
134 {
135 return std::make_shared<TilingWindowManager>(focus_controller);
136 }
137 else if (selection == wm_fullscreen)
138 {
139 return std::make_shared<FullscreenWindowManager>(focus_controller, server.the_shell_display_layout());
140 }
141 else if (selection == wm_canonical)
142 {
143 return std::make_shared<CanonicalWindowManager>(focus_controller, server.the_shell_display_layout());
144 }
145 else if (selection == wm_system_compositor)
146 {
147 return std::make_shared<msh::SystemCompositorWindowManager>(
148 focus_controller,
149 server.the_shell_display_layout(),
150 server.the_session_coordinator());
151 }
152
153 throw mir::AbnormalExit("Unknown window manager: " + selection);
154 });
155}
0156
=== added file 'src/platforms/mirserver/wm-wip/server_example_window_management.h'
--- src/platforms/mirserver/wm-wip/server_example_window_management.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_window_management.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,33 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored By: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_EXAMPLES_WINDOW_MANAGEMENT_H_
20#define MIR_EXAMPLES_WINDOW_MANAGEMENT_H_
21
22namespace mir
23{
24class Server;
25
26namespace examples
27{
28void add_window_manager_option_to(Server& server);
29}
30} // namespace mir
31
32
33#endif // MIR_EXAMPLES_WINDOW_MANAGEMENT_H_
034
=== added file 'src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp'
--- src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_window_management_info.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,406 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "server_example_window_management_info.h"
20
21#include "mir/scene/surface.h"
22#include "mir/scene/surface_creation_parameters.h"
23
24#include "mir/graphics/buffer.h"
25
26#include <atomic>
27
28namespace me = mir::examples;
29namespace ms = mir::scene;
30namespace mg = mir::graphics;
31using namespace mir::geometry;
32
33me::SurfaceInfo::SurfaceInfo(
34 std::shared_ptr<scene::Session> const& session,
35 std::shared_ptr<scene::Surface> const& surface,
36 scene::SurfaceCreationParameters const& params) :
37 type{surface->type()},
38 state{surface->state()},
39 restore_rect{surface->top_left(), surface->size()},
40 session{session},
41 parent{params.parent},
42 min_width{params.min_width.is_set() ? params.min_width.value() : Width{}},
43 min_height{params.min_height.is_set() ? params.min_height.value() : Height{}},
44 max_width{params.max_width.is_set() ? params.max_width.value() : Width{std::numeric_limits<int>::max()}},
45 max_height{params.max_height.is_set() ? params.max_height.value() : Height{std::numeric_limits<int>::max()}},
46 width_inc{params.width_inc},
47 height_inc{params.height_inc},
48 min_aspect{params.min_aspect},
49 max_aspect{params.max_aspect}
50{
51 if (params.output_id != mir::graphics::DisplayConfigurationOutputId{0})
52 output_id = params.output_id;
53}
54
55bool me::SurfaceInfo::can_be_active() const
56{
57 switch (type)
58 {
59 case mir_surface_type_normal: /**< AKA "regular" */
60 case mir_surface_type_utility: /**< AKA "floating" */
61 case mir_surface_type_dialog:
62 case mir_surface_type_satellite: /**< AKA "toolbox"/"toolbar" */
63 case mir_surface_type_freestyle:
64 case mir_surface_type_menu:
65 case mir_surface_type_inputmethod: /**< AKA "OSK" or handwriting etc. */
66 return true;
67
68 case mir_surface_type_gloss:
69 case mir_surface_type_tip: /**< AKA "tooltip" */
70 default:
71 // Cannot have input focus
72 return false;
73 }
74}
75
76bool me::SurfaceInfo::must_have_parent() const
77{
78 switch (type)
79 {
80 case mir_surface_type_overlay:;
81 case mir_surface_type_inputmethod:
82 case mir_surface_type_satellite:
83 case mir_surface_type_tip:
84 return true;
85
86 default:
87 return false;
88 }
89}
90
91bool me::SurfaceInfo::can_morph_to(MirSurfaceType new_type) const
92{
93 switch (new_type)
94 {
95 case mir_surface_type_normal:
96 case mir_surface_type_utility:
97 case mir_surface_type_satellite:
98 switch (type)
99 {
100 case mir_surface_type_normal:
101 case mir_surface_type_utility:
102 case mir_surface_type_dialog:
103 case mir_surface_type_satellite:
104 return true;
105
106 default:
107 break;
108 }
109 break;
110
111 case mir_surface_type_dialog:
112 switch (type)
113 {
114 case mir_surface_type_normal:
115 case mir_surface_type_utility:
116 case mir_surface_type_dialog:
117 case mir_surface_type_popover:
118 case mir_surface_type_satellite:
119 return true;
120
121 default:
122 break;
123 }
124 break;
125
126 default:
127 break;
128 }
129
130 return false;
131}
132
133bool me::SurfaceInfo::must_not_have_parent() const
134{
135 switch (type)
136 {
137 case mir_surface_type_normal:
138 case mir_surface_type_utility:
139 return true;
140
141 default:
142 return false;
143 }
144}
145
146bool me::SurfaceInfo::is_visible() const
147{
148 switch (state)
149 {
150 case mir_surface_state_hidden:
151 case mir_surface_state_minimized:
152 return false;
153 default:
154 break;
155 }
156 return true;
157}
158
159struct mir::examples::SurfaceInfo::StreamPainter
160{
161 virtual void paint(int) = 0;
162 virtual ~StreamPainter() = default;
163 StreamPainter() = default;
164 StreamPainter(StreamPainter const&) = delete;
165 StreamPainter& operator=(StreamPainter const&) = delete;
166};
167
168struct mir::examples::SurfaceInfo::SwappingPainter
169 : mir::examples::SurfaceInfo::StreamPainter
170{
171 SwappingPainter(std::shared_ptr<frontend::BufferStream> const& buffer_stream) :
172 buffer_stream{buffer_stream}, buffer{nullptr}
173 {
174 swap_buffers();
175 }
176
177 void swap_buffers()
178 {
179 auto const callback = [this](mir::graphics::Buffer* new_buffer)
180 {
181 buffer.store(new_buffer);
182 };
183
184 buffer_stream->swap_buffers(buffer, callback);
185 }
186
187 void paint(int intensity) override
188 {
189 if (auto const buf = buffer.load())
190 {
191 auto const format = buffer_stream->pixel_format();
192 auto const sz = buf->size().height.as_int() *
193 buf->size().width.as_int() * MIR_BYTES_PER_PIXEL(format);
194 std::vector<unsigned char> pixels(sz, intensity);
195 buf->write(pixels.data(), sz);
196 swap_buffers();
197 }
198 }
199
200 std::shared_ptr<frontend::BufferStream> const buffer_stream;
201 std::atomic<graphics::Buffer*> buffer;
202};
203
204struct mir::examples::SurfaceInfo::AllocatingPainter
205 : mir::examples::SurfaceInfo::StreamPainter
206{
207 AllocatingPainter(std::shared_ptr<frontend::BufferStream> const& buffer_stream, Size size) :
208 buffer_stream(buffer_stream),
209 properties({
210 size,
211 buffer_stream->pixel_format(),
212 mg::BufferUsage::software
213 }),
214 front_buffer(buffer_stream->allocate_buffer(properties)),
215 back_buffer(buffer_stream->allocate_buffer(properties))
216 {
217 }
218
219 void paint(int intensity) override
220 {
221 buffer_stream->with_buffer(back_buffer,
222 [this, intensity](graphics::Buffer& buffer)
223 {
224 auto const format = buffer.pixel_format();
225 auto const sz = buffer.size().height.as_int() *
226 buffer.size().width.as_int() * MIR_BYTES_PER_PIXEL(format);
227 std::vector<unsigned char> pixels(sz, intensity);
228 buffer.write(pixels.data(), sz);
229 buffer_stream->swap_buffers(&buffer, [](mg::Buffer*){});
230 });
231 std::swap(front_buffer, back_buffer);
232 }
233
234 ~AllocatingPainter()
235 {
236 buffer_stream->remove_buffer(front_buffer);
237 buffer_stream->remove_buffer(back_buffer);
238 }
239
240 std::shared_ptr<frontend::BufferStream> const buffer_stream;
241 mg::BufferProperties properties;
242 mg::BufferID front_buffer;
243 mg::BufferID back_buffer;
244};
245
246void mir::examples::SurfaceInfo::init_titlebar(std::shared_ptr<scene::Surface> const& surface)
247{
248 auto stream = surface->primary_buffer_stream();
249 try
250 {
251 stream_painter = std::make_shared<AllocatingPainter>(stream, surface->size());
252 }
253 catch (...)
254 {
255 stream_painter = std::make_shared<SwappingPainter>(stream);
256 }
257}
258
259void mir::examples::SurfaceInfo::paint_titlebar(int intensity)
260{
261 stream_painter->paint(intensity);
262}
263
264void me::SurfaceInfo::constrain_resize(
265 std::shared_ptr<ms::Surface> const& surface,
266 Point& requested_pos,
267 Size& requested_size,
268 bool const left_resize,
269 bool const top_resize,
270 Rectangle const& /*bounds*/) const
271{
272 Point new_pos = requested_pos;
273 Size new_size = requested_size;
274
275 if (min_aspect.is_set())
276 {
277 auto const ar = min_aspect.value();
278
279 auto const error = new_size.height.as_int()*long(ar.width) - new_size.width.as_int()*long(ar.height);
280
281 if (error > 0)
282 {
283 // Add (denominator-1) to numerator to ensure rounding up
284 auto const width_correction = (error+(ar.height-1))/ar.height;
285 auto const height_correction = (error+(ar.width-1))/ar.width;
286
287 if (width_correction < height_correction)
288 {
289 new_size.width = new_size.width + DeltaX(width_correction);
290 }
291 else
292 {
293 new_size.height = new_size.height - DeltaY(height_correction);
294 }
295 }
296 }
297
298 if (max_aspect.is_set())
299 {
300 auto const ar = max_aspect.value();
301
302 auto const error = new_size.width.as_int()*long(ar.height) - new_size.height.as_int()*long(ar.width);
303
304 if (error > 0)
305 {
306 // Add (denominator-1) to numerator to ensure rounding up
307 auto const height_correction = (error+(ar.width-1))/ar.width;
308 auto const width_correction = (error+(ar.height-1))/ar.height;
309
310 if (width_correction < height_correction)
311 {
312 new_size.width = new_size.width - DeltaX(width_correction);
313 }
314 else
315 {
316 new_size.height = new_size.height + DeltaY(height_correction);
317 }
318 }
319 }
320
321 if (min_width > new_size.width)
322 new_size.width = min_width;
323
324 if (min_height > new_size.height)
325 new_size.height = min_height;
326
327 if (max_width < new_size.width)
328 new_size.width = max_width;
329
330 if (max_height < new_size.height)
331 new_size.height = max_height;
332
333 if (width_inc.is_set())
334 {
335 auto const width = new_size.width.as_int() - min_width.as_int();
336 auto inc = width_inc.value().as_int();
337 if (width % inc)
338 new_size.width = min_width + DeltaX{inc*(((2L*width + inc)/2)/inc)};
339 }
340
341 if (height_inc.is_set())
342 {
343 auto const height = new_size.height.as_int() - min_height.as_int();
344 auto inc = height_inc.value().as_int();
345 if (height % inc)
346 new_size.height = min_height + DeltaY{inc*(((2L*height + inc)/2)/inc)};
347 }
348
349 if (left_resize)
350 new_pos.x += new_size.width - requested_size.width;
351
352 if (top_resize)
353 new_pos.y += new_size.height - requested_size.height;
354
355 // placeholder - constrain onscreen
356
357 switch (state)
358 {
359 case mir_surface_state_restored:
360 break;
361
362 // "A vertically maximised surface is anchored to the top and bottom of
363 // the available workspace and can have any width."
364 case mir_surface_state_vertmaximized:
365 new_pos.y = surface->top_left().y;
366 new_size.height = surface->size().height;
367 break;
368
369 // "A horizontally maximised surface is anchored to the left and right of
370 // the available workspace and can have any height"
371 case mir_surface_state_horizmaximized:
372 new_pos.x = surface->top_left().x;
373 new_size.width = surface->size().width;
374 break;
375
376 // "A maximised surface is anchored to the top, bottom, left and right of the
377 // available workspace. For example, if the launcher is always-visible then
378 // the left-edge of the surface is anchored to the right-edge of the launcher."
379 case mir_surface_state_maximized:
380 default:
381 new_pos.x = surface->top_left().x;
382 new_pos.y = surface->top_left().y;
383 new_size.width = surface->size().width;
384 new_size.height = surface->size().height;
385 break;
386 }
387
388 requested_pos = new_pos;
389 requested_size = new_size;
390}
391
392bool me::SurfaceInfo::needs_titlebar(MirSurfaceType type)
393{
394 switch (type)
395 {
396 case mir_surface_type_freestyle:
397 case mir_surface_type_menu:
398 case mir_surface_type_inputmethod:
399 case mir_surface_type_gloss:
400 case mir_surface_type_tip:
401 // No decorations for these surface types
402 return false;
403 default:
404 return true;
405 }
406}
0407
=== added file 'src/platforms/mirserver/wm-wip/server_example_window_management_info.h'
--- src/platforms/mirserver/wm-wip/server_example_window_management_info.h 1970-01-01 00:00:00 +0000
+++ src/platforms/mirserver/wm-wip/server_example_window_management_info.h 2016-03-11 11:36:44 +0000
@@ -0,0 +1,103 @@
1/*
2 * Copyright © 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H
20#define MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H
21
22#include "mir/geometry/rectangles.h"
23#include "mir/optional_value.h"
24#include "mir/shell/surface_specification.h"
25
26#include <vector>
27
28namespace mir
29{
30namespace scene { class Session; class Surface; class SurfaceCreationParameters; }
31namespace examples
32{
33struct SurfaceInfo
34{
35 SurfaceInfo(
36 std::shared_ptr <scene::Session> const& session,
37 std::shared_ptr <scene::Surface> const& surface,
38 scene::SurfaceCreationParameters const& params);
39
40 bool can_be_active() const;
41
42 bool can_morph_to(MirSurfaceType new_type) const;
43
44 bool must_have_parent() const;
45
46 bool must_not_have_parent() const;
47
48 bool is_visible() const;
49
50 static bool needs_titlebar(MirSurfaceType type);
51
52 void constrain_resize(
53 std::shared_ptr <scene::Surface> const& surface,
54 geometry::Point& requested_pos,
55 geometry::Size& requested_size,
56 const bool left_resize,
57 const bool top_resize,
58 geometry::Rectangle const& bounds) const;
59
60 MirSurfaceType type;
61 MirSurfaceState state;
62 geometry::Rectangle restore_rect;
63 std::weak_ptr <scene::Session> session;
64 std::weak_ptr <scene::Surface> parent;
65 std::vector <std::weak_ptr<scene::Surface>> children;
66 std::shared_ptr <scene::Surface> titlebar;
67 frontend::SurfaceId titlebar_id;
68 bool is_titlebar = false;
69 geometry::Width min_width;
70 geometry::Height min_height;
71 geometry::Width max_width;
72 geometry::Height max_height;
73 mir::optional_value<geometry::DeltaX> width_inc;
74 mir::optional_value<geometry::DeltaY> height_inc;
75 mir::optional_value<shell::SurfaceAspectRatio> min_aspect;
76 mir::optional_value<shell::SurfaceAspectRatio> max_aspect;
77 mir::optional_value<graphics::DisplayConfigurationOutputId> output_id;
78
79 void init_titlebar(std::shared_ptr <scene::Surface> const& surface);
80
81 void paint_titlebar(int intensity);
82
83private:
84
85 struct StreamPainter;
86 struct AllocatingPainter;
87 struct SwappingPainter;
88
89 std::shared_ptr <StreamPainter> stream_painter;
90};
91
92struct SessionInfo
93{
94 std::vector<std::weak_ptr<scene::Surface>> surfaces;
95
96 // This is only used by the TilingWindowManagerPolicy,
97 // perhaps we need a more extensible mechanism. (std::experimental::any?)
98 geometry::Rectangle tile;
99};
100}
101}
102
103#endif //MIR_SERVER_EXAMPLE_WINDOW_MANAGEMENT_INFO_H
0104
=== modified file 'tests/framework/mock_proc_info.cpp'
--- tests/framework/mock_proc_info.cpp 2015-11-20 16:47:09 +0000
+++ tests/framework/mock_proc_info.cpp 2016-03-11 11:36:44 +0000
@@ -21,6 +21,8 @@
2121
22MockProcInfo::MockProcInfo()22MockProcInfo::MockProcInfo()
23{23{
24 using namespace ::testing;
25 ON_CALL(*this, command_line(_)).WillByDefault(Return(QByteArray()));
24}26}
2527
26MockProcInfo::~MockProcInfo()28MockProcInfo::~MockProcInfo()
2729
=== modified file 'tests/framework/mock_session.cpp'
--- tests/framework/mock_session.cpp 2015-10-19 10:45:42 +0000
+++ tests/framework/mock_session.cpp 2016-03-11 11:36:44 +0000
@@ -23,6 +23,7 @@
23 : SessionInterface(0)23 : SessionInterface(0)
24{24{
25 m_state = Starting;25 m_state = Starting;
26 ON_CALL(*this, name()).WillByDefault(::testing::Return(QString()));
26 ON_CALL(*this, suspend()).WillByDefault(::testing::Invoke(this, &MockSession::doSuspend));27 ON_CALL(*this, suspend()).WillByDefault(::testing::Invoke(this, &MockSession::doSuspend));
27 ON_CALL(*this, resume()).WillByDefault(::testing::Invoke(this, &MockSession::doResume));28 ON_CALL(*this, resume()).WillByDefault(::testing::Invoke(this, &MockSession::doResume));
28 ON_CALL(*this, stop()).WillByDefault(::testing::Invoke(this, &MockSession::doStop));29 ON_CALL(*this, stop()).WillByDefault(::testing::Invoke(this, &MockSession::doStop));
2930
=== modified file 'tests/framework/mock_task_controller.cpp'
--- tests/framework/mock_task_controller.cpp 2016-02-11 11:52:06 +0000
+++ tests/framework/mock_task_controller.cpp 2016-03-11 11:36:44 +0000
@@ -68,11 +68,11 @@
6868
69bool MockTaskController::doAppIdHasProcessId(const QString &appId, pid_t pid)69bool MockTaskController::doAppIdHasProcessId(const QString &appId, pid_t pid)
70{70{
71 auto it = children.find(appId);71 auto primaryPid = primaryPidForAppId(appId);
72 if (it == children.end())72 if (primaryPid == -1)
73 return -1;73 return false;
7474
75 return it->pid() == pid;75 return primaryPid == pid;
76}76}
7777
7878
7979
=== modified file 'tests/framework/qtmir_test.cpp'
--- tests/framework/qtmir_test.cpp 2016-02-11 11:52:06 +0000
+++ tests/framework/qtmir_test.cpp 2016-03-11 11:36:44 +0000
@@ -99,13 +99,13 @@
99};99};
100100
101101
102namespace { char const* argv[] = { nullptr }; }102namespace { int argc = 0; char* argv[] = { nullptr }; }
103103
104class FakeMirServer: private TestMirServerInit, public MirServer104class FakeMirServer: private TestMirServerInit, public MirServer
105{105{
106public:106public:
107 FakeMirServer(std::shared_ptr<StubPromptSessionManager> const& promptSessionManager)107 FakeMirServer(std::shared_ptr<StubPromptSessionManager> const& promptSessionManager)
108 : TestMirServerInit(promptSessionManager), MirServer(0, argv, QSharedPointer<ScreenController>())108 : TestMirServerInit(promptSessionManager), MirServer(argc, argv, QSharedPointer<ScreenController>())
109 {109 {
110 }110 }
111111
112112
=== added directory 'tests/mirserver/ArgvHelper'
=== added file 'tests/mirserver/ArgvHelper/CMakeLists.txt'
--- tests/mirserver/ArgvHelper/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/mirserver/ArgvHelper/CMakeLists.txt 2016-03-11 11:36:44 +0000
@@ -0,0 +1,18 @@
1set(
2 ARGVHELPER_TEST_SOURCES
3 argvHelper_test.cpp
4)
5
6add_executable(ArgvHelperTest ${ARGVHELPER_TEST_SOURCES})
7
8include_directories(
9 ${CMAKE_SOURCE_DIR}/src/platforms/mirserver
10)
11
12target_link_libraries(
13 ArgvHelperTest
14
15 ${GTEST_BOTH_LIBRARIES}
16)
17
18add_test(ArgvHelper, ArgvHelperTest)
019
=== added file 'tests/mirserver/ArgvHelper/argvHelper_test.cpp'
--- tests/mirserver/ArgvHelper/argvHelper_test.cpp 1970-01-01 00:00:00 +0000
+++ tests/mirserver/ArgvHelper/argvHelper_test.cpp 2016-03-11 11:36:44 +0000
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <gtest/gtest.h>
18
19#include <argvHelper.h>
20
21using namespace qtmir;
22
23TEST(ArgvHelperTest, StripsCorrectly)
24{
25 int argc = 5;
26 const char *argv[6] = { "/usr/bin/unity8", "-fullscreen", "--debug",
27 "--platform-input-lib=/path/to/lib.so", "-testability", nullptr };
28
29 const int filteredArgc = 2;
30 const char *filteredArgv[3] = { "-fullscreen", "-testability", nullptr };
31
32 editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv);
33
34 EXPECT_EQ(argc, 3);
35 EXPECT_EQ(argv[0], "/usr/bin/unity8");
36 EXPECT_EQ(argv[1], "-fullscreen");
37 EXPECT_EQ(argv[2], "-testability");
38 EXPECT_EQ(argv[3], nullptr);
39}
40
41TEST(ArgvHelperTest, NothingToStrip)
42{
43 int argc = 4;
44 const char *argv[5] = { "/usr/bin/unity8", "-fullscreen", "--multisample", "-testability", nullptr };
45
46 const int filteredArgc = 3;
47 const char *filteredArgv[4] = { "-fullscreen", "-testability", "--multisample", nullptr };
48
49 editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv);
50
51 EXPECT_EQ(argc, 4);
52 EXPECT_EQ(argv[0], "/usr/bin/unity8");
53 EXPECT_EQ(argv[1], "-fullscreen");
54 EXPECT_EQ(argv[2], "-testability");
55 EXPECT_EQ(argv[3], "--multisample");
56 EXPECT_EQ(argv[4], nullptr);
57}
58
59TEST(ArgvHelperTest, NothingToDo)
60{
61 int argc = 1;
62 const char *argv[2] = { "/usr/bin/unity8", nullptr };
63
64 const int filteredArgc = 0;
65 const char *filteredArgv[1] = { nullptr };
66
67 editArgvToMatch(argc, const_cast<char**>(argv), filteredArgc, filteredArgv);
68
69 EXPECT_EQ(argc, 1);
70 EXPECT_EQ(argv[0], "/usr/bin/unity8");
71 EXPECT_EQ(argv[1], nullptr);
72}
073
=== modified file 'tests/mirserver/CMakeLists.txt'
--- tests/mirserver/CMakeLists.txt 2015-10-27 10:17:45 +0000
+++ tests/mirserver/CMakeLists.txt 2016-03-11 11:36:44 +0000
@@ -1,3 +1,4 @@
1add_subdirectory(ArgvHelper)
1add_subdirectory(QtEventFeeder)2add_subdirectory(QtEventFeeder)
2add_subdirectory(Clipboard)3add_subdirectory(Clipboard)
3add_subdirectory(Screen)4add_subdirectory(Screen)
45
=== modified file 'tests/mirserver/Screen/screen_test.cpp'
--- tests/mirserver/Screen/screen_test.cpp 2015-10-14 22:59:04 +0000
+++ tests/mirserver/Screen/screen_test.cpp 2016-03-11 11:36:44 +0000
@@ -42,9 +42,23 @@
42 Screen::skipDBusRegistration = true;42 Screen::skipDBusRegistration = true;
43}43}
4444
45TEST_F(ScreenTest, OrientationSensor)45TEST_F(ScreenTest, OrientationSensorForExternalDisplay)
46{46{
47 Screen *screen = new Screen(fakeOutput1);47 Screen *screen = new Screen(fakeOutput1); // is external display (dvi)
48
49 // Default state should be disabled
50 ASSERT_FALSE(screen->orientationSensorEnabled());
51
52 screen->onDisplayPowerStateChanged(0,0);
53 ASSERT_FALSE(screen->orientationSensorEnabled());
54
55 screen->onDisplayPowerStateChanged(1,0);
56 ASSERT_FALSE(screen->orientationSensorEnabled());
57}
58
59TEST_F(ScreenTest, OrientationSensorForInternalDisplay)
60{
61 Screen *screen = new Screen(fakeOutput2); // is internal display
4862
49 // Default state should be active63 // Default state should be active
50 ASSERT_TRUE(screen->orientationSensorEnabled());64 ASSERT_TRUE(screen->orientationSensorEnabled());
5165
=== modified file 'tests/modules/ApplicationManager/application_manager_test.cpp'
--- tests/modules/ApplicationManager/application_manager_test.cpp 2016-02-12 00:07:09 +0000
+++ tests/modules/ApplicationManager/application_manager_test.cpp 2016-03-11 11:36:44 +0000
@@ -71,6 +71,13 @@
71 ASSERT_EQ(Application::InternalState::Suspended, application->internalState());71 ASSERT_EQ(Application::InternalState::Suspended, application->internalState());
72 }72 }
7373
74 static inline qtmir::DesktopFileReader* createMockDesktopFileReader(const QString &appId, const QFileInfo &fi) {
75 using namespace ::testing;
76 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, fi);
77 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));
78 return mockDesktopFileReader;
79 }
80
74protected:81protected:
75 virtual void SetUp() override {82 virtual void SetUp() override {
76 if (m_tempDir.isValid()) qputenv("XDG_CACHE_HOME", m_tempDir.path().toUtf8());83 if (m_tempDir.isValid()) qputenv("XDG_CACHE_HOME", m_tempDir.path().toUtf8());
@@ -751,11 +758,7 @@
751 const QString appId("testAppId");758 const QString appId("testAppId");
752759
753 // Set up Mocks & signal watcher760 // Set up Mocks & signal watcher
754 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());761 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
755 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));
756 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
757
758 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
759762
760 EXPECT_CALL(*taskController, start(appId, _))763 EXPECT_CALL(*taskController, start(appId, _))
761 .Times(1)764 .Times(1)
@@ -789,11 +792,8 @@
789 const pid_t procId = 5551;792 const pid_t procId = 5551;
790793
791 // Set up Mocks & signal watcher794 // Set up Mocks & signal watcher
792 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());795 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
793 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));796 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
794 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
795
796 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
797797
798 EXPECT_CALL(*taskController, start(appId, _))798 EXPECT_CALL(*taskController, start(appId, _))
799 .Times(1)799 .Times(1)
@@ -833,11 +833,8 @@
833 const pid_t procId = 5551;833 const pid_t procId = 5551;
834834
835 // Set up Mocks & signal watcher835 // Set up Mocks & signal watcher
836 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());836 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
837 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));837 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
838 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
839
840 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
841838
842 EXPECT_CALL(*taskController, start(appId, _))839 EXPECT_CALL(*taskController, start(appId, _))
843 .Times(1)840 .Times(1)
@@ -869,16 +866,11 @@
869{866{
870 using namespace ::testing;867 using namespace ::testing;
871 const QString appId("testAppId");868 const QString appId("testAppId");
872 const QString desktopFilePath("testAppId.desktop");
873 const pid_t procId = 5551;869 const pid_t procId = 5551;
874870
875 // Set up Mocks & signal watcher871 // Set up Mocks & signal watcher
876 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());872 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
877 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));873 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
878 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
879 ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(desktopFilePath));
880
881 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
882874
883 EXPECT_CALL(*taskController, start(appId, _))875 EXPECT_CALL(*taskController, start(appId, _))
884 .Times(1)876 .Times(1)
@@ -917,11 +909,8 @@
917 const pid_t procId = 5551;909 const pid_t procId = 5551;
918910
919 // Set up Mocks & signal watcher911 // Set up Mocks & signal watcher
920 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());912 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
921 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));913 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
922 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
923
924 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
925914
926 EXPECT_CALL(*taskController, start(appId, _))915 EXPECT_CALL(*taskController, start(appId, _))
927 .Times(1)916 .Times(1)
@@ -960,11 +949,8 @@
960 const pid_t procId = 5551;949 const pid_t procId = 5551;
961950
962 // Set up Mocks & signal watcher951 // Set up Mocks & signal watcher
963 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());952 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
964 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));953 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
965 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
966
967 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
968954
969 EXPECT_CALL(*taskController, start(appId, _))955 EXPECT_CALL(*taskController, start(appId, _))
970 .Times(1)956 .Times(1)
@@ -1006,11 +992,8 @@
1006 const pid_t procId = 5551;992 const pid_t procId = 5551;
1007993
1008 // Set up Mocks & signal watcher994 // Set up Mocks & signal watcher
1009 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());995 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1010 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));996 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1011 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1012
1013 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
1014997
1015 EXPECT_CALL(*taskController, start(appId, _))998 EXPECT_CALL(*taskController, start(appId, _))
1016 .Times(1)999 .Times(1)
@@ -1051,11 +1034,8 @@
1051 const pid_t procId = 5551;1034 const pid_t procId = 5551;
10521035
1053 // Set up Mocks & signal watcher1036 // Set up Mocks & signal watcher
1054 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1037 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1055 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1038 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1056 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1057
1058 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
10591039
1060 EXPECT_CALL(*taskController, start(appId, _))1040 EXPECT_CALL(*taskController, start(appId, _))
1061 .Times(1)1041 .Times(1)
@@ -1102,11 +1082,8 @@
1102 const pid_t procId = 5551;1082 const pid_t procId = 5551;
11031083
1104 // Set up Mocks & signal watcher1084 // Set up Mocks & signal watcher
1105 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1085 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1106 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1086 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1107 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1108
1109 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
11101087
1111 EXPECT_CALL(*taskController, start(appId, _))1088 EXPECT_CALL(*taskController, start(appId, _))
1112 .Times(1)1089 .Times(1)
@@ -1160,11 +1137,8 @@
1160 const pid_t procId = 5551;1137 const pid_t procId = 5551;
11611138
1162 // Set up Mocks & signal watcher1139 // Set up Mocks & signal watcher
1163 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1140 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1164 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1141 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1165 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1166
1167 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
11681142
1169 EXPECT_CALL(*taskController, start(appId, _))1143 EXPECT_CALL(*taskController, start(appId, _))
1170 .Times(1)1144 .Times(1)
@@ -1213,11 +1187,8 @@
1213 const pid_t procId = 5551;1187 const pid_t procId = 5551;
12141188
1215 // Set up Mocks & signal watcher1189 // Set up Mocks & signal watcher
1216 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1190 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1217 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1191 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1218 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1219
1220 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
12211192
1222 EXPECT_CALL(*taskController, start(appId, _))1193 EXPECT_CALL(*taskController, start(appId, _))
1223 .Times(1)1194 .Times(1)
@@ -1252,11 +1223,8 @@
1252 const pid_t procId = 5551;1223 const pid_t procId = 5551;
12531224
1254 // Set up Mocks & signal watcher1225 // Set up Mocks & signal watcher
1255 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1226 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1256 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1227 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1257 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1258
1259 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
12601228
1261 EXPECT_CALL(*taskController, start(appId, _))1229 EXPECT_CALL(*taskController, start(appId, _))
1262 .Times(1)1230 .Times(1)
@@ -1348,11 +1316,8 @@
1348 const pid_t procId = 5551;1316 const pid_t procId = 5551;
13491317
1350 // Set up Mocks & signal watcher1318 // Set up Mocks & signal watcher
1351 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1319 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1352 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1320 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1353 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1354
1355 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
13561321
1357 EXPECT_CALL(*taskController, start(appId, _))1322 EXPECT_CALL(*taskController, start(appId, _))
1358 .Times(1)1323 .Times(1)
@@ -1407,12 +1372,8 @@
1407 const pid_t procId = 5551;1372 const pid_t procId = 5551;
14081373
1409 // Set up Mocks & signal watcher1374 // Set up Mocks & signal watcher
1410 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1375 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1411 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1376 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1412 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1413 ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop"));
1414
1415 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
14161377
1417 EXPECT_CALL(*taskController, start(appId, _))1378 EXPECT_CALL(*taskController, start(appId, _))
1418 .Times(1)1379 .Times(1)
@@ -1465,11 +1426,7 @@
1465 ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false));1426 ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false));
14661427
1467 // Set up Mocks & signal watcher1428 // Set up Mocks & signal watcher
1468 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1429 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1469 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));
1470 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1471
1472 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
14731430
1474 EXPECT_CALL(*taskController, start(appId, _))1431 EXPECT_CALL(*taskController, start(appId, _))
1475 .Times(1)1432 .Times(1)
@@ -1525,11 +1482,7 @@
1525 ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false));1482 ON_CALL(*taskController,appIdHasProcessId(_, procId2)).WillByDefault(Return(false));
15261483
1527 // Set up Mocks & signal watcher1484 // Set up Mocks & signal watcher
1528 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1485 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1529 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));
1530 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1531
1532 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
15331486
1534 EXPECT_CALL(*taskController, start(appId, _))1487 EXPECT_CALL(*taskController, start(appId, _))
1535 .Times(1)1488 .Times(1)
@@ -1583,11 +1536,8 @@
1583 const pid_t procId = 5551;1536 const pid_t procId = 5551;
15841537
1585 // Set up Mocks & signal watcher1538 // Set up Mocks & signal watcher
1586 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1539 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1587 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1540 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1588 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1589
1590 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
15911541
1592 EXPECT_CALL(*taskController, start(appId, _))1542 EXPECT_CALL(*taskController, start(appId, _))
1593 .Times(1)1543 .Times(1)
@@ -1629,19 +1579,14 @@
1629{1579{
1630 using namespace testing;1580 using namespace testing;
1631 const QString appId("webapp");1581 const QString appId("webapp");
1632 const QString desktopFilePath("webapp.desktop");
1633 const pid_t procId = 5551;1582 const pid_t procId = 5551;
16341583
1635 std::mutex mutex;1584 std::mutex mutex;
1636 std::condition_variable cv;1585 std::condition_variable cv;
1637 bool done = false;1586 bool done = false;
16381587
1639 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1588 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1640 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1589 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1641 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1642 ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(desktopFilePath));
1643
1644 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
16451590
1646 EXPECT_CALL(*taskController, start(appId, _))1591 EXPECT_CALL(*taskController, start(appId, _))
1647 .Times(1)1592 .Times(1)
@@ -1753,11 +1698,8 @@
1753 const quint64 procId = 12345;1698 const quint64 procId = 12345;
17541699
1755 // Set up Mocks & signal watcher1700 // Set up Mocks & signal watcher
1756 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1701 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1757 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1702 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1758 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1759
1760 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
17611703
1762 EXPECT_CALL(*taskController, start(appId, _))1704 EXPECT_CALL(*taskController, start(appId, _))
1763 .Times(1)1705 .Times(1)
@@ -1821,11 +1763,8 @@
1821 const quint64 procId = 12345;1763 const quint64 procId = 12345;
18221764
1823 // Set up Mocks & signal watcher1765 // Set up Mocks & signal watcher
1824 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1766 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1825 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1767 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1826 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1827
1828 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
18291768
1830 EXPECT_CALL(*taskController, start(appId, _))1769 EXPECT_CALL(*taskController, start(appId, _))
1831 .Times(1)1770 .Times(1)
@@ -1863,12 +1802,8 @@
1863 const pid_t procId = 5551;1802 const pid_t procId = 5551;
18641803
1865 // Set up Mocks & signal watcher1804 // Set up Mocks & signal watcher
1866 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1805 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1867 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1806 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1868 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1869 ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop"));
1870
1871 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
18721807
1873 EXPECT_CALL(*taskController, start(appId, _))1808 EXPECT_CALL(*taskController, start(appId, _))
1874 .Times(1)1809 .Times(1)
@@ -1908,11 +1843,8 @@
1908 const pid_t procId = 5551;1843 const pid_t procId = 5551;
19091844
1910 // Set up Mocks & signal watcher1845 // Set up Mocks & signal watcher
1911 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1846 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1912 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1847 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1913 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1914
1915 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
19161848
1917 EXPECT_CALL(*taskController, start(appId, _))1849 EXPECT_CALL(*taskController, start(appId, _))
1918 .Times(1)1850 .Times(1)
@@ -1957,11 +1889,8 @@
1957 const pid_t procId = 5551;1889 const pid_t procId = 5551;
19581890
1959 // Set up Mocks & signal watcher1891 // Set up Mocks & signal watcher
1960 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1892 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
1961 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1893 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
1962 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
1963
1964 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
19651894
1966 EXPECT_CALL(*taskController, start(appId, _))1895 EXPECT_CALL(*taskController, start(appId, _))
1967 .Times(1)1896 .Times(1)
@@ -2032,12 +1961,8 @@
2032 const QString appId("testAppId");1961 const QString appId("testAppId");
2033 quint64 procId = 5551;1962 quint64 procId = 5551;
20341963
2035 auto mockDesktopFileReader = new NiceMock<MockDesktopFileReader>(appId, QFileInfo());1964 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
2036 ON_CALL(*mockDesktopFileReader, loaded()).WillByDefault(Return(true));1965 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
2037 ON_CALL(*mockDesktopFileReader, appId()).WillByDefault(Return(appId));
2038 ON_CALL(*mockDesktopFileReader, file()).WillByDefault(Return(appId + ".desktop"));
2039
2040 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Return(mockDesktopFileReader));
20411966
2042 EXPECT_CALL(*taskController, start(appId, _))1967 EXPECT_CALL(*taskController, start(appId, _))
2043 .Times(1)1968 .Times(1)
@@ -2085,10 +2010,8 @@
2085 const QString appId("testAppId");2010 const QString appId("testAppId");
2086 quint64 procId = 5551;2011 quint64 procId = 5551;
20872012
2088 ON_CALL(desktopFileReaderFactory, createInstance(appId, _))2013 ON_CALL(*taskController, primaryPidForAppId(appId)).WillByDefault(Return(procId));
2089 .WillByDefault(Invoke(2014 ON_CALL(desktopFileReaderFactory, createInstance(appId, _)).WillByDefault(Invoke(createMockDesktopFileReader));
2090 [](const QString &appId, const QFileInfo&) { return new FakeDesktopFileReader(appId); }
2091 ));
20922015
2093 EXPECT_CALL(*taskController, start(appId, _))2016 EXPECT_CALL(*taskController, start(appId, _))
2094 .Times(1)2017 .Times(1)

Subscribers

People subscribed via source and target branches