Merge lp:~alan-griffiths/miral/test-active-window into lp:miral

Proposed by Alan Griffiths
Status: Merged
Approved by: Gerry Boland
Approved revision: 452
Merged at revision: 450
Proposed branch: lp:~alan-griffiths/miral/test-active-window
Merge into: lp:miral
Diff against target: 231 lines (+192/-1)
3 files modified
miral/basic_window_manager.cpp (+10/-0)
test/CMakeLists.txt (+3/-1)
test/active_window.cpp (+179/-0)
To merge this branch: bzr merge lp:~alan-griffiths/miral/test-active-window
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
Cemil Azizoglu (community) Approve
Review via email: mp+310905@code.launchpad.net

Commit message

Add some initial tests of tools.active_window() and fixes that make them pass

Description of the change

Add some initial tests of tools.active_window() and fixes that make them pass

Experimenting with mircade I found that restoring the only window from a hidden state left active_window() unset. So these initial tests cover this minimal case and the fixture is ready to support additional tests (which I plan to work on soon).

To post a comment you must log in.
450. By Alan Griffiths

tweak code

451. By Alan Griffiths

 More tests, tighter conditions

452. By Alan Griffiths

Ensure a single window is notified of focus loss when hidden

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Looks good

review: Approve
Revision history for this message
Gerry Boland (gerboland) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'miral/basic_window_manager.cpp'
2--- miral/basic_window_manager.cpp 2016-11-15 12:19:31 +0000
3+++ miral/basic_window_manager.cpp 2016-11-16 12:50:51 +0000
4@@ -863,6 +863,9 @@
5 return;
6 }
7
8+ bool const was_hidden = window_info.state() == mir_surface_state_hidden ||
9+ window_info.state() == mir_surface_state_minimized;
10+
11 policy->advise_state_change(window_info, value);
12 window_info.state(value);
13
14@@ -886,11 +889,18 @@
15 auto const w = candidate;
16 return !(select_active_window(w));
17 });
18+
19+ if (window == active_window())
20+ select_active_window({});
21+
22+ mru_active_windows.erase(window);
23 }
24 break;
25
26 default:
27 mir_surface->show();
28+ if (was_hidden && !active_window())
29+ select_active_window(window);
30 }
31 }
32
33
34=== modified file 'test/CMakeLists.txt'
35--- test/CMakeLists.txt 2016-11-15 12:18:29 +0000
36+++ test/CMakeLists.txt 2016-11-16 12:50:51 +0000
37@@ -40,7 +40,9 @@
38 modify_window_state.cpp
39 test_server.cpp test_server.h
40 test_window_manager_tools.h
41- display_reconfiguration.cpp)
42+ display_reconfiguration.cpp
43+ active_window.cpp
44+)
45
46 target_link_libraries(miral-test
47 ${MIRTEST_LDFLAGS}
48
49=== added file 'test/active_window.cpp'
50--- test/active_window.cpp 1970-01-01 00:00:00 +0000
51+++ test/active_window.cpp 2016-11-16 12:50:51 +0000
52@@ -0,0 +1,179 @@
53+/*
54+ * Copyright © 2016 Canonical Ltd.
55+ *
56+ * This program is free software: you can redistribute it and/or modify it
57+ * under the terms of the GNU General Public License version 3,
58+ * as published by the Free Software Foundation.
59+ *
60+ * This program is distributed in the hope that it will be useful,
61+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
62+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63+ * GNU General Public License for more details.
64+ *
65+ * You should have received a copy of the GNU General Public License
66+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
67+ *
68+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
69+ */
70+
71+#include "test_server.h"
72+
73+#include <miral/toolkit/surface.h>
74+#include <miral/toolkit/surface_spec.h>
75+#include <mir_toolkit/mir_buffer_stream.h>
76+
77+#include <miral/application_info.h>
78+
79+#include <mir/test/signal.h>
80+
81+#include <gtest/gtest.h>
82+
83+using namespace testing;
84+using namespace miral::toolkit;
85+using namespace std::chrono_literals;
86+
87+namespace
88+{
89+class FocusChangeSync
90+{
91+public:
92+ void exec(std::function<void()> const& f)
93+ {
94+ signal.reset();
95+ f();
96+ signal.wait_for(100ms);
97+ }
98+
99+ static void raise_signal_on_focus_change(MirSurface* /*surface*/, MirEvent const* event, void* context)
100+ {
101+ if (mir_event_get_type(event) == mir_event_type_surface &&
102+ mir_surface_event_get_attribute(mir_event_get_surface_event(event)) == mir_surface_attrib_focus)
103+ {
104+ ((FocusChangeSync*)context)->signal.raise();
105+ }
106+ }
107+
108+ auto signal_raised() -> bool { return signal.raised(); }
109+
110+private:
111+ mir::test::Signal signal;
112+};
113+
114+struct ActiveWindow : public miral::TestServer
115+{
116+ FocusChangeSync sync1;
117+ FocusChangeSync sync2;
118+
119+ auto create_surface(Connection const& connection, char const* name, FocusChangeSync& sync) -> Surface
120+ {
121+ auto const spec = SurfaceSpec::for_normal_surface(connection, 50, 50, mir_pixel_format_argb_8888)
122+ .set_buffer_usage(mir_buffer_usage_software)
123+ .set_event_handler(&FocusChangeSync::raise_signal_on_focus_change, &sync)
124+ .set_name(name);
125+
126+ Surface const surface{spec.create_surface()};
127+
128+ sync.exec([&]{ mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface)); });
129+ EXPECT_TRUE(sync.signal_raised());
130+
131+ return surface;
132+ }
133+
134+ void assert_no_active_window()
135+ {
136+ invoke_tools([&](miral::WindowManagerTools& tools)
137+ {
138+ auto const window = tools.active_window();
139+ ASSERT_FALSE(window);
140+ });
141+ }
142+
143+ void assert_active_window_is(char const* const name)
144+ {
145+ invoke_tools([&](miral::WindowManagerTools& tools)
146+ {
147+ auto const window = tools.active_window();
148+ ASSERT_TRUE(window);
149+ auto const& window_info = tools.info_for(window);
150+ ASSERT_THAT(window_info.name(), Eq(name));
151+ });
152+ }
153+};
154+}
155+
156+TEST_F(ActiveWindow, a_single_window_when_ready_becomes_active)
157+{
158+ char const* const test_name = __PRETTY_FUNCTION__;
159+ auto const connection = connect_client(test_name);
160+
161+ auto const surface = create_surface(connection, test_name, sync1);
162+
163+ assert_active_window_is(test_name);
164+}
165+
166+TEST_F(ActiveWindow, a_single_window_when_hiding_becomes_inactive)
167+{
168+ char const* const test_name = __PRETTY_FUNCTION__;
169+ auto const connection = connect_client(test_name);
170+ auto const surface = create_surface(connection, test_name, sync1);
171+
172+ sync1.exec([&]{ mir_surface_set_state(surface, mir_surface_state_hidden); });
173+
174+ EXPECT_TRUE(sync1.signal_raised());
175+ assert_no_active_window();
176+}
177+
178+TEST_F(ActiveWindow, a_single_window_when_unhiding_becomes_active)
179+{
180+ char const* const test_name = __PRETTY_FUNCTION__;
181+ auto const connection = connect_client(test_name);
182+ auto const surface = create_surface(connection, test_name, sync1);
183+ sync1.exec([&]{ mir_surface_set_state(surface, mir_surface_state_hidden); });
184+
185+ sync1.exec([&]{ mir_surface_set_state(surface, mir_surface_state_restored); });
186+ EXPECT_TRUE(sync1.signal_raised());
187+
188+ assert_active_window_is(test_name);
189+}
190+
191+TEST_F(ActiveWindow, a_second_window_when_ready_becomes_active)
192+{
193+ char const* const test_name = __PRETTY_FUNCTION__;
194+ auto const connection = connect_client(test_name);
195+
196+ auto const first_surface = create_surface(connection, "first", sync1);
197+ auto const surface = create_surface(connection, test_name, sync2);
198+
199+ assert_active_window_is(test_name);
200+}
201+
202+TEST_F(ActiveWindow, a_second_window_hiding_makes_first_active)
203+{
204+ char const* const test_name = __PRETTY_FUNCTION__;
205+ auto const connection = connect_client(test_name);
206+
207+ auto const first_surface = create_surface(connection, test_name, sync1);
208+ auto const surface = create_surface(connection, "second", sync2);
209+
210+ sync2.exec([&]{ mir_surface_set_state(surface, mir_surface_state_hidden); });
211+
212+ EXPECT_TRUE(sync2.signal_raised());
213+ assert_active_window_is(test_name);
214+}
215+
216+TEST_F(ActiveWindow, a_second_window_unhiding_leaves_first_active)
217+{
218+ char const* const test_name = __PRETTY_FUNCTION__;
219+ auto const connection = connect_client(test_name);
220+
221+ auto const first_surface = create_surface(connection, test_name, sync1);
222+ auto const surface = create_surface(connection, "second", sync2);
223+
224+ sync1.exec([&]{ mir_surface_set_state(surface, mir_surface_state_hidden); });
225+
226+ // Expect this to timeout
227+ sync2.exec([&]{ mir_surface_set_state(surface, mir_surface_state_restored); });
228+
229+ EXPECT_THAT(sync2.signal_raised(), Eq(false));
230+ assert_active_window_is(test_name);
231+}

Subscribers

People subscribed via source and target branches