Merge lp:~mzanetti/unity-mir/appimage-sourcesize-rotate-n7 into lp:unity-mir
- appimage-sourcesize-rotate-n7
- Merge into trunk
Proposed by
Michael Zanetti
Status: | Superseded |
---|---|
Proposed branch: | lp:~mzanetti/unity-mir/appimage-sourcesize-rotate-n7 |
Merge into: | lp:unity-mir |
Diff against target: |
1970 lines (+1001/-273) 25 files modified
CMakeLists.txt (+1/-0) cmake/LinuxCrossCompile.cmake (+39/-0) cross-compile-chroot.sh (+85/-0) debian/control (+1/-0) scripts/fix-qt-cmake.sh (+10/-0) scripts/setup-partial-armhf-chroot.sh (+67/-0) src/modules/Unity/Application/ApplicationImage.qml (+12/-5) src/modules/Unity/Application/CMakeLists.txt (+5/-6) src/modules/Unity/Application/application.cpp (+23/-1) src/modules/Unity/Application/application.h (+6/-0) src/modules/Unity/Application/application_manager.cpp (+254/-171) src/modules/Unity/Application/application_manager.h (+25/-4) src/modules/Unity/Application/applicationscreenshotprovider.cpp (+0/-1) src/modules/Unity/Application/applicationscreenshotprovider.h (+0/-1) src/modules/Unity/Application/inputarea.cpp (+32/-6) src/modules/Unity/Application/proc_info.cpp (+52/-0) src/modules/Unity/Application/proc_info.h (+48/-0) src/unity-mir/CMakeLists.txt (+3/-5) tests/CMakeLists.txt (+1/-0) tests/application_manager_test.cpp (+186/-64) tests/auto/modules/Unity/Application/CMakeLists.txt (+3/-3) tests/auto/modules/Unity/Application/main.cpp (+5/-6) tests/mock_focus_controller.h (+37/-0) tests/mock_proc_info.h (+37/-0) tests/mock_session.h (+69/-0) |
To merge this branch: | bzr merge lp:~mzanetti/unity-mir/appimage-sourcesize-rotate-n7 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email:
|
This proposal has been superseded by a proposal from 2014-02-21.
Commit message
export AppImage's sourceSize
Description of the change
To post a comment you must log in.
- 180. By Michael Zanetti
-
merge upstream
- 181. By Michael Zanetti
-
keep the aspect ratio also when cropping
Unmerged revisions
- 181. By Michael Zanetti
-
keep the aspect ratio also when cropping
- 180. By Michael Zanetti
-
merge upstream
- 179. By Michael Zanetti
-
export ApplicationImage's sourceSize
- 178. By Gerry Boland
-
Fix for OSK on Manta
- 177. By Gerry Boland
-
Hacky fix for InputArea positioning with a rotated shell
- 176. By Gerry Boland
-
Fix OSK positioning on manta & flo
- 175. By Gerry Boland
-
Merge trunk
- 174. By Daniel d'Andrada
-
ApplicationImage - rotate image to compensate for shell rotation
- 173. By Daniel d'Andrada
-
Take app window placement information from given QQuickItems
Benefits:
- no more hardcoded values (like panel height)
- supports unity shell in any rotation
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-02-14 15:42:49 +0000 |
3 | +++ CMakeLists.txt 2014-02-21 16:48:46 +0000 |
4 | @@ -59,6 +59,7 @@ |
5 | find_package(Qt5Core REQUIRED) |
6 | find_package(Qt5Quick REQUIRED) |
7 | find_package(Qt5DBus REQUIRED) |
8 | +find_package(Boost 1.50 COMPONENTS system REQUIRED) |
9 | |
10 | find_package(Protobuf REQUIRED) |
11 | if(PROTOBUF_PROTOC_EXECUTABLE STREQUAL "PROTOBUF_PROTOC_EXECUTABLE-NOTFOUND") |
12 | |
13 | === added directory 'cmake' |
14 | === added file 'cmake/LinuxCrossCompile.cmake' |
15 | --- cmake/LinuxCrossCompile.cmake 1970-01-01 00:00:00 +0000 |
16 | +++ cmake/LinuxCrossCompile.cmake 2014-02-21 16:48:46 +0000 |
17 | @@ -0,0 +1,39 @@ |
18 | +set(CMAKE_SYSTEM_NAME Linux) |
19 | +set(CMAKE_SYSTEM_VERSION 1) |
20 | + |
21 | +set(UNITYMIR_CHROOT_DIR $ENV{UNITYMIR_CHROOT_DIR} CACHE STRING "directory containing partial chroot for unity-mir cross-compilation") |
22 | +set(UNITYMIR_ARM_EABI "arm-linux-gnueabihf") |
23 | + |
24 | +set(CMAKE_C_COMPILER /usr/bin/${UNITYMIR_ARM_EABI}-gcc) |
25 | +set(CMAKE_CXX_COMPILER /usr/bin/${UNITYMIR_ARM_EABI}-g++) |
26 | + |
27 | +# where to look to find dependencies in the target environment |
28 | +set(CMAKE_FIND_ROOT_PATH "${UNITYMIR_CHROOT_DIR}") |
29 | + |
30 | +#treat the chroot's includes as system includes |
31 | +include_directories(SYSTEM "${UNITYMIR_CHROOT_DIR}/usr/include" "${UNITYMIR_CHROOT_DIR}/usr/include/${UNITYMIR_ARM_EABI}") |
32 | + |
33 | +list(APPEND CMAKE_SYSTEM_INCLUDE_PATH "${UNITYMIR_CHROOT_DIR}/usr/include" "${UNITYMIR_CHROOT_DIR}/usr/include/${UNITYMIR_ARM_EABI}" ) |
34 | + |
35 | +# Add the chroot libraries as system libraries |
36 | +list(APPEND CMAKE_SYSTEM_LIBRARY_PATH |
37 | + "${UNITYMIR_CHROOT_DIR}/lib" |
38 | + "${UNITYMIR_CHROOT_DIR}/lib/${UNITYMIR_ARM_EABI}" |
39 | + "${UNITYMIR_CHROOT_DIR}/usr/lib" |
40 | + "${UNITYMIR_CHROOT_DIR}/usr/lib/${UNITYMIR_ARM_EABI}" |
41 | +) |
42 | + |
43 | +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) |
44 | +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) |
45 | +set(CMAKE_EXECUTABLE_RUNTIME_C_FLAG "-Wl,-rpath-link,") |
46 | +set(CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG "-Wl,-rpath-link,") |
47 | +set(CMAKE_INSTALL_RPATH "${UNITYMIR_CHROOT_DIR}/lib:${UNITYMIR_CHROOT_DIR}/lib/${UNITYMIR_ARM_EABI}:${UNITYMIR_CHROOT_DIR}/usr/lib:${UNITYMIR_CHROOT_DIR}/usr/lib/${UNITYMIR_ARM_EABI}:${UNITYMIR_CHROOT_DIR}/usr/lib/${UNITYMIR_ARM_EABI}/mesa-egl") |
48 | + |
49 | +set(ENV{PKG_CONFIG_PATH} "${UNITYMIR_CHROOT_DIR}/usr/lib/pkgconfig:${UNITYMIR_CHROOT_DIR}/usr/lib/${UNITYMIR_ARM_EABI}/pkgconfig") |
50 | +set(ENV{PKG_CONFIG_SYSROOT_DIR} "${UNITYMIR_CHROOT_DIR}") |
51 | + |
52 | +#use only the cross compile system |
53 | +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) |
54 | +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) |
55 | +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
56 | + |
57 | |
58 | === added file 'cross-compile-chroot.sh' |
59 | --- cross-compile-chroot.sh 1970-01-01 00:00:00 +0000 |
60 | +++ cross-compile-chroot.sh 2014-02-21 16:48:46 +0000 |
61 | @@ -0,0 +1,85 @@ |
62 | +#!/bin/bash |
63 | +# build script to compile unity-mir for armhf devices |
64 | + |
65 | +set -e |
66 | + |
67 | +usage() { |
68 | + echo "usage: $(basename $0) [-c] [-u]" |
69 | + echo "-c clean before building" |
70 | + echo "-u update partial chroot directory" |
71 | + echo "-h this message" |
72 | +} |
73 | + |
74 | +clean_build_dir() { |
75 | + rm -rf ${1} |
76 | + mkdir ${1} |
77 | +} |
78 | + |
79 | +BUILD_DIR=build-android-arm |
80 | +NUM_JOBS=$(( $(grep -c ^processor /proc/cpuinfo) + 1 )) |
81 | +_do_update_chroot=0 |
82 | + |
83 | +while getopts "cuh" OPTNAME |
84 | +do |
85 | + case $OPTNAME in |
86 | + c ) |
87 | + clean_build_dir ${BUILD_DIR} |
88 | + ;; |
89 | + u ) |
90 | + _do_update_chroot=1 |
91 | + ;; |
92 | + h ) |
93 | + usage |
94 | + exit 0 |
95 | + ;; |
96 | + * ) |
97 | + echo "invalid option specified" |
98 | + usage |
99 | + exit 1 |
100 | + ;; |
101 | + esac |
102 | +done |
103 | + |
104 | + |
105 | +if [ "${UNITYMIR_CHROOT_DIR}" = "" ]; then |
106 | + export UNITYMIR_CHROOT_DIR=$(pwd)/partial-armhf-chroot |
107 | +fi |
108 | + |
109 | +if [ ! -d ${UNITYMIR_CHROOT_DIR} ]; then |
110 | + echo "no partial chroot dir detected. attempting to create one" |
111 | + _do_update_chroot=1 |
112 | +fi |
113 | + |
114 | +if [ ! -d ${BUILD_DIR} ]; then |
115 | + mkdir ${BUILD_DIR} |
116 | +fi |
117 | + |
118 | +if [ ${_do_update_chroot} -eq 1 ] ; then |
119 | + pushd scripts > /dev/null |
120 | + ./setup-partial-armhf-chroot.sh ${UNITYMIR_CHROOT_DIR} |
121 | + popd > /dev/null |
122 | + # force a clean build after an update, since CMake cache maybe out of date |
123 | + clean_build_dir ${BUILD_DIR} |
124 | +fi |
125 | + |
126 | +echo "Using UNITYMIR_CHROOT_DIR: ${UNITYMIR_CHROOT_DIR}" |
127 | + |
128 | +pushd ${BUILD_DIR} > /dev/null |
129 | + |
130 | + export CMAKE_PREFIX_PATH=${UNITYMIR_CHROOT_DIR}/usr/lib/arm-linux-gnueabihf/cmake |
131 | + export PKG_CONFIG_PATH="${UNITYMIR_CHROOT_DIR}/usr/lib/pkgconfig:${UNITYMIR_CHROOT_DIR}/usr/lib/arm-linux-gnueabihf/pkgconfig" |
132 | + export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 |
133 | + export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 |
134 | + export PKG_CONFIG_SYSROOT_DIR=${UNITYMIR_CHROOT_DIR} |
135 | + export PKG_CONFIG_EXECUTABLE=`which pkg-config` |
136 | + echo "Using PKG_CONFIG_PATH: $PKG_CONFIG_PATH" |
137 | + echo "Using PKG_CONFIG_EXECUTABLE: $PKG_CONFIG_EXECUTABLE" |
138 | + |
139 | + # These are used to make cmake select the host machine QT MOC compiler in the AutoMocInfo module |
140 | + export DEB_HOST_MULTIARCH=arm-linux-gnueabihf |
141 | + export DEB_BUILD_MULTIARCH=$(gcc -dumpmachine) |
142 | + |
143 | + cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/LinuxCrossCompile.cmake .. |
144 | + make -j${NUM_JOBS} |
145 | + |
146 | +popd ${BUILD_DIR} > /dev/null |
147 | |
148 | === modified file 'debian/control' |
149 | --- debian/control 2014-02-14 15:42:49 +0000 |
150 | +++ debian/control 2014-02-21 16:48:46 +0000 |
151 | @@ -6,6 +6,7 @@ |
152 | cmake, |
153 | google-mock (>= 1.6.0+svn437), |
154 | pkg-config, |
155 | + libboost-dev, |
156 | libboost-system-dev, |
157 | libplatform-api1-dev, |
158 | libmirserver-dev (>= 0.1.5), |
159 | |
160 | === added directory 'scripts' |
161 | === added file 'scripts/fix-qt-cmake.sh' |
162 | --- scripts/fix-qt-cmake.sh 1970-01-01 00:00:00 +0000 |
163 | +++ scripts/fix-qt-cmake.sh 2014-02-21 16:48:46 +0000 |
164 | @@ -0,0 +1,10 @@ |
165 | +#!/bin/bash |
166 | + |
167 | +# $1 must contain path to QT cmake files |
168 | +# Given that path, all hardcoded root paths are fixed up |
169 | +for file in $(find ${1} -type f -name \*.cmake) |
170 | +do |
171 | + echo "fixing $file" |
172 | + sed -i 's/NO_DEFAULT_PATH/ONLY_CMAKE_FIND_ROOT_PATH/g' $file |
173 | + sed -i 's/\/usr/${CMAKE_FIND_ROOT_PATH}\/usr/g' $file |
174 | +done |
175 | |
176 | === added file 'scripts/setup-partial-armhf-chroot.sh' |
177 | --- scripts/setup-partial-armhf-chroot.sh 1970-01-01 00:00:00 +0000 |
178 | +++ scripts/setup-partial-armhf-chroot.sh 2014-02-21 16:48:46 +0000 |
179 | @@ -0,0 +1,67 @@ |
180 | +#!/bin/bash |
181 | + |
182 | +set -e |
183 | + |
184 | +if [ -z ${1} ]; then |
185 | + echo "please supply directory to create partial chroot in. (eg, ./setup-partial-armhf-chroot.sh mychroot-dir)" |
186 | + exit |
187 | +fi |
188 | + |
189 | +echo "creating phablet-compatible armhf partial chroot for unity-mir compilation in directory ${1}" |
190 | + |
191 | +if [ ! -d ${1} ]; then |
192 | + mkdir -p ${1} |
193 | +fi |
194 | + |
195 | +DEBCONTROL=$(pwd)/../debian/control |
196 | + |
197 | +pushd ${1} > /dev/null |
198 | + |
199 | +# Empty dpkg status file, so that ALL dependencies are listed with dpkg-checkbuilddeps |
200 | +echo "" > status |
201 | + |
202 | +# Manual error code checking is needed for dpkg-checkbuilddeps |
203 | +set +e |
204 | + |
205 | +# Parse dependencies from debian/control |
206 | +# dpkg-checkbuilddeps returns 1 when dependencies are not met and the list is sent to stderr |
207 | +builddeps=$(dpkg-checkbuilddeps -a armhf --admindir=. ${DEBCONTROL} 2>&1 ) |
208 | +if [ $? -ne 1 ] ; then |
209 | + echo "${builddeps}" |
210 | + exit 2 |
211 | +fi |
212 | + |
213 | +# now turn exit on error option |
214 | +set -e |
215 | + |
216 | +# Sanitize dependencies list for submission to debootstrap |
217 | +# build-essential is not needed as we are cross-compiling |
218 | +builddeps=$(echo ${builddeps} | sed -e 's/dpkg-checkbuilddeps://g' -e 's/Unmet build dependencies://g' -e 's/build-essential:native//g') |
219 | +builddeps=$(echo ${builddeps} | sed 's/([^)]*)//g') |
220 | +# TODO: figure out why debootstrap is not finding libunity-api-dev package - it doesn't seem to be needed for cross-compilation - is it needed in debian/control? |
221 | +builddeps=$(echo ${builddeps} | sed 's/libunity-api-dev//g') |
222 | +builddeps=$(echo ${builddeps} | sed 's/ /,/g') |
223 | + |
224 | +fakeroot debootstrap --include=${builddeps} --arch=armhf --download-only --variant=buildd trusty . |
225 | + |
226 | +# Remove libc libraries that confuse the cross-compiler |
227 | +rm var/cache/apt/archives/libc-dev*.deb |
228 | +rm var/cache/apt/archives/libc6*.deb |
229 | + |
230 | +for deb in var/cache/apt/archives/* ; do |
231 | +if [ ! -d ${deb} ] ; then |
232 | + echo "unpacking: ${deb}" |
233 | + dpkg -x ${deb} . |
234 | +fi |
235 | +done |
236 | + |
237 | +# Fix up symlinks which asssumed the usual root path |
238 | +for broken_symlink in $(find . -name \*.so -type l -xtype l) ; do |
239 | + ln -sf $(pwd)$(readlink ${broken_symlink}) ${broken_symlink} |
240 | +done |
241 | + |
242 | +popd > /dev/null |
243 | + |
244 | +# QT CMake files have hardcoded root paths - fix them up |
245 | +./fix-qt-cmake.sh ${1}/usr/lib/arm-linux-gnueabihf/cmake/ |
246 | + |
247 | |
248 | === modified file 'src/modules/Unity/Application/ApplicationImage.qml' |
249 | --- src/modules/Unity/Application/ApplicationImage.qml 2013-10-01 17:45:26 +0000 |
250 | +++ src/modules/Unity/Application/ApplicationImage.qml 2014-02-21 16:48:46 +0000 |
251 | @@ -15,11 +15,14 @@ |
252 | */ |
253 | |
254 | import QtQuick 2.0 |
255 | +import QtQuick.Window 2.0 |
256 | +import Ubuntu.Components 0.1 |
257 | |
258 | Item { |
259 | id: root |
260 | property var source: null |
261 | readonly property bool ready: source && (image.status == Image.Ready) |
262 | + property var sourceSize: orientationHelper.orientationAngle == 0 ? image.sourceSize : Qt.size(image.sourceSize.height, image.sourceSize.width) |
263 | |
264 | function scheduleUpdate() { |
265 | image.source = ""; |
266 | @@ -34,10 +37,14 @@ |
267 | scheduleUpdate(); |
268 | } |
269 | |
270 | - Image { |
271 | - id: image |
272 | - anchors.fill: parent |
273 | - source: (root.source) ? "image://screenshot/" + root.source.appId : "" |
274 | - cache: false |
275 | + OrientationHelper { |
276 | + orientationAngle: Screen.angleBetween(Screen.primaryOrientation, nativeOrientation) // compensate for Shell rotation |
277 | + transitionEnabled: false |
278 | + Image { |
279 | + id: image |
280 | + anchors.fill: parent |
281 | + source: (root.source) ? "image://screenshot/" + root.source.appId : "" |
282 | + cache: false |
283 | + } |
284 | } |
285 | } |
286 | |
287 | === modified file 'src/modules/Unity/Application/CMakeLists.txt' |
288 | --- src/modules/Unity/Application/CMakeLists.txt 2014-01-27 11:29:44 +0000 |
289 | +++ src/modules/Unity/Application/CMakeLists.txt 2014-02-21 16:48:46 +0000 |
290 | @@ -31,6 +31,7 @@ |
291 | inputfilterarea.cpp |
292 | processcontroller.h |
293 | processcontroller.cpp |
294 | + proc_info.cpp |
295 | shellinputarea.cpp |
296 | ubuntukeyboardinfo.cpp |
297 | |
298 | @@ -74,12 +75,10 @@ |
299 | ${CMAKE_THREAD_LIBS_INIT} |
300 | |
301 | ${GLIB_LDFLAGS} |
302 | - ${UBUNTU_PLATFORM_API_LIBRARIES} |
303 | - ${MIRCOMMON_LIBRARIES} |
304 | - ${MIRSERVER_LIBRARIES} |
305 | - ${PROCESS_CPP_LIBRARIES} |
306 | - ${UBUNTU_PLATFORM_API_LIBRARIES} |
307 | - ${UPSTART_APP_LAUNCH_LIBRARIES} |
308 | + ${UBUNTU_PLATFORM_API_LDFLAGS} |
309 | + ${MIRSERVER_LDFLAGS} |
310 | + ${PROCESS_CPP_LDFLAGS} |
311 | + ${UPSTART_APP_LAUNCH_LDFLAGS} |
312 | |
313 | ubuntu_application_api_mirserver |
314 | ) |
315 | |
316 | === modified file 'src/modules/Unity/Application/application.cpp' |
317 | --- src/modules/Unity/Application/application.cpp 2014-01-27 11:29:44 +0000 |
318 | +++ src/modules/Unity/Application/application.cpp 2014-02-21 16:48:46 +0000 |
319 | @@ -40,6 +40,7 @@ |
320 | , m_state(state) |
321 | , m_focused(false) |
322 | , m_fullscreen(false) |
323 | + , m_visible(false) |
324 | , m_arguments(arguments) |
325 | , m_suspendTimer(new QTimer(this)) |
326 | { |
327 | @@ -52,7 +53,7 @@ |
328 | |
329 | Application::~Application() |
330 | { |
331 | - DLOG("Application::~Application"); |
332 | + DLOG("Application::~Application (this=%p)", this); |
333 | delete m_desktopData; |
334 | } |
335 | |
336 | @@ -125,6 +126,11 @@ |
337 | return m_session; |
338 | } |
339 | |
340 | +bool Application::visible() const |
341 | +{ |
342 | + return m_visible; |
343 | +} |
344 | + |
345 | pid_t Application::pid() const |
346 | { |
347 | return m_pid; |
348 | @@ -141,6 +147,7 @@ |
349 | |
350 | // TODO(greyback) what if called with new surface? |
351 | m_session = session; |
352 | + m_visible = true; // bit of an assumption that, but no other way to deduce an actual Surface has been created |
353 | } |
354 | |
355 | void Application::setSessionName(const QString& name) |
356 | @@ -216,6 +223,21 @@ |
357 | } |
358 | } |
359 | |
360 | +void Application::setVisible(const bool visible) |
361 | +{ |
362 | + DLOG("Application::setVisible (this=%p, visible=%s)", this, visible ? "yes" : "no"); |
363 | + // FIXME: this is bad, as should a MirSurface of this app exist, it won't be notified of the visiblity change. |
364 | + if (visible != m_visible) { |
365 | + if (visible) { |
366 | + m_session->show(); |
367 | + } else { |
368 | + m_session->hide(); |
369 | + } |
370 | + m_visible = visible; |
371 | + Q_EMIT visibleChanged(); |
372 | + } |
373 | +} |
374 | + |
375 | void Application::suspend() |
376 | { |
377 | DLOG("Application::suspend (this=%p)", this); |
378 | |
379 | === modified file 'src/modules/Unity/Application/application.h' |
380 | --- src/modules/Unity/Application/application.h 2014-01-27 11:29:44 +0000 |
381 | +++ src/modules/Unity/Application/application.h 2014-02-21 16:48:46 +0000 |
382 | @@ -38,6 +38,7 @@ |
383 | Q_PROPERTY(QString desktopFile READ desktopFile CONSTANT) |
384 | Q_PROPERTY(QString exec READ exec CONSTANT) |
385 | Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged) |
386 | + Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged) |
387 | Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged) |
388 | |
389 | public: |
390 | @@ -57,7 +58,10 @@ |
391 | State state() const override; |
392 | bool focused() const override; |
393 | |
394 | + bool visible() const; |
395 | + |
396 | void setStage(Stage stage); |
397 | + void setVisible(const bool); |
398 | |
399 | bool isValid() const; |
400 | QString desktopFile() const; |
401 | @@ -74,6 +78,7 @@ |
402 | Q_SIGNALS: |
403 | void fullscreenChanged(); |
404 | void stageChanged(Stage stage); |
405 | + void visibleChanged(); |
406 | |
407 | private: |
408 | void setPid(pid_t pid); |
409 | @@ -90,6 +95,7 @@ |
410 | State m_state; |
411 | bool m_focused; |
412 | bool m_fullscreen; |
413 | + bool m_visible; // duplicating internal Mir data :( |
414 | std::shared_ptr<mir::shell::Session> m_session; |
415 | QString m_sessionName; |
416 | QStringList m_arguments; |
417 | |
418 | === modified file 'src/modules/Unity/Application/application_manager.cpp' |
419 | --- src/modules/Unity/Application/application_manager.cpp 2014-02-11 09:47:56 +0000 |
420 | +++ src/modules/Unity/Application/application_manager.cpp 2014-02-21 16:48:46 +0000 |
421 | @@ -16,6 +16,7 @@ |
422 | |
423 | // local |
424 | #include "application_manager.h" |
425 | +#include "proc_info.h" |
426 | #include "application.h" |
427 | #include "desktopfilereader.h" |
428 | #include "dbuswindowstack.h" |
429 | @@ -44,33 +45,134 @@ |
430 | // Qt |
431 | #include <QCoreApplication> |
432 | |
433 | -// Default element sizes |
434 | -#define SIDE_STAGE_WIDTH_GU 40 |
435 | - |
436 | namespace msh = mir::shell; |
437 | |
438 | using namespace unity::shell::application; |
439 | |
440 | -ApplicationManager *ApplicationManager::the_application_manager = nullptr; |
441 | +namespace |
442 | +{ |
443 | + |
444 | +QSize get_display_size(std::shared_ptr<mir::graphics::Display> const& display) { |
445 | + // Obtain display size |
446 | + mir::geometry::Rectangles view_area; |
447 | + display->for_each_display_buffer( |
448 | + [&view_area](mir::graphics::DisplayBuffer const& db) |
449 | + { |
450 | + view_area.add(db.view_area()); |
451 | + }); |
452 | + |
453 | + return QSize( |
454 | + view_area.bounding_rectangle().size.width.as_uint32_t(), |
455 | + view_area.bounding_rectangle().size.height.as_uint32_t() |
456 | + ); |
457 | +} |
458 | + |
459 | + |
460 | +void connectToSessionListener(ApplicationManager * manager, SessionListener * listener) |
461 | +{ |
462 | + |
463 | + QObject::connect(listener, &SessionListener::sessionStarting, |
464 | + manager, &ApplicationManager::onSessionStarting); |
465 | + QObject::connect(listener, &SessionListener::sessionStopping, |
466 | + manager, &ApplicationManager::onSessionStopping); |
467 | + QObject::connect(listener, &SessionListener::sessionFocused, |
468 | + manager, &ApplicationManager::onSessionFocused, Qt::QueuedConnection); |
469 | + QObject::connect(listener, &SessionListener::sessionUnfocused, |
470 | + manager, &ApplicationManager::onSessionUnfocused); |
471 | + QObject::connect(listener, &SessionListener::sessionCreatedSurface, |
472 | + manager, &ApplicationManager::onSessionCreatedSurface); |
473 | + QObject::connect(listener, &SessionListener::sessionStarting, |
474 | + manager, &ApplicationManager::onSessionStarting); |
475 | + QObject::connect(listener, &SessionListener::sessionStopping, |
476 | + manager, &ApplicationManager::onSessionStopping); |
477 | + QObject::connect(listener, &SessionListener::sessionFocused, |
478 | + manager, &ApplicationManager::onSessionFocused, Qt::QueuedConnection); |
479 | + QObject::connect(listener, &SessionListener::sessionUnfocused, |
480 | + manager, &ApplicationManager::onSessionUnfocused); |
481 | + QObject::connect(listener, &SessionListener::sessionCreatedSurface, |
482 | + manager, &ApplicationManager::onSessionCreatedSurface); |
483 | +} |
484 | + |
485 | +void connectToSessionAuthorizer(ApplicationManager * manager, SessionAuthorizer * authorizer) |
486 | +{ |
487 | + QObject::connect(authorizer, &SessionAuthorizer::requestAuthorizationForSession, |
488 | + manager, &ApplicationManager::authorizeSession, Qt::BlockingQueuedConnection); |
489 | +} |
490 | + |
491 | + |
492 | +void connectToPlacementStrategy(ApplicationManager * manager, InitialSurfacePlacementStrategy * strategy) |
493 | +{ |
494 | + QObject::connect(strategy, &InitialSurfacePlacementStrategy::requestPlacementForSession, |
495 | + manager, &ApplicationManager::placeSession, Qt::DirectConnection); |
496 | + |
497 | +} |
498 | + |
499 | +void connectToTaskController(ApplicationManager * manager, TaskController * controller) |
500 | +{ |
501 | + QObject::connect(controller, &TaskController::processStartReport, |
502 | + manager, &ApplicationManager::onProcessStartReportReceived); |
503 | + QObject::connect(controller, &TaskController::processStopped, |
504 | + manager, &ApplicationManager::onProcessStopped); |
505 | + QObject::connect(controller, &TaskController::requestFocus, |
506 | + manager, &ApplicationManager::onFocusRequested); |
507 | + QObject::connect(controller, &TaskController::requestResume, |
508 | + manager, &ApplicationManager::onResumeRequested); |
509 | + |
510 | +} |
511 | +} |
512 | + |
513 | +QSharedPointer<ApplicationManager> ApplicationManager::Factory::Factory::create() |
514 | +{ |
515 | + QMirServerApplication* mirServerApplication = dynamic_cast<QMirServerApplication*>(QCoreApplication::instance()); |
516 | + if (mirServerApplication == NULL) { |
517 | + LOG("Need to use QMirServerApplication"); |
518 | + QCoreApplication::quit(); |
519 | + return QSharedPointer<ApplicationManager>(nullptr); |
520 | + } |
521 | + |
522 | + ShellServerConfiguration * mirServer = mirServerApplication->server(); |
523 | + |
524 | + QSize displaySize{get_display_size(mirServer->the_display())}; |
525 | + |
526 | + QSharedPointer<upstart::ApplicationController> appController(new upstart::ApplicationController()); |
527 | + QSharedPointer<TaskController> taskController(new TaskController(nullptr, appController)); |
528 | + QSharedPointer<DesktopFileReader::Factory> fileReaderFactory(new DesktopFileReader::Factory()); |
529 | + QSharedPointer<ProcInfo> procInfo(new ProcInfo()); |
530 | + QSharedPointer<ApplicationManager> appManager( |
531 | + new ApplicationManager( |
532 | + taskController, |
533 | + fileReaderFactory, |
534 | + procInfo, |
535 | + mirServer->the_focus_controller(), |
536 | + displaySize |
537 | + ) |
538 | + ); |
539 | + |
540 | + |
541 | + connectToSessionListener(appManager.data(), mirServer->sessionListener()); |
542 | + connectToSessionAuthorizer(appManager.data(), mirServer->sessionAuthorizer()); |
543 | + connectToPlacementStrategy(appManager.data(), mirServer->placementStrategy()); |
544 | + connectToTaskController(appManager.data(), taskController.data()); |
545 | + |
546 | + return appManager; |
547 | +} |
548 | |
549 | ApplicationManager* ApplicationManager::singleton() |
550 | { |
551 | - if (!the_application_manager) { |
552 | - the_application_manager = new ApplicationManager( |
553 | - QSharedPointer<TaskController>( |
554 | - new TaskController( |
555 | - nullptr, |
556 | - QSharedPointer<ApplicationController>( |
557 | - new upstart::ApplicationController()))), |
558 | - QSharedPointer<DesktopFileReader::Factory>( |
559 | - new DesktopFileReader::Factory())); |
560 | + static QSharedPointer<ApplicationManager> instance; |
561 | + if (!instance) { |
562 | + Factory appFactory; |
563 | + instance = appFactory.create(); |
564 | } |
565 | - return the_application_manager; |
566 | + return instance.data(); |
567 | } |
568 | |
569 | ApplicationManager::ApplicationManager( |
570 | const QSharedPointer<TaskController>& taskController, |
571 | const QSharedPointer<DesktopFileReader::Factory>& desktopFileReaderFactory, |
572 | + const QSharedPointer<ProcInfo>& procInfo, |
573 | + const std::shared_ptr<mir::shell::FocusController> & controller, |
574 | + const QSize & displaySize, |
575 | QObject *parent) |
576 | : ApplicationManagerInterface(parent) |
577 | , m_focusedApplication(nullptr) |
578 | @@ -79,63 +181,18 @@ |
579 | , m_msApplicationToBeFocused(nullptr) |
580 | , m_ssApplicationToBeFocused(nullptr) |
581 | , m_lifecycleExceptions(QStringList() << "com.ubuntu.music") |
582 | + , m_focusController(controller) |
583 | + , m_dbusWindowStack(new DBusWindowStack(this)) |
584 | , m_taskController(taskController) |
585 | , m_desktopFileReaderFactory(desktopFileReaderFactory) |
586 | + , m_procInfo(procInfo) |
587 | , m_gridUnitPx(8) |
588 | , m_fenceNext(false) |
589 | + , m_displaySize(displaySize) |
590 | , m_panelHeight(54) |
591 | { |
592 | DLOG("ApplicationManager::ApplicationManager (this=%p)", this); |
593 | |
594 | - QMirServerApplication* mirServerApplication = dynamic_cast<QMirServerApplication*>(QCoreApplication::instance()); |
595 | - if (mirServerApplication == NULL) { |
596 | - LOG("Need to use QMirServerApplication"); |
597 | - QCoreApplication::quit(); |
598 | - return; |
599 | - } |
600 | - m_mirServer = mirServerApplication->server(); |
601 | - |
602 | - QObject::connect(m_mirServer->sessionListener(), &SessionListener::sessionStarting, |
603 | - this, &ApplicationManager::onSessionStarting); |
604 | - QObject::connect(m_mirServer->sessionListener(), &SessionListener::sessionStopping, |
605 | - this, &ApplicationManager::onSessionStopping); |
606 | - QObject::connect(m_mirServer->sessionListener(), &SessionListener::sessionFocused, |
607 | - this, &ApplicationManager::onSessionFocused, Qt::QueuedConnection); |
608 | - QObject::connect(m_mirServer->sessionListener(), &SessionListener::sessionUnfocused, |
609 | - this, &ApplicationManager::onSessionUnfocused); |
610 | - QObject::connect(m_mirServer->sessionListener(), &SessionListener::sessionCreatedSurface, |
611 | - this, &ApplicationManager::onSessionCreatedSurface); |
612 | - QObject::connect(m_mirServer->sessionAuthorizer(), &SessionAuthorizer::requestAuthorizationForSession, |
613 | - this, &ApplicationManager::authorizeSession, Qt::BlockingQueuedConnection); |
614 | - QObject::connect(m_mirServer->placementStrategy(), &InitialSurfacePlacementStrategy::requestPlacementForSession, |
615 | - this, &ApplicationManager::placeSession, Qt::DirectConnection); |
616 | - |
617 | - QObject::connect(m_taskController.data(), &TaskController::processStartReport, |
618 | - this, &ApplicationManager::onProcessStartReportReceived); |
619 | - QObject::connect(m_taskController.data(), &TaskController::processStopped, |
620 | - this, &ApplicationManager::onProcessStopped); |
621 | - QObject::connect(m_taskController.data(), &TaskController::requestFocus, |
622 | - this, &ApplicationManager::onFocusRequested); |
623 | - QObject::connect(m_taskController.data(), &TaskController::requestResume, |
624 | - this, &ApplicationManager::onResumeRequested); |
625 | - |
626 | - m_dbusWindowStack = new DBusWindowStack(this); |
627 | - |
628 | - std::shared_ptr<mir::graphics::Display> mirDisplay = m_mirServer->the_display(); |
629 | - |
630 | - // Obtain display size |
631 | - mir::geometry::Rectangles view_area; |
632 | - mirDisplay->for_each_display_buffer( |
633 | - [&view_area](mir::graphics::DisplayBuffer const& db) |
634 | - { |
635 | - view_area.add(db.view_area()); |
636 | - }); |
637 | - |
638 | - m_displaySize = QSize( |
639 | - view_area.bounding_rectangle().size.width.as_uint32_t(), |
640 | - view_area.bounding_rectangle().size.height.as_uint32_t() |
641 | - ); |
642 | - |
643 | // Setup panel height |
644 | QByteArray gridUnitString = qgetenv("GRID_UNIT_PX"); |
645 | if (!gridUnitString.isEmpty()) { |
646 | @@ -143,12 +200,9 @@ |
647 | int value = gridUnitString.toInt(&ok); |
648 | if (ok) { |
649 | m_gridUnitPx = value; |
650 | + m_panelHeight = (3 * m_gridUnitPx) + static_cast<int>(2 * qFloor(static_cast<float>(m_gridUnitPx) / 8)); |
651 | } |
652 | } |
653 | - |
654 | - int densityPixelPx = qFloor( (float)m_gridUnitPx / 8 ); |
655 | - |
656 | - m_panelHeight = 3 * m_gridUnitPx + 2 * densityPixelPx; |
657 | } |
658 | |
659 | ApplicationManager::~ApplicationManager() |
660 | @@ -156,11 +210,6 @@ |
661 | DLOG("ApplicationManager::~ApplicationManager"); |
662 | } |
663 | |
664 | -int ApplicationManager::panelHeight() |
665 | -{ |
666 | - return m_panelHeight; |
667 | -} |
668 | - |
669 | int ApplicationManager::rowCount(const QModelIndex &parent) const |
670 | { |
671 | return !parent.isValid() ? m_applications.size() : 0; |
672 | @@ -222,6 +271,7 @@ |
673 | if (application == nullptr) |
674 | return; |
675 | |
676 | + DLOG("ApplicationManager::suspend(this=%p, application(%p)->appId(%s) )",this, application, qPrintable(application->appId())); |
677 | // Present in exceptions list, return. |
678 | if (!m_lifecycleExceptions.filter(application->appId().section('_',0,0)).empty()) |
679 | return; |
680 | @@ -232,8 +282,8 @@ |
681 | |
682 | bool ApplicationManager::focusApplication(const QString &appId) |
683 | { |
684 | - DLOG("ApplicationManager::focusApplication (this=%p, appId=%s)", this, qPrintable(appId)); |
685 | Application *application = findApplication(appId); |
686 | + DLOG("ApplicationManager::focusApplication (this=%p, application=%p, appId=%s)", this, application, qPrintable(appId)); |
687 | |
688 | if (!application) { |
689 | DLOG("No such running application '%s'", qPrintable(appId)); |
690 | @@ -256,7 +306,7 @@ |
691 | move(from, m_applications.length()-1); |
692 | } else { |
693 | if (application->session()) |
694 | - m_mirServer->the_focus_controller()->set_focus_to(application->session()); |
695 | + m_focusController->set_focus_to(application->session()); |
696 | } |
697 | |
698 | // FIXME(dandrader): lying here. The operation is async. So we will only know whether |
699 | @@ -275,7 +325,7 @@ |
700 | // Clear both stages |
701 | m_msApplicationToBeFocused = nullptr; |
702 | m_ssApplicationToBeFocused = nullptr; |
703 | - m_mirServer->the_focus_controller()->set_focus_to(NULL); //FIXME(greyback) |
704 | + m_focusController->set_focus_to(NULL); //FIXME(greyback) |
705 | } |
706 | |
707 | Application* ApplicationManager::startApplication(const QString &appId, |
708 | @@ -294,6 +344,16 @@ |
709 | return nullptr; |
710 | } |
711 | |
712 | + { |
713 | + Application * application = findApplication(appId); |
714 | + if (application) |
715 | + { |
716 | + DLOG("ApplicationManager::startApplication - application already " |
717 | + "exists: (this=%p, app=%p, appId=%s)", |
718 | + this, application, qPrintable(appId)); |
719 | + } |
720 | + } |
721 | + |
722 | Application* application = new Application( |
723 | m_taskController, |
724 | m_desktopFileReaderFactory->createInstanceForAppId(appId), |
725 | @@ -320,7 +380,9 @@ |
726 | this, qPrintable(appId), (failure) ? 'Y' : 'N'); |
727 | |
728 | if (failure) { |
729 | - onProcessStopped(appId, true); |
730 | + DLOG("ApplicationManager::onProcessStartReportReceived handling failure:"); |
731 | + stopStartingApplication(appId); |
732 | + return; |
733 | } |
734 | |
735 | Application *application = findApplication(appId); |
736 | @@ -338,30 +400,23 @@ |
737 | add(application); |
738 | Q_EMIT focusRequested(appId); |
739 | } |
740 | + else { |
741 | + DLOG("ApplicationManager::onProcessStartReportReceived application already found: (app=%p, appId=%s)", application, qPrintable(appId)); |
742 | + } |
743 | } |
744 | |
745 | bool ApplicationManager::stopApplication(const QString &appId) |
746 | { |
747 | - DLOG("ApplicationManager::stopApplication (this=%p, appId=%s)", this, qPrintable(appId)); |
748 | - |
749 | Application *application = findApplication(appId); |
750 | + DLOG("ApplicationManager::stopApplication (this=%p, application=%p, appId=%s)", this, application, qPrintable(appId)); |
751 | |
752 | if (!application) { |
753 | DLOG("No such running application '%s'", qPrintable(appId)); |
754 | return false; |
755 | } |
756 | |
757 | - if (application == m_focusedApplication) { |
758 | - // TODO(greyback) What to do?? Focus next app, or unfocus everything?? |
759 | - m_focusedApplication = NULL; |
760 | - Q_EMIT focusedApplicationIdChanged(); |
761 | - } |
762 | + checkFocusOnRemovedApplication(application); |
763 | |
764 | - if (application == m_mainStageApplication) |
765 | - m_mainStageApplication = nullptr; |
766 | - if (application == m_sideStageApplication) |
767 | - m_sideStageApplication = nullptr; |
768 | - |
769 | remove(application); |
770 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); |
771 | |
772 | @@ -376,37 +431,28 @@ |
773 | return result; |
774 | } |
775 | |
776 | +void ApplicationManager::stopStartingApplication(const QString &appId) |
777 | +{ |
778 | + Application *application = findApplication(appId); |
779 | + |
780 | + if (application && application->state() == Application::Starting) { |
781 | + shutdownApplication(application); |
782 | + } |
783 | + else if (application) { |
784 | + DLOG("onProcessStartReportReceived failure - but application=%p, appId=%s is not in Starting state",application, qPrintable(appId)); |
785 | + } |
786 | +} |
787 | + |
788 | void ApplicationManager::onProcessStopped(const QString &appId, const bool unexpected) |
789 | { |
790 | Application *application = findApplication(appId); |
791 | + DLOG("ApplicationManager::onProcessStopped (this=%p, application=%p, appId=%s)", this, application, qPrintable(appId)); |
792 | |
793 | // if shell did not stop the application, but upstart says it died, we assume the process has been |
794 | // killed, so it can be respawned later. Only exception is if that application is focused or running |
795 | // as then it most likely crashed. Update this logic when upstart gives some failure info. |
796 | if (application) { |
797 | - bool removeApplication = false; |
798 | - |
799 | - if (application == m_focusedApplication) { |
800 | - // Very bad case where focused application dies. Remove from list. Should give error message |
801 | - m_focusedApplication = nullptr; |
802 | - Q_EMIT focusedApplicationIdChanged(); |
803 | - removeApplication = true; |
804 | - } |
805 | - |
806 | - if (application->state() == Application::Running || application->state() == Application::Starting) { |
807 | - // Application probably crashed, else OOM killer struck. Either way state wasn't saved |
808 | - // so just remove application |
809 | - removeApplication = true; |
810 | - } else if (application->state() == Application::Suspended) { |
811 | - application->setState(Application::Stopped); |
812 | - application->setSession(nullptr); |
813 | - } |
814 | - |
815 | - if (removeApplication) { |
816 | - remove(application); |
817 | - m_dbusWindowStack->WindowDestroyed(0, application->appId()); |
818 | - delete application; |
819 | - } |
820 | + shutdownApplication(application); |
821 | } |
822 | |
823 | if (unexpected) { |
824 | @@ -415,6 +461,27 @@ |
825 | } |
826 | } |
827 | |
828 | +void ApplicationManager::shutdownApplication(Application* application) |
829 | +{ |
830 | + bool removeApplication = checkFocusOnRemovedApplication(application); |
831 | + |
832 | + if (application->state() == Application::Running || application->state() == Application::Starting) { |
833 | + // Application probably crashed, else OOM killer struck. Either way state wasn't saved |
834 | + // so just remove application |
835 | + removeApplication = true; |
836 | + } else if (application->state() == Application::Suspended) { |
837 | + application->setState(Application::Stopped); |
838 | + application->setSession(nullptr); |
839 | + } |
840 | + |
841 | + if (removeApplication) { |
842 | + remove(application); |
843 | + m_dbusWindowStack->WindowDestroyed(0, application->appId()); |
844 | + delete application; |
845 | + } |
846 | + |
847 | +} |
848 | + |
849 | void ApplicationManager::onFocusRequested(const QString& appId) |
850 | { |
851 | DLOG("ApplicationManager::onFocusRequested (this=%p, appId=%s)", this, qPrintable(appId)); |
852 | @@ -424,9 +491,9 @@ |
853 | |
854 | void ApplicationManager::onResumeRequested(const QString& appId) |
855 | { |
856 | - DLOG("ApplicationManager::onResumeRequested (this=%p, appId=%s)", this, qPrintable(appId)); |
857 | - |
858 | Application *application = findApplication(appId); |
859 | + DLOG("ApplicationManager::onResumeRequested (this=%p, application=%p, appId=%s)", this, application, qPrintable(appId)); |
860 | + |
861 | |
862 | if (!application) { |
863 | DLOG("ApplicationManager::onResumeRequested: No such running application '%s'", qPrintable(appId)); |
864 | @@ -452,6 +519,7 @@ |
865 | if (app->state() == Application::Starting |
866 | && m_taskController->appIdHasProcessId(app->appId(), pid)) { |
867 | app->setPid(pid); |
868 | + DLOG("ApplicationManager::authorizeSession - connecting: application=%p and pid=%lld", app, pid); |
869 | authorized = true; |
870 | return; |
871 | } |
872 | @@ -463,41 +531,35 @@ |
873 | * notify shell it is starting an application and so shell should allow it. Also reads |
874 | * the --stage parameter to determine the desired stage |
875 | */ |
876 | - QFile cmdline(QString("/proc/%1/cmdline").arg(pid)); |
877 | - if (!cmdline.open(QIODevice::ReadOnly | QIODevice::Text)) { |
878 | + std::unique_ptr<ProcInfo::CommandLine> info = m_procInfo->command_line(pid); |
879 | + if (!info) { |
880 | DLOG("ApplicationManager REJECTED connection from app with pid %lld as unable to read process command", pid); |
881 | return; |
882 | } |
883 | |
884 | - QByteArray command = cmdline.readLine().replace('\0', ' '); |
885 | - |
886 | - // FIXME: special exception for the OSK - maliit-server - not very secure |
887 | - if (command.startsWith("maliit-server") || command.startsWith("/usr/lib/arm-linux-gnueabihf/qt5/libexec/QtWebProcess") |
888 | - || command.startsWith("/usr/bin/signon-ui")) { |
889 | + if (info->starts_with("maliit-server") || info->starts_with("/usr/lib/arm-linux-gnueabihf/qt5/libexec/QtWebProcess") |
890 | + || info->starts_with("/usr/bin/signon-ui")) { |
891 | authorized = true; |
892 | m_fenceNext = true; |
893 | return; |
894 | } |
895 | |
896 | - QString pattern = QRegularExpression::escape("--desktop_file_hint=") + "(\\S+)"; |
897 | - QRegularExpression regExp(pattern); |
898 | - QRegularExpressionMatch regExpMatch = regExp.match(command); |
899 | + boost::optional<QString> desktopFileName{ info->get_parameter("--desktop_file_hint=") }; |
900 | |
901 | - if (!regExpMatch.hasMatch()) { |
902 | + if (!desktopFileName) { |
903 | LOG("ApplicationManager REJECTED connection from app with pid %lld as no desktop_file_hint specified", pid); |
904 | return; |
905 | } |
906 | |
907 | - QString desktopFileName = regExpMatch.captured(1); |
908 | - DLOG("Process supplied desktop_file_hint, loading '%s'", desktopFileName.toLatin1().data()); |
909 | + DLOG("Process supplied desktop_file_hint, loading '%s'", desktopFileName.get().toLatin1().data()); |
910 | |
911 | // FIXME: right now we support --desktop_file_hint=appId for historical reasons. So let's try that in |
912 | // case we didn't get an existing .desktop file path |
913 | DesktopFileReader* desktopData; |
914 | - if (QFileInfo(desktopFileName).exists()) { |
915 | - desktopData = m_desktopFileReaderFactory->createInstanceForDesktopFile(QFileInfo(desktopFileName)); |
916 | + if (QFileInfo(desktopFileName.get()).exists()) { |
917 | + desktopData = m_desktopFileReaderFactory->createInstanceForDesktopFile(QFileInfo(desktopFileName.get())); |
918 | } else { |
919 | - desktopData = m_desktopFileReaderFactory->createInstanceForAppId(desktopFileName); |
920 | + desktopData = m_desktopFileReaderFactory->createInstanceForAppId(desktopFileName.get()); |
921 | } |
922 | |
923 | if (!desktopData->loaded()) { |
924 | @@ -521,18 +583,15 @@ |
925 | |
926 | // if stage supplied in CLI, fetch that |
927 | Application::Stage stage = Application::MainStage; |
928 | - pattern = QRegularExpression::escape("--stage_hint=") + "(\\S+)"; |
929 | - regExp.setPattern(pattern); |
930 | - regExpMatch = regExp.match(command); |
931 | + boost::optional<QString> stageParam = info->get_parameter("--stage_hint="); |
932 | |
933 | - if (regExpMatch.hasMatch() && regExpMatch.captured(1) == "side_stage") { |
934 | + if (stageParam && stageParam.get() == "side_stage") { |
935 | stage = Application::SideStage; |
936 | } |
937 | |
938 | DLOG("Existing process with pid %lld appeared, adding '%s' to application lists", pid, desktopData->name().toLatin1().data()); |
939 | |
940 | - QString argStr(command.data()); |
941 | - QStringList arguments(argStr.split(' ')); |
942 | + QStringList arguments(info->as_string_list()); |
943 | application = new Application(m_taskController, desktopData, Application::Starting, arguments, this); |
944 | application->setPid(pid); |
945 | application->setStage(stage); |
946 | @@ -542,44 +601,50 @@ |
947 | |
948 | void ApplicationManager::placeSession(msh::Session const* session, uint32_t &x, uint32_t &y) |
949 | { |
950 | - DLOG("ApplicationManager::placeSession (this=%p, session=%p)", this, session); |
951 | - |
952 | Application* application = findApplicationWithSession(session); |
953 | + DLOG("ApplicationManager::placeSession (this=%p, application=%p, session=%p, name=%s)", this, application, session, session?(session->name().c_str()):"null"); |
954 | |
955 | // Application defaults |
956 | x = 0; |
957 | - y = m_panelHeight; |
958 | + y = 0; |
959 | |
960 | - // Shell client override |
961 | - if (!session) { |
962 | - y = 0; |
963 | - return; |
964 | + if (application && !application->fullscreen() && session) { |
965 | + if (application->stage() == Application::SideStage && !m_sideStageAppRect.isNull()) { |
966 | + QRectF localRect(0., 0., m_sideStageAppRect->width(), m_sideStageAppRect->height()); |
967 | + QRectF sceneRect = m_sideStageAppRect->mapRectToScene(localRect); |
968 | + x = (uint32_t)(sceneRect.x()); |
969 | + y = (uint32_t)(sceneRect.y()); |
970 | + } else if (!m_mainStageAppRect.isNull()) { |
971 | + QRectF localRect(0., 0., m_sideStageAppRect->width(), m_mainStageAppRect->height()); |
972 | + QRectF sceneRect = m_mainStageAppRect->mapRectToScene(localRect); |
973 | + x = (uint32_t)(sceneRect.x()); |
974 | + y = (uint32_t)(sceneRect.y()); |
975 | + } |
976 | + } else if (session) { // if a valid session, but no application associated, it must be a helper like OSK |
977 | + if (qgetenv("NATIVE_ORIENTATION") == "landscape") { |
978 | + x = 0; |
979 | + y = 0; |
980 | + } else { |
981 | + x = 0; |
982 | + y = m_panelHeight; |
983 | + } |
984 | } |
985 | |
986 | - // Fullscreen applications override |
987 | - if (application && application->fullscreen()) |
988 | - y = 0; |
989 | - |
990 | - // SideStage override |
991 | - if (application && application->stage() == Application::SideStage) |
992 | - x = m_displaySize.width() - (SIDE_STAGE_WIDTH_GU * m_gridUnitPx); |
993 | - |
994 | DLOG("ApplicationManager::placeSession (x=%d, y=%d)", x, y); |
995 | } |
996 | |
997 | void ApplicationManager::onSessionStarting(std::shared_ptr<msh::Session> const& session) |
998 | { |
999 | - DLOG("ApplicationManager::onSessionStarting (this=%p, application=%s)", this, session->name().c_str()); |
1000 | + DLOG("ApplicationManager::onSessionStarting (this=%p, application=%s)", this, session?session->name().c_str():"null"); |
1001 | |
1002 | if (m_fenceNext) { |
1003 | m_fenceNext = false; |
1004 | return; |
1005 | } |
1006 | |
1007 | - //FIXME(greyback) Mir not supplying any identifier that we can use to link the PID to the session |
1008 | - // so am assuming that the *most recently* launched application session is the one that connects |
1009 | - Application* application = findLastExecutedApplication(); |
1010 | - if (application && application->state() != Application::Running) { |
1011 | + Application* application = findApplicationWithPid(session->process_id()); |
1012 | + if (application && application->state() != Application::Running && |
1013 | + !application->session()) { |
1014 | application->setSession(session); |
1015 | if (application->stage() == Application::MainStage) |
1016 | m_msApplicationToBeFocused = application; |
1017 | @@ -592,10 +657,11 @@ |
1018 | |
1019 | void ApplicationManager::onSessionStopping(std::shared_ptr<msh::Session> const& session) |
1020 | { |
1021 | - DLOG("ApplicationManager::onSessionStopping (this=%p, application=%s)", this, session->name().c_str()); |
1022 | - |
1023 | // in case application closed not by hand of shell, check again here: |
1024 | Application* application = findApplicationWithSession(session); |
1025 | + |
1026 | + DLOG("ApplicationManager::onSessionStopping (this=%p, application=%p, appId=%s, session name=%s)", this, application, application?qPrintable(application->appId()):"null", session?session->name().c_str():"null"); |
1027 | + |
1028 | if (application) { |
1029 | bool removeApplication = true; |
1030 | |
1031 | @@ -604,7 +670,7 @@ |
1032 | application->setSession(nullptr); |
1033 | m_dbusWindowStack->WindowDestroyed(0, application->appId()); |
1034 | if (application != m_focusedApplication) { |
1035 | - removeApplication = false; |
1036 | + removeApplication = false; |
1037 | } |
1038 | } |
1039 | |
1040 | @@ -626,8 +692,8 @@ |
1041 | |
1042 | void ApplicationManager::onSessionFocused(std::shared_ptr<msh::Session> const& session) |
1043 | { |
1044 | - DLOG("ApplicationManager::onSessionFocused (this=%p, session=%p)", this, session.get()); |
1045 | Application* application = findApplicationWithSession(session); |
1046 | + DLOG("ApplicationManager::onSessionFocused (this=%p, application=%p, appId=%s, session name=%s)", this, application, application?qPrintable(application->appId()):"null", session?session->name().c_str():"null"); |
1047 | |
1048 | // Don't give application focus until it has created it's surface, when it is set as state "Running" |
1049 | // and only notify shell of focus changes that it actually expects |
1050 | @@ -649,7 +715,7 @@ |
1051 | |
1052 | void ApplicationManager::onSessionUnfocused() |
1053 | { |
1054 | - DLOG("ApplicationManager::onSessionUnfocused (this=%p)", this); |
1055 | + DLOG("ApplicationManager::onSessionUnfocused (this=%p, application=%p)", this, m_focusedApplication); |
1056 | if (NULL != m_focusedApplication) { |
1057 | Q_ASSERT(m_focusedApplication->focused()); |
1058 | m_focusedApplication->setFocused(false); |
1059 | @@ -666,7 +732,7 @@ |
1060 | } |
1061 | |
1062 | void ApplicationManager::onSessionCreatedSurface(msh::Session const* session, |
1063 | - std::shared_ptr<msh::Surface> const& surface) |
1064 | + std::shared_ptr<msh::Surface> const& surface) |
1065 | { |
1066 | DLOG("ApplicationManager::onSessionCreatedSurface (this=%p)", this); |
1067 | Q_UNUSED(surface); |
1068 | @@ -683,7 +749,7 @@ |
1069 | |
1070 | void ApplicationManager::setFocused(Application *application) |
1071 | { |
1072 | - DLOG("ApplicationManager::setFocused (appId=%s)", qPrintable(application->appId())); |
1073 | + DLOG("ApplicationManager::setFocused (application=%p, appId=%s)", application, qPrintable(application->appId())); |
1074 | |
1075 | if (application == m_focusedApplication) |
1076 | return; |
1077 | @@ -734,15 +800,6 @@ |
1078 | return nullptr; |
1079 | } |
1080 | |
1081 | -Application* ApplicationManager::findLastExecutedApplication() |
1082 | -{ |
1083 | - if (m_applications.length() > 0) { |
1084 | - return m_applications.last(); |
1085 | - } else { |
1086 | - return NULL; |
1087 | - } |
1088 | -} |
1089 | - |
1090 | Application* ApplicationManager::applicationForStage(Application::Stage stage) |
1091 | { |
1092 | DLOG("ApplicationManager::focusedApplicationForStage(this=%p)", this); |
1093 | @@ -769,6 +826,11 @@ |
1094 | DASSERT(application != NULL); |
1095 | DLOG("ApplicationManager::remove (this=%p, application='%s')", this, qPrintable(application->name())); |
1096 | |
1097 | + if (application == m_sideStageApplication) |
1098 | + m_sideStageApplication = nullptr; |
1099 | + if (application == m_mainStageApplication) |
1100 | + m_mainStageApplication = nullptr; |
1101 | + |
1102 | int i = m_applications.indexOf(application); |
1103 | if (i != -1) { |
1104 | beginRemoveRows(QModelIndex(), i, i); |
1105 | @@ -793,6 +855,16 @@ |
1106 | } |
1107 | } |
1108 | |
1109 | +void ApplicationManager::setMainStageAppRect(QQuickItem *item) |
1110 | +{ |
1111 | + m_mainStageAppRect = item; |
1112 | +} |
1113 | + |
1114 | +void ApplicationManager::setSideStageAppRect(QQuickItem *item) |
1115 | +{ |
1116 | + m_sideStageAppRect = item; |
1117 | +} |
1118 | + |
1119 | QModelIndex ApplicationManager::findIndex(Application* application) |
1120 | { |
1121 | for (int i = 0; i < m_applications.size(); ++i) { |
1122 | @@ -803,3 +875,14 @@ |
1123 | |
1124 | return QModelIndex(); |
1125 | } |
1126 | + |
1127 | +bool ApplicationManager::checkFocusOnRemovedApplication(Application * application) |
1128 | +{ |
1129 | + if (application == m_focusedApplication) { |
1130 | + // TODO(greyback) What to do?? Focus next app, or unfocus everything?? |
1131 | + m_focusedApplication = nullptr; |
1132 | + Q_EMIT focusedApplicationIdChanged(); |
1133 | + return true; |
1134 | + } |
1135 | + return false; |
1136 | +} |
1137 | |
1138 | === modified file 'src/modules/Unity/Application/application_manager.h' |
1139 | --- src/modules/Unity/Application/application_manager.h 2014-01-27 11:29:44 +0000 |
1140 | +++ src/modules/Unity/Application/application_manager.h 2014-02-21 16:48:46 +0000 |
1141 | @@ -25,6 +25,8 @@ |
1142 | |
1143 | // Qt |
1144 | #include <QObject> |
1145 | +#include <QPointer> |
1146 | +#include <QQuickItem> |
1147 | #include <QSharedPointer> |
1148 | #include <QStringList> |
1149 | |
1150 | @@ -38,6 +40,7 @@ |
1151 | class DBusWindowStack; |
1152 | class MirSurfaceManager; |
1153 | class TaskController; |
1154 | +class ProcInfo; |
1155 | |
1156 | namespace mir { |
1157 | namespace geometry { |
1158 | @@ -46,6 +49,7 @@ |
1159 | namespace shell { |
1160 | class Session; |
1161 | class Surface; |
1162 | + class FocusController; |
1163 | } |
1164 | } |
1165 | |
1166 | @@ -55,6 +59,11 @@ |
1167 | Q_FLAGS(ExecFlags) |
1168 | |
1169 | public: |
1170 | + class Factory |
1171 | + { |
1172 | + public: |
1173 | + QSharedPointer<ApplicationManager> create(); |
1174 | + }; |
1175 | // Mapping enums to Ubuntu Platform API enums. |
1176 | enum Flag { |
1177 | NoFlag = 0x0, |
1178 | @@ -66,6 +75,9 @@ |
1179 | |
1180 | explicit ApplicationManager(const QSharedPointer<TaskController>& taskController, |
1181 | const QSharedPointer<DesktopFileReader::Factory>& desktopFileReaderFactory, |
1182 | + const QSharedPointer<ProcInfo>& processInfo, |
1183 | + std::shared_ptr<mir::shell::FocusController> const& controller, |
1184 | + QSize const& displaySize, |
1185 | QObject *parent = 0); |
1186 | virtual ~ApplicationManager(); |
1187 | |
1188 | @@ -86,12 +98,14 @@ |
1189 | const QStringList &arguments = QStringList()); |
1190 | Q_INVOKABLE void move(int from, int to); |
1191 | |
1192 | + Q_INVOKABLE void setMainStageAppRect(QQuickItem *item); |
1193 | + Q_INVOKABLE void setSideStageAppRect(QQuickItem *item); |
1194 | + |
1195 | const QList<Application*> &list() const { return m_applications; } |
1196 | Application* findApplicationWithPid(const qint64 pid); |
1197 | |
1198 | // Internal helpers |
1199 | void suspendApplication(Application *application); |
1200 | - int panelHeight(); |
1201 | QSize displaySize() const { return m_displaySize; } |
1202 | |
1203 | public Q_SLOTS: |
1204 | @@ -119,9 +133,11 @@ |
1205 | void remove(Application* application); |
1206 | Application* findApplicationWithSession(const std::shared_ptr<mir::shell::Session> &session); |
1207 | Application* findApplicationWithSession(const mir::shell::Session *session); |
1208 | - Application* findLastExecutedApplication(); |
1209 | Application* applicationForStage(Application::Stage stage); |
1210 | QModelIndex findIndex(Application* application); |
1211 | + bool checkFocusOnRemovedApplication(Application* application); |
1212 | + void shutdownApplication(Application* application); |
1213 | + void stopStartingApplication(const QString &appId); |
1214 | |
1215 | QList<Application*> m_applications; |
1216 | Application* m_focusedApplication; // remove as Mir has API for this |
1217 | @@ -130,16 +146,21 @@ |
1218 | Application* m_msApplicationToBeFocused; // placeholder store for async focusing |
1219 | Application* m_ssApplicationToBeFocused; // placeholder store for async focusing |
1220 | QStringList m_lifecycleExceptions; |
1221 | - ShellServerConfiguration* m_mirServer; |
1222 | + std::shared_ptr<mir::shell::FocusController> m_focusController; |
1223 | DBusWindowStack* m_dbusWindowStack; |
1224 | QSharedPointer<TaskController> m_taskController; |
1225 | QSharedPointer<DesktopFileReader::Factory> m_desktopFileReaderFactory; |
1226 | - static ApplicationManager* the_application_manager; |
1227 | + QSharedPointer<ProcInfo> m_procInfo; |
1228 | int m_gridUnitPx; |
1229 | bool m_fenceNext; |
1230 | QSize m_displaySize; |
1231 | int m_panelHeight; |
1232 | |
1233 | + // The rectangular area that should be occupied by an application on the main |
1234 | + // or side stage. |
1235 | + QPointer<QQuickItem> m_mainStageAppRect; |
1236 | + QPointer<QQuickItem> m_sideStageAppRect; |
1237 | + |
1238 | friend class DBusWindowStack; |
1239 | friend class MirSurfaceManager; |
1240 | }; |
1241 | |
1242 | === modified file 'src/modules/Unity/Application/applicationscreenshotprovider.cpp' |
1243 | --- src/modules/Unity/Application/applicationscreenshotprovider.cpp 2013-12-20 03:38:43 +0000 |
1244 | +++ src/modules/Unity/Application/applicationscreenshotprovider.cpp 2014-02-21 16:48:46 +0000 |
1245 | @@ -28,7 +28,6 @@ |
1246 | ApplicationScreenshotProvider::ApplicationScreenshotProvider(ApplicationManager *appManager) |
1247 | : QQuickImageProvider(QQuickImageProvider::Image) |
1248 | , m_appManager(appManager) |
1249 | - , m_panelHeight(m_appManager->panelHeight()) |
1250 | { |
1251 | } |
1252 | |
1253 | |
1254 | === modified file 'src/modules/Unity/Application/applicationscreenshotprovider.h' |
1255 | --- src/modules/Unity/Application/applicationscreenshotprovider.h 2013-08-14 14:24:17 +0000 |
1256 | +++ src/modules/Unity/Application/applicationscreenshotprovider.h 2014-02-21 16:48:46 +0000 |
1257 | @@ -30,7 +30,6 @@ |
1258 | |
1259 | private: |
1260 | ApplicationManager* m_appManager; |
1261 | - int m_panelHeight; |
1262 | }; |
1263 | |
1264 | #endif // APPLICATIONSCREENSHOTPROVIDER_H |
1265 | |
1266 | === modified file 'src/modules/Unity/Application/inputarea.cpp' |
1267 | --- src/modules/Unity/Application/inputarea.cpp 2013-11-26 08:56:08 +0000 |
1268 | +++ src/modules/Unity/Application/inputarea.cpp 2014-02-21 16:48:46 +0000 |
1269 | @@ -176,12 +176,38 @@ |
1270 | { |
1271 | DLOG("InputArea::setMirInputArea (this=%p, x=%lf, y=%lf, width=%lf, height=%lf)", this, relativeGeometry.x(), relativeGeometry.y(), relativeGeometry.width(), relativeGeometry.height()); |
1272 | using namespace mir::geometry; |
1273 | - const QRect rect = parentItem()->mapRectToScene(relativeGeometry).toRect(); |
1274 | - |
1275 | - m_mirInputArea.top_left.x = X{rect.x()}; |
1276 | - m_mirInputArea.top_left.y = Y{rect.y()}; |
1277 | - m_mirInputArea.size.width = Width{rect.width()}; |
1278 | - m_mirInputArea.size.height = Height{rect.height()}; |
1279 | + QQuickItem* parent = parentItem(); |
1280 | + bool shellFound = false; |
1281 | + const bool landscape = qgetenv("NATIVE_ORIENTATION") == "landscape"; |
1282 | + |
1283 | + // FIXME: It seems Qt's mapRectToScene/Item returns incorrect position coordinates once rotations are performed. |
1284 | + // As a work around, we try to find the "shell" Item, find the InputArea geometry relative to that, and then |
1285 | + // manually perform the rotation for landscape mode. |
1286 | + while (landscape && parent) { |
1287 | + if (parent->objectName() == "shell") { |
1288 | + shellFound = true; |
1289 | + break; |
1290 | + } |
1291 | + parent = parent->parentItem(); |
1292 | + } |
1293 | + |
1294 | + QRect rect; |
1295 | + |
1296 | + if (landscape && shellFound) { |
1297 | + rect = mapRectToItem(parent, relativeGeometry).toRect(); |
1298 | + |
1299 | + m_mirInputArea.top_left.x = X{parent->height() - rect.y() - rect.height()}; |
1300 | + m_mirInputArea.top_left.y = Y{rect.x()}; |
1301 | + m_mirInputArea.size.width = Width{rect.height()}; |
1302 | + m_mirInputArea.size.height = Height{rect.width()}; |
1303 | + } else { // position relative to scene as usual |
1304 | + rect = parentItem()->mapRectToScene(relativeGeometry).toRect(); |
1305 | + |
1306 | + m_mirInputArea.top_left.x = X{rect.x()}; |
1307 | + m_mirInputArea.top_left.y = Y{rect.y()}; |
1308 | + m_mirInputArea.size.width = Width{rect.width()}; |
1309 | + m_mirInputArea.size.height = Height{rect.height()}; |
1310 | + } |
1311 | |
1312 | if (m_surface) { |
1313 | m_surface->installInputArea(this); |
1314 | |
1315 | === added file 'src/modules/Unity/Application/proc_info.cpp' |
1316 | --- src/modules/Unity/Application/proc_info.cpp 1970-01-01 00:00:00 +0000 |
1317 | +++ src/modules/Unity/Application/proc_info.cpp 2014-02-21 16:48:46 +0000 |
1318 | @@ -0,0 +1,52 @@ |
1319 | +/* |
1320 | + * Copyright (C) 2014 Canonical, Ltd. |
1321 | + * |
1322 | + * This program is free software: you can redistribute it and/or modify it under |
1323 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1324 | + * the Free Software Foundation. |
1325 | + * |
1326 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1327 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1328 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1329 | + * Lesser General Public License for more details. |
1330 | + * |
1331 | + * You should have received a copy of the GNU Lesser General Public License |
1332 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1333 | + */ |
1334 | + |
1335 | +#include "proc_info.h" |
1336 | + |
1337 | +#include <QFile> |
1338 | +#include <QRegularExpression> |
1339 | + |
1340 | +ProcInfo::~ProcInfo() { |
1341 | +} |
1342 | + |
1343 | +std::unique_ptr<ProcInfo::CommandLine> ProcInfo::command_line(quint64 pid) { |
1344 | + QFile cmdline(QString("/proc/%1/cmdline").arg(pid)); |
1345 | + if (!cmdline.open(QIODevice::ReadOnly | QIODevice::Text)) { |
1346 | + return nullptr; |
1347 | + } |
1348 | + |
1349 | + return std::unique_ptr<CommandLine>(new CommandLine{ cmdline.readLine().replace('\0', ' ') }); |
1350 | +} |
1351 | +QStringList ProcInfo::CommandLine::as_string_list() const { |
1352 | + return QString(command.data()).split(' '); |
1353 | +} |
1354 | + |
1355 | +bool ProcInfo::CommandLine::starts_with(char const* prefix) const { |
1356 | + return command.startsWith(prefix); |
1357 | +} |
1358 | + |
1359 | +boost::optional<QString> ProcInfo::CommandLine::get_parameter(const char* name) const { |
1360 | + QString pattern = QRegularExpression::escape(name) + "(\\S+)"; |
1361 | + QRegularExpression regExp(pattern); |
1362 | + QRegularExpressionMatch regExpMatch = regExp.match(command); |
1363 | + |
1364 | + if (!regExpMatch.hasMatch()) { |
1365 | + return boost::optional<QString>{}; |
1366 | + } |
1367 | + |
1368 | + return boost::optional<QString>{regExpMatch.captured(1)}; |
1369 | +} |
1370 | + |
1371 | |
1372 | === added file 'src/modules/Unity/Application/proc_info.h' |
1373 | --- src/modules/Unity/Application/proc_info.h 1970-01-01 00:00:00 +0000 |
1374 | +++ src/modules/Unity/Application/proc_info.h 2014-02-21 16:48:46 +0000 |
1375 | @@ -0,0 +1,48 @@ |
1376 | +/* |
1377 | + * Copyright (C) 2014 Canonical, Ltd. |
1378 | + * |
1379 | + * This program is free software: you can redistribute it and/or modify it under |
1380 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1381 | + * the Free Software Foundation. |
1382 | + * |
1383 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1384 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1385 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1386 | + * Lesser General Public License for more details. |
1387 | + * |
1388 | + * You should have received a copy of the GNU Lesser General Public License |
1389 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1390 | + */ |
1391 | + |
1392 | +// Process Information |
1393 | + |
1394 | +#ifndef PROC_INFO_H |
1395 | +#define PROC_INFO_H |
1396 | + |
1397 | +#include <memory> |
1398 | + |
1399 | +#include <boost/optional.hpp> |
1400 | + |
1401 | +#include <QByteArray> |
1402 | +#include <QStringList> |
1403 | + |
1404 | +class QString; |
1405 | + |
1406 | +class ProcInfo |
1407 | +{ |
1408 | +public: |
1409 | + class CommandLine |
1410 | + { |
1411 | + public: |
1412 | + QByteArray command; |
1413 | + |
1414 | + bool starts_with(const char* prefix) const; |
1415 | + boost::optional<QString> get_parameter(const char* name) const; |
1416 | + QStringList as_string_list() const; |
1417 | + }; |
1418 | + virtual std::unique_ptr<CommandLine> command_line(quint64 pid); |
1419 | + virtual ~ProcInfo(); |
1420 | +}; |
1421 | + |
1422 | +#endif |
1423 | + |
1424 | |
1425 | === modified file 'src/unity-mir/CMakeLists.txt' |
1426 | --- src/unity-mir/CMakeLists.txt 2014-02-07 16:10:12 +0000 |
1427 | +++ src/unity-mir/CMakeLists.txt 2014-02-21 16:48:46 +0000 |
1428 | @@ -74,12 +74,10 @@ |
1429 | |
1430 | ${CMAKE_THREAD_LIBS_INIT} |
1431 | |
1432 | - ${UBUNTU_PLATFORM_API_LIBRARIES} |
1433 | - ${MIRCOMMON_LIBRARIES} |
1434 | - ${MIRSERVER_LIBRARIES} |
1435 | + ${UBUNTU_PLATFORM_API_LDFLAGS} |
1436 | + ${MIRSERVER_LDFLAGS} |
1437 | ${PROTOBUF_LIBRARIES} |
1438 | - |
1439 | - boost_system |
1440 | + ${Boost_SYSTEM_LIBRARY_RELEASE} |
1441 | |
1442 | ubuntu_application_api_mirserver) |
1443 | |
1444 | |
1445 | === modified file 'tests/CMakeLists.txt' |
1446 | --- tests/CMakeLists.txt 2014-01-27 11:29:44 +0000 |
1447 | +++ tests/CMakeLists.txt 2014-02-21 16:48:46 +0000 |
1448 | @@ -20,6 +20,7 @@ |
1449 | ${CMAKE_SOURCE_DIR}/src/modules |
1450 | ${GMOCK_INCLUDE_DIR} |
1451 | ${GTEST_INCLUDE_DIR} |
1452 | + ${MIRSERVER_INCLUDE_DIRS} |
1453 | ) |
1454 | |
1455 | add_executable( |
1456 | |
1457 | === modified file 'tests/application_manager_test.cpp' |
1458 | --- tests/application_manager_test.cpp 2014-01-27 11:29:44 +0000 |
1459 | +++ tests/application_manager_test.cpp 2014-02-21 16:48:46 +0000 |
1460 | @@ -19,6 +19,7 @@ |
1461 | |
1462 | #include <Unity/Application/applicationcontroller.h> |
1463 | #include <Unity/Application/taskcontroller.h> |
1464 | +#include <Unity/Application/proc_info.h> |
1465 | |
1466 | #include <core/posix/linux/proc/process/oom_score_adj.h> |
1467 | |
1468 | @@ -29,43 +30,54 @@ |
1469 | #include "mock_desktop_file_reader.h" |
1470 | #include "mock_oom_controller.h" |
1471 | #include "mock_process_controller.h" |
1472 | - |
1473 | -TEST(ApplicationManager, SuspendingAndResumingARunningApplicationResultsInOomScoreAdjustment) |
1474 | +#include "mock_proc_info.h" |
1475 | +#include "mock_session.h" |
1476 | +#include "mock_focus_controller.h" |
1477 | + |
1478 | + |
1479 | +class ApplicationManagerTests : public ::testing::Test |
1480 | { |
1481 | - using namespace ::testing; |
1482 | - |
1483 | - const QString appId("com.canonical.does.not.exist"); |
1484 | - |
1485 | - NiceMock<testing::MockOomController> oomController; |
1486 | - QSharedPointer<ProcessController::OomController> oomControllerPtr( |
1487 | +public: |
1488 | + ApplicationManagerTests() |
1489 | + : processController{ |
1490 | + QSharedPointer<ProcessController::OomController> ( |
1491 | &oomController, |
1492 | - [](ProcessController::OomController*){}); |
1493 | - |
1494 | - NiceMock<testing::MockProcessController> processController(oomControllerPtr); |
1495 | - QSharedPointer<ProcessController> processControllerPtr( |
1496 | - &processController, |
1497 | - [](ProcessController*){}); |
1498 | - |
1499 | - NiceMock<testing::MockApplicationController> appController; |
1500 | - QSharedPointer<ApplicationController> appControllerPtr( |
1501 | - &appController, |
1502 | - [](ApplicationController*){}); |
1503 | - |
1504 | - QSharedPointer<TaskController> taskController( |
1505 | + [](ProcessController::OomController*){}) |
1506 | + }, |
1507 | + applicationManager{ |
1508 | + QSharedPointer<TaskController>{ |
1509 | new TaskController( |
1510 | nullptr, |
1511 | - appControllerPtr, |
1512 | - processControllerPtr |
1513 | - )); |
1514 | - |
1515 | - NiceMock<MockDesktopFileReaderFactory> desktopFileReaderFactory; |
1516 | - QSharedPointer<DesktopFileReader::Factory> desktopFileReaderFactoryPtr( |
1517 | + QSharedPointer<ApplicationController>( |
1518 | + &appController, |
1519 | + [](ApplicationController*){}), |
1520 | + QSharedPointer<ProcessController>( |
1521 | + &processController, |
1522 | + [](ProcessController*){}) |
1523 | + )}, |
1524 | + QSharedPointer<DesktopFileReader::Factory>( |
1525 | &desktopFileReaderFactory, |
1526 | - [](DesktopFileReader::Factory*){}); |
1527 | - |
1528 | - ApplicationManager applicationManager( |
1529 | - taskController, |
1530 | - desktopFileReaderFactoryPtr); |
1531 | + [](DesktopFileReader::Factory*){}), |
1532 | + QSharedPointer<ProcInfo>(&procInfo,[](ProcInfo *){}), |
1533 | + std::shared_ptr<mir::shell::FocusController>(&focusController, [](void*){}), |
1534 | + QSize(400,400) |
1535 | + } |
1536 | + { |
1537 | + } |
1538 | + testing::NiceMock<testing::MockOomController> oomController; |
1539 | + testing::NiceMock<testing::MockProcessController> processController; |
1540 | + testing::NiceMock<testing::MockApplicationController> appController; |
1541 | + testing::NiceMock<testing::MockProcInfo> procInfo; |
1542 | + testing::NiceMock<testing::MockDesktopFileReaderFactory> desktopFileReaderFactory; |
1543 | + testing::NiceMock<testing::MockFocusController> focusController; |
1544 | + ApplicationManager applicationManager; |
1545 | +}; |
1546 | + |
1547 | +TEST_F(ApplicationManagerTests, SuspendingAndResumingARunningApplicationResultsInOomScoreAdjustment) |
1548 | +{ |
1549 | + using namespace ::testing; |
1550 | + |
1551 | + const QString appId("com.canonical.does.not.exist"); |
1552 | |
1553 | EXPECT_CALL(appController, startApplicationWithAppIdAndArgs(_, _)).Times(1); |
1554 | |
1555 | @@ -86,43 +98,12 @@ |
1556 | } |
1557 | |
1558 | // Currently disabled as we need to make sure that we have a corresponding mir session, too. |
1559 | -TEST(ApplicationManager, DISABLED_FocusingRunningApplicationResultsInOomScoreAdjustment) |
1560 | +TEST_F(ApplicationManagerTests, DISABLED_FocusingRunningApplicationResultsInOomScoreAdjustment) |
1561 | { |
1562 | using namespace ::testing; |
1563 | |
1564 | const QString appId("com.canonical.does.not.exist"); |
1565 | |
1566 | - NiceMock<testing::MockOomController> oomController; |
1567 | - QSharedPointer<ProcessController::OomController> oomControllerPtr( |
1568 | - &oomController, |
1569 | - [](ProcessController::OomController*){}); |
1570 | - |
1571 | - NiceMock<testing::MockProcessController> processController(oomControllerPtr); |
1572 | - QSharedPointer<ProcessController> processControllerPtr( |
1573 | - &processController, |
1574 | - [](ProcessController*){}); |
1575 | - |
1576 | - NiceMock<testing::MockApplicationController> appController; |
1577 | - QSharedPointer<ApplicationController> appControllerPtr( |
1578 | - &appController, |
1579 | - [](ApplicationController*){}); |
1580 | - |
1581 | - QSharedPointer<TaskController> taskController( |
1582 | - new TaskController( |
1583 | - nullptr, |
1584 | - appControllerPtr, |
1585 | - processControllerPtr |
1586 | - )); |
1587 | - |
1588 | - NiceMock<MockDesktopFileReaderFactory> desktopFileReaderFactory; |
1589 | - QSharedPointer<DesktopFileReader::Factory> desktopFileReaderFactoryPtr( |
1590 | - &desktopFileReaderFactory, |
1591 | - [](DesktopFileReader::Factory*){}); |
1592 | - |
1593 | - ApplicationManager applicationManager( |
1594 | - taskController, |
1595 | - desktopFileReaderFactoryPtr); |
1596 | - |
1597 | QSet<QString> appIds; |
1598 | |
1599 | for (unsigned int i = 0; i < 50; i++) |
1600 | @@ -135,6 +116,9 @@ |
1601 | ApplicationManager::NoFlag, |
1602 | QStringList()); |
1603 | |
1604 | + std::shared_ptr<mir::shell::Session> mirSession = std::make_shared<MockSession>(appIdFormat.toStdString(), i); |
1605 | + applicationManager.onSessionStarting( mirSession ); |
1606 | + |
1607 | EXPECT_NE(nullptr, application); |
1608 | |
1609 | appIds.insert(appId); |
1610 | @@ -149,3 +133,141 @@ |
1611 | applicationManager.focusApplication(appId); |
1612 | } |
1613 | } |
1614 | + |
1615 | + |
1616 | +TEST_F(ApplicationManagerTests,bug_case_1240400_second_dialer_app_fails_to_authorize_and_gets_mixed_up_with_first_one) |
1617 | +{ |
1618 | + using namespace ::testing; |
1619 | + std::shared_ptr<mir::shell::Surface> aSurface(nullptr); |
1620 | + quint64 firstProcId = 5921; |
1621 | + quint64 secondProcId = 5922; |
1622 | + const char dialer_app_id[] = "dialer-app"; |
1623 | + QByteArray cmdLine( "/usr/bin/dialer-app --desktop_file_hint=dialer-app"); |
1624 | + QByteArray secondcmdLine( "/usr/bin/dialer-app"); |
1625 | + |
1626 | + EXPECT_CALL(procInfo,command_line_(firstProcId)) |
1627 | + .Times(1) |
1628 | + .WillOnce(Return(cmdLine)); |
1629 | + EXPECT_CALL(procInfo,command_line_(secondProcId)) |
1630 | + .Times(1) |
1631 | + .WillOnce(Return(secondcmdLine)); |
1632 | + |
1633 | + bool authed = true; |
1634 | + |
1635 | + std::shared_ptr<mir::shell::Session> mirSession = std::make_shared<MockSession>(dialer_app_id, firstProcId); |
1636 | + applicationManager.authorizeSession(firstProcId, authed); |
1637 | + EXPECT_EQ(true, authed); |
1638 | + applicationManager.onSessionStarting(mirSession); |
1639 | + applicationManager.onSessionCreatedSurface(mirSession.get(),aSurface); |
1640 | + Application * app = applicationManager.findApplication(dialer_app_id); |
1641 | + EXPECT_NE(nullptr,app); |
1642 | + |
1643 | + // now a second session without desktop file is launched: |
1644 | + applicationManager.authorizeSession(secondProcId, authed); |
1645 | + applicationManager.onProcessStartReportReceived(dialer_app_id, true); |
1646 | + |
1647 | + EXPECT_EQ(false,authed); |
1648 | + EXPECT_EQ(app,applicationManager.findApplication(dialer_app_id)); |
1649 | + EXPECT_EQ(QString(dialer_app_id),applicationManager.focusedApplicationId()); |
1650 | +} |
1651 | + |
1652 | +TEST_F(ApplicationManagerTests,application_dies_while_starting) |
1653 | +{ |
1654 | + using namespace ::testing; |
1655 | + quint64 procId = 5921; |
1656 | + const char app_id[] = "my-app"; |
1657 | + QByteArray cmdLine( "/usr/bin/my-app --desktop_file_hint=my-app"); |
1658 | + |
1659 | + EXPECT_CALL(procInfo,command_line_(procId)) |
1660 | + .Times(1) |
1661 | + .WillOnce(Return(cmdLine)); |
1662 | + |
1663 | + bool authed = true; |
1664 | + |
1665 | + std::shared_ptr<mir::shell::Session> mirSession = std::make_shared<MockSession>(app_id, procId); |
1666 | + applicationManager.authorizeSession(procId, authed); |
1667 | + applicationManager.onSessionStarting(mirSession); |
1668 | + Application * beforeFailure = applicationManager.findApplication(app_id); |
1669 | + applicationManager.onProcessStartReportReceived(app_id,true); |
1670 | + Application * afterFailure = applicationManager.findApplication(app_id); |
1671 | + |
1672 | + EXPECT_EQ(true, authed); |
1673 | + EXPECT_NE(nullptr, beforeFailure); |
1674 | + EXPECT_EQ(nullptr, afterFailure); |
1675 | +} |
1676 | + |
1677 | +TEST_F(ApplicationManagerTests,application_start_failure_after_starting) |
1678 | +{ |
1679 | + using namespace ::testing; |
1680 | + quint64 procId = 5921; |
1681 | + std::shared_ptr<mir::shell::Surface> aSurface(nullptr); |
1682 | + const char app_id[] = "my-app"; |
1683 | + QByteArray cmdLine( "/usr/bin/my-app --desktop_file_hint=my-app"); |
1684 | + |
1685 | + EXPECT_CALL(procInfo,command_line_(procId)) |
1686 | + .Times(1) |
1687 | + .WillOnce(Return(cmdLine)); |
1688 | + |
1689 | + bool authed = true; |
1690 | + |
1691 | + std::shared_ptr<mir::shell::Session> mirSession = std::make_shared<MockSession>(app_id, procId); |
1692 | + applicationManager.authorizeSession(procId, authed); |
1693 | + applicationManager.onSessionStarting(mirSession); |
1694 | + Application * beforeFailure = applicationManager.findApplication(app_id); |
1695 | + applicationManager.onSessionCreatedSurface(mirSession.get(), aSurface); |
1696 | + applicationManager.onProcessStartReportReceived(app_id, true); |
1697 | + Application * afterFailure = applicationManager.findApplication(app_id); |
1698 | + |
1699 | + EXPECT_EQ(true, authed); |
1700 | + EXPECT_NE(nullptr, beforeFailure); |
1701 | + EXPECT_EQ(beforeFailure, afterFailure); |
1702 | +} |
1703 | + |
1704 | +TEST_F(ApplicationManagerTests,bug_case_1281075_session_ptrs_always_distributed_to_last_started_app) |
1705 | +{ |
1706 | + using namespace ::testing; |
1707 | + quint64 first_procId = 5921; |
1708 | + quint64 second_procId = 5922; |
1709 | + quint64 third_procId = 5923; |
1710 | + std::shared_ptr<mir::shell::Surface> aSurface(nullptr); |
1711 | + const char first_app_id[] = "app1"; |
1712 | + QByteArray first_cmdLine( "/usr/bin/app1 --desktop_file_hint=app1"); |
1713 | + const char second_app_id[] = "app2"; |
1714 | + QByteArray second_cmdLine( "/usr/bin/app2--desktop_file_hint=app2"); |
1715 | + const char third_app_id[] = "app3"; |
1716 | + QByteArray third_cmdLine( "/usr/bin/app3 --desktop_file_hint=app3"); |
1717 | + |
1718 | + EXPECT_CALL(procInfo,command_line_(first_procId)) |
1719 | + .Times(1) |
1720 | + .WillOnce(Return(first_cmdLine)); |
1721 | + |
1722 | + ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); |
1723 | + |
1724 | + EXPECT_CALL(procInfo,command_line_(second_procId)) |
1725 | + .Times(1) |
1726 | + .WillOnce(Return(second_cmdLine)); |
1727 | + |
1728 | + EXPECT_CALL(procInfo,command_line_(third_procId)) |
1729 | + .Times(1) |
1730 | + .WillOnce(Return(third_cmdLine)); |
1731 | + |
1732 | + bool authed = true; |
1733 | + |
1734 | + std::shared_ptr<mir::shell::Session> first_session = std::make_shared<MockSession>("Oo", first_procId); |
1735 | + std::shared_ptr<mir::shell::Session> second_session = std::make_shared<MockSession>("oO", second_procId); |
1736 | + std::shared_ptr<mir::shell::Session> third_session = std::make_shared<MockSession>("OO", third_procId); |
1737 | + applicationManager.authorizeSession(first_procId, authed); |
1738 | + applicationManager.authorizeSession(second_procId, authed); |
1739 | + applicationManager.authorizeSession(third_procId, authed); |
1740 | + applicationManager.onSessionStarting(first_session); |
1741 | + applicationManager.onSessionStarting(third_session); |
1742 | + applicationManager.onSessionStarting(second_session); |
1743 | + |
1744 | + Application * firstApp = applicationManager.findApplication(first_app_id); |
1745 | + Application * secondApp = applicationManager.findApplication(second_app_id); |
1746 | + Application * thirdApp = applicationManager.findApplication(third_app_id); |
1747 | + |
1748 | + EXPECT_EQ(first_session, firstApp->session()); |
1749 | + EXPECT_EQ(second_session, secondApp->session()); |
1750 | + EXPECT_EQ(third_session, thirdApp->session()); |
1751 | +} |
1752 | |
1753 | === modified file 'tests/auto/modules/Unity/Application/CMakeLists.txt' |
1754 | --- tests/auto/modules/Unity/Application/CMakeLists.txt 2014-01-27 11:29:44 +0000 |
1755 | +++ tests/auto/modules/Unity/Application/CMakeLists.txt 2014-02-21 16:48:46 +0000 |
1756 | @@ -11,7 +11,7 @@ |
1757 | unity-mir-test-app |
1758 | main.cpp) |
1759 | |
1760 | -qt5_use_modules(unity-mir-test-app Test DBus Gui) |
1761 | +qt5_use_modules(unity-mir-test-app Test DBus Gui Quick) |
1762 | |
1763 | target_link_libraries( |
1764 | unity-mir-test-app |
1765 | @@ -19,8 +19,8 @@ |
1766 | unity-mir |
1767 | unityapplicationplugin |
1768 | |
1769 | - ${MIRSERVER_LIBRARIES} |
1770 | - ${UPSTART_APP_LAUNCH_LIBRARIES}) |
1771 | + ${MIRSERVER_LDFLAGS} |
1772 | + ${UPSTART_APP_LAUNCH_LDFLAGS}) |
1773 | |
1774 | install( |
1775 | TARGETS unity-mir-test-app |
1776 | |
1777 | === modified file 'tests/auto/modules/Unity/Application/main.cpp' |
1778 | --- tests/auto/modules/Unity/Application/main.cpp 2014-01-27 11:29:44 +0000 |
1779 | +++ tests/auto/modules/Unity/Application/main.cpp 2014-02-21 16:48:46 +0000 |
1780 | @@ -18,6 +18,7 @@ |
1781 | |
1782 | #include "application_manager.h" |
1783 | #include "processcontroller.h" |
1784 | +#include "proc_info.h" |
1785 | #include "taskcontroller.h" |
1786 | #include "upstart/applicationcontroller.h" |
1787 | |
1788 | @@ -44,12 +45,10 @@ |
1789 | |
1790 | void ApplicationManagerTests::testStartStop() |
1791 | { |
1792 | - QSharedPointer<upstart::ApplicationController> appController(new upstart::ApplicationController()); |
1793 | - QSharedPointer<TaskController> taskController(new TaskController(nullptr, appController)); |
1794 | - QSharedPointer<DesktopFileReader::Factory> fileReaderFactory(new DesktopFileReader::Factory()); |
1795 | + ApplicationManager::Factory appFactory; |
1796 | + QSharedPointer<ApplicationManager> manager{appFactory.create()}; |
1797 | |
1798 | - ApplicationManager manager(taskController, fileReaderFactory); |
1799 | - Application *app = manager.startApplication("unity-mir-test-helper-app", QStringList()); |
1800 | + Application *app = manager->startApplication("unity-mir-test-helper-app", QStringList()); |
1801 | QVERIFY(app); |
1802 | QCOMPARE(app->desktopFile(), QString("/usr/share/applications/unity-mir-test-helper-app.desktop")); |
1803 | QCOMPARE(app->name(), QString("My Fake App")); |
1804 | @@ -61,7 +60,7 @@ |
1805 | QString simplifiedCommand = pidCommandLine(app->pid()); |
1806 | QCOMPARE(simplifiedCommand, QString("unity-mir-test-helper-app")); |
1807 | |
1808 | - manager.stopApplication(app->appId()); |
1809 | + manager->stopApplication(app->appId()); |
1810 | |
1811 | QDir d; |
1812 | QTRY_VERIFY(!d.exists(QString("/proc/%1").arg(app->pid()))); |
1813 | |
1814 | === added file 'tests/mock_focus_controller.h' |
1815 | --- tests/mock_focus_controller.h 1970-01-01 00:00:00 +0000 |
1816 | +++ tests/mock_focus_controller.h 2014-02-21 16:48:46 +0000 |
1817 | @@ -0,0 +1,37 @@ |
1818 | +/* |
1819 | + * Copyright (C) 2014 Canonical, Ltd. |
1820 | + * |
1821 | + * This program is free software: you can redistribute it and/or modify it under |
1822 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1823 | + * the Free Software Foundation. |
1824 | + * |
1825 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1826 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1827 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1828 | + * Lesser General Public License for more details. |
1829 | + * |
1830 | + * You should have received a copy of the GNU Lesser General Public License |
1831 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1832 | + * |
1833 | + */ |
1834 | + |
1835 | +#ifndef MOCK_MIR_SHELL_FOCUS_CONTROLLER_H |
1836 | +#define MOCK_MIR_SHELL_FOCUS_CONTROLLER_H |
1837 | + |
1838 | +#include <mir/shell/focus_controller.h> |
1839 | +#include <gmock/gmock.h> |
1840 | + |
1841 | +#include <string> |
1842 | + |
1843 | +namespace testing |
1844 | +{ |
1845 | +class MockFocusController : public mir::shell::FocusController |
1846 | +{ |
1847 | +public: |
1848 | + MOCK_METHOD0(focus_next, void()); |
1849 | + MOCK_CONST_METHOD0(focussed_application, std::weak_ptr<mir::shell::Session>()); |
1850 | + MOCK_METHOD1(set_focus_to, void(std::shared_ptr<mir::shell::Session>const&)); |
1851 | +}; |
1852 | +} |
1853 | + |
1854 | +#endif // MOCK_MIR_SHELL_FOCUS_CONTROLLER_H_ |
1855 | |
1856 | === added file 'tests/mock_proc_info.h' |
1857 | --- tests/mock_proc_info.h 1970-01-01 00:00:00 +0000 |
1858 | +++ tests/mock_proc_info.h 2014-02-21 16:48:46 +0000 |
1859 | @@ -0,0 +1,37 @@ |
1860 | +/* |
1861 | + * Copyright (C) 2014 Canonical, Ltd. |
1862 | + * |
1863 | + * This program is free software: you can redistribute it and/or modify it under |
1864 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1865 | + * the Free Software Foundation. |
1866 | + * |
1867 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1868 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1869 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1870 | + * Lesser General Public License for more details. |
1871 | + * |
1872 | + * You should have received a copy of the GNU Lesser General Public License |
1873 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1874 | + * |
1875 | + */ |
1876 | + |
1877 | +#ifndef MOCK_PROC_INFO_H |
1878 | +#define MOCK_PROC_INFO_H |
1879 | + |
1880 | +#include <Unity/Application/proc_info.h> |
1881 | + |
1882 | +#include <gmock/gmock.h> |
1883 | + |
1884 | +namespace testing |
1885 | +{ |
1886 | +struct MockProcInfo : public ProcInfo |
1887 | +{ |
1888 | + MOCK_METHOD1(command_line_, QByteArray(quint64)); |
1889 | + std::unique_ptr<CommandLine> command_line(quint64 pid) |
1890 | + { |
1891 | + return std::unique_ptr<CommandLine>(new CommandLine{command_line_(pid)}); |
1892 | + } |
1893 | +}; |
1894 | +} |
1895 | + |
1896 | +#endif // MOCK_OOM_CONTROLLER_H |
1897 | |
1898 | === added file 'tests/mock_session.h' |
1899 | --- tests/mock_session.h 1970-01-01 00:00:00 +0000 |
1900 | +++ tests/mock_session.h 2014-02-21 16:48:46 +0000 |
1901 | @@ -0,0 +1,69 @@ |
1902 | +/* |
1903 | + * Copyright (C) 2014 Canonical, Ltd. |
1904 | + * |
1905 | + * This program is free software: you can redistribute it and/or modify it under |
1906 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1907 | + * the Free Software Foundation. |
1908 | + * |
1909 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1910 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1911 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1912 | + * Lesser General Public License for more details. |
1913 | + * |
1914 | + * You should have received a copy of the GNU Lesser General Public License |
1915 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1916 | + * |
1917 | + */ |
1918 | + |
1919 | +#ifndef MOCK_MIR_SHELL_SESSION_H |
1920 | +#define MOCK_MIR_SHELL_SESSION_H |
1921 | + |
1922 | +#include <mir/shell/session.h> |
1923 | +#include <mir/graphics/display_configuration.h> |
1924 | +#include <mir/shell/surface_creation_parameters.h> |
1925 | +#include <gmock/gmock.h> |
1926 | + |
1927 | +#include <string> |
1928 | + |
1929 | +namespace testing |
1930 | +{ |
1931 | +struct MockSession : public mir::shell::Session |
1932 | +{ |
1933 | + MockSession() {} |
1934 | + MockSession(std::string const& sessionName, pid_t processId) |
1935 | + : m_sessionName(sessionName), m_sessionId(processId) |
1936 | + {} |
1937 | + |
1938 | + std::string name() const override |
1939 | + { |
1940 | + return m_sessionName; |
1941 | + } |
1942 | + |
1943 | + pid_t process_id() const override |
1944 | + { |
1945 | + return m_sessionId; |
1946 | + } |
1947 | + |
1948 | + typedef mir::frontend::SurfaceId SurfaceId; |
1949 | + |
1950 | + MOCK_METHOD0(force_requests_to_complete, void()); |
1951 | + |
1952 | + MOCK_CONST_METHOD0(default_surface, std::shared_ptr<mir::shell::Surface>()); |
1953 | + MOCK_CONST_METHOD1(get_surface, std::shared_ptr<mir::frontend::Surface>(SurfaceId)); |
1954 | + |
1955 | + MOCK_METHOD1(take_snapshot, void(mir::shell::SnapshotCallback const&)); |
1956 | + MOCK_METHOD1(set_lifecycle_state, void(MirLifecycleState)); |
1957 | + MOCK_METHOD1(create_surface, SurfaceId(mir::shell::SurfaceCreationParameters const&)); |
1958 | + MOCK_METHOD1(destroy_surface, void (SurfaceId)); |
1959 | + |
1960 | + MOCK_METHOD0(hide, void()); |
1961 | + MOCK_METHOD0(show, void()); |
1962 | + MOCK_METHOD1(send_display_config, void(mir::graphics::DisplayConfiguration const&)); |
1963 | + MOCK_METHOD3(configure_surface, int(SurfaceId, MirSurfaceAttrib, int)); |
1964 | +private: |
1965 | + std::string m_sessionName; |
1966 | + pid_t m_sessionId; |
1967 | +}; |
1968 | +} |
1969 | + |
1970 | +#endif // MOCK_MIR_SHELL_SESSION_H |