Merge lp:~dandrader/qtmir/multiSessionApp into lp:qtmir
- multiSessionApp
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Gerry Boland |
Approved revision: | 639 |
Merged at revision: | 638 |
Proposed branch: | lp:~dandrader/qtmir/multiSessionApp |
Merge into: | lp:qtmir |
Diff against target: |
1193 lines (+292/-239) 9 files modified
src/modules/Unity/Application/application.cpp (+146/-90) src/modules/Unity/Application/application.h (+12/-13) src/modules/Unity/Application/application_manager.cpp (+29/-58) src/modules/Unity/Application/application_manager.h (+3/-7) src/modules/Unity/Application/dbusfocusinfo.cpp (+28/-25) src/modules/Unity/Application/session.cpp (+1/-1) src/modules/Unity/Application/session_interface.h (+6/-5) tests/modules/Application/application_test.cpp (+15/-15) tests/modules/ApplicationManager/application_manager_test.cpp (+52/-25) |
To merge this branch: | bzr merge lp:~dandrader/qtmir/multiSessionApp |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Sawicz | Approve | ||
Gerry Boland (community) | Approve | ||
Unity8 CI Bot (community) | continuous-integration | Approve | |
Review via email: mp+321581@code.launchpad.net |
Commit message
Support multiple sessions per Application
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Gerry Boland (gerboland) wrote : | # |
+ if (session->state() > combinedState) {
+ combinedState = session->state();
+ }
I guess this is as good a "combined" state as any.
The code, you're using the convenience to the order of the states in its enum? Strikes me as something easily broken in future - but I'm glad to see you've added a comment to make that less likely.
+void Application::die()
terminate() would match the "kill" term
Going from memory, the setApplicationPid stuff was a workaround for supporting apps that are not launched via UAL - we had to save the pid we got from Mir. Are apps launched with desktop_file_hint still working?
How are you testing this? I made this simple client which might be handy: git clone -b multiple-
Is moving the InitialSurfaceSize calls into the Application required for this MP?
Daniel d'Andrada (dandrader) wrote : | # |
On 31/03/2017 13:26, Gerry Boland wrote:
> +void Application::die()
> terminate() would match the "kill" term
Ok. Renamed.
> Going from memory, the setApplicationPid stuff was a workaround for supporting apps that are not launched via UAL - we had to save the pid we got from Mir. Are apps launched with desktop_file_hint still working?
Ooops! You're right. Being able to remove this bookkeeping of pids from
ApplicationManager was too good to be true.
Fixed.
> How are you testing this? I made this simple client which might be handy: git clone -b multiple-
That's not handy. Launching some random app from the application drawer
is handy. I tried with nautilus and mahjongg.
As a general rule: try to launch some apps from the app drawer without
this patch. You should get endless splash screens for them. Then install
this patch and try the same ones again. They should now work.
You can also add debug-level logging to surface and application
categories and check in unity8.log that such applications are indeed
getting *3* separate mir sessions each (at least the gtk ones I checked).
> Is moving the InitialSurfaceSize calls into the Application required for this MP?
That was how things were being done before the latest landing (had the
patch ready) and that sure is simpler as well as the application has
many sessions and thus entries in that InitialSurfaceSize singleton.
Application knows his own pids and his own initialSurfaceSize. So it can
update InitialSurfaceSize on his own. No need to involve
ApplicationManager in that. Don't know what you gain from it.
Furthermore, ApplicationManager no longer keeps tracks of all pids going
around. It just momentarily holds them between the moment a session is
authorized and the moment it shows up to be assigned to an Application
object.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:638
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:639
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Gerry Boland (gerboland) wrote : | # |
Ok, this does improve the situation a lot.
Gerry Boland (gerboland) wrote : | # |
<bregma> Saviq, the first way to test the multiple-connection situation would probably be to create a custom .desktop file that removes GDK_BACKEND from the app's environment, which will force it to autoprobe and use Mir instead
Saviq tried this and got http://
Gerry Boland (gerboland) wrote : | # |
Still fixes the main thing, will keep
Michał Sawicz (saviq) wrote : | # |
Sorry, apparently GTK_BACKEND="" is incorrect, ="*" or unsetting it altogether showed GTK apps launch fine.
Preview Diff
1 | === modified file 'src/modules/Unity/Application/application.cpp' | |||
2 | --- src/modules/Unity/Application/application.cpp 2017-03-28 17:12:03 +0000 | |||
3 | +++ src/modules/Unity/Application/application.cpp 2017-03-31 21:11:21 +0000 | |||
4 | @@ -28,10 +28,14 @@ | |||
5 | 28 | 28 | ||
6 | 29 | // QPA mirserver | 29 | // QPA mirserver |
7 | 30 | #include "logging.h" | 30 | #include "logging.h" |
8 | 31 | #include "initialsurfacesizes.h" | ||
9 | 31 | 32 | ||
10 | 32 | // Unity API | 33 | // Unity API |
11 | 33 | #include <unity/shell/application/MirSurfaceInterface.h> | 34 | #include <unity/shell/application/MirSurfaceInterface.h> |
12 | 34 | 35 | ||
13 | 36 | // std | ||
14 | 37 | #include <csignal> | ||
15 | 38 | |||
16 | 35 | namespace unityapp = unity::shell::application; | 39 | namespace unityapp = unity::shell::application; |
17 | 36 | 40 | ||
18 | 37 | #define DEBUG_MSG qCDebug(QTMIR_APPLICATIONS).nospace() << "Application[" << appId() <<"]::" << __func__ | 41 | #define DEBUG_MSG qCDebug(QTMIR_APPLICATIONS).nospace() << "Application[" << appId() <<"]::" << __func__ |
19 | @@ -50,12 +54,10 @@ | |||
20 | 50 | , m_supportedStages(Application::MainStage|Application::SideStage) | 54 | , m_supportedStages(Application::MainStage|Application::SideStage) |
21 | 51 | , m_state(InternalState::Starting) | 55 | , m_state(InternalState::Starting) |
22 | 52 | , m_arguments(arguments) | 56 | , m_arguments(arguments) |
23 | 53 | , m_session(nullptr) | ||
24 | 54 | , m_requestedState(RequestedRunning) | 57 | , m_requestedState(RequestedRunning) |
25 | 55 | , m_processState(ProcessUnknown) | 58 | , m_processState(ProcessUnknown) |
26 | 56 | , m_stopTimer(nullptr) | 59 | , m_stopTimer(nullptr) |
27 | 57 | , m_exemptFromLifecycle(false) | 60 | , m_exemptFromLifecycle(false) |
28 | 58 | , m_proxySurfaceList(new ProxySurfaceListModel(this)) | ||
29 | 59 | , m_proxyPromptSurfaceList(new ProxySurfaceListModel(this)) | 61 | , m_proxyPromptSurfaceList(new ProxySurfaceListModel(this)) |
30 | 60 | { | 62 | { |
31 | 61 | INFO_MSG << "()"; | 63 | INFO_MSG << "()"; |
32 | @@ -69,7 +71,7 @@ | |||
33 | 69 | 71 | ||
34 | 70 | setStopTimer(new Timer); | 72 | setStopTimer(new Timer); |
35 | 71 | 73 | ||
37 | 72 | connect(m_proxySurfaceList, &unityapp::MirSurfaceListInterface::countChanged, this, &unityapp::ApplicationInfoInterface::surfaceCountChanged); | 74 | connect(&m_surfaceList, &unityapp::MirSurfaceListInterface::countChanged, this, &unityapp::ApplicationInfoInterface::surfaceCountChanged); |
38 | 73 | } | 75 | } |
39 | 74 | 76 | ||
40 | 75 | Application::~Application() | 77 | Application::~Application() |
41 | @@ -100,10 +102,11 @@ | |||
42 | 100 | break; | 102 | break; |
43 | 101 | } | 103 | } |
44 | 102 | 104 | ||
48 | 103 | if (m_session) { | 105 | for (SessionInterface *session : m_sessions) { |
49 | 104 | m_session->setApplication(nullptr); | 106 | session->setApplication(nullptr); |
50 | 105 | delete m_session; | 107 | delete session; |
51 | 106 | } | 108 | } |
52 | 109 | m_sessions.clear(); | ||
53 | 107 | 110 | ||
54 | 108 | delete m_stopTimer; | 111 | delete m_stopTimer; |
55 | 109 | } | 112 | } |
56 | @@ -281,20 +284,22 @@ | |||
57 | 281 | 284 | ||
58 | 282 | void Application::updateState() | 285 | void Application::updateState() |
59 | 283 | { | 286 | { |
61 | 284 | if ((!m_session && m_state != InternalState::Starting && m_state != InternalState::StoppedResumable) | 287 | SessionInterface *singleSession = m_sessions.count() == 1 ? m_sessions[0] : nullptr; |
62 | 288 | |||
63 | 289 | if ((m_sessions.isEmpty() && m_state != InternalState::Starting && m_state != InternalState::StoppedResumable) | ||
64 | 285 | || | 290 | || |
66 | 286 | (m_session && m_session->surfaceList()->isEmpty() && m_session->hasClosingSurfaces())) { | 291 | (singleSession && singleSession->surfaceList()->isEmpty() && singleSession->hasClosingSurfaces())) { |
67 | 287 | // As we might not be able to go to Closing state right now (eg, SuspendingWaitProcess), | 292 | // As we might not be able to go to Closing state right now (eg, SuspendingWaitProcess), |
68 | 288 | // store the intent in a separate variable. | 293 | // store the intent in a separate variable. |
69 | 289 | m_closing = true; | 294 | m_closing = true; |
70 | 290 | } | 295 | } |
71 | 291 | 296 | ||
74 | 292 | bool lostAllSurfaces = m_session && m_session->surfaceList()->isEmpty() && m_session->hadSurface() | 297 | bool lostAllSurfaces = singleSession && singleSession->surfaceList()->isEmpty() && singleSession->hadSurface() |
75 | 293 | && !m_session->hasClosingSurfaces(); | 298 | && !singleSession->hasClosingSurfaces(); |
76 | 294 | 299 | ||
77 | 295 | if (m_closing || (lostAllSurfaces && m_state != InternalState::StoppedResumable)) { | 300 | if (m_closing || (lostAllSurfaces && m_state != InternalState::StoppedResumable)) { |
78 | 296 | applyClosing(); | 301 | applyClosing(); |
80 | 297 | } else if (m_requestedState == RequestedRunning || (m_session && m_session->hasClosingSurfaces())) { | 302 | } else if (m_requestedState == RequestedRunning || (singleSession && singleSession->hasClosingSurfaces())) { |
81 | 298 | applyRequestedRunning(); | 303 | applyRequestedRunning(); |
82 | 299 | } else { | 304 | } else { |
83 | 300 | applyRequestedSuspended(); | 305 | applyRequestedSuspended(); |
84 | @@ -410,12 +415,22 @@ | |||
85 | 410 | 415 | ||
86 | 411 | bool Application::focused() const | 416 | bool Application::focused() const |
87 | 412 | { | 417 | { |
89 | 413 | return m_session && m_session->focused(); | 418 | for (auto session : m_sessions) { |
90 | 419 | if (session->focused()) { | ||
91 | 420 | return true; | ||
92 | 421 | } | ||
93 | 422 | } | ||
94 | 423 | return false; | ||
95 | 414 | } | 424 | } |
96 | 415 | 425 | ||
97 | 416 | bool Application::fullscreen() const | 426 | bool Application::fullscreen() const |
98 | 417 | { | 427 | { |
100 | 418 | return m_session ? m_session->fullscreen() : false; | 428 | for (auto session : m_sessions) { |
101 | 429 | if (session->fullscreen()) { | ||
102 | 430 | return true; | ||
103 | 431 | } | ||
104 | 432 | } | ||
105 | 433 | return false; | ||
106 | 419 | } | 434 | } |
107 | 420 | 435 | ||
108 | 421 | void Application::close() | 436 | void Application::close() |
109 | @@ -433,7 +448,9 @@ | |||
110 | 433 | case InternalState::SuspendingWaitSession: | 448 | case InternalState::SuspendingWaitSession: |
111 | 434 | case InternalState::SuspendingWaitProcess: | 449 | case InternalState::SuspendingWaitProcess: |
112 | 435 | case InternalState::Suspended: | 450 | case InternalState::Suspended: |
114 | 436 | m_session->close(); | 451 | for (auto session : m_sessions) { |
115 | 452 | session->close(); | ||
116 | 453 | } | ||
117 | 437 | break; | 454 | break; |
118 | 438 | case InternalState::Closing: | 455 | case InternalState::Closing: |
119 | 439 | // already on the way | 456 | // already on the way |
120 | @@ -453,69 +470,73 @@ | |||
121 | 453 | m_arguments = arguments; | 470 | m_arguments = arguments; |
122 | 454 | } | 471 | } |
123 | 455 | 472 | ||
125 | 456 | void Application::setSession(SessionInterface *newSession) | 473 | void Application::removeSession(SessionInterface *session) |
126 | 474 | { | ||
127 | 475 | if (!m_sessions.contains(session)) | ||
128 | 476 | return; | ||
129 | 477 | |||
130 | 478 | m_surfaceList.removeSurfaceList(session->surfaceList()); | ||
131 | 479 | m_proxyPromptSurfaceList->setSourceList(nullptr); | ||
132 | 480 | session->disconnect(this); | ||
133 | 481 | session->surfaceList()->disconnect(this); | ||
134 | 482 | session->setApplication(nullptr); | ||
135 | 483 | session->setParent(nullptr); | ||
136 | 484 | |||
137 | 485 | m_sessions.removeAll(session); | ||
138 | 486 | |||
139 | 487 | InitialSurfaceSizes::remove(session->pid()); | ||
140 | 488 | } | ||
141 | 489 | |||
142 | 490 | void Application::addSession(SessionInterface *newSession) | ||
143 | 457 | { | 491 | { |
144 | 458 | INFO_MSG << "(session=" << newSession << ")"; | 492 | INFO_MSG << "(session=" << newSession << ")"; |
145 | 459 | 493 | ||
147 | 460 | if (newSession == m_session) | 494 | if (!newSession || m_sessions.contains(newSession)) |
148 | 461 | return; | 495 | return; |
149 | 462 | 496 | ||
150 | 463 | if (m_session) { | ||
151 | 464 | m_proxySurfaceList->setSourceList(nullptr); | ||
152 | 465 | m_proxyPromptSurfaceList->setSourceList(nullptr); | ||
153 | 466 | m_session->disconnect(this); | ||
154 | 467 | m_session->surfaceList()->disconnect(this); | ||
155 | 468 | m_session->setApplication(nullptr); | ||
156 | 469 | m_session->setParent(nullptr); | ||
157 | 470 | } | ||
158 | 471 | |||
159 | 472 | bool oldFullscreen = fullscreen(); | 497 | bool oldFullscreen = fullscreen(); |
206 | 473 | m_session = newSession; | 498 | m_sessions << newSession; |
207 | 474 | 499 | ||
208 | 475 | if (m_session) { | 500 | newSession->setParent(this); |
209 | 476 | m_session->setParent(this); | 501 | newSession->setApplication(this); |
210 | 477 | m_session->setApplication(this); | 502 | |
211 | 478 | 503 | switch (m_state) { | |
212 | 479 | switch (m_state) { | 504 | case InternalState::Starting: |
213 | 480 | case InternalState::Starting: | 505 | case InternalState::Running: |
214 | 481 | case InternalState::Running: | 506 | case InternalState::RunningInBackground: |
215 | 482 | case InternalState::RunningInBackground: | 507 | case InternalState::Closing: |
216 | 483 | case InternalState::Closing: | 508 | newSession->resume(); |
217 | 484 | m_session->resume(); | 509 | break; |
218 | 485 | break; | 510 | case InternalState::SuspendingWaitSession: |
219 | 486 | case InternalState::SuspendingWaitSession: | 511 | case InternalState::SuspendingWaitProcess: |
220 | 487 | case InternalState::SuspendingWaitProcess: | 512 | case InternalState::Suspended: |
221 | 488 | case InternalState::Suspended: | 513 | newSession->suspend(); |
222 | 489 | m_session->suspend(); | 514 | break; |
223 | 490 | break; | 515 | case InternalState::Stopped: |
224 | 491 | case InternalState::Stopped: | 516 | default: |
225 | 492 | default: | 517 | newSession->stop(); |
226 | 493 | m_session->stop(); | 518 | break; |
227 | 494 | break; | 519 | } |
228 | 495 | } | 520 | |
229 | 496 | 521 | connect(newSession, &SessionInterface::stateChanged, this, &Application::onSessionStateChanged); | |
230 | 497 | connect(m_session, &SessionInterface::stateChanged, this, &Application::onSessionStateChanged); | 522 | connect(newSession, &SessionInterface::fullscreenChanged, this, &Application::fullscreenChanged); |
231 | 498 | connect(m_session, &SessionInterface::fullscreenChanged, this, &Application::fullscreenChanged); | 523 | connect(newSession, &SessionInterface::hasClosingSurfacesChanged, this, &Application::updateState); |
232 | 499 | connect(m_session, &SessionInterface::hasClosingSurfacesChanged, this, &Application::updateState); | 524 | connect(newSession, &SessionInterface::focusRequested, this, &Application::focusRequested); |
233 | 500 | connect(m_session, &SessionInterface::focusRequested, this, &Application::focusRequested); | 525 | connect(newSession->surfaceList(), &MirSurfaceListModel::emptyChanged, this, &Application::updateState); |
234 | 501 | connect(m_session->surfaceList(), &MirSurfaceListModel::emptyChanged, this, &Application::updateState); | 526 | connect(newSession, &SessionInterface::focusedChanged, this, [&](bool focused) { |
235 | 502 | connect(m_session, &SessionInterface::focusedChanged, this, [&](bool focused) { | 527 | qCDebug(QTMIR_APPLICATIONS).nospace() << "Application[" << appId() <<"]::focusedChanged(" << focused << ")"; |
236 | 503 | qCDebug(QTMIR_APPLICATIONS).nospace() << "Application[" << appId() <<"]::focusedChanged(" << focused << ")"; | 528 | Q_EMIT focusedChanged(focused); |
237 | 504 | Q_EMIT focusedChanged(focused); | 529 | }); |
238 | 505 | }); | 530 | |
239 | 506 | 531 | if (m_initialSurfaceSize.isValid() && newSession->pid() != 0) { | |
240 | 507 | if (oldFullscreen != fullscreen()) | 532 | InitialSurfaceSizes::set(newSession->pid(), m_initialSurfaceSize); |
241 | 508 | Q_EMIT fullscreenChanged(fullscreen()); | 533 | } |
242 | 509 | 534 | ||
243 | 510 | m_proxySurfaceList->setSourceList(m_session->surfaceList()); | 535 | if (oldFullscreen != fullscreen()) |
244 | 511 | m_proxyPromptSurfaceList->setSourceList(m_session->promptSurfaceList()); | 536 | Q_EMIT fullscreenChanged(fullscreen()); |
245 | 512 | } else { | 537 | |
246 | 513 | // this can only happen after the session has stopped | 538 | m_surfaceList.addSurfaceList(newSession->surfaceList()); |
247 | 514 | Q_ASSERT(m_state == InternalState::Stopped || m_state == InternalState::StoppedResumable | 539 | m_proxyPromptSurfaceList->setSourceList(newSession->promptSurfaceList()); |
202 | 515 | || m_state == InternalState::Closing); | ||
203 | 516 | } | ||
204 | 517 | |||
205 | 518 | Q_EMIT sessionChanged(m_session); | ||
248 | 519 | } | 540 | } |
249 | 520 | 541 | ||
250 | 521 | void Application::setInternalState(Application::InternalState state) | 542 | void Application::setInternalState(Application::InternalState state) |
251 | @@ -587,7 +608,7 @@ | |||
252 | 587 | break; | 608 | break; |
253 | 588 | case ProcessFailed: | 609 | case ProcessFailed: |
254 | 589 | // we assume the session always stop before the process | 610 | // we assume the session always stop before the process |
256 | 590 | Q_ASSERT(!m_session || m_session->state() == Session::Stopped); | 611 | Q_ASSERT(m_sessions.isEmpty() || combinedSessionState() == Session::Stopped); |
257 | 591 | 612 | ||
258 | 592 | if (m_state == InternalState::Starting) { | 613 | if (m_state == InternalState::Starting) { |
259 | 593 | // that was way too soon. let it go away | 614 | // that was way too soon. let it go away |
260 | @@ -599,7 +620,7 @@ | |||
261 | 599 | break; | 620 | break; |
262 | 600 | case ProcessStopped: | 621 | case ProcessStopped: |
263 | 601 | // we assume the session always stop before the process | 622 | // we assume the session always stop before the process |
265 | 602 | Q_ASSERT(!m_session || m_session->state() == Session::Stopped); | 623 | Q_ASSERT(m_sessions.isEmpty() || combinedSessionState() == Session::Stopped); |
266 | 603 | 624 | ||
267 | 604 | if (m_state == InternalState::Starting) { | 625 | if (m_state == InternalState::Starting) { |
268 | 605 | // that was way too soon. let it go away | 626 | // that was way too soon. let it go away |
269 | @@ -622,7 +643,7 @@ | |||
270 | 622 | INFO_MSG << "()"; | 643 | INFO_MSG << "()"; |
271 | 623 | 644 | ||
272 | 624 | Q_ASSERT(m_state == InternalState::Running); | 645 | Q_ASSERT(m_state == InternalState::Running); |
274 | 625 | Q_ASSERT(m_session != nullptr); | 646 | Q_ASSERT(!m_sessions.isEmpty()); |
275 | 626 | 647 | ||
276 | 627 | if (exemptFromLifecycle()) { | 648 | if (exemptFromLifecycle()) { |
277 | 628 | // There's no need to keep the wakelock as the process is never suspended | 649 | // There's no need to keep the wakelock as the process is never suspended |
278 | @@ -631,7 +652,9 @@ | |||
279 | 631 | setInternalState(InternalState::RunningInBackground); | 652 | setInternalState(InternalState::RunningInBackground); |
280 | 632 | } else { | 653 | } else { |
281 | 633 | setInternalState(InternalState::SuspendingWaitSession); | 654 | setInternalState(InternalState::SuspendingWaitSession); |
283 | 634 | m_session->suspend(); | 655 | for (auto session : m_sessions) { |
284 | 656 | session->suspend(); | ||
285 | 657 | } | ||
286 | 635 | } | 658 | } |
287 | 636 | } | 659 | } |
288 | 637 | 660 | ||
289 | @@ -645,12 +668,14 @@ | |||
290 | 645 | if (m_processState == ProcessSuspended) { | 668 | if (m_processState == ProcessSuspended) { |
291 | 646 | setProcessState(ProcessRunning); // should we wait for a resumed() signal? | 669 | setProcessState(ProcessRunning); // should we wait for a resumed() signal? |
292 | 647 | } | 670 | } |
295 | 648 | if (m_session) { | 671 | for (auto session : m_sessions) { |
296 | 649 | m_session->resume(); | 672 | session->resume(); |
297 | 650 | } | 673 | } |
298 | 651 | } else if (m_state == InternalState::SuspendingWaitSession) { | 674 | } else if (m_state == InternalState::SuspendingWaitSession) { |
299 | 652 | setInternalState(InternalState::Running); | 675 | setInternalState(InternalState::Running); |
301 | 653 | m_session->resume(); | 676 | for (auto session : m_sessions) { |
302 | 677 | session->resume(); | ||
303 | 678 | } | ||
304 | 654 | } else if (m_state == InternalState::RunningInBackground) { | 679 | } else if (m_state == InternalState::RunningInBackground) { |
305 | 655 | setInternalState(InternalState::Running); | 680 | setInternalState(InternalState::Running); |
306 | 656 | } | 681 | } |
307 | @@ -704,11 +729,6 @@ | |||
308 | 704 | return m_rotatesWindowContents; | 729 | return m_rotatesWindowContents; |
309 | 705 | } | 730 | } |
310 | 706 | 731 | ||
311 | 707 | SessionInterface* Application::session() const | ||
312 | 708 | { | ||
313 | 709 | return m_session; | ||
314 | 710 | } | ||
315 | 711 | |||
316 | 712 | void Application::acquireWakelock() const | 732 | void Application::acquireWakelock() const |
317 | 713 | { | 733 | { |
318 | 714 | if (appId() == QLatin1String("unity8-dash")) | 734 | if (appId() == QLatin1String("unity8-dash")) |
319 | @@ -725,9 +745,28 @@ | |||
320 | 725 | m_sharedWakelock->release(this); | 745 | m_sharedWakelock->release(this); |
321 | 726 | } | 746 | } |
322 | 727 | 747 | ||
326 | 728 | void Application::onSessionStateChanged(Session::State sessionState) | 748 | SessionInterface::State Application::combinedSessionState() |
327 | 729 | { | 749 | { |
328 | 730 | switch (sessionState) { | 750 | // This doesn't make sense when there are no sessions |
329 | 751 | Q_ASSERT(m_sessions.count() > 0); | ||
330 | 752 | |||
331 | 753 | if (m_sessions.count() == 1) { | ||
332 | 754 | // easy case | ||
333 | 755 | return m_sessions[0]->state(); | ||
334 | 756 | } | ||
335 | 757 | |||
336 | 758 | SessionInterface::State combinedState = SessionInterface::Stopped; | ||
337 | 759 | for (auto session : m_sessions) { | ||
338 | 760 | if (session->state() > combinedState) { | ||
339 | 761 | combinedState = session->state(); | ||
340 | 762 | } | ||
341 | 763 | } | ||
342 | 764 | return combinedState; | ||
343 | 765 | } | ||
344 | 766 | |||
345 | 767 | void Application::onSessionStateChanged() | ||
346 | 768 | { | ||
347 | 769 | switch (combinedSessionState()) { | ||
348 | 731 | case Session::Starting: | 770 | case Session::Starting: |
349 | 732 | break; | 771 | break; |
350 | 733 | case Session::Running: | 772 | case Session::Running: |
351 | @@ -825,13 +864,18 @@ | |||
352 | 825 | 864 | ||
353 | 826 | if (size != m_initialSurfaceSize) { | 865 | if (size != m_initialSurfaceSize) { |
354 | 827 | m_initialSurfaceSize = size; | 866 | m_initialSurfaceSize = size; |
355 | 867 | if (m_initialSurfaceSize.isValid()) { | ||
356 | 868 | for (auto session : m_sessions) { | ||
357 | 869 | InitialSurfaceSizes::set(session->pid(), size); | ||
358 | 870 | } | ||
359 | 871 | } | ||
360 | 828 | Q_EMIT initialSurfaceSizeChanged(m_initialSurfaceSize); | 872 | Q_EMIT initialSurfaceSizeChanged(m_initialSurfaceSize); |
361 | 829 | } | 873 | } |
362 | 830 | } | 874 | } |
363 | 831 | 875 | ||
364 | 832 | unityapp::MirSurfaceListInterface* Application::surfaceList() const | 876 | unityapp::MirSurfaceListInterface* Application::surfaceList() const |
365 | 833 | { | 877 | { |
367 | 834 | return m_proxySurfaceList; | 878 | return &m_surfaceList; |
368 | 835 | } | 879 | } |
369 | 836 | 880 | ||
370 | 837 | unityapp::MirSurfaceListInterface* Application::promptSurfaceList() const | 881 | unityapp::MirSurfaceListInterface* Application::promptSurfaceList() const |
371 | @@ -841,11 +885,11 @@ | |||
372 | 841 | 885 | ||
373 | 842 | void Application::requestFocus() | 886 | void Application::requestFocus() |
374 | 843 | { | 887 | { |
376 | 844 | if (m_proxySurfaceList->rowCount() > 0) { | 888 | if (m_surfaceList.rowCount() > 0) { |
377 | 845 | INFO_MSG << "() - Requesting focus for most recent toplevel app surface"; | 889 | INFO_MSG << "() - Requesting focus for most recent toplevel app surface"; |
378 | 846 | 890 | ||
381 | 847 | for (int i = 0; i < m_proxySurfaceList->count(); ++i) { | 891 | for (int i = 0; i < m_surfaceList.count(); ++i) { |
382 | 848 | auto surface = static_cast<MirSurfaceInterface*>(m_proxySurfaceList->get(i)); | 892 | auto surface = static_cast<MirSurfaceInterface*>(m_surfaceList.get(i)); |
383 | 849 | if (!surface->parentSurface()) { | 893 | if (!surface->parentSurface()) { |
384 | 850 | surface->requestFocus(); | 894 | surface->requestFocus(); |
385 | 851 | break; | 895 | break; |
386 | @@ -857,4 +901,16 @@ | |||
387 | 857 | } | 901 | } |
388 | 858 | } | 902 | } |
389 | 859 | 903 | ||
390 | 904 | void Application::terminate() | ||
391 | 905 | { | ||
392 | 906 | for (auto session : m_sessions) { | ||
393 | 907 | kill(session->pid(), SIGTERM); | ||
394 | 908 | } | ||
395 | 909 | } | ||
396 | 910 | |||
397 | 911 | QVector<SessionInterface*> Application::sessions() const | ||
398 | 912 | { | ||
399 | 913 | return m_sessions; | ||
400 | 914 | } | ||
401 | 915 | |||
402 | 860 | } // namespace qtmir | 916 | } // namespace qtmir |
403 | 861 | 917 | ||
404 | === modified file 'src/modules/Unity/Application/application.h' | |||
405 | --- src/modules/Unity/Application/application.h 2017-03-22 14:57:19 +0000 | |||
406 | +++ src/modules/Unity/Application/application.h 2017-03-31 21:11:21 +0000 | |||
407 | @@ -1,5 +1,5 @@ | |||
408 | 1 | /* | 1 | /* |
410 | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. | 2 | * Copyright (C) 2013-2017 Canonical, Ltd. |
411 | 3 | * | 3 | * |
412 | 4 | * This program is free software: you can redistribute it and/or modify it under | 4 | * This program is free software: you can redistribute it and/or modify it under |
413 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | 5 | * the terms of the GNU Lesser General Public License version 3, as published by |
414 | @@ -24,6 +24,7 @@ | |||
415 | 24 | #include <QtCore/QtCore> | 24 | #include <QtCore/QtCore> |
416 | 25 | #include <QImage> | 25 | #include <QImage> |
417 | 26 | #include <QSharedPointer> | 26 | #include <QSharedPointer> |
418 | 27 | #include <QVector> | ||
419 | 27 | 28 | ||
420 | 28 | // Unity API | 29 | // Unity API |
421 | 29 | #include <unity/shell/application/ApplicationInfoInterface.h> | 30 | #include <unity/shell/application/ApplicationInfoInterface.h> |
422 | @@ -109,9 +110,11 @@ | |||
423 | 109 | void setProcessState(ProcessState value); | 110 | void setProcessState(ProcessState value); |
424 | 110 | 111 | ||
425 | 111 | QStringList arguments() const { return m_arguments; } | 112 | QStringList arguments() const { return m_arguments; } |
426 | 113 | void setArguments(const QStringList &arguments); | ||
427 | 112 | 114 | ||
430 | 113 | SessionInterface* session() const; | 115 | void addSession(SessionInterface *session); |
431 | 114 | void setSession(SessionInterface *session); | 116 | void removeSession(SessionInterface *session); |
432 | 117 | QVector<SessionInterface*> sessions() const; | ||
433 | 115 | 118 | ||
434 | 116 | bool isValid() const; | 119 | bool isValid() const; |
435 | 117 | bool fullscreen() const; | 120 | bool fullscreen() const; |
436 | @@ -123,13 +126,13 @@ | |||
437 | 123 | 126 | ||
438 | 124 | void requestFocus(); | 127 | void requestFocus(); |
439 | 125 | 128 | ||
440 | 129 | void terminate(); | ||
441 | 130 | |||
442 | 126 | // for tests | 131 | // for tests |
443 | 127 | void setStopTimer(AbstractTimer *timer); | 132 | void setStopTimer(AbstractTimer *timer); |
444 | 128 | AbstractTimer *stopTimer() const { return m_stopTimer; } | 133 | AbstractTimer *stopTimer() const { return m_stopTimer; } |
445 | 129 | |||
446 | 130 | Q_SIGNALS: | 134 | Q_SIGNALS: |
447 | 131 | void fullscreenChanged(bool fullscreen); | 135 | void fullscreenChanged(bool fullscreen); |
448 | 132 | void sessionChanged(SessionInterface *session); | ||
449 | 133 | 136 | ||
450 | 134 | void startProcessRequested(); | 137 | void startProcessRequested(); |
451 | 135 | void stopProcessRequested(); | 138 | void stopProcessRequested(); |
452 | @@ -139,7 +142,7 @@ | |||
453 | 139 | void closing(); | 142 | void closing(); |
454 | 140 | 143 | ||
455 | 141 | private Q_SLOTS: | 144 | private Q_SLOTS: |
457 | 142 | void onSessionStateChanged(SessionInterface::State sessionState); | 145 | void onSessionStateChanged(); |
458 | 143 | 146 | ||
459 | 144 | void respawn(); | 147 | void respawn(); |
460 | 145 | 148 | ||
461 | @@ -147,7 +150,6 @@ | |||
462 | 147 | 150 | ||
463 | 148 | void acquireWakelock() const; | 151 | void acquireWakelock() const; |
464 | 149 | void releaseWakelock() const; | 152 | void releaseWakelock() const; |
465 | 150 | void setArguments(const QStringList &arguments); | ||
466 | 151 | void setInternalState(InternalState state); | 153 | void setInternalState(InternalState state); |
467 | 152 | void wipeQMLCache(); | 154 | void wipeQMLCache(); |
468 | 153 | void suspend(); | 155 | void suspend(); |
469 | @@ -160,6 +162,7 @@ | |||
470 | 160 | void applyRequestedSuspended(); | 162 | void applyRequestedSuspended(); |
471 | 161 | void applyClosing(); | 163 | void applyClosing(); |
472 | 162 | void onSessionStopped(); | 164 | void onSessionStopped(); |
473 | 165 | SessionInterface::State combinedSessionState(); | ||
474 | 163 | 166 | ||
475 | 164 | QSharedPointer<SharedWakelock> m_sharedWakelock; | 167 | QSharedPointer<SharedWakelock> m_sharedWakelock; |
476 | 165 | QSharedPointer<ApplicationInfo> m_appInfo; | 168 | QSharedPointer<ApplicationInfo> m_appInfo; |
477 | @@ -168,7 +171,7 @@ | |||
478 | 168 | QStringList m_arguments; | 171 | QStringList m_arguments; |
479 | 169 | Qt::ScreenOrientations m_supportedOrientations; | 172 | Qt::ScreenOrientations m_supportedOrientations; |
480 | 170 | bool m_rotatesWindowContents; | 173 | bool m_rotatesWindowContents; |
482 | 171 | SessionInterface *m_session; | 174 | QVector<SessionInterface*> m_sessions; |
483 | 172 | RequestedState m_requestedState; | 175 | RequestedState m_requestedState; |
484 | 173 | ProcessState m_processState; | 176 | ProcessState m_processState; |
485 | 174 | AbstractTimer *m_stopTimer; | 177 | AbstractTimer *m_stopTimer; |
486 | @@ -176,12 +179,8 @@ | |||
487 | 176 | QSize m_initialSurfaceSize; | 179 | QSize m_initialSurfaceSize; |
488 | 177 | bool m_closing{false}; | 180 | bool m_closing{false}; |
489 | 178 | 181 | ||
491 | 179 | ProxySurfaceListModel *m_proxySurfaceList; | 182 | mutable MirSurfaceListModel m_surfaceList; |
492 | 180 | ProxySurfaceListModel *m_proxyPromptSurfaceList; | 183 | ProxySurfaceListModel *m_proxyPromptSurfaceList; |
493 | 181 | |||
494 | 182 | friend class ApplicationManager; | ||
495 | 183 | friend class SessionManager; | ||
496 | 184 | friend class Session; | ||
497 | 185 | }; | 184 | }; |
498 | 186 | 185 | ||
499 | 187 | } // namespace qtmir | 186 | } // namespace qtmir |
500 | 188 | 187 | ||
501 | === modified file 'src/modules/Unity/Application/application_manager.cpp' | |||
502 | --- src/modules/Unity/Application/application_manager.cpp 2017-03-28 17:12:54 +0000 | |||
503 | +++ src/modules/Unity/Application/application_manager.cpp 2017-03-31 21:11:21 +0000 | |||
504 | @@ -28,7 +28,6 @@ | |||
505 | 28 | #include "settings.h" | 28 | #include "settings.h" |
506 | 29 | 29 | ||
507 | 30 | // mirserver | 30 | // mirserver |
508 | 31 | #include "initialsurfacesizes.h" | ||
509 | 32 | #include "nativeinterface.h" | 31 | #include "nativeinterface.h" |
510 | 33 | #include "logging.h" | 32 | #include "logging.h" |
511 | 34 | 33 | ||
512 | @@ -425,7 +424,6 @@ | |||
513 | 425 | 424 | ||
514 | 426 | Q_UNUSED(error); // FIXME(greyback) upstart reports app that fully started up & crashes as failing during startup?? | 425 | Q_UNUSED(error); // FIXME(greyback) upstart reports app that fully started up & crashes as failing during startup?? |
515 | 427 | application->setProcessState(Application::ProcessFailed); | 426 | application->setProcessState(Application::ProcessFailed); |
516 | 428 | setApplicationPid(application, 0); | ||
517 | 429 | } | 427 | } |
518 | 430 | 428 | ||
519 | 431 | void ApplicationManager::onProcessStopped(const QString &appId) | 429 | void ApplicationManager::onProcessStopped(const QString &appId) |
520 | @@ -450,7 +448,6 @@ | |||
521 | 450 | // we don't want to override what onProcessFailed already set. | 448 | // we don't want to override what onProcessFailed already set. |
522 | 451 | if (application->processState() != Application::ProcessFailed) { | 449 | if (application->processState() != Application::ProcessFailed) { |
523 | 452 | application->setProcessState(Application::ProcessStopped); | 450 | application->setProcessState(Application::ProcessStopped); |
524 | 453 | setApplicationPid(application, 0); | ||
525 | 454 | } | 451 | } |
526 | 455 | } | 452 | } |
527 | 456 | 453 | ||
528 | @@ -527,8 +524,8 @@ | |||
529 | 527 | if (app->state() == Application::Starting) { | 524 | if (app->state() == Application::Starting) { |
530 | 528 | tracepoint(qtmir, appIdHasProcessId_start); | 525 | tracepoint(qtmir, appIdHasProcessId_start); |
531 | 529 | if (m_taskController->appIdHasProcessId(app->appId(), pid)) { | 526 | if (m_taskController->appIdHasProcessId(app->appId(), pid)) { |
532 | 530 | setApplicationPid(app, pid); | ||
533 | 531 | authorized = true; | 527 | authorized = true; |
534 | 528 | m_authorizedPids.insertMulti(pid, app->appId()); | ||
535 | 532 | tracepoint(qtmir, appIdHasProcessId_end, 1); //found | 529 | tracepoint(qtmir, appIdHasProcessId_end, 1); //found |
536 | 533 | return; | 530 | return; |
537 | 534 | } | 531 | } |
538 | @@ -581,17 +578,18 @@ | |||
539 | 581 | // some naughty applications use a script to launch the actual application. Check for the | 578 | // some naughty applications use a script to launch the actual application. Check for the |
540 | 582 | // case where shell actually launched the script. | 579 | // case where shell actually launched the script. |
541 | 583 | Application *application = findApplicationMutexHeld(appInfo->appId()); | 580 | Application *application = findApplicationMutexHeld(appInfo->appId()); |
543 | 584 | if (application && application->state() == Application::Starting) { | 581 | if (application) { |
544 | 585 | qCDebug(QTMIR_APPLICATIONS) << "Process with pid" << pid << "appeared, attaching to existing entry" | 582 | qCDebug(QTMIR_APPLICATIONS) << "Process with pid" << pid << "appeared, attaching to existing entry" |
545 | 586 | << "in application list with appId:" << application->appId(); | 583 | << "in application list with appId:" << application->appId(); |
546 | 587 | setApplicationPid(application, pid); | ||
547 | 588 | authorized = true; | 584 | authorized = true; |
548 | 585 | m_authorizedPids.insertMulti(pid, appInfo->appId()); | ||
549 | 589 | return; | 586 | return; |
550 | 590 | } | 587 | } |
551 | 591 | 588 | ||
552 | 592 | const QStringList arguments(info->asStringList()); | 589 | const QStringList arguments(info->asStringList()); |
553 | 593 | queuedAddApp(appInfo, arguments, pid); | 590 | queuedAddApp(appInfo, arguments, pid); |
554 | 594 | authorized = true; | 591 | authorized = true; |
555 | 592 | m_authorizedPids.insertMulti(pid, appInfo->appId()); | ||
556 | 595 | } | 593 | } |
557 | 596 | 594 | ||
558 | 597 | 595 | ||
559 | @@ -603,26 +601,22 @@ | |||
560 | 603 | auto qtmirSurface = static_cast<qtmir::MirSurfaceInterface*>(surface); | 601 | auto qtmirSurface = static_cast<qtmir::MirSurfaceInterface*>(surface); |
561 | 604 | 602 | ||
562 | 605 | QMutexLocker locker(&m_mutex); | 603 | QMutexLocker locker(&m_mutex); |
564 | 606 | return findApplicationWithPid(miral::pid_of(qtmirSurface->session()->session())); | 604 | return findApplicationWithSession(qtmirSurface->session()->session()); |
565 | 607 | } | 605 | } |
566 | 608 | 606 | ||
568 | 609 | Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session) | 607 | Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session) const |
569 | 610 | { | 608 | { |
570 | 611 | if (!session) | 609 | if (!session) |
571 | 612 | return nullptr; | 610 | return nullptr; |
583 | 613 | return findApplicationWithPid(miral::pid_of(session)); | 611 | |
584 | 614 | } | 612 | for (auto *application : m_applications) { |
585 | 615 | 613 | for (auto *qmlSession : application->sessions()) { | |
586 | 616 | Application* ApplicationManager::findApplicationWithPid(const pid_t pid) const | 614 | if (qmlSession->session() == session) { |
587 | 617 | { | 615 | return application; |
588 | 618 | if (pid <= 0) | 616 | } |
578 | 619 | return nullptr; | ||
579 | 620 | |||
580 | 621 | for (Application *app : m_applications) { | ||
581 | 622 | if (m_applicationsPid.value(app) == pid) { | ||
582 | 623 | return app; | ||
589 | 624 | } | 617 | } |
590 | 625 | } | 618 | } |
591 | 619 | |||
592 | 626 | return nullptr; | 620 | return nullptr; |
593 | 627 | } | 621 | } |
594 | 628 | 622 | ||
595 | @@ -638,7 +632,6 @@ | |||
596 | 638 | appInfo, | 632 | appInfo, |
597 | 639 | arguments, | 633 | arguments, |
598 | 640 | this); | 634 | this); |
599 | 641 | setApplicationPid(application, pid); | ||
600 | 642 | add(application); | 635 | add(application); |
601 | 643 | } | 636 | } |
602 | 644 | 637 | ||
603 | @@ -653,22 +646,8 @@ | |||
604 | 653 | DEBUG_MSG << "(appId=" << application->appId() << ")"; | 646 | DEBUG_MSG << "(appId=" << application->appId() << ")"; |
605 | 654 | 647 | ||
606 | 655 | connect(application, &QObject::destroyed, this, [this, application] { | 648 | connect(application, &QObject::destroyed, this, [this, application] { |
607 | 656 | const pid_t pid = m_applicationsPid.value(application); | ||
608 | 657 | if (pid != 0) { | ||
609 | 658 | InitialSurfaceSizes::remove(pid); | ||
610 | 659 | m_applicationsPid.remove(application); | ||
611 | 660 | } | ||
612 | 661 | m_closingApplications.removeAll(application); | 649 | m_closingApplications.removeAll(application); |
613 | 662 | }); | 650 | }); |
614 | 663 | connect(application, &Application::initialSurfaceSizeChanged, this, [this, application] { | ||
615 | 664 | const pid_t pid = m_applicationsPid.value(application); | ||
616 | 665 | if (pid != 0) { | ||
617 | 666 | const QSize size = application->initialSurfaceSize(); | ||
618 | 667 | if (size.isValid()) { | ||
619 | 668 | InitialSurfaceSizes::set(pid, size); | ||
620 | 669 | } | ||
621 | 670 | } | ||
622 | 671 | }); | ||
623 | 672 | 651 | ||
624 | 673 | Q_ASSERT(!m_modelUnderChange); | 652 | Q_ASSERT(!m_modelUnderChange); |
625 | 674 | m_modelUnderChange = true; | 653 | m_modelUnderChange = true; |
626 | @@ -707,13 +686,10 @@ | |||
627 | 707 | 686 | ||
628 | 708 | connect(application, &Application::stopProcessRequested, this, [=]() { | 687 | connect(application, &Application::stopProcessRequested, this, [=]() { |
629 | 709 | if (!m_taskController->stop(appId)) { | 688 | if (!m_taskController->stop(appId)) { |
637 | 710 | const pid_t pid = m_applicationsPid.value(application); | 689 | qWarning() << "FAILED to ask Upstart to stop application with appId" << appId |
638 | 711 | if (pid > 0) { | 690 | << "Sending SIGTERM to process:" << appId; |
639 | 712 | qWarning() << "FAILED to ask Upstart to stop application with appId" << appId | 691 | application->terminate(); |
640 | 713 | << "Sending SIGTERM to process:" << appId; | 692 | application->setProcessState(Application::ProcessStopped); |
634 | 714 | kill(pid, SIGTERM); | ||
635 | 715 | application->setProcessState(Application::ProcessStopped); | ||
636 | 716 | } | ||
641 | 717 | } | 693 | } |
642 | 718 | }); | 694 | }); |
643 | 719 | 695 | ||
644 | @@ -805,27 +781,22 @@ | |||
645 | 805 | return nullptr; | 781 | return nullptr; |
646 | 806 | } | 782 | } |
647 | 807 | 783 | ||
648 | 808 | void ApplicationManager::setApplicationPid(Application *app, pid_t pid) | ||
649 | 809 | { | ||
650 | 810 | const pid_t oldPid = m_applicationsPid.value(app); | ||
651 | 811 | if (oldPid != 0) { | ||
652 | 812 | InitialSurfaceSizes::remove(oldPid); | ||
653 | 813 | } | ||
654 | 814 | |||
655 | 815 | m_applicationsPid.insert(app, pid); | ||
656 | 816 | |||
657 | 817 | if (app->initialSurfaceSize().isValid() && pid != 0) { | ||
658 | 818 | InitialSurfaceSizes::set(pid, app->initialSurfaceSize()); | ||
659 | 819 | } | ||
660 | 820 | } | ||
661 | 821 | |||
662 | 822 | void ApplicationManager::onSessionStarting(SessionInterface *qmlSession) | 784 | void ApplicationManager::onSessionStarting(SessionInterface *qmlSession) |
663 | 823 | { | 785 | { |
664 | 824 | QMutexLocker locker(&m_mutex); | 786 | QMutexLocker locker(&m_mutex); |
665 | 825 | 787 | ||
669 | 826 | Application* application = findApplicationWithSession(qmlSession->session()); | 788 | Application* application = nullptr; |
670 | 827 | if (application && application->state() != Application::Running) { | 789 | { |
671 | 828 | application->setSession(qmlSession); | 790 | auto iter = m_authorizedPids.find(miral::pid_of(qmlSession->session())); |
672 | 791 | if (iter != m_authorizedPids.end()) { | ||
673 | 792 | QString appId = iter.value(); | ||
674 | 793 | application = findApplication(appId); | ||
675 | 794 | m_authorizedPids.erase(iter); | ||
676 | 795 | } | ||
677 | 796 | } | ||
678 | 797 | |||
679 | 798 | if (application) { | ||
680 | 799 | application->addSession(qmlSession); | ||
681 | 829 | } | 800 | } |
682 | 830 | } | 801 | } |
683 | 831 | 802 | ||
684 | 832 | 803 | ||
685 | === modified file 'src/modules/Unity/Application/application_manager.h' | |||
686 | --- src/modules/Unity/Application/application_manager.h 2017-03-24 08:44:32 +0000 | |||
687 | +++ src/modules/Unity/Application/application_manager.h 2017-03-31 21:11:21 +0000 | |||
688 | @@ -110,10 +110,9 @@ | |||
689 | 110 | 110 | ||
690 | 111 | private: | 111 | private: |
691 | 112 | // All calls to private functions happen with the mutex held | 112 | // All calls to private functions happen with the mutex held |
692 | 113 | qtmir::Application* findApplicationWithPid(const pid_t pid) const; | ||
693 | 114 | Application* findApplicationMutexHeld(const QString &inputAppId) const; | 113 | Application* findApplicationMutexHeld(const QString &inputAppId) const; |
694 | 115 | 114 | ||
696 | 116 | Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session); | 115 | Application* findApplicationWithSession(const std::shared_ptr<mir::scene::Session> &session) const; |
697 | 117 | void setFocused(Application *application); | 116 | void setFocused(Application *application); |
698 | 118 | void add(Application *application); | 117 | void add(Application *application); |
699 | 119 | void remove(Application* application); | 118 | void remove(Application* application); |
700 | @@ -125,10 +124,7 @@ | |||
701 | 125 | Application* findApplicationWithPromptSession(const mir::scene::PromptSession* promptSession); | 124 | Application* findApplicationWithPromptSession(const mir::scene::PromptSession* promptSession); |
702 | 126 | Application *findClosingApplication(const QString &inputAppId) const; | 125 | Application *findClosingApplication(const QString &inputAppId) const; |
703 | 127 | 126 | ||
704 | 128 | void setApplicationPid(Application *application, pid_t pid); | ||
705 | 129 | |||
706 | 130 | QList<Application*> m_applications; | 127 | QList<Application*> m_applications; |
707 | 131 | QHash<Application*, pid_t> m_applicationsPid; | ||
708 | 132 | DBusFocusInfo *m_dbusFocusInfo; | 128 | DBusFocusInfo *m_dbusFocusInfo; |
709 | 133 | QSharedPointer<TaskController> m_taskController; | 129 | QSharedPointer<TaskController> m_taskController; |
710 | 134 | QSharedPointer<ProcInfo> m_procInfo; | 130 | QSharedPointer<ProcInfo> m_procInfo; |
711 | @@ -139,8 +135,8 @@ | |||
712 | 139 | bool m_modelUnderChange{false}; | 135 | bool m_modelUnderChange{false}; |
713 | 140 | static ApplicationManager* the_application_manager; | 136 | static ApplicationManager* the_application_manager; |
714 | 141 | 137 | ||
717 | 142 | friend class Application; | 138 | QHash<pid_t, QString> m_authorizedPids; |
718 | 143 | friend class DBusWindowStack; | 139 | |
719 | 144 | mutable QMutex m_mutex; | 140 | mutable QMutex m_mutex; |
720 | 145 | }; | 141 | }; |
721 | 146 | 142 | ||
722 | 147 | 143 | ||
723 | === modified file 'src/modules/Unity/Application/dbusfocusinfo.cpp' | |||
724 | --- src/modules/Unity/Application/dbusfocusinfo.cpp 2017-03-07 20:20:21 +0000 | |||
725 | +++ src/modules/Unity/Application/dbusfocusinfo.cpp 2017-03-31 21:11:21 +0000 | |||
726 | @@ -75,18 +75,20 @@ | |||
727 | 75 | SessionInterface* DBusFocusInfo::findSessionWithPid(const QSet<pid_t> &pidSet) | 75 | SessionInterface* DBusFocusInfo::findSessionWithPid(const QSet<pid_t> &pidSet) |
728 | 76 | { | 76 | { |
729 | 77 | Q_FOREACH (Application* application, m_applications) { | 77 | Q_FOREACH (Application* application, m_applications) { |
742 | 78 | auto session = application->session(); | 78 | QVector<SessionInterface*> sessions = application->sessions(); |
743 | 79 | if (pidSet.contains(session->pid())) { | 79 | for (auto session : sessions) { |
744 | 80 | return session; | 80 | if (pidSet.contains(session->pid())) { |
745 | 81 | } | 81 | return session; |
746 | 82 | SessionInterface *chosenChildSession = nullptr; | 82 | } |
747 | 83 | session->foreachChildSession([&](SessionInterface* childSession) { | 83 | SessionInterface *chosenChildSession = nullptr; |
748 | 84 | if (pidSet.contains(childSession->pid())) { | 84 | session->foreachChildSession([&](SessionInterface* childSession) { |
749 | 85 | chosenChildSession = childSession; | 85 | if (pidSet.contains(childSession->pid())) { |
750 | 86 | } | 86 | chosenChildSession = childSession; |
751 | 87 | }); | 87 | } |
752 | 88 | if (chosenChildSession) { | 88 | }); |
753 | 89 | return chosenChildSession; | 89 | if (chosenChildSession) { |
754 | 90 | return chosenChildSession; | ||
755 | 91 | } | ||
756 | 90 | } | 92 | } |
757 | 91 | } | 93 | } |
758 | 92 | return nullptr; | 94 | return nullptr; |
759 | @@ -111,21 +113,22 @@ | |||
760 | 111 | MirSurfaceInterface *DBusFocusInfo::findQmlSurface(const QString &serializedId) | 113 | MirSurfaceInterface *DBusFocusInfo::findQmlSurface(const QString &serializedId) |
761 | 112 | { | 114 | { |
762 | 113 | for (Application* application : m_applications) { | 115 | for (Application* application : m_applications) { |
770 | 114 | auto session = application->session(); | 116 | for (SessionInterface *session : application->sessions()) { |
771 | 115 | if (session) { | 117 | if (session) { |
772 | 116 | auto surfaceList = static_cast<MirSurfaceListModel*>(session->surfaceList()); | 118 | auto surfaceList = static_cast<MirSurfaceListModel*>(session->surfaceList()); |
773 | 117 | for (int i = 0; i < surfaceList->count(); ++i) { | 119 | for (int i = 0; i < surfaceList->count(); ++i) { |
774 | 118 | auto qmlSurface = static_cast<MirSurfaceInterface*>(surfaceList->get(i)); | 120 | auto qmlSurface = static_cast<MirSurfaceInterface*>(surfaceList->get(i)); |
775 | 119 | if (qmlSurface->persistentId() == serializedId) { | 121 | if (qmlSurface->persistentId() == serializedId) { |
776 | 120 | return qmlSurface; | 122 | return qmlSurface; |
777 | 123 | } | ||
778 | 121 | } | 124 | } |
779 | 122 | } | ||
780 | 123 | 125 | ||
786 | 124 | surfaceList = static_cast<MirSurfaceListModel*>(session->promptSurfaceList()); | 126 | surfaceList = static_cast<MirSurfaceListModel*>(session->promptSurfaceList()); |
787 | 125 | for (int i = 0; i < surfaceList->count(); ++i) { | 127 | for (int i = 0; i < surfaceList->count(); ++i) { |
788 | 126 | auto qmlSurface = static_cast<MirSurfaceInterface*>(surfaceList->get(i)); | 128 | auto qmlSurface = static_cast<MirSurfaceInterface*>(surfaceList->get(i)); |
789 | 127 | if (qmlSurface->persistentId() == serializedId) { | 129 | if (qmlSurface->persistentId() == serializedId) { |
790 | 128 | return qmlSurface; | 130 | return qmlSurface; |
791 | 131 | } | ||
792 | 129 | } | 132 | } |
793 | 130 | } | 133 | } |
794 | 131 | } | 134 | } |
795 | 132 | 135 | ||
796 | === modified file 'src/modules/Unity/Application/session.cpp' | |||
797 | --- src/modules/Unity/Application/session.cpp 2017-02-21 18:39:45 +0000 | |||
798 | +++ src/modules/Unity/Application/session.cpp 2017-03-31 21:11:21 +0000 | |||
799 | @@ -92,7 +92,7 @@ | |||
800 | 92 | delete child; | 92 | delete child; |
801 | 93 | } | 93 | } |
802 | 94 | if (m_application) { | 94 | if (m_application) { |
804 | 95 | m_application->setSession(nullptr); | 95 | m_application->removeSession(this); |
805 | 96 | } | 96 | } |
806 | 97 | 97 | ||
807 | 98 | delete m_children; m_children = nullptr; | 98 | delete m_children; m_children = nullptr; |
808 | 99 | 99 | ||
809 | === modified file 'src/modules/Unity/Application/session_interface.h' | |||
810 | --- src/modules/Unity/Application/session_interface.h 2017-02-21 18:46:30 +0000 | |||
811 | +++ src/modules/Unity/Application/session_interface.h 2017-03-31 21:11:21 +0000 | |||
812 | @@ -53,12 +53,13 @@ | |||
813 | 53 | SessionInterface(QObject *parent = 0) : QObject(parent) {} | 53 | SessionInterface(QObject *parent = 0) : QObject(parent) {} |
814 | 54 | virtual ~SessionInterface() {} | 54 | virtual ~SessionInterface() {} |
815 | 55 | 55 | ||
816 | 56 | // Ordered by importance/activity. Used for calculating the combined state of multiple sessions | ||
817 | 56 | enum State { | 57 | enum State { |
823 | 57 | Starting, | 58 | Running = 4, |
824 | 58 | Running, | 59 | Starting = 3, |
825 | 59 | Suspending, | 60 | Suspending = 2, |
826 | 60 | Suspended, | 61 | Suspended = 1, |
827 | 61 | Stopped | 62 | Stopped = 0 |
828 | 62 | }; | 63 | }; |
829 | 63 | 64 | ||
830 | 64 | //getters | 65 | //getters |
831 | 65 | 66 | ||
832 | === modified file 'tests/modules/Application/application_test.cpp' | |||
833 | --- tests/modules/Application/application_test.cpp 2017-02-21 18:46:30 +0000 | |||
834 | +++ tests/modules/Application/application_test.cpp 2017-03-31 21:11:21 +0000 | |||
835 | @@ -49,7 +49,7 @@ | |||
836 | 49 | inline void suspend(Application *application) | 49 | inline void suspend(Application *application) |
837 | 50 | { | 50 | { |
838 | 51 | application->setRequestedState(Application::RequestedSuspended); | 51 | application->setRequestedState(Application::RequestedSuspended); |
840 | 52 | auto session = dynamic_cast<Session*>(application->session()); | 52 | auto session = dynamic_cast<Session*>(application->sessions()[0]); |
841 | 53 | 53 | ||
842 | 54 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); | 54 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); |
843 | 55 | ASSERT_EQ(Session::Suspending, session->state()); | 55 | ASSERT_EQ(Session::Suspending, session->state()); |
844 | @@ -115,7 +115,7 @@ | |||
845 | 115 | 115 | ||
846 | 116 | FakeSession *session = new FakeSession; | 116 | FakeSession *session = new FakeSession; |
847 | 117 | 117 | ||
849 | 118 | application->setSession(session); | 118 | application->addSession(session); |
850 | 119 | 119 | ||
851 | 120 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); | 120 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); |
852 | 121 | 121 | ||
853 | @@ -150,7 +150,7 @@ | |||
854 | 150 | 150 | ||
855 | 151 | // Get it running and then suspend it | 151 | // Get it running and then suspend it |
856 | 152 | application->setProcessState(Application::ProcessRunning); | 152 | application->setProcessState(Application::ProcessRunning); |
858 | 153 | application->setSession(session); | 153 | application->addSession(session); |
859 | 154 | session->setState(SessionInterface::Running); | 154 | session->setState(SessionInterface::Running); |
860 | 155 | application->setRequestedState(Application::RequestedSuspended); | 155 | application->setRequestedState(Application::RequestedSuspended); |
861 | 156 | session->setState(SessionInterface::Suspended); | 156 | session->setState(SessionInterface::Suspended); |
862 | @@ -175,7 +175,7 @@ | |||
863 | 175 | 175 | ||
864 | 176 | // Get it running, suspend it, and finally stop it | 176 | // Get it running, suspend it, and finally stop it |
865 | 177 | application->setProcessState(Application::ProcessRunning); | 177 | application->setProcessState(Application::ProcessRunning); |
867 | 178 | application->setSession(session); | 178 | application->addSession(session); |
868 | 179 | session->setState(SessionInterface::Running); | 179 | session->setState(SessionInterface::Running); |
869 | 180 | application->setRequestedState(Application::RequestedSuspended); | 180 | application->setRequestedState(Application::RequestedSuspended); |
870 | 181 | session->setState(SessionInterface::Suspended); | 181 | session->setState(SessionInterface::Suspended); |
871 | @@ -215,7 +215,7 @@ | |||
872 | 215 | 215 | ||
873 | 216 | FakeSession *session = new FakeSession; | 216 | FakeSession *session = new FakeSession; |
874 | 217 | 217 | ||
876 | 218 | application->setSession(session); | 218 | application->addSession(session); |
877 | 219 | 219 | ||
878 | 220 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); | 220 | ASSERT_EQ(Application::InternalState::Starting, application->internalState()); |
879 | 221 | 221 | ||
880 | @@ -250,7 +250,7 @@ | |||
881 | 250 | application->setProcessState(Application::ProcessRunning); | 250 | application->setProcessState(Application::ProcessRunning); |
882 | 251 | 251 | ||
883 | 252 | FakeSession *session = new FakeSession; | 252 | FakeSession *session = new FakeSession; |
885 | 253 | application->setSession(session); | 253 | application->addSession(session); |
886 | 254 | 254 | ||
887 | 255 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); | 255 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); |
888 | 256 | 256 | ||
889 | @@ -283,7 +283,7 @@ | |||
890 | 283 | application->setProcessState(Application::ProcessRunning); | 283 | application->setProcessState(Application::ProcessRunning); |
891 | 284 | 284 | ||
892 | 285 | Session *session = createSessionWithFakes(); | 285 | Session *session = createSessionWithFakes(); |
894 | 286 | application->setSession(session); | 286 | application->addSession(session); |
895 | 287 | 287 | ||
896 | 288 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); | 288 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); |
897 | 289 | 289 | ||
898 | @@ -318,7 +318,7 @@ | |||
899 | 318 | application->setProcessState(Application::ProcessRunning); | 318 | application->setProcessState(Application::ProcessRunning); |
900 | 319 | 319 | ||
901 | 320 | FakeSession *session = new FakeSession; | 320 | FakeSession *session = new FakeSession; |
903 | 321 | application->setSession(session); | 321 | application->addSession(session); |
904 | 322 | 322 | ||
905 | 323 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); | 323 | QSignalSpy spyAppStopped(application.data(), SIGNAL(stopped())); |
906 | 324 | 324 | ||
907 | @@ -380,7 +380,7 @@ | |||
908 | 380 | 380 | ||
909 | 381 | Session *session = createSessionWithFakes(); | 381 | Session *session = createSessionWithFakes(); |
910 | 382 | 382 | ||
912 | 383 | application->setSession(session); | 383 | application->addSession(session); |
913 | 384 | 384 | ||
914 | 385 | FakeMirSurface *surface = new FakeMirSurface; | 385 | FakeMirSurface *surface = new FakeMirSurface; |
915 | 386 | session->registerSurface(surface); | 386 | session->registerSurface(surface); |
916 | @@ -437,7 +437,7 @@ | |||
917 | 437 | 437 | ||
918 | 438 | Session *session = createSessionWithFakes(); | 438 | Session *session = createSessionWithFakes(); |
919 | 439 | 439 | ||
921 | 440 | application->setSession(session); | 440 | application->addSession(session); |
922 | 441 | 441 | ||
923 | 442 | FakeMirSurface *surface = new FakeMirSurface; | 442 | FakeMirSurface *surface = new FakeMirSurface; |
924 | 443 | session->registerSurface(surface); | 443 | session->registerSurface(surface); |
925 | @@ -488,7 +488,7 @@ | |||
926 | 488 | 488 | ||
927 | 489 | QPointer<Session> session(createSessionWithFakes()); | 489 | QPointer<Session> session(createSessionWithFakes()); |
928 | 490 | 490 | ||
930 | 491 | application->setSession(session); | 491 | application->addSession(session); |
931 | 492 | 492 | ||
932 | 493 | FakeMirSurface *surface = new FakeMirSurface; | 493 | FakeMirSurface *surface = new FakeMirSurface; |
933 | 494 | session->registerSurface(surface); | 494 | session->registerSurface(surface); |
934 | @@ -532,7 +532,7 @@ | |||
935 | 532 | application->setProcessState(Application::ProcessRunning); | 532 | application->setProcessState(Application::ProcessRunning); |
936 | 533 | 533 | ||
937 | 534 | QPointer<Session> session(createSessionWithFakes()); | 534 | QPointer<Session> session(createSessionWithFakes()); |
939 | 535 | application->setSession(session); | 535 | application->addSession(session); |
940 | 536 | 536 | ||
941 | 537 | FakeMirSurface *surface = new FakeMirSurface; | 537 | FakeMirSurface *surface = new FakeMirSurface; |
942 | 538 | session->registerSurface(surface); | 538 | session->registerSurface(surface); |
943 | @@ -570,7 +570,7 @@ | |||
944 | 570 | 570 | ||
945 | 571 | Session *session = createSessionWithFakes(); | 571 | Session *session = createSessionWithFakes(); |
946 | 572 | 572 | ||
948 | 573 | application->setSession(session); | 573 | application->addSession(session); |
949 | 574 | 574 | ||
950 | 575 | FakeMirSurface *surface = new FakeMirSurface; | 575 | FakeMirSurface *surface = new FakeMirSurface; |
951 | 576 | session->registerSurface(surface); | 576 | session->registerSurface(surface); |
952 | @@ -602,7 +602,7 @@ | |||
953 | 602 | application->setProcessState(Application::ProcessRunning); | 602 | application->setProcessState(Application::ProcessRunning); |
954 | 603 | Session *session = createSessionWithFakes(); | 603 | Session *session = createSessionWithFakes(); |
955 | 604 | 604 | ||
957 | 605 | application->setSession(session); | 605 | application->addSession(session); |
958 | 606 | 606 | ||
959 | 607 | QSignalSpy surfaceCountChangedSpy(application.data(), &Application::surfaceCountChanged); | 607 | QSignalSpy surfaceCountChangedSpy(application.data(), &Application::surfaceCountChanged); |
960 | 608 | 608 | ||
961 | @@ -641,7 +641,7 @@ | |||
962 | 641 | 641 | ||
963 | 642 | FakeSession *session = new FakeSession; | 642 | FakeSession *session = new FakeSession; |
964 | 643 | 643 | ||
966 | 644 | application->setSession(session); | 644 | application->addSession(session); |
967 | 645 | 645 | ||
968 | 646 | QSignalSpy spyStartProcess(application.data(), SIGNAL(startProcessRequested())); | 646 | QSignalSpy spyStartProcess(application.data(), SIGNAL(startProcessRequested())); |
969 | 647 | 647 | ||
970 | 648 | 648 | ||
971 | === modified file 'tests/modules/ApplicationManager/application_manager_test.cpp' | |||
972 | --- tests/modules/ApplicationManager/application_manager_test.cpp 2017-02-21 18:46:30 +0000 | |||
973 | +++ tests/modules/ApplicationManager/application_manager_test.cpp 2017-03-31 21:11:21 +0000 | |||
974 | @@ -59,7 +59,7 @@ | |||
975 | 59 | inline void suspend(Application *application) { | 59 | inline void suspend(Application *application) { |
976 | 60 | application->setRequestedState(Application::RequestedSuspended); | 60 | application->setRequestedState(Application::RequestedSuspended); |
977 | 61 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); | 61 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState()); |
979 | 62 | static_cast<qtmir::Session*>(application->session())->doSuspend(); | 62 | static_cast<qtmir::Session*>(application->sessions()[0])->doSuspend(); |
980 | 63 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState()); | 63 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState()); |
981 | 64 | applicationManager.onProcessSuspended(application->appId()); | 64 | applicationManager.onProcessSuspended(application->appId()); |
982 | 65 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); | 65 | ASSERT_EQ(Application::InternalState::Suspended, application->internalState()); |
983 | @@ -85,6 +85,11 @@ | |||
984 | 85 | 85 | ||
985 | 86 | FakeMirSurface surface; | 86 | FakeMirSurface surface; |
986 | 87 | 87 | ||
987 | 88 | EXPECT_CALL(*taskController,appIdHasProcessId(QString(dialer_app_id), firstProcId)) | ||
988 | 89 | .WillRepeatedly(Return(true)); | ||
989 | 90 | EXPECT_CALL(*taskController,appIdHasProcessId(QString(dialer_app_id), secondProcId)) | ||
990 | 91 | .WillRepeatedly(Return(true)); | ||
991 | 92 | |||
992 | 88 | EXPECT_CALL(procInfo,command_line(firstProcId)) | 93 | EXPECT_CALL(procInfo,command_line(firstProcId)) |
993 | 89 | .Times(1) | 94 | .Times(1) |
994 | 90 | .WillOnce(Return(cmdLine)); | 95 | .WillOnce(Return(cmdLine)); |
995 | @@ -226,12 +231,22 @@ | |||
996 | 226 | const char third_app_id[] = "app3"; | 231 | const char third_app_id[] = "app3"; |
997 | 227 | QByteArray third_cmdLine( "/usr/bin/app3 --desktop_file_hint=app3"); | 232 | QByteArray third_cmdLine( "/usr/bin/app3 --desktop_file_hint=app3"); |
998 | 228 | 233 | ||
999 | 234 | ON_CALL(*taskController,appIdHasProcessId(QString(first_app_id), first_procId)).WillByDefault(Return(true)); | ||
1000 | 235 | ON_CALL(*taskController,appIdHasProcessId(QString(first_app_id), second_procId)).WillByDefault(Return(false)); | ||
1001 | 236 | ON_CALL(*taskController,appIdHasProcessId(QString(first_app_id), third_procId)).WillByDefault(Return(false)); | ||
1002 | 237 | |||
1003 | 238 | ON_CALL(*taskController,appIdHasProcessId(QString(second_app_id), second_procId)).WillByDefault(Return(true)); | ||
1004 | 239 | ON_CALL(*taskController,appIdHasProcessId(QString(second_app_id), first_procId)).WillByDefault(Return(false)); | ||
1005 | 240 | ON_CALL(*taskController,appIdHasProcessId(QString(second_app_id), third_procId)).WillByDefault(Return(false)); | ||
1006 | 241 | |||
1007 | 242 | ON_CALL(*taskController,appIdHasProcessId(QString(third_app_id), third_procId)).WillByDefault(Return(true)); | ||
1008 | 243 | ON_CALL(*taskController,appIdHasProcessId(QString(third_app_id), first_procId)).WillByDefault(Return(false)); | ||
1009 | 244 | ON_CALL(*taskController,appIdHasProcessId(QString(third_app_id), second_procId)).WillByDefault(Return(false)); | ||
1010 | 245 | |||
1011 | 229 | EXPECT_CALL(procInfo,command_line(first_procId)) | 246 | EXPECT_CALL(procInfo,command_line(first_procId)) |
1012 | 230 | .Times(1) | 247 | .Times(1) |
1013 | 231 | .WillOnce(Return(first_cmdLine)); | 248 | .WillOnce(Return(first_cmdLine)); |
1014 | 232 | 249 | ||
1015 | 233 | ON_CALL(*taskController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | ||
1016 | 234 | |||
1017 | 235 | EXPECT_CALL(procInfo,command_line(second_procId)) | 250 | EXPECT_CALL(procInfo,command_line(second_procId)) |
1018 | 236 | .Times(1) | 251 | .Times(1) |
1019 | 237 | .WillOnce(Return(second_cmdLine)); | 252 | .WillOnce(Return(second_cmdLine)); |
1020 | @@ -257,12 +272,12 @@ | |||
1021 | 257 | Application * secondApp = applicationManager.findApplication(second_app_id); | 272 | Application * secondApp = applicationManager.findApplication(second_app_id); |
1022 | 258 | Application * thirdApp = applicationManager.findApplication(third_app_id); | 273 | Application * thirdApp = applicationManager.findApplication(third_app_id); |
1023 | 259 | 274 | ||
1027 | 260 | EXPECT_EQ(firstAppInfo.application(), firstApp->session()->session()); | 275 | EXPECT_EQ(firstAppInfo.application(), firstApp->sessions()[0]->session()); |
1028 | 261 | EXPECT_EQ(secondAppInfo.application(), secondApp->session()->session()); | 276 | EXPECT_EQ(secondAppInfo.application(), secondApp->sessions()[0]->session()); |
1029 | 262 | EXPECT_EQ(thirdAppInfo.application(), thirdApp->session()->session()); | 277 | EXPECT_EQ(thirdAppInfo.application(), thirdApp->sessions()[0]->session()); |
1030 | 263 | } | 278 | } |
1031 | 264 | 279 | ||
1033 | 265 | TEST_F(ApplicationManagerTests,two_session_on_one_application) | 280 | TEST_F(ApplicationManagerTests,two_sessions_on_one_application) |
1034 | 266 | { | 281 | { |
1035 | 267 | int argc = 0; | 282 | int argc = 0; |
1036 | 268 | char* argv[0]; | 283 | char* argv[0]; |
1037 | @@ -275,28 +290,30 @@ | |||
1038 | 275 | 290 | ||
1039 | 276 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | 291 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); |
1040 | 277 | 292 | ||
1042 | 278 | ON_CALL(*taskController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 293 | ON_CALL(*taskController,appIdHasProcessId(QString(an_app_id), a_procId)).WillByDefault(Return(true)); |
1043 | 279 | 294 | ||
1044 | 280 | bool authed = true; | 295 | bool authed = true; |
1045 | 281 | 296 | ||
1046 | 282 | auto firstAppInfo = createApplicationInfoFor("Oo", a_procId); | 297 | auto firstAppInfo = createApplicationInfoFor("Oo", a_procId); |
1047 | 283 | auto secondAppInfo = createApplicationInfoFor("oO", a_procId); | 298 | auto secondAppInfo = createApplicationInfoFor("oO", a_procId); |
1048 | 299 | |||
1049 | 284 | applicationManager.authorizeSession(a_procId, authed); | 300 | applicationManager.authorizeSession(a_procId, authed); |
1050 | 285 | |||
1051 | 286 | taskController->onSessionStarting(firstAppInfo); | 301 | taskController->onSessionStarting(firstAppInfo); |
1052 | 302 | |||
1053 | 303 | applicationManager.authorizeSession(a_procId, authed); | ||
1054 | 287 | taskController->onSessionStarting(secondAppInfo); | 304 | taskController->onSessionStarting(secondAppInfo); |
1055 | 288 | 305 | ||
1056 | 289 | Application * the_app = applicationManager.findApplication(an_app_id); | 306 | Application * the_app = applicationManager.findApplication(an_app_id); |
1057 | 290 | 307 | ||
1058 | 291 | EXPECT_EQ(true, authed); | 308 | EXPECT_EQ(true, authed); |
1060 | 292 | EXPECT_EQ(secondAppInfo.application(), the_app->session()->session()); | 309 | EXPECT_EQ(2, the_app->sessions().count()); |
1061 | 293 | 310 | ||
1062 | 294 | taskController->onSessionStopping(firstAppInfo); | 311 | taskController->onSessionStopping(firstAppInfo); |
1063 | 295 | taskController->onSessionStopping(secondAppInfo); | 312 | taskController->onSessionStopping(secondAppInfo); |
1064 | 296 | qtApp.sendPostedEvents(nullptr, QEvent::DeferredDelete); | 313 | qtApp.sendPostedEvents(nullptr, QEvent::DeferredDelete); |
1065 | 297 | } | 314 | } |
1066 | 298 | 315 | ||
1068 | 299 | TEST_F(ApplicationManagerTests,two_session_on_one_application_after_starting) | 316 | TEST_F(ApplicationManagerTests,two_sessions_on_one_application_after_starting) |
1069 | 300 | { | 317 | { |
1070 | 301 | int argc = 0; | 318 | int argc = 0; |
1071 | 302 | char* argv[0]; | 319 | char* argv[0]; |
1072 | @@ -310,24 +327,30 @@ | |||
1073 | 310 | 327 | ||
1074 | 311 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); | 328 | ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd)); |
1075 | 312 | 329 | ||
1077 | 313 | ON_CALL(*taskController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 330 | ON_CALL(*taskController,appIdHasProcessId(QString(an_app_id), a_procId)).WillByDefault(Return(true)); |
1078 | 314 | 331 | ||
1079 | 315 | bool authed = true; | 332 | bool authed = true; |
1080 | 316 | 333 | ||
1081 | 317 | auto firstAppInfo = createApplicationInfoFor("Oo", a_procId); | 334 | auto firstAppInfo = createApplicationInfoFor("Oo", a_procId); |
1082 | 318 | auto secondAppInfo = createApplicationInfoFor("oO", a_procId); | 335 | auto secondAppInfo = createApplicationInfoFor("oO", a_procId); |
1083 | 336 | |||
1084 | 319 | applicationManager.authorizeSession(a_procId, authed); | 337 | applicationManager.authorizeSession(a_procId, authed); |
1085 | 320 | |||
1086 | 321 | taskController->onSessionStarting(firstAppInfo); | 338 | taskController->onSessionStarting(firstAppInfo); |
1087 | 339 | |||
1088 | 340 | EXPECT_EQ(true, authed); | ||
1089 | 341 | |||
1090 | 322 | onSessionCreatedSurface(firstAppInfo, &aSurface); | 342 | onSessionCreatedSurface(firstAppInfo, &aSurface); |
1091 | 323 | aSurface.setReady(); | 343 | aSurface.setReady(); |
1092 | 344 | |||
1093 | 345 | Application * the_app = applicationManager.findApplication(an_app_id); | ||
1094 | 346 | EXPECT_EQ(1, the_app->sessions().count()); | ||
1095 | 347 | |||
1096 | 348 | applicationManager.authorizeSession(a_procId, authed); | ||
1097 | 324 | taskController->onSessionStarting(secondAppInfo); | 349 | taskController->onSessionStarting(secondAppInfo); |
1098 | 325 | 350 | ||
1099 | 326 | Application * the_app = applicationManager.findApplication(an_app_id); | ||
1100 | 327 | |||
1101 | 328 | EXPECT_EQ(true, authed); | 351 | EXPECT_EQ(true, authed); |
1102 | 329 | EXPECT_EQ(Application::Running, the_app->state()); | 352 | EXPECT_EQ(Application::Running, the_app->state()); |
1104 | 330 | EXPECT_EQ(firstAppInfo.application(), the_app->session()->session()); | 353 | EXPECT_EQ(2, the_app->sessions().count()); |
1105 | 331 | 354 | ||
1106 | 332 | taskController->onSessionStopping(firstAppInfo); | 355 | taskController->onSessionStopping(firstAppInfo); |
1107 | 333 | taskController->onSessionStopping(secondAppInfo); | 356 | taskController->onSessionStopping(secondAppInfo); |
1108 | @@ -345,7 +368,7 @@ | |||
1109 | 345 | .Times(1) | 368 | .Times(1) |
1110 | 346 | .WillOnce(Return(cmdLine)); | 369 | .WillOnce(Return(cmdLine)); |
1111 | 347 | 370 | ||
1113 | 348 | ON_CALL(*taskController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 371 | ON_CALL(*taskController,appIdHasProcessId(QString("app"), procId)).WillByDefault(Return(true)); |
1114 | 349 | 372 | ||
1115 | 350 | bool authed = true; | 373 | bool authed = true; |
1116 | 351 | 374 | ||
1117 | @@ -383,7 +406,9 @@ | |||
1118 | 383 | .Times(1) | 406 | .Times(1) |
1119 | 384 | .WillOnce(Return(first_cmdLine)); | 407 | .WillOnce(Return(first_cmdLine)); |
1120 | 385 | 408 | ||
1122 | 386 | ON_CALL(*taskController,appIdHasProcessId(_,_)).WillByDefault(Return(false)); | 409 | ON_CALL(*taskController,appIdHasProcessId(QString("app1"), first_procId)).WillByDefault(Return(true)); |
1123 | 410 | ON_CALL(*taskController,appIdHasProcessId(QString("app2"), second_procId)).WillByDefault(Return(true)); | ||
1124 | 411 | ON_CALL(*taskController,appIdHasProcessId(QString("app3"), third_procId)).WillByDefault(Return(true)); | ||
1125 | 387 | 412 | ||
1126 | 388 | EXPECT_CALL(procInfo,command_line(second_procId)) | 413 | EXPECT_CALL(procInfo,command_line(second_procId)) |
1127 | 389 | .Times(1) | 414 | .Times(1) |
1128 | @@ -718,7 +743,7 @@ | |||
1129 | 718 | 743 | ||
1130 | 719 | // Check application state and session are correctly set | 744 | // Check application state and session are correctly set |
1131 | 720 | Application *theApp = applicationManager.findApplication(appId); | 745 | Application *theApp = applicationManager.findApplication(appId); |
1133 | 721 | EXPECT_EQ(theApp->session()->session(), appInfo.application()); | 746 | EXPECT_EQ(theApp->sessions()[0]->session(), appInfo.application()); |
1134 | 722 | EXPECT_EQ(theApp->focused(), false); | 747 | EXPECT_EQ(theApp->focused(), false); |
1135 | 723 | } | 748 | } |
1136 | 724 | 749 | ||
1137 | @@ -1115,6 +1140,8 @@ | |||
1138 | 1115 | QByteArray cmdLine("/usr/bin/testApp --desktop_file_hint="); | 1140 | QByteArray cmdLine("/usr/bin/testApp --desktop_file_hint="); |
1139 | 1116 | cmdLine = cmdLine.append(appId); | 1141 | cmdLine = cmdLine.append(appId); |
1140 | 1117 | 1142 | ||
1141 | 1143 | ON_CALL(*taskController,appIdHasProcessId(appId, procId)).WillByDefault(Return(true)); | ||
1142 | 1144 | |||
1143 | 1118 | // Set up Mocks & signal watcher | 1145 | // Set up Mocks & signal watcher |
1144 | 1119 | EXPECT_CALL(procInfo,command_line(procId)) | 1146 | EXPECT_CALL(procInfo,command_line(procId)) |
1145 | 1120 | .Times(1) | 1147 | .Times(1) |
1146 | @@ -1181,7 +1208,7 @@ | |||
1147 | 1181 | 1208 | ||
1148 | 1182 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, app->internalState()); | 1209 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, app->internalState()); |
1149 | 1183 | 1210 | ||
1151 | 1184 | static_cast<qtmir::Session*>(app->session())->doSuspend(); | 1211 | static_cast<qtmir::Session*>(app->sessions()[0])->doSuspend(); |
1152 | 1185 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, app->internalState()); | 1212 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, app->internalState()); |
1153 | 1186 | 1213 | ||
1154 | 1187 | applicationManager.onProcessSuspended(app->appId()); | 1214 | applicationManager.onProcessSuspended(app->appId()); |
1155 | @@ -1412,10 +1439,10 @@ | |||
1156 | 1412 | 1439 | ||
1157 | 1413 | // Session should have called deleteLater() on itself, as it's zombie and doesn't hold any surface | 1440 | // Session should have called deleteLater() on itself, as it's zombie and doesn't hold any surface |
1158 | 1414 | // But DeferredDelete is special: likes to be called out specifically or it won't come out | 1441 | // But DeferredDelete is special: likes to be called out specifically or it won't come out |
1160 | 1415 | qtApp.sendPostedEvents(app->session(), QEvent::DeferredDelete); | 1442 | qtApp.sendPostedEvents(app->sessions()[0], QEvent::DeferredDelete); |
1161 | 1416 | qtApp.sendPostedEvents(); | 1443 | qtApp.sendPostedEvents(); |
1162 | 1417 | 1444 | ||
1164 | 1418 | ASSERT_EQ(app->session(), nullptr); | 1445 | ASSERT_EQ(app->sessions().count(), 0); |
1165 | 1419 | 1446 | ||
1166 | 1420 | QSignalSpy focusRequestSpy(&applicationManager, SIGNAL(focusRequested(const QString &))); | 1447 | QSignalSpy focusRequestSpy(&applicationManager, SIGNAL(focusRequested(const QString &))); |
1167 | 1421 | 1448 | ||
1168 | @@ -1461,7 +1488,7 @@ | |||
1169 | 1461 | the_app->setRequestedState(Application::RequestedSuspended); | 1488 | the_app->setRequestedState(Application::RequestedSuspended); |
1170 | 1462 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, the_app->internalState()); | 1489 | ASSERT_EQ(Application::InternalState::SuspendingWaitSession, the_app->internalState()); |
1171 | 1463 | 1490 | ||
1173 | 1464 | static_cast<qtmir::Session*>(the_app->session())->doSuspend(); | 1491 | static_cast<qtmir::Session*>(the_app->sessions()[0])->doSuspend(); |
1174 | 1465 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, the_app->internalState()); | 1492 | ASSERT_EQ(Application::InternalState::SuspendingWaitProcess, the_app->internalState()); |
1175 | 1466 | applicationManager.onProcessSuspended(the_app->appId()); | 1493 | applicationManager.onProcessSuspended(the_app->appId()); |
1176 | 1467 | ASSERT_EQ(Application::InternalState::Suspended, the_app->internalState()); | 1494 | ASSERT_EQ(Application::InternalState::Suspended, the_app->internalState()); |
1177 | @@ -1838,7 +1865,7 @@ | |||
1178 | 1838 | taskController->onSessionStarting(appInfo1); | 1865 | taskController->onSessionStarting(appInfo1); |
1179 | 1839 | 1866 | ||
1180 | 1840 | FakeMirSurface surface1; | 1867 | FakeMirSurface surface1; |
1182 | 1841 | surface1.setSession(app1->session()); | 1868 | surface1.setSession(app1->sessions()[0]); |
1183 | 1842 | onSessionCreatedSurface(appInfo1, &surface1); | 1869 | onSessionCreatedSurface(appInfo1, &surface1); |
1184 | 1843 | surface1.setReady(); | 1870 | surface1.setReady(); |
1185 | 1844 | 1871 | ||
1186 | @@ -1864,7 +1891,7 @@ | |||
1187 | 1864 | taskController->onSessionStarting(appInfo2); | 1891 | taskController->onSessionStarting(appInfo2); |
1188 | 1865 | 1892 | ||
1189 | 1866 | FakeMirSurface surface2; | 1893 | FakeMirSurface surface2; |
1191 | 1867 | surface2.setSession(app2->session()); | 1894 | surface2.setSession(app2->sessions()[0]); |
1192 | 1868 | onSessionCreatedSurface(appInfo2, &surface2); | 1895 | onSessionCreatedSurface(appInfo2, &surface2); |
1193 | 1869 | surface2.setReady(); | 1896 | surface2.setReady(); |
1194 | 1870 | 1897 |
PASSED: Continuous integration, rev:636 /unity8- jenkins. ubuntu. com/job/ lp-qtmir- ci/652/ /unity8- jenkins. ubuntu. com/job/ build/4810 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/4838 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 4650/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/4650/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 4650/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/4650/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 4650/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/4650 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/4650/ artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-qtmir- ci/652/ rebuild
https:/