Merge lp:~mterry/unity-mir/dont-hide-focused-apps into lp:unity-mir

Proposed by Michael Terry
Status: Merged
Approved by: Gerry Boland
Approved revision: 226
Merged at revision: 224
Proposed branch: lp:~mterry/unity-mir/dont-hide-focused-apps
Merge into: lp:unity-mir
Diff against target: 188 lines (+88/-10)
4 files modified
src/modules/Unity/Application/application.cpp (+0/-4)
src/modules/Unity/Application/application_manager.cpp (+12/-5)
src/modules/Unity/Application/application_manager.h (+1/-1)
tests/application_manager_test.cpp (+75/-0)
To merge this branch: bzr merge lp:~mterry/unity-mir/dont-hide-focused-apps
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+220130@code.launchpad.net

Commit message

Separate suspend logic from visibility logic, to allow top app to remain visible even when suspended.

Description of the change

Separate suspend logic from visibility logic, to allow top app to remain visible even when suspended.

When testing the split greeter, Saviq noticed that the user session would go black if an app was open while the greeter was up (sliding the greeter lets you peek at user session).

This is because unity-mir hides() app sessions when they are suspended to optimized compositing. But the top app should remain visible for cross-session compositing like the greeter wants to do.

So don't automatically hide() when suspending, but instead only hide() if we are unfocusing an app to bring another app above it.

(We still automatically show() when resuming because we want to ensure that the app is visible now.)

== Checklist ==
 * 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?
 - NA

To post a comment you must log in.
222. By Michael Terry

Separate suspend logic from visibility logic, to allow top app to remain visible even when suspended.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

It reads strange that you call setVisible(true) in Application, but setVisible(false) in ApplicationManager. Could you make this more consistent please?

I'd appreciate you adding a test or two, to verify nothing breaks.

review: Needs Fixing
223. By Michael Terry

Move setVisible call to application manager

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
224. By Michael Terry

Add some tests

Revision history for this message
Michael Terry (mterry) wrote :

OK, setVisible calls moved out, and a couple tests added.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

+ std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("Oo", a_procId);
The "Oo" not needed, jut an empty string will do

+ EXPECT_EQ(true, the_app->visible());
Could you please switch the arguments around?

Am testing now

225. By Michael Terry

Simplify test

Revision history for this message
Michael Terry (mterry) wrote :

> The "Oo" not needed, jut an empty string will do

Ah, OK. Fixed. Just copy and paste junk.

> Could you please switch the arguments around?

Really? Looking at the other tests, it seems common to have a "static value" on left and the interesting call on right.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

> > Could you please switch the arguments around?
>
> Really? Looking at the other tests, it seems common to have a "static value"
> on left and the interesting call on right.
Yeah sorry I know, I want to standardize things to the "value to check" and "correct value" order - see the newer tests I added recently.

226. By Michael Terry

Swap test value placement

Revision history for this message
Michael Terry (mterry) wrote :

Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

Thank you. Approved!

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Y
 * Did CI run pass? If not, please explain why.
Y

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/modules/Unity/Application/application.cpp'
2--- src/modules/Unity/Application/application.cpp 2014-05-19 12:36:27 +0000
3+++ src/modules/Unity/Application/application.cpp 2014-05-26 12:21:08 +0000
4@@ -223,9 +223,6 @@
5 case Application::Suspended:
6 if (m_state == Application::Running) {
7 session()->set_lifecycle_state(mir_lifecycle_state_will_suspend);
8-
9- session()->hide();
10-
11 m_suspendTimer->start(3000);
12 }
13 break;
14@@ -236,7 +233,6 @@
15 if (m_state == Application::Suspended) {
16 resume();
17 session()->set_lifecycle_state(mir_lifecycle_state_resumed);
18- session()->show();
19 } else if (m_state == Application::Stopped) {
20 respawn();
21 state = Application::Starting;
22
23=== modified file 'src/modules/Unity/Application/application_manager.cpp'
24--- src/modules/Unity/Application/application_manager.cpp 2014-05-19 15:30:15 +0000
25+++ src/modules/Unity/Application/application_manager.cpp 2014-05-26 12:21:08 +0000
26@@ -345,20 +345,22 @@
27 }
28 }
29
30-void ApplicationManager::suspendApplication(Application *application)
31+bool ApplicationManager::suspendApplication(Application *application)
32 {
33 if (application == nullptr)
34- return;
35+ return false;
36
37 updateScreenshot(application->appId());
38
39 DLOG("ApplicationManager::suspend(this=%p, application(%p)->appId(%s) )",this, application, qPrintable(application->appId()));
40 // Present in exceptions list, return.
41 if (!m_lifecycleExceptions.filter(application->appId().section('_',0,0)).empty())
42- return;
43+ return false;
44
45 if (application->state() == Application::Running)
46 application->setState(Application::Suspended);
47+
48+ return true;
49 }
50
51 void ApplicationManager::resumeApplication(Application *application)
52@@ -366,8 +368,10 @@
53 if (application == nullptr)
54 return;
55
56- if (application->state() != Application::Running)
57+ if (application->state() != Application::Running) {
58+ application->setVisible(true);
59 application->setState(Application::Running);
60+ }
61 }
62
63 bool ApplicationManager::focusApplication(const QString &inputAppId)
64@@ -644,6 +648,7 @@
65 // If app Stopped, trust that upstart-app-launch respawns it itself, and AppManager will
66 // be notified of that through the onProcessStarting slot. Else resume.
67 if (application->state() == Application::Suspended) {
68+ application->setVisible(true);
69 application->setState(Application::Running);
70 }
71 }
72@@ -910,7 +915,8 @@
73 // set state of previously focused app to suspended
74 if (m_focusedApplication && m_lifecycleExceptions.filter(m_focusedApplication->appId().section('_',0,0)).empty()) {
75 Application *lastApplication = applicationForStage(application->stage());
76- suspendApplication(lastApplication);
77+ if (suspendApplication(lastApplication))
78+ lastApplication->setVisible(false);
79 }
80
81 if (application->stage() == Application::MainStage)
82@@ -920,6 +926,7 @@
83
84 m_focusedApplication = application;
85 m_focusedApplication->setFocused(true);
86+ m_focusedApplication->setVisible(true);
87 m_focusedApplication->setState(Application::Running);
88 move(m_applications.indexOf(application), 0);
89 Q_EMIT focusedApplicationIdChanged();
90
91=== modified file 'src/modules/Unity/Application/application_manager.h'
92--- src/modules/Unity/Application/application_manager.h 2014-05-19 15:30:15 +0000
93+++ src/modules/Unity/Application/application_manager.h 2014-05-26 12:21:08 +0000
94@@ -109,7 +109,7 @@
95 unitymir::Application* findApplicationWithPid(const qint64 pid);
96
97 // Internal helpers
98- void suspendApplication(Application *application);
99+ bool suspendApplication(Application *application);
100 void resumeApplication(Application *application);
101 int panelHeight();
102 QSize displaySize() const { return m_displaySize; }
103
104=== modified file 'tests/application_manager_test.cpp'
105--- tests/application_manager_test.cpp 2014-05-20 10:21:20 +0000
106+++ tests/application_manager_test.cpp 2014-05-26 12:21:08 +0000
107@@ -474,6 +474,81 @@
108
109 }
110
111+TEST_F(ApplicationManagerTests,suspend_does_not_hide)
112+{
113+ using namespace ::testing;
114+ quint64 a_procId = 5921;
115+ const char an_app_id[] = "some_app";
116+ QByteArray a_cmd("/usr/bin/app1 --desktop_file_hint=some_app");
117+ std::shared_ptr<mir::scene::Surface> aSurface(nullptr);
118+
119+ ON_CALL(procInfo,command_line(_)).WillByDefault(Return(a_cmd));
120+
121+ ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false));
122+
123+ bool authed = true;
124+
125+ std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("", a_procId);
126+ applicationManager.authorizeSession(a_procId, authed);
127+
128+ applicationManager.onSessionStarting(first_session);
129+ applicationManager.onSessionCreatedSurface(first_session.get(), aSurface);
130+
131+ Application * the_app = applicationManager.findApplication(an_app_id);
132+
133+ EXPECT_EQ(the_app->visible(), true);
134+ EXPECT_EQ(the_app->state(), Application::Running);
135+
136+ applicationManager.setSuspended(true);
137+
138+ EXPECT_EQ(the_app->visible(), true);
139+ EXPECT_EQ(the_app->state(), Application::Suspended);
140+}
141+
142+TEST_F(ApplicationManagerTests,focus_hides_old_app)
143+{
144+ using namespace ::testing;
145+ quint64 first_procId = 5921;
146+ quint64 second_procId = 5922;
147+ const char first_appId[] = "app1";
148+ const char second_appId[] = "app2";
149+ std::shared_ptr<mir::scene::Surface> aSurface(nullptr);
150+ QByteArray first_cmdLine("/usr/bin/app1 --desktop_file_hint=app1");
151+ QByteArray second_cmdLine("/usr/bin/app2--desktop_file_hint=app2");
152+
153+ EXPECT_CALL(procInfo,command_line(first_procId))
154+ .Times(1)
155+ .WillOnce(Return(first_cmdLine));
156+
157+ ON_CALL(appController,appIdHasProcessId(_,_)).WillByDefault(Return(false));
158+
159+ EXPECT_CALL(procInfo,command_line(second_procId))
160+ .Times(1)
161+ .WillOnce(Return(second_cmdLine));
162+
163+ bool authed = true;
164+
165+ std::shared_ptr<mir::scene::Session> first_session = std::make_shared<MockSession>("", first_procId);
166+ std::shared_ptr<mir::scene::Session> second_session = std::make_shared<MockSession>("", second_procId);
167+ applicationManager.authorizeSession(first_procId, authed);
168+ applicationManager.authorizeSession(second_procId, authed);
169+ applicationManager.onSessionStarting(first_session);
170+ applicationManager.onSessionStarting(second_session);
171+
172+ Application * first_app = applicationManager.findApplication(first_appId);
173+ Application * second_app = applicationManager.findApplication(second_appId);
174+
175+ // Confirm that both start visible, but also mark first_app as the
176+ // active app by creating a surface for its session.
177+ applicationManager.onSessionCreatedSurface(first_session.get(), aSurface);
178+ EXPECT_EQ(first_app->visible(), true);
179+ EXPECT_EQ(second_app->visible(), true);
180+
181+ applicationManager.onSessionCreatedSurface(second_session.get(), aSurface);
182+ EXPECT_EQ(first_app->visible(), false);
183+ EXPECT_EQ(second_app->visible(), true);
184+}
185+
186 TEST_F(ApplicationManagerTests,requestFocusApplication)
187 {
188 using namespace ::testing;

Subscribers

People subscribed via source and target branches