Merge lp:~ricmm/unity-mir/extend_lifecycle_mir into lp:unity-mir
- extend_lifecycle_mir
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Gerry Boland |
Approved revision: | 53 |
Merged at revision: | 62 |
Proposed branch: | lp:~ricmm/unity-mir/extend_lifecycle_mir |
Merge into: | lp:unity-mir |
Diff against target: |
492 lines (+244/-16) 9 files modified
src/modules/Unity/ApplicationManager/ApplicationManager.pro (+4/-2) src/modules/Unity/ApplicationManager/application.cpp (+64/-2) src/modules/Unity/ApplicationManager/application.h (+14/-2) src/modules/Unity/ApplicationManager/application_list_model.cpp (+9/-0) src/modules/Unity/ApplicationManager/application_list_model.h (+1/-0) src/modules/Unity/ApplicationManager/application_manager.cpp (+52/-9) src/modules/Unity/ApplicationManager/application_manager.h (+4/-1) src/modules/Unity/ApplicationManager/taskcontroller.cpp (+57/-0) src/modules/Unity/ApplicationManager/taskcontroller.h (+39/-0) |
To merge this branch: | bzr merge lp:~ricmm/unity-mir/extend_lifecycle_mir |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gerry Boland (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Albert Astals Cid (community) | Needs Fixing | ||
Review via email:
|
Commit message
* Add TaskController class for lower level process control
* Extend Application states to support the full lifecycle model
* Implement respawning applications (Stopped state) as part of the AppMgr
* Implement delayed process suspension
* Fix FTBFS due to Mir API change (SurfacePlaceme
Description of the change
- 44. By Ricardo Mendoza
-
Set application to Running when it is actually focused, not when it has created its surfaces
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:44
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 45. By Ricardo Mendoza
-
merge trunk
- 46. By Ricardo Mendoza
-
Add missing files
- 47. By Ricardo Mendoza
-
Remove irrelevant file
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:47
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
src/unity-
QTimer:
looks dangerous, what if the application gets back to Running state before those 3000 ms? You should stop the timer, in that case, shouldn't you?
the debug log in ApplicationList
May make sense to abstract the qprocess code into a function so both startProcess and respawnProcess use it?
I don't understand why you moved m_mainStageAppl
QStringList arguments -> const QStringList &arguments
79 + }
80 + else if (m_state == Application:
looks like needs going one line up
Probably you don't need these includes in the header
454 +#include "application_
455 +#include "mircommon/
456 +#include <mir/shell/
If you are going to ApplicationManager* appMgr = static_
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
QTimer:
Yep, it is risky. What if you switch to away from the app, then switch back to it, then switch away, all within 2900ms. Then app only gets 100ms before is frozen.
I would not bother abstracting the QProcess code just yet, as it will be replaced by upstart launch code soon, and that will provide the refactoring.
- 48. By Ricardo Mendoza
-
Dont use a singleShot timer, instead keep track of the timer object
- 49. By Ricardo Mendoza
-
Merge trunk
- 50. By Ricardo Mendoza
-
Build errors
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:50
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
You're still not stopping the timer, if application is set to running again, or if application stops while timer is running. So add
m_suspendTimer-
Albert has a few comments too, can you address those please.
- 51. By Ricardo Mendoza
-
* Fix logging in list model
* Make TaskController parent more explicitly typed
* Fix argument passing in application ctor
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:51
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
As Gerry says it seems that you never stop the timer, i.e. m_suspendTimer-
Also the timer should be probably set to singleshot not to suspend it every 3 seconds
- 52. By Ricardo Mendoza
-
Stop timer if caught active when transitioning to the Stopped state
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:52
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 53. By Ricardo Mendoza
-
Make timer single shot
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
Ok, looks good enough to me, it's a bit "brain hard" to realize we don't need the stop in Running because when the timer triggers it'll be ignored, it's also a bit of "a waste" of resources to have the timer running if we're not going to use it, but oh well :D
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:53
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gerry Boland (gerboland) wrote : | # |
Looks good to me, approving
Preview Diff
1 | === modified file 'src/modules/Unity/ApplicationManager/ApplicationManager.pro' |
2 | --- src/modules/Unity/ApplicationManager/ApplicationManager.pro 2013-08-21 09:36:24 +0000 |
3 | +++ src/modules/Unity/ApplicationManager/ApplicationManager.pro 2013-08-27 14:37:14 +0000 |
4 | @@ -23,14 +23,16 @@ |
5 | desktopfilereader.cpp \ |
6 | plugin.cpp \ |
7 | applicationscreenshotprovider.cpp \ |
8 | - dbuswindowstack.cpp |
9 | + dbuswindowstack.cpp \ |
10 | + taskcontroller.cpp |
11 | |
12 | HEADERS += application_manager.h \ |
13 | application.h \ |
14 | application_list_model.h \ |
15 | desktopfilereader.h \ |
16 | applicationscreenshotprovider.h \ |
17 | - dbuswindowstack.h |
18 | + dbuswindowstack.h \ |
19 | + taskcontroller.h |
20 | |
21 | installPath = $$[QT_INSTALL_IMPORTS]/$$replace(uri, \\., /) |
22 | |
23 | |
24 | === modified file 'src/modules/Unity/ApplicationManager/application.cpp' |
25 | --- src/modules/Unity/ApplicationManager/application.cpp 2013-08-16 15:54:51 +0000 |
26 | +++ src/modules/Unity/ApplicationManager/application.cpp 2013-08-27 14:37:14 +0000 |
27 | @@ -26,17 +26,24 @@ |
28 | #include <mir/shell/application_session.h> |
29 | |
30 | Application::Application(DesktopFileReader* desktopData, qint64 pid, |
31 | - Application::Stage stage, Application::State state) |
32 | + Application::Stage stage, Application::State state, |
33 | + const QStringList& arguments, TaskController* taskController) |
34 | : m_desktopData(desktopData) |
35 | , m_pid(pid) |
36 | , m_stage(stage) |
37 | , m_state(state) |
38 | , m_focus(false) |
39 | , m_fullscreen(false) |
40 | + , m_arguments(arguments) |
41 | + , m_taskController(taskController) |
42 | + , m_suspendTimer(new QTimer(this)) |
43 | { |
44 | DASSERT(desktopData != NULL); |
45 | DLOG("Application::Application (this=%p, desktopData=%p, pid=%lld, stage=%d, state=%d", |
46 | this, desktopData, pid, static_cast<int>(stage), static_cast<int>(state)); |
47 | + |
48 | + m_suspendTimer->setSingleShot(true); |
49 | + connect(m_suspendTimer, SIGNAL(timeout()), this, SLOT(suspend())); |
50 | } |
51 | |
52 | Application::~Application() |
53 | @@ -100,6 +107,16 @@ |
54 | return m_session; |
55 | } |
56 | |
57 | +pid_t Application::pid() const |
58 | +{ |
59 | + return m_pid; |
60 | +} |
61 | + |
62 | +void Application::setPid(pid_t pid) |
63 | +{ |
64 | + m_pid = pid; |
65 | +} |
66 | + |
67 | void Application::setSession(const std::shared_ptr<mir::shell::ApplicationSession>& session) |
68 | { |
69 | // TODO(greyback) what if called with new surface? |
70 | @@ -129,7 +146,31 @@ |
71 | { |
72 | DLOG("Application::setState (this=%p, state=%d)", this, static_cast<int>(state)); |
73 | if (m_state != state) { |
74 | - m_state = state; |
75 | + switch (state) |
76 | + { |
77 | + case Application::Suspended: |
78 | + if (m_state == Application::Running) { |
79 | + session()->set_lifecycle_state(mir_lifecycle_state_will_suspend); |
80 | + m_suspendTimer->start(3000); |
81 | + } |
82 | + break; |
83 | + case Application::Running: |
84 | + if (m_state == Application::Suspended) { |
85 | + resume(); |
86 | + session()->set_lifecycle_state(mir_lifecycle_state_resumed); |
87 | + } else if (m_state == Application::Stopped) { |
88 | + respawn(); |
89 | + state = Application::Starting; |
90 | + } |
91 | + break; |
92 | + case Application::Stopped: |
93 | + if (m_suspendTimer->isActive()) |
94 | + m_suspendTimer->stop(); |
95 | + break; |
96 | + default: |
97 | + break; |
98 | + } |
99 | + m_state = state; |
100 | emit stateChanged(); |
101 | } |
102 | } |
103 | @@ -151,3 +192,24 @@ |
104 | emit fullscreenChanged(); |
105 | } |
106 | } |
107 | + |
108 | +void Application::suspend() |
109 | +{ |
110 | + DLOG("Application::suspend (this=%p)", this); |
111 | + |
112 | + m_taskController->do_suspend(this); |
113 | +} |
114 | + |
115 | +void Application::resume() |
116 | +{ |
117 | + DLOG("Application::resume (this=%p)", this); |
118 | + |
119 | + m_taskController->do_resume(this); |
120 | +} |
121 | + |
122 | +void Application::respawn() |
123 | +{ |
124 | + DLOG("Application::respawn (this=%p)", this); |
125 | + |
126 | + m_taskController->do_respawn(this); |
127 | +} |
128 | |
129 | === modified file 'src/modules/Unity/ApplicationManager/application.h' |
130 | --- src/modules/Unity/ApplicationManager/application.h 2013-08-14 14:24:17 +0000 |
131 | +++ src/modules/Unity/ApplicationManager/application.h 2013-08-27 14:37:14 +0000 |
132 | @@ -29,6 +29,7 @@ |
133 | |
134 | class QImage; |
135 | class DesktopFileReader; |
136 | +class TaskController; |
137 | namespace mir { namespace shell { class ApplicationSession; }} |
138 | |
139 | class Application : public QObject { |
140 | @@ -48,9 +49,9 @@ |
141 | |
142 | public: |
143 | enum Stage { MainStage, SideStage }; |
144 | - enum State { Starting, Running }; |
145 | + enum State { Starting, Running, Suspended, Stopped }; |
146 | |
147 | - Application(DesktopFileReader* desktopData, qint64 pid, Stage stage, State state); |
148 | + Application(DesktopFileReader* desktopData, qint64 pid, Stage stage, State state, const QStringList& arguments, TaskController* taskController); |
149 | ~Application(); |
150 | |
151 | QString desktopFile() const; |
152 | @@ -65,6 +66,11 @@ |
153 | bool fullscreen() const; |
154 | std::shared_ptr<mir::shell::ApplicationSession> session() const; |
155 | |
156 | +public slots: |
157 | + void suspend(); |
158 | + void resume(); |
159 | + void respawn(); |
160 | + |
161 | Q_SIGNALS: |
162 | void stageChanged(); |
163 | void stateChanged(); |
164 | @@ -72,6 +78,8 @@ |
165 | void fullscreenChanged(); |
166 | |
167 | private: |
168 | + pid_t pid() const; |
169 | + void setPid(pid_t pid); |
170 | void setStage(Stage stage); |
171 | void setState(State state); |
172 | void setFocus(bool focus); |
173 | @@ -87,7 +95,11 @@ |
174 | bool m_fullscreen; |
175 | std::shared_ptr<mir::shell::ApplicationSession> m_session; |
176 | QString m_sessionName; |
177 | + QStringList m_arguments; |
178 | + TaskController* m_taskController; |
179 | + QTimer* m_suspendTimer; |
180 | |
181 | + friend class TaskController; |
182 | friend class ApplicationManager; |
183 | friend class ApplicationListModel; |
184 | }; |
185 | |
186 | === modified file 'src/modules/Unity/ApplicationManager/application_list_model.cpp' |
187 | --- src/modules/Unity/ApplicationManager/application_list_model.cpp 2013-08-15 15:37:00 +0000 |
188 | +++ src/modules/Unity/ApplicationManager/application_list_model.cpp 2013-08-27 14:37:14 +0000 |
189 | @@ -64,6 +64,15 @@ |
190 | return data(index(row), 0); |
191 | } |
192 | |
193 | +int ApplicationListModel::indexOf(Application* application) const |
194 | +{ |
195 | + DASSERT(application != NULL); |
196 | + DLOG("ApplicationListModel::indexOf (this=%p, application='%s')", this, |
197 | + application->name().toLatin1().data()); |
198 | + |
199 | + return m_applications.indexOf(application); |
200 | +} |
201 | + |
202 | void ApplicationListModel::move(int from, int to) |
203 | { |
204 | DLOG("ApplicationListModel::move (this=%p, from=%d, to=%d)", this, from, to); |
205 | |
206 | === modified file 'src/modules/Unity/ApplicationManager/application_list_model.h' |
207 | --- src/modules/Unity/ApplicationManager/application_list_model.h 2013-08-14 14:24:17 +0000 |
208 | +++ src/modules/Unity/ApplicationManager/application_list_model.h 2013-08-27 14:37:14 +0000 |
209 | @@ -37,6 +37,7 @@ |
210 | int rowCount(const QModelIndex& parent = QModelIndex()) const; |
211 | QVariant data(const QModelIndex& index, int role) const; |
212 | QHash<int,QByteArray> roleNames() const { return m_roleNames; } |
213 | + int indexOf(Application* application) const; |
214 | Q_INVOKABLE QVariant get(int index) const; |
215 | Q_INVOKABLE void move(int from, int to); |
216 | |
217 | |
218 | === modified file 'src/modules/Unity/ApplicationManager/application_manager.cpp' |
219 | --- src/modules/Unity/ApplicationManager/application_manager.cpp 2013-08-23 17:26:40 +0000 |
220 | +++ src/modules/Unity/ApplicationManager/application_manager.cpp 2013-08-27 14:37:14 +0000 |
221 | @@ -75,6 +75,7 @@ |
222 | qsrand(QTime::currentTime().msec()); |
223 | |
224 | m_dbusWindowStack = new DBusWindowStack(this); |
225 | + m_taskController = new TaskController(this); |
226 | } |
227 | |
228 | ApplicationManager::~ApplicationManager() |
229 | @@ -120,6 +121,40 @@ |
230 | m_mirServer->the_session_manager()->set_focus_to(NULL); //FIXME(greyback) |
231 | } |
232 | |
233 | +Application* ApplicationManager::respawnApplication(Application* application) |
234 | +{ |
235 | + DLOG("ApplicationManager::respawnApplication(this=%p, application=%p)", this, application); |
236 | + |
237 | + // Start process - set correct environment |
238 | + setenv("QT_QPA_PLATFORM", "ubuntumirclient", 1); |
239 | + |
240 | + bool result; |
241 | + qint64 pid = 0; |
242 | + struct passwd* passwd = getpwuid(getuid()); |
243 | + DLOG("current working directory: '%s' - args='%s'", passwd ? passwd->pw_dir : "/", application->m_arguments.join(' ').toLatin1().data()); |
244 | + QProcess builder; |
245 | + builder.setProcessChannelMode(QProcess::ForwardedChannels); |
246 | + QString exec(application->m_arguments[0]); |
247 | + application->m_arguments.removeFirst(); |
248 | + result = builder.startDetached(exec, application->m_arguments, QString(passwd ? passwd->pw_dir : "/"), &pid); |
249 | + application->m_arguments.prepend(exec); |
250 | + DLOG_IF(result == false, "process failed to start"); |
251 | + if (result) { |
252 | + // Set existing application's pid to new instance |
253 | + application->setPid(pid); |
254 | + |
255 | + // Push to front |
256 | + if (m_mainStageApplications->rowCount() > 1) |
257 | + m_mainStageApplications->move(m_mainStageApplications->indexOf(application), 0); |
258 | + |
259 | + DLOG("builder '%s' respawned with pid %lld", application->name().toLatin1().data(), pid); |
260 | + return application; |
261 | + } else { |
262 | + DLOG("builder '%s' failed to respawn", application->name().toLatin1().data()); |
263 | + return NULL; |
264 | + } |
265 | +} |
266 | + |
267 | Application* ApplicationManager::startProcess(QString desktopFile, ApplicationManager::ExecFlags flags, |
268 | QStringList arguments) |
269 | { |
270 | @@ -191,18 +226,23 @@ |
271 | path = passwd->pw_dir; |
272 | } |
273 | DLOG("current working directory: '%s'", path.toLatin1().data()); |
274 | - result = QProcess::startDetached(exec, arguments, path, &pid); |
275 | + QProcess builder; |
276 | + builder.setProcessChannelMode(QProcess::ForwardedChannels); |
277 | + result = builder.startDetached(exec, arguments, path, &pid); |
278 | + |
279 | DLOG_IF(result == false, "process failed to start"); |
280 | if (result) { |
281 | #endif |
282 | - |
283 | DLOG("process started with pid %lld, adding '%s' to application lists", pid, desktopData->name().toLatin1().data()); |
284 | + arguments.prepend(exec); |
285 | Application* application = new Application( |
286 | desktopData, pid, |
287 | (flags.testFlag(ApplicationManager::ForceMainStage) |
288 | || desktopData->stageHint() != "SideStage") |
289 | ? Application::MainStage : Application::SideStage, |
290 | - Application::Starting //FIXME(greyback): assuming running immediately |
291 | + Application::Starting, //FIXME(greyback): assuming running immediately |
292 | + arguments, |
293 | + m_taskController |
294 | ); |
295 | |
296 | m_mainStageApplications->add(application); |
297 | @@ -319,7 +359,10 @@ |
298 | } |
299 | |
300 | DLOG("Existing process with pid %lld appeared, adding '%s' to application lists", pid, desktopData->name().toLatin1().data()); |
301 | - application = new Application(desktopData, pid, stage, Application::Starting); |
302 | + |
303 | + QString argStr(command.data()); |
304 | + QStringList arguments(argStr.split(' ')); |
305 | + application = new Application(desktopData, pid, stage, Application::Starting, arguments, m_taskController); |
306 | m_mainStageApplications->add(application); |
307 | authorized = true; |
308 | } |
309 | @@ -348,9 +391,10 @@ |
310 | if (application == m_mainStageFocusedApplication) { |
311 | // TODO(greyback) What to do?? Focus next app, or unfocus everything?? |
312 | m_mainStageFocusedApplication = NULL; |
313 | + m_mainStageApplications->remove(application); |
314 | Q_EMIT mainStageFocusedApplicationChanged(); |
315 | } |
316 | - m_mainStageApplications->remove(application); |
317 | + application->setState(Application::Stopped); |
318 | m_dbusWindowStack->WindowDestroyed(0, application->name()); |
319 | } |
320 | } |
321 | @@ -359,7 +403,7 @@ |
322 | { |
323 | DLOG("ApplicationManager::sessionFocused (this=%p, application=%s)", this, session->name().c_str()); |
324 | Application* application = m_mainStageApplications->getApplicationWithSession(session); |
325 | - |
326 | + |
327 | // Don't give application focus until it has created it's surface, when it is set as state "Running" |
328 | if (application && application->state() != Application::Starting |
329 | && application != m_mainStageFocusedApplication) { |
330 | @@ -372,6 +416,7 @@ |
331 | DLOG("ApplicationManager::sessionUnfocused (this=%p)", this); |
332 | if (NULL != m_mainStageFocusedApplication) { |
333 | m_mainStageFocusedApplication->setFocus(false); |
334 | + m_mainStageFocusedApplication->setState(Application::Suspended); |
335 | m_mainStageFocusedApplication = NULL; |
336 | Q_EMIT mainStageFocusedApplicationChanged(); |
337 | m_dbusWindowStack->FocusedWindowChanged(0, QString(), 0); |
338 | @@ -386,10 +431,7 @@ |
339 | |
340 | Application* application = m_mainStageApplications->getApplicationWithSession(session); |
341 | if (application && application->state() == Application::Starting) { |
342 | - application->setState(Application::Running); |
343 | - |
344 | m_dbusWindowStack->WindowCreated(0, application->name()); |
345 | - |
346 | // only when Session creates a Surface will we actually mark it focused |
347 | setFocused(application); |
348 | } |
349 | @@ -399,6 +441,7 @@ |
350 | { |
351 | m_mainStageFocusedApplication = application; |
352 | m_mainStageFocusedApplication->setFocus(true); |
353 | + m_mainStageFocusedApplication->setState(Application::Running); |
354 | Q_EMIT mainStageFocusedApplicationChanged(); |
355 | m_dbusWindowStack->FocusedWindowChanged(0, application->name(), application->stage()); |
356 | } |
357 | |
358 | === modified file 'src/modules/Unity/ApplicationManager/application_manager.h' |
359 | --- src/modules/Unity/ApplicationManager/application_manager.h 2013-08-15 18:10:19 +0000 |
360 | +++ src/modules/Unity/ApplicationManager/application_manager.h 2013-08-27 14:37:14 +0000 |
361 | @@ -24,7 +24,7 @@ |
362 | #include <QObject> |
363 | #include <QStringList> |
364 | |
365 | -#include "application.h" |
366 | +#include "taskcontroller.h" |
367 | #include "application_list_model.h" |
368 | |
369 | class ShellServerConfiguration; |
370 | @@ -102,13 +102,16 @@ |
371 | |
372 | private: |
373 | void setFocused(Application *application); |
374 | + Application* respawnApplication(Application* application); |
375 | |
376 | ApplicationListModel* m_mainStageApplications; |
377 | Application* m_mainStageFocusedApplication; // remove as Mir has API for this |
378 | ShellServerConfiguration* m_mirServer; |
379 | DBusWindowStack* m_dbusWindowStack; |
380 | + TaskController* m_taskController; |
381 | |
382 | friend class DBusWindowStack; |
383 | + friend class TaskController; |
384 | }; |
385 | |
386 | Q_DECLARE_OPERATORS_FOR_FLAGS(ApplicationManager::ExecFlags) |
387 | |
388 | === added file 'src/modules/Unity/ApplicationManager/taskcontroller.cpp' |
389 | --- src/modules/Unity/ApplicationManager/taskcontroller.cpp 1970-01-01 00:00:00 +0000 |
390 | +++ src/modules/Unity/ApplicationManager/taskcontroller.cpp 2013-08-27 14:37:14 +0000 |
391 | @@ -0,0 +1,57 @@ |
392 | +/* |
393 | + * Copyright (C) 2013 Canonical, Ltd. |
394 | + * |
395 | + * This program is free software: you can redistribute it and/or modify it under |
396 | + * the terms of the GNU Lesser General Public License version 3, as published by |
397 | + * the Free Software Foundation. |
398 | + * |
399 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
400 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
401 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
402 | + * Lesser General Public License for more details. |
403 | + * |
404 | + * You should have received a copy of the GNU Lesser General Public License |
405 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
406 | + * |
407 | + * Authored by: Ricardo Mendoza <ricardo.mendoza@canonical.com> |
408 | + */ |
409 | + |
410 | +#include "logging.h" |
411 | +#include "taskcontroller.h" |
412 | +#include "application_manager.h" |
413 | +#include <signal.h> |
414 | +#include <unistd.h> |
415 | + |
416 | +TaskController::TaskController(ApplicationManager *parent) : |
417 | + QObject(parent) |
418 | +{ |
419 | + DLOG("TaskController::TaskController (this=%p)", this); |
420 | +} |
421 | + |
422 | +TaskController::~TaskController() |
423 | +{ |
424 | + DLOG("TaskController::~TaskController (this=%p)", this); |
425 | +} |
426 | + |
427 | +void TaskController::do_suspend(Application* application) |
428 | +{ |
429 | + DLOG("TaskController::do_suspend (this=%p, application=%p)", this, application); |
430 | + if (application->state() == Application::Suspended) |
431 | + kill(application->pid(), SIGSTOP); |
432 | +} |
433 | + |
434 | +void TaskController::do_resume(Application* application) |
435 | +{ |
436 | + DLOG("TaskController::do_resume (this=%p, application=%p)", this, application); |
437 | + if (application->state() == Application::Suspended) |
438 | + kill(application->pid(), SIGCONT); |
439 | +} |
440 | + |
441 | +void TaskController::do_respawn(Application* application) |
442 | +{ |
443 | + DLOG("TaskController::do_respwn (this=%p, application=%p)", this, application); |
444 | + if (application->state() == Application::Stopped) { |
445 | + ApplicationManager *appMgr = static_cast<ApplicationManager*>(parent()); |
446 | + appMgr->respawnApplication(application); |
447 | + } |
448 | +} |
449 | |
450 | === added file 'src/modules/Unity/ApplicationManager/taskcontroller.h' |
451 | --- src/modules/Unity/ApplicationManager/taskcontroller.h 1970-01-01 00:00:00 +0000 |
452 | +++ src/modules/Unity/ApplicationManager/taskcontroller.h 2013-08-27 14:37:14 +0000 |
453 | @@ -0,0 +1,39 @@ |
454 | +/* |
455 | + * Copyright (C) 2013 Canonical, Ltd. |
456 | + * |
457 | + * This program is free software: you can redistribute it and/or modify it under |
458 | + * the terms of the GNU Lesser General Public License version 3, as published by |
459 | + * the Free Software Foundation. |
460 | + * |
461 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
462 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
463 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
464 | + * Lesser General Public License for more details. |
465 | + * |
466 | + * You should have received a copy of the GNU Lesser General Public License |
467 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
468 | + * |
469 | + * Authored by: Ricardo Mendoza <ricardo.mendoza@canonical.com> |
470 | + */ |
471 | + |
472 | +#ifndef TASKCONTROLLER_H |
473 | +#define TASKCONTROLLER_H |
474 | + |
475 | +#include <QObject> |
476 | + |
477 | +#include "application.h" |
478 | + |
479 | +class ApplicationManager; |
480 | +class TaskController : public QObject |
481 | +{ |
482 | + Q_OBJECT |
483 | +public: |
484 | + explicit TaskController(ApplicationManager* parent); |
485 | + ~TaskController(); |
486 | + |
487 | + void do_resume(Application* application); |
488 | + void do_suspend(Application* application); |
489 | + void do_respawn(Application* application); |
490 | +}; |
491 | + |
492 | +#endif // TASKCONTROLLER_H |
FAILED: Continuous integration, rev:43 jenkins. qa.ubuntu. com/job/ unity-mir- ci/20/ jenkins. qa.ubuntu. com/job/ unity-mir- saucy-armhf- ci/20/console jenkins. qa.ubuntu. com/job/ unity-mir- saucy-i386- ci/20/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ unity-mir- ci/20/rebuild
http://