Mir

Merge lp:~vanvugt/mir/surface-types into lp:~mir-team/mir/trunk

Proposed by Daniel van Vugt
Status: Superseded
Proposed branch: lp:~vanvugt/mir/surface-types
Merge into: lp:~mir-team/mir/trunk
Diff against target: 1561 lines (+838/-13)
48 files modified
debian/control (+12/-0)
debian/libmirserver-dev.install (+1/-0)
debian/mircommon-dev.install (+1/-0)
include/mir/frontend/application_mediator.h (+5/-0)
include/mir/frontend/application_mediator_report.h (+3/-0)
include/mir/logging/application_mediator_report.h (+2/-0)
include/mir/shell/application_session.h (+8/-1)
include/mir/shell/nullshell.h (+43/-0)
include/mir/shell/session.h (+3/-0)
include/mir/shell/session_manager.h (+4/-0)
include/mir/shell/session_store.h (+20/-0)
include/mir/shell/shell.h (+42/-0)
include/mir/shell/surface.h (+3/-0)
include/mir/surface.h (+48/-0)
include/mir/surfaces/surface.h (+7/-0)
include/mir_toolkit/mir_client_library.h (+19/-0)
src/CMakeLists.txt (+19/-3)
src/client/mir_client_library.cpp (+22/-0)
src/client/mir_surface.cpp (+47/-0)
src/client/mir_surface.h (+12/-0)
src/client/mir_wait_handle.cpp (+16/-5)
src/client/mir_wait_handle.h (+4/-1)
src/frontend/application_mediator.cpp (+27/-0)
src/frontend/null_application_mediator_report.cpp (+4/-0)
src/frontend/protobuf_message_processor.cpp (+4/-0)
src/logging/application_mediator_report.cpp (+5/-0)
src/protobuf/mir_protobuf.proto (+10/-0)
src/shell/CMakeLists.txt (+4/-0)
src/shell/application_session.cpp (+26/-1)
src/shell/nullshell.cpp (+49/-0)
src/shell/session_manager.cpp (+11/-1)
src/surfaces/proxy_surface.cpp (+11/-0)
src/surfaces/proxy_surface.h (+2/-0)
src/surfaces/surface.cpp (+38/-1)
tests/acceptance-tests/test_client_library.cpp (+66/-0)
tests/acceptance-tests/test_focus_management_api.cpp (+4/-0)
tests/behavior-tests/session_management_context.cpp (+5/-0)
tests/integration-tests/cucumber/test_session_management_context.cpp (+6/-0)
tests/unit-tests/CMakeLists.txt (+1/-0)
tests/unit-tests/client/CMakeLists.txt (+1/-0)
tests/unit-tests/client/test_client_mir_surface.cpp (+19/-0)
tests/unit-tests/client/test_wait_handle.cpp (+114/-0)
tests/unit-tests/frontend/test_application_mediator.cpp (+6/-0)
tests/unit-tests/frontend/test_application_mediator_gbm.cpp (+6/-0)
tests/unit-tests/sessions/test_application_session.cpp (+2/-0)
tests/unit-tests/shell/CMakeLists.txt (+5/-0)
tests/unit-tests/shell/test_nullshell.cpp (+53/-0)
tests/unit-tests/surfaces/test_surface.cpp (+18/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/surface-types
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+151166@code.launchpad.net

This proposal has been superseded by a proposal from 2013-03-07.

Commit message

Add support for surface types (to the client API, protocol and server).

This work will also form the foundation of supporting surface states and
necessitates a prototype of the beginnings of a shell interface.

Description of the change

THIS IS A PREVIEW

It's not intended for approval, but intended for early review. I need to write more test cases in the very least. However before then, I have a long weekend to see to :)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

87 === modified file 'include/mir/graphics/display.h'
...
94 +#include "mir/shell/shell.h"

This feels very wrong - I don't believe that graphics::Display needs to know about shell::Shell.

Unless there is a compelling reason for something different, there should be an interface in *graphics* that determines the functionality that graphics::Display needs, and that will be implemented by shell::Shell.

~~~~

102 + void set_shell(std::shared_ptr<mir::Shell> s);
103 + bool start_shell();
104 + void stop_shell();
105 + std::shared_ptr<mir::Shell> current_shell() const;

I find it very hard to believe that these are functions that belong to graphics::Display.

In addition, graphics::Display is an interface and should not provide an implementation. (It is used in compositing - it should probably be there, but that's an existing issue.)

~~~~

252 +#include <mir/surface.h>

Don't use system includes for our files.

~~~~

298 +#ifndef __MIR_COMMON_SURFACE_H__
299 +#define __MIR_COMMON_SURFACE_H__

Does not match project naming style

~~~~

307 + MIR_SURFACE_TYPE,
308 + MirSurfaceAttrib_ARRAYSIZE

Does not match project naming style

~~~~

608 === added file 'src/display.cpp'

This is a confusing place to implement mir::graphics::Display

~~~~

633 +using namespace mir;
634 +using namespace mir::graphics;
635 +using namespace mir::shell;

This is a very different style to the rest of the codebase. I don't like it as it isn't clear where the classes mentioned in the code come from. (It can also lead to free functions being defined in global namespace and not the intended namespace.)

~~~~

735 + auto const shell = graphics_display->current_shell();
736 + if (!shell->supports(attrib))
737 + BOOST_THROW_EXCEPTION(std::logic_error("Current shell does not "
738 + "support the specified surface "
739 + "attribute"));

Application logic doesn't belong in ApplicationMediator.

~~~

814 +message SurfaceSetting {
815 + required SurfaceId surfaceid = 1;
816 + required int32 attrib = 2;
817 + optional int32 ivalue = 3;
818 + // optional string svalue = 4; // Expected for future use
819 +
820 + optional string error = 127;
821 +}

As this is returned by the RPC framework all the fields should be optional (as, in the event of an exception, it may be the only field populated).

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Alan,

"Shell in Display"
I kind of agree. This was the last part I wrote and I later saw one or two alternative places to attach Shell other than inside Display. But from a conceptional standpoint, can we discuss why the "shell" is not a 1:1 part of a "display"?

"#include <mir/surface.h>"
Yes this is correct because it is included from a public system header (shell.h). Hence angle brackets are required.

"__MIR_COMMON_SURFACE_H__"
Yeah I can change the style no problem.

"MIR_SURFACE_TYPE"
This is C code. Not C++. What is the established convention for C-compatible enums that I should change to?

"src/display.cpp"
It's not really a confusing place because it's the same directory where other sources relating to it already reside. If I put display.cpp in a subdir then it has to be built into a static library and then bundled into the server library. Seems like an overkill for one small source file right now.

"using namespace mir"
I prefer this because it makes the code much more readable, and will argue to the very end that the convention seen in existing mir code is ugly, hard to read and more time-consuming to maintain. It is never confusing where a symbol comes from if it is only defined in one place in the project.

"Application logic doesn't belong in ApplicationMediator."
Yeah I had the same feeling. Just haven't yet found a cleaner place to put it where the logic had full access to all the objects in question.

"required vs optional"
I don't care enough to argue. Will change it.

All in all, I think that's a good initial review. Good only because I only disagree deeply with one of the points made.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2013-03-04 20:11:18 +0000
3+++ debian/control 2013-03-07 08:31:22 +0000
4@@ -56,11 +56,22 @@
5 .
6 Contains the shared library needed by server applications for Mir.
7
8+Package: mircommon-dev
9+Section: libdevel
10+Architecture: any
11+Depends: ${misc:Depends},
12+Description: Display server for Ubuntu - development headers
13+ Mir is a display server running on linux systems, with a focus on efficiency,
14+ robust operation and a well-defined driver model.
15+ .
16+ Contains header files required for server and/or client development.
17+
18 Package: libmirserver-dev
19 Section: libdevel
20 Architecture: any
21 Depends: libmirserver0 (= ${binary:Version}),
22 libmirprotobuf-dev (= ${source:Version}),
23+ mircommon-dev (= ${source:Version}),
24 ${misc:Depends},
25 Description: Display server for Ubuntu - development headers
26 Mir is a display server running on linux systems, with a focus on efficiency,
27@@ -84,6 +95,7 @@
28 Architecture: any
29 Depends: libmirclient0 (= ${binary:Version}),
30 libmirprotobuf-dev (= ${source:Version}),
31+ mircommon-dev (= ${source:Version}),
32 ${misc:Depends},
33 Description: Display server for Ubuntu - development headers
34 Mir is a display server running on linux systems, with a focus on efficiency,
35
36=== modified file 'debian/libmirserver-dev.install'
37--- debian/libmirserver-dev.install 2013-02-01 11:08:00 +0000
38+++ debian/libmirserver-dev.install 2013-03-07 08:31:22 +0000
39@@ -1,2 +1,3 @@
40+usr/include/mir/server
41 usr/lib/pkgconfig/mirserver.pc
42 usr/lib/libmirserver.so
43
44=== added file 'debian/mircommon-dev.install'
45--- debian/mircommon-dev.install 1970-01-01 00:00:00 +0000
46+++ debian/mircommon-dev.install 2013-03-07 08:31:22 +0000
47@@ -0,0 +1,1 @@
48+usr/include/mir/*.h
49
50=== modified file 'include/mir/frontend/application_mediator.h'
51--- include/mir/frontend/application_mediator.h 2013-03-06 12:25:34 +0000
52+++ include/mir/frontend/application_mediator.h 2013-03-07 08:31:22 +0000
53@@ -103,6 +103,11 @@
54 mir::protobuf::DRMAuthMagicStatus* response,
55 google::protobuf::Closure* done);
56
57+ void configure_surface(google::protobuf::RpcController* controller,
58+ const mir::protobuf::SurfaceSetting*,
59+ mir::protobuf::SurfaceSetting*,
60+ google::protobuf::Closure* done);
61+
62 private:
63 std::shared_ptr<shell::SessionStore> const session_store;
64 std::shared_ptr<graphics::Platform> const graphics_platform;
65
66=== modified file 'include/mir/frontend/application_mediator_report.h'
67--- include/mir/frontend/application_mediator_report.h 2013-03-04 16:02:02 +0000
68+++ include/mir/frontend/application_mediator_report.h 2013-03-07 08:31:22 +0000
69@@ -41,6 +41,7 @@
70 virtual void application_disconnect_called(std::string const& app_name) = 0;
71
72 virtual void application_drm_auth_magic_called(std::string const& app_name) = 0;
73+ virtual void application_configure_surface_called(std::string const& app_name) = 0;
74
75 virtual void application_error(
76 std::string const& app_name,
77@@ -63,6 +64,8 @@
78
79 virtual void application_drm_auth_magic_called(std::string const& app_name);
80
81+ virtual void application_configure_surface_called(std::string const& app_name);
82+
83 virtual void application_error(
84 std::string const& app_name,
85 char const* method,
86
87=== modified file 'include/mir/logging/application_mediator_report.h'
88--- include/mir/logging/application_mediator_report.h 2013-03-04 16:02:02 +0000
89+++ include/mir/logging/application_mediator_report.h 2013-03-07 08:31:22 +0000
90@@ -47,6 +47,8 @@
91
92 virtual void application_drm_auth_magic_called(std::string const& app_name);
93
94+ virtual void application_configure_surface_called(std::string const& app_name);
95+
96 virtual void application_error(
97 std::string const& app_name,
98 char const* method,
99
100=== modified file 'include/mir/shell/application_session.h'
101--- include/mir/shell/application_session.h 2013-03-06 12:25:34 +0000
102+++ include/mir/shell/application_session.h 2013-03-07 08:31:22 +0000
103@@ -25,6 +25,7 @@
104
105 namespace mir
106 {
107+class Shell;
108
109 namespace shell
110 {
111@@ -33,7 +34,10 @@
112 class ApplicationSession : public Session
113 {
114 public:
115- explicit ApplicationSession(std::shared_ptr<SurfaceFactory> const& surface_factory, std::string const& session_name);
116+ explicit ApplicationSession(
117+ std::shared_ptr<SurfaceFactory> const& surface_factory,
118+ std::string const& session_name,
119+ std::shared_ptr<mir::Shell> sh = nullptr);
120 ~ApplicationSession();
121
122 SurfaceId create_surface(SurfaceCreationParameters const& params);
123@@ -46,6 +50,8 @@
124 void hide();
125 void show();
126
127+ int configure_surface(SurfaceId id, MirSurfaceAttrib attrib, int value);
128+
129 protected:
130 ApplicationSession(ApplicationSession const&) = delete;
131 ApplicationSession& operator=(ApplicationSession const&) = delete;
132@@ -53,6 +59,7 @@
133 private:
134 std::shared_ptr<SurfaceFactory> const surface_factory;
135 std::string const session_name;
136+ std::shared_ptr<mir::Shell> shell;
137
138 SurfaceId next_id();
139
140
141=== added file 'include/mir/shell/nullshell.h'
142--- include/mir/shell/nullshell.h 1970-01-01 00:00:00 +0000
143+++ include/mir/shell/nullshell.h 2013-03-07 08:31:22 +0000
144@@ -0,0 +1,43 @@
145+/*
146+ * Null Shell
147+ *
148+ * Copyright © 2013 Canonical Ltd.
149+ *
150+ * This program is free software: you can redistribute it and/or modify
151+ * it under the terms of the GNU General Public License version 3 as
152+ * published by the Free Software Foundation.
153+ *
154+ * This program is distributed in the hope that it will be useful,
155+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
156+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157+ * GNU General Public License for more details.
158+ *
159+ * You should have received a copy of the GNU General Public License
160+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
161+ *
162+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
163+ */
164+
165+#ifndef MIR_SHELL_NULLSHELL_H_
166+#define MIR_SHELL_NULLSHELL_H_
167+
168+#include "mir/shell/shell.h"
169+
170+namespace mir
171+{
172+namespace shell
173+{
174+
175+class NullShell : public mir::Shell
176+{
177+public:
178+ ~NullShell();
179+
180+ bool supports(MirSurfaceAttrib attrib) const;
181+ bool supports(MirSurfaceAttrib attrib, int value) const;
182+};
183+
184+} // namespace shell
185+} // namespace mir
186+
187+#endif
188
189=== modified file 'include/mir/shell/session.h'
190--- include/mir/shell/session.h 2013-03-06 12:25:34 +0000
191+++ include/mir/shell/session.h 2013-03-07 08:31:22 +0000
192@@ -19,6 +19,7 @@
193 #ifndef MIR_SHELL_SESSION_H_
194 #define MIR_SHELL_SESSION_H_
195
196+#include "mir/surface.h" // for MirSurfaceAttrib
197 #include "mir/shell/surface_id.h"
198
199 #include <mutex>
200@@ -50,6 +51,8 @@
201 virtual void hide() = 0;
202 virtual void show() = 0;
203
204+ virtual int configure_surface(SurfaceId id, MirSurfaceAttrib attrib, int value) = 0;
205+
206 protected:
207 Session() = default;
208 Session(Session const&) = delete;
209
210=== modified file 'include/mir/shell/session_manager.h'
211--- include/mir/shell/session_manager.h 2013-03-06 12:25:34 +0000
212+++ include/mir/shell/session_manager.h 2013-03-07 08:31:22 +0000
213@@ -52,6 +52,8 @@
214 virtual void tag_session_with_lightdm_id(std::shared_ptr<Session> const& session, int id);
215 virtual void focus_session_with_lightdm_id(int id);
216
217+ virtual std::shared_ptr<mir::Shell> current_shell() const;
218+
219 void focus_next();
220
221 protected:
222@@ -64,6 +66,8 @@
223 std::shared_ptr<FocusSequence> const focus_sequence;
224 std::shared_ptr<FocusSetter> const focus_setter;
225
226+ mutable std::shared_ptr<mir::Shell> shell;
227+
228 std::mutex mutex;
229 std::weak_ptr<Session> focus_application;
230 typedef std::vector<std::pair<int, std::shared_ptr<Session>>> Tags;
231
232=== modified file 'include/mir/shell/session_store.h'
233--- include/mir/shell/session_store.h 2013-03-06 12:25:34 +0000
234+++ include/mir/shell/session_store.h 2013-03-07 08:31:22 +0000
235@@ -20,6 +20,7 @@
236 #define MIR_SHELL_SESSION_STORE_H_
237
238 #include <memory>
239+#include "mir/shell/shell.h"
240
241 namespace mir
242 {
243@@ -29,6 +30,23 @@
244
245 class Session;
246
247+/*
248+ * The word "Session" is overloaded and over-abstracted here. "Session" can
249+ * be used to represent either an application or a login. Both are sessional
250+ * concepts capable of creating and destroying surfaces. This seems
251+ * straightforward but what then is a SessionStore?
252+ *
253+ * A SessionStore is anything capable of opening and closing sessions. So by
254+ * the previous definition, a SessionStore could be any of:
255+ * - a single login (creates App sessions, but is also a session itself)
256+ * - a single seat (usually one per machine; creates login sessions)
257+ *
258+ * It seems feasible that in future someone will specialize Session and
259+ * SessionStore into more concrete classes like "Application", "Login" and
260+ * "Seat". That would be easier to comprehend, but is a job for another day.
261+ * - Daniel
262+ */
263+
264 class SessionStore
265 {
266 public:
267@@ -42,6 +60,8 @@
268
269 virtual void shutdown() = 0;
270
271+ virtual std::shared_ptr<mir::Shell> current_shell() const = 0;
272+
273 protected:
274 SessionStore() = default;
275 SessionStore(const SessionStore&) = delete;
276
277=== added file 'include/mir/shell/shell.h'
278--- include/mir/shell/shell.h 1970-01-01 00:00:00 +0000
279+++ include/mir/shell/shell.h 2013-03-07 08:31:22 +0000
280@@ -0,0 +1,42 @@
281+/*
282+ * Mir shell interface PUBLIC HEADER
283+ *
284+ * Copyright © 2013 Canonical Ltd.
285+ *
286+ * This program is free software: you can redistribute it and/or modify
287+ * it under the terms of the GNU General Public License version 3 as
288+ * published by the Free Software Foundation.
289+ *
290+ * This program is distributed in the hope that it will be useful,
291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
293+ * GNU General Public License for more details.
294+ *
295+ * You should have received a copy of the GNU General Public License
296+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
297+ *
298+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
299+ */
300+
301+#ifndef MIR_SHELL_SHELL_H_
302+#define MIR_SHELL_SHELL_H_
303+
304+#include <mir/surface.h>
305+
306+namespace mir
307+{
308+
309+class Shell
310+{
311+public:
312+ virtual ~Shell() {}
313+
314+ virtual bool supports(MirSurfaceAttrib attrib) const = 0;
315+ virtual bool supports(MirSurfaceAttrib attrib, int value) const = 0;
316+
317+ // TODO: Lots more will go here I guess.
318+};
319+
320+} // namespace mir
321+
322+#endif
323
324=== modified file 'include/mir/shell/surface.h'
325--- include/mir/shell/surface.h 2013-03-06 12:25:34 +0000
326+++ include/mir/shell/surface.h 2013-03-07 08:31:22 +0000
327@@ -23,6 +23,7 @@
328 #include "mir/geometry/pixel_format.h"
329 #include "mir/geometry/point.h"
330 #include "mir/geometry/size.h"
331+#include "mir/surface.h"
332
333 #include <memory>
334
335@@ -55,6 +56,8 @@
336 virtual void advance_client_buffer() = 0;
337 virtual std::shared_ptr<compositor::Buffer> client_buffer() const = 0;
338
339+ virtual int configure(MirSurfaceAttrib attrib, int value) = 0;
340+
341 protected:
342 Surface() = default;
343 Surface(Surface const&) = delete;
344
345=== added file 'include/mir/surface.h'
346--- include/mir/surface.h 1970-01-01 00:00:00 +0000
347+++ include/mir/surface.h 2013-03-07 08:31:22 +0000
348@@ -0,0 +1,48 @@
349+/*
350+ * Surface-related declarations common to client and server
351+ * This is C. Not C++.
352+ *
353+ * Copyright © 2013 Canonical Ltd.
354+ *
355+ * This program is free software: you can redistribute it and/or modify
356+ * it under the terms of the GNU Lesser General Public License version 3 as
357+ * published by the Free Software Foundation.
358+ *
359+ * This program is distributed in the hope that it will be useful,
360+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
361+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
362+ * GNU Lesser General Public License for more details.
363+ *
364+ * You should have received a copy of the GNU Lesser General Public License
365+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
366+ *
367+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
368+ */
369+
370+#ifndef MIR_SURFACE_H_
371+#define MIR_SURFACE_H_
372+
373+/*
374+ * Attributes of a surface that the client and server/shell may wish to
375+ * get or set over the wire.
376+ */
377+typedef enum MirSurfaceAttrib
378+{
379+ MIR_SURFACE_TYPE,
380+ MirSurfaceAttrib_ARRAYSIZE
381+} MirSurfaceAttrib;
382+
383+typedef enum MirSurfaceType
384+{
385+ MIR_SURFACE_NORMAL,
386+ MIR_SURFACE_UTILITY,
387+ MIR_SURFACE_DIALOG,
388+ MIR_SURFACE_OVERLAY,
389+ MIR_SURFACE_FREESTYLE,
390+ MIR_SURFACE_POPOVER,
391+ MirSurfaceType_ARRAYSIZE
392+} MirSurfaceType;
393+
394+/* TODO: Surface states here */
395+
396+#endif
397
398=== modified file 'include/mir/surfaces/surface.h'
399--- include/mir/surfaces/surface.h 2013-03-04 16:02:02 +0000
400+++ include/mir/surfaces/surface.h 2013-03-07 08:31:22 +0000
401@@ -22,6 +22,7 @@
402 #include "mir/geometry/pixel_format.h"
403 #include "mir/graphics/renderable.h"
404 #include "mir/compositor/buffer_properties.h"
405+#include "mir/surface.h"
406
407 #include <memory>
408 #include <string>
409@@ -71,6 +72,10 @@
410 std::shared_ptr<compositor::Buffer> client_buffer() const;
411 void shutdown();
412
413+ int configure(MirSurfaceAttrib attrib, int value);
414+ MirSurfaceType type() const;
415+ bool set_type(MirSurfaceType t);
416+
417 private:
418 std::string surface_name;
419 std::shared_ptr<BufferBundle> buffer_bundle;
420@@ -81,6 +86,8 @@
421 float alpha_value;
422
423 bool is_hidden;
424+
425+ MirSurfaceType type_value;
426 };
427
428 }
429
430=== modified file 'include/mir_toolkit/mir_client_library.h'
431--- include/mir_toolkit/mir_client_library.h 2013-03-04 16:02:02 +0000
432+++ include/mir_toolkit/mir_client_library.h 2013-03-07 08:31:22 +0000
433@@ -18,6 +18,8 @@
434 #ifndef MIR_CLIENT_LIBRARY_H
435 #define MIR_CLIENT_LIBRARY_H
436
437+#include <mir/surface.h> /* Surface definitions common to client & server */
438+
439 #ifdef __cplusplus
440 /** The C client API
441 */
442@@ -322,6 +324,23 @@
443 */
444 int mir_debug_surface_id(MirSurface *surface);
445
446+/**
447+ * Set the type (purpose) of a surface. This is not guaranteed to always work
448+ * with some shell types (e.g. phone/tablet UIs). As such, you may have to
449+ * wait on the function and check the result using mir_surface_get_type.
450+ * \param [in] surface The surface to operate on
451+ * \param [in] type The new type of the surface
452+ * \return A wait handle that can be passed to mir_wait_for
453+ */
454+MirWaitHandle* mir_surface_set_type(MirSurface *surface, MirSurfaceType type);
455+
456+/**
457+ * Get the type (purpose) of a surface from the server.
458+ * \param [in] surface The surface to query
459+ * \return The type of the surface
460+ */
461+MirSurfaceType mir_surface_get_type(MirSurface *surface);
462+
463 #ifdef __cplusplus
464 }
465 }
466
467=== modified file 'src/CMakeLists.txt'
468--- src/CMakeLists.txt 2013-03-06 12:25:34 +0000
469+++ src/CMakeLists.txt 2013-03-07 08:31:22 +0000
470@@ -45,6 +45,7 @@
471 mirgraphics
472 mirinput
473 mirsurfaces
474+ mirnullshell
475 )
476
477 list(APPEND MIRSERVER_LINKS
478@@ -63,9 +64,6 @@
479 LINK_PUBLIC
480 ${MIRSERVER_LINKS}
481 )
482- install(TARGETS mirserver
483- LIBRARY DESTINATION lib
484- )
485 else()
486 target_link_libraries(mirserver
487 LINK_PUBLIC
488@@ -74,9 +72,19 @@
489 )
490 endif()
491
492+set (MIR_SERVER_HEADERS
493+ ${CMAKE_SOURCE_DIR}/include/mir/shell/shell.h
494+)
495+
496 set_target_properties(mirserver PROPERTIES
497 VERSION ${MIR_VERSION_MAJOR}.${MIR_VERSION_MINOR}.${MIR_VERSION_PATCH}
498 SOVERSION ${MIR_VERSION_MAJOR}
499+ PUBLIC_HEADER ${MIR_SERVER_HEADERS}
500+)
501+
502+install (TARGETS mirserver
503+ LIBRARY DESTINATION lib
504+ PUBLIC_HEADER DESTINATION "include/mir/server/"
505 )
506
507 target_link_libraries(mirds
508@@ -84,6 +92,14 @@
509 ${Boost_LIBRARIES}
510 )
511
512+# Some headers contain common definitions required for both client and
513+# server development...
514+set (MIR_COMMON_HEADERS
515+ ${CMAKE_SOURCE_DIR}/include/mir/surface.h
516+)
517+
518+install (FILES ${MIR_COMMON_HEADERS} DESTINATION "include/mir/")
519+
520 install(TARGETS mirds
521 RUNTIME DESTINATION bin
522 )
523
524=== modified file 'src/client/mir_client_library.cpp'
525--- src/client/mir_client_library.cpp 2013-03-04 16:02:02 +0000
526+++ src/client/mir_client_library.cpp 2013-03-07 08:31:22 +0000
527@@ -227,3 +227,25 @@
528 {
529 // Ignore
530 }
531+
532+mir_toolkit::MirWaitHandle* mir_toolkit::mir_surface_set_type(MirSurface *surf,
533+ MirSurfaceType type)
534+{
535+ return surf ? surf->configure(MIR_SURFACE_TYPE, type) : NULL;
536+}
537+
538+MirSurfaceType mir_toolkit::mir_surface_get_type(MirSurface *surf)
539+{
540+ MirSurfaceType type = MIR_SURFACE_NORMAL;
541+
542+ if (surf)
543+ {
544+ // I assume the type can only change from the client side. Otherwise
545+ // we would have to send off a message to retrieve the latest...
546+
547+ int t = surf->attrib(MIR_SURFACE_TYPE);
548+ type = static_cast<MirSurfaceType>(t);
549+ }
550+
551+ return type;
552+}
553
554=== modified file 'src/client/mir_surface.cpp'
555--- src/client/mir_surface.cpp 2013-03-04 16:02:02 +0000
556+++ src/client/mir_surface.cpp 2013-03-07 08:31:22 +0000
557@@ -50,6 +50,10 @@
558 message.set_buffer_usage(params.buffer_usage);
559
560 server.create_surface(0, &message, &surface, gp::NewCallback(this, &MirSurface::created, callback, context));
561+
562+ for (int i = 0; i < MirSurfaceAttrib_ARRAYSIZE; i++)
563+ attrib_cache[i] = -1;
564+ attrib_cache[MIR_SURFACE_TYPE] = MIR_SURFACE_NORMAL;
565 }
566
567 mir_toolkit::MirSurface::~MirSurface()
568@@ -226,3 +230,46 @@
569 {
570 return *accelerated_window;
571 }
572+
573+MirWaitHandle* MirSurface::configure(MirSurfaceAttrib at, int value)
574+{
575+ mp::SurfaceSetting setting;
576+ setting.mutable_surfaceid()->CopyFrom(surface.id());
577+ setting.set_attrib(at);
578+ setting.set_ivalue(value);
579+
580+ configure_wait_handle.expect_result();
581+ server.configure_surface(0, &setting, &configure_result,
582+ google::protobuf::NewCallback(this, &MirSurface::on_configured));
583+
584+ return &configure_wait_handle;
585+}
586+
587+void MirSurface::on_configured()
588+{
589+ if (configure_result.has_surfaceid() &&
590+ configure_result.surfaceid().value() == surface.id().value() &&
591+ configure_result.has_attrib())
592+ {
593+ switch (configure_result.attrib())
594+ {
595+ case MIR_SURFACE_TYPE:
596+ if (configure_result.has_ivalue())
597+ {
598+ int t = configure_result.ivalue();
599+ attrib_cache[MIR_SURFACE_TYPE] = t;
600+ } // else error is probably set due to an unsupported attrib/value
601+ break;
602+ default:
603+ assert(false);
604+ break;
605+ }
606+
607+ configure_wait_handle.result_received();
608+ }
609+}
610+
611+int MirSurface::attrib(MirSurfaceAttrib at) const
612+{
613+ return attrib_cache[at];
614+}
615
616=== modified file 'src/client/mir_surface.h'
617--- src/client/mir_surface.h 2013-03-04 16:02:02 +0000
618+++ src/client/mir_surface.h 2013-03-07 08:31:22 +0000
619@@ -23,6 +23,8 @@
620 #include "mir/geometry/pixel_format.h"
621 #include "mir/geometry/dimensions.h"
622 #include "mir_toolkit/mir_client_library.h"
623+#include "mir/surface.h"
624+#include "mir_logger.h"
625 #include "client_buffer_depository.h"
626 #include "mir_wait_handle.h"
627 #include "mir_client_surface.h"
628@@ -72,7 +74,11 @@
629 void release_cpu_region();
630 EGLNativeWindowType generate_native_window();
631
632+ MirWaitHandle* configure(MirSurfaceAttrib a, int value);
633+ int attrib(MirSurfaceAttrib a) const;
634+
635 private:
636+ void on_configured();
637 void process_incoming_buffer();
638 void populate(MirBufferPackage& buffer_package);
639 void created(mir_surface_lifecycle_callback callback, void * context);
640@@ -88,6 +94,7 @@
641 MirConnection *connection;
642 MirWaitHandle create_wait_handle;
643 MirWaitHandle next_buffer_wait_handle;
644+ MirWaitHandle configure_wait_handle;
645
646 int last_buffer_id;
647
648@@ -96,6 +103,11 @@
649
650 std::shared_ptr<mir::client::Logger> logger;
651 std::shared_ptr<EGLNativeWindowType> accelerated_window;
652+
653+ mir::protobuf::SurfaceSetting configure_result;
654+
655+ // Cache of latest SurfaceSettings returned from the server
656+ int attrib_cache[MirSurfaceAttrib_ARRAYSIZE];
657 };
658
659 #endif /* MIR_CLIENT_PRIVATE_MIR_WAIT_HANDLE_H_ */
660
661=== modified file 'src/client/mir_wait_handle.cpp'
662--- src/client/mir_wait_handle.cpp 2013-03-04 16:02:02 +0000
663+++ src/client/mir_wait_handle.cpp 2013-03-07 08:31:22 +0000
664@@ -14,6 +14,7 @@
665 * along with this program. If not, see <http://www.gnu.org/licenses/>.
666 *
667 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
668+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
669 */
670
671 #include "mir_wait_handle.h"
672@@ -21,7 +22,8 @@
673 mir_toolkit::MirWaitHandle::MirWaitHandle() :
674 guard(),
675 wait_condition(),
676- result_has_occurred(false)
677+ expecting(0),
678+ received(0)
679 {
680 }
681
682@@ -29,20 +31,29 @@
683 {
684 }
685
686+void mir_toolkit::MirWaitHandle::expect_result()
687+{
688+ std::unique_lock<std::mutex> lock(guard);
689+
690+ expecting++;
691+}
692+
693 void mir_toolkit::MirWaitHandle::result_received()
694 {
695 std::unique_lock<std::mutex> lock(guard);
696- result_has_occurred = true;
697
698+ received++;
699 wait_condition.notify_all();
700 }
701
702 void mir_toolkit::MirWaitHandle::wait_for_result()
703 {
704 std::unique_lock<std::mutex> lock(guard);
705- while ( (!result_has_occurred) )
706+
707+ while ((!expecting && !received) || (received < expecting))
708 wait_condition.wait(lock);
709- result_has_occurred = false;
710+
711+ received = 0;
712+ expecting = 0;
713 }
714
715-
716
717=== modified file 'src/client/mir_wait_handle.h'
718--- src/client/mir_wait_handle.h 2013-03-04 16:02:02 +0000
719+++ src/client/mir_wait_handle.h 2013-03-07 08:31:22 +0000
720@@ -14,6 +14,7 @@
721 * along with this program. If not, see <http://www.gnu.org/licenses/>.
722 *
723 * Authored by: Thomas Guest <thomas.guest@canonical.com>
724+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
725 */
726
727 #ifndef MIR_CLIENT_MIR_WAIT_HANDLE_H_
728@@ -30,6 +31,7 @@
729 MirWaitHandle();
730 ~MirWaitHandle();
731
732+ void expect_result();
733 void result_received();
734 void wait_for_result();
735
736@@ -37,7 +39,8 @@
737 std::mutex guard;
738 std::condition_variable wait_condition;
739
740- bool result_has_occurred;
741+ int expecting;
742+ int received;
743 };
744 }
745
746
747=== modified file 'src/frontend/application_mediator.cpp'
748--- src/frontend/application_mediator.cpp 2013-03-06 12:25:34 +0000
749+++ src/frontend/application_mediator.cpp 2013-03-07 08:31:22 +0000
750@@ -24,6 +24,7 @@
751 #include "mir/shell/surface_creation_parameters.h"
752 #include "mir/frontend/resource_cache.h"
753
754+#include "mir/surface.h"
755 #include "mir/compositor/buffer_ipc_package.h"
756 #include "mir/compositor/buffer_id.h"
757 #include "mir/compositor/buffer.h"
758@@ -220,3 +221,29 @@
759 done->Run();
760 }
761
762+void mir::frontend::ApplicationMediator::configure_surface(
763+ google::protobuf::RpcController*, // controller,
764+ const mir::protobuf::SurfaceSetting* request,
765+ mir::protobuf::SurfaceSetting* response,
766+ google::protobuf::Closure* done)
767+{
768+ MirSurfaceAttrib attrib = static_cast<MirSurfaceAttrib>(request->attrib());
769+
770+ // Required response fields:
771+ response->mutable_surfaceid()->CopyFrom(request->surfaceid());
772+ response->set_attrib(attrib);
773+
774+ if (application_session.get() == nullptr)
775+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
776+
777+ report->application_configure_surface_called(application_session->name());
778+
779+ auto const id = shell::SurfaceId(request->surfaceid().value());
780+ int value = request->ivalue();
781+ int newvalue = application_session->configure_surface(id, attrib, value);
782+
783+ response->set_ivalue(newvalue);
784+
785+ done->Run();
786+}
787+
788
789=== modified file 'src/frontend/null_application_mediator_report.cpp'
790--- src/frontend/null_application_mediator_report.cpp 2013-03-04 16:02:02 +0000
791+++ src/frontend/null_application_mediator_report.cpp 2013-03-07 08:31:22 +0000
792@@ -42,6 +42,10 @@
793 {
794 }
795
796+void mir::frontend::NullApplicationMediatorReport::application_configure_surface_called(std::string const&)
797+{
798+}
799+
800 void mir::frontend::NullApplicationMediatorReport::application_error(
801 std::string const&,
802 char const* ,
803
804=== modified file 'src/frontend/protobuf_message_processor.cpp'
805--- src/frontend/protobuf_message_processor.cpp 2013-03-04 16:02:02 +0000
806+++ src/frontend/protobuf_message_processor.cpp 2013-03-07 08:31:22 +0000
807@@ -176,6 +176,10 @@
808 {
809 invoke(&protobuf::DisplayServer::select_focus_by_lightdm_id, invocation);
810 }
811+ else if ("configure_surface" == invocation.method_name())
812+ {
813+ invoke(&protobuf::DisplayServer::configure_surface, invocation);
814+ }
815 else if ("disconnect" == invocation.method_name())
816 {
817 invoke(&protobuf::DisplayServer::disconnect, invocation);
818
819=== modified file 'src/logging/application_mediator_report.cpp'
820--- src/logging/application_mediator_report.cpp 2013-03-04 16:02:02 +0000
821+++ src/logging/application_mediator_report.cpp 2013-03-07 08:31:22 +0000
822@@ -63,6 +63,11 @@
823 log->log<Logger::informational>("application_drm_auth_magic_called(\"" + app_name + "\")", component);
824 }
825
826+void ml::ApplicationMediatorReport::application_configure_surface_called(std::string const& app_name)
827+{
828+ log->log<Logger::informational>("application_configure_surface_called(\"" + app_name + "\")", component);
829+}
830+
831 void ml::ApplicationMediatorReport::application_error(
832 std::string const& app_name,
833 char const* method,
834
835=== modified file 'src/protobuf/mir_protobuf.proto'
836--- src/protobuf/mir_protobuf.proto 2013-01-10 16:58:01 +0000
837+++ src/protobuf/mir_protobuf.proto 2013-03-07 08:31:22 +0000
838@@ -111,6 +111,14 @@
839 optional string error = 127;
840 }
841
842+message SurfaceSetting {
843+ optional SurfaceId surfaceid = 1;
844+ optional int32 attrib = 2;
845+ optional int32 ivalue = 3;
846+ // optional string svalue = 4; // Expected for future use
847+ optional string error = 127;
848+}
849+
850 service DisplayServer {
851 // Platform independent requests
852 rpc connect(ConnectParameters) returns (Connection);
853@@ -124,5 +132,7 @@
854 rpc drm_auth_magic(DRMMagic) returns (DRMAuthMagicStatus);
855
856 rpc test_file_descriptors(Void) returns (Buffer);
857+
858+ rpc configure_surface(SurfaceSetting) returns (SurfaceSetting);
859 }
860
861
862=== modified file 'src/shell/CMakeLists.txt'
863--- src/shell/CMakeLists.txt 2013-03-06 12:25:34 +0000
864+++ src/shell/CMakeLists.txt 2013-03-07 08:31:22 +0000
865@@ -16,3 +16,7 @@
866
867 ${SHELL_SOURCES}
868 )
869+
870+add_library (mirnullshell STATIC
871+ nullshell.cpp
872+)
873
874=== modified file 'src/shell/application_session.cpp'
875--- src/shell/application_session.cpp 2013-03-06 12:54:33 +0000
876+++ src/shell/application_session.cpp 2013-03-07 08:31:22 +0000
877@@ -20,6 +20,7 @@
878 #include "mir/shell/surface.h"
879
880 #include "mir/surfaces/surface_controller.h"
881+#include "mir/shell/nullshell.h"
882
883 #include <boost/throw_exception.hpp>
884
885@@ -33,12 +34,16 @@
886
887 msh::ApplicationSession::ApplicationSession(
888 std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
889- std::string const& session_name) :
890+ std::string const& session_name, std::shared_ptr<mir::Shell> sh) :
891 surface_factory(surface_factory),
892 session_name(session_name),
893+ shell(sh),
894 next_surface_id(0)
895 {
896 assert(surface_factory);
897+
898+ if (!shell)
899+ shell.reset(new mir::shell::NullShell);
900 }
901
902 msh::ApplicationSession::~ApplicationSession()
903@@ -122,3 +127,23 @@
904 id_s.second->show();
905 }
906 }
907+
908+int msh::ApplicationSession::configure_surface(msh::SurfaceId id,
909+ MirSurfaceAttrib attrib,
910+ int value)
911+{
912+ if (!shell->supports(attrib))
913+ BOOST_THROW_EXCEPTION(std::logic_error("Current shell does not "
914+ "support the specified surface "
915+ "attribute"));
916+
917+ if (!shell->supports(attrib, value))
918+ BOOST_THROW_EXCEPTION(std::logic_error("Current shell does not "
919+ "support the specified value "
920+ "for this attribute"));
921+
922+ std::unique_lock<std::mutex> lock(surfaces_mutex);
923+ std::shared_ptr<msh::Surface> surf(checked_find(id)->second);
924+
925+ return surf->configure(attrib, value);
926+}
927
928=== added file 'src/shell/nullshell.cpp'
929--- src/shell/nullshell.cpp 1970-01-01 00:00:00 +0000
930+++ src/shell/nullshell.cpp 2013-03-07 08:31:22 +0000
931@@ -0,0 +1,49 @@
932+/*
933+ * Null Shell
934+ *
935+ * Copyright © 2013 Canonical Ltd.
936+ *
937+ * This program is free software: you can redistribute it and/or modify
938+ * it under the terms of the GNU General Public License version 3 as
939+ * published by the Free Software Foundation.
940+ *
941+ * This program is distributed in the hope that it will be useful,
942+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
943+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
944+ * GNU General Public License for more details.
945+ *
946+ * You should have received a copy of the GNU General Public License
947+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
948+ *
949+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
950+ */
951+
952+#include "mir/shell/nullshell.h"
953+
954+using namespace mir;
955+using namespace shell;
956+
957+NullShell::~NullShell()
958+{
959+}
960+
961+bool NullShell::supports(MirSurfaceAttrib attrib) const
962+{
963+ return (attrib == MIR_SURFACE_TYPE);
964+}
965+
966+bool NullShell::supports(MirSurfaceAttrib attrib, int value) const
967+{
968+ bool valid = false;
969+
970+ switch (attrib)
971+ {
972+ case MIR_SURFACE_TYPE:
973+ valid = (value >= 0 && value < MirSurfaceType_ARRAYSIZE);
974+ break;
975+ default:
976+ break;
977+ }
978+
979+ return valid;
980+}
981
982=== modified file 'src/shell/session_manager.cpp'
983--- src/shell/session_manager.cpp 2013-03-06 12:54:33 +0000
984+++ src/shell/session_manager.cpp 2013-03-07 08:31:22 +0000
985@@ -22,6 +22,7 @@
986 #include "mir/shell/surface_factory.h"
987 #include "mir/shell/focus_sequence.h"
988 #include "mir/shell/focus_setter.h"
989+#include "mir/shell/nullshell.h"
990
991 #include <memory>
992 #include <cassert>
993@@ -51,7 +52,8 @@
994
995 std::shared_ptr<msh::Session> msh::SessionManager::open_session(std::string const& name)
996 {
997- auto new_session = std::make_shared<msh::ApplicationSession>(surface_factory, name);
998+ auto new_session = std::make_shared<msh::ApplicationSession>(
999+ surface_factory, name, current_shell());
1000
1001 app_container->insert_session(new_session);
1002
1003@@ -134,3 +136,11 @@
1004 set_focus_to(match->second);
1005 }
1006 }
1007+
1008+std::shared_ptr<mir::Shell> msh::SessionManager::current_shell() const
1009+{
1010+ if (!shell)
1011+ shell.reset(new mir::shell::NullShell);
1012+
1013+ return shell;
1014+}
1015
1016=== modified file 'src/surfaces/proxy_surface.cpp'
1017--- src/surfaces/proxy_surface.cpp 2013-03-06 12:25:34 +0000
1018+++ src/surfaces/proxy_surface.cpp 2013-03-07 08:31:22 +0000
1019@@ -109,6 +109,17 @@
1020 surface_stack->destroy_surface(surface);
1021 }
1022
1023+int ms::BasicProxySurface::configure(MirSurfaceAttrib attrib, int value)
1024+{
1025+ if (auto const& s = surface.lock())
1026+ {
1027+ return s->configure(attrib, value);
1028+ }
1029+ else
1030+ {
1031+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface"));
1032+ }
1033+}
1034
1035 ms::ProxySurface::ProxySurface(
1036 SurfaceStackModel* const surface_stack_,
1037
1038=== modified file 'src/surfaces/proxy_surface.h'
1039--- src/surfaces/proxy_surface.h 2013-03-06 12:25:34 +0000
1040+++ src/surfaces/proxy_surface.h 2013-03-07 08:31:22 +0000
1041@@ -56,6 +56,8 @@
1042
1043 std::shared_ptr<compositor::Buffer> client_buffer() const;
1044
1045+ int configure(MirSurfaceAttrib attrib, int value);
1046+
1047 protected:
1048 void destroy_surface(SurfaceStackModel* const surface_stack) const;
1049
1050
1051=== modified file 'src/surfaces/surface.cpp'
1052--- src/surfaces/surface.cpp 2013-03-04 16:02:02 +0000
1053+++ src/surfaces/surface.cpp 2013-03-07 08:31:22 +0000
1054@@ -36,7 +36,8 @@
1055 surface_name(name),
1056 buffer_bundle(buffer_bundle),
1057 alpha_value(1.0f),
1058- is_hidden(false)
1059+ is_hidden(false),
1060+ type_value(MIR_SURFACE_NORMAL)
1061 {
1062 // TODO(tvoss,kdub): Does a surface without a buffer_bundle make sense?
1063 assert(buffer_bundle);
1064@@ -128,3 +129,39 @@
1065 {
1066 return client_buffer_resource;
1067 }
1068+
1069+int ms::Surface::configure(MirSurfaceAttrib attrib, int value)
1070+{
1071+ int result = 0;
1072+
1073+ switch (attrib)
1074+ {
1075+ case MIR_SURFACE_TYPE:
1076+ set_type(static_cast<MirSurfaceType>(value));
1077+ result = type_value;
1078+ break;
1079+ default:
1080+ assert(false);
1081+ break;
1082+ }
1083+
1084+ return result;
1085+}
1086+
1087+MirSurfaceType ms::Surface::type() const
1088+{
1089+ return type_value;
1090+}
1091+
1092+bool ms::Surface::set_type(MirSurfaceType t)
1093+{
1094+ bool valid = false;
1095+
1096+ if (t >= 0 && t < MirSurfaceType_ARRAYSIZE)
1097+ {
1098+ type_value = t;
1099+ valid = true;
1100+ }
1101+
1102+ return valid;
1103+}
1104
1105=== modified file 'tests/acceptance-tests/test_client_library.cpp'
1106--- tests/acceptance-tests/test_client_library.cpp 2013-02-26 16:48:46 +0000
1107+++ tests/acceptance-tests/test_client_library.cpp 2013-03-07 08:31:22 +0000
1108@@ -168,6 +168,72 @@
1109 launch_client_process(client_config);
1110 }
1111
1112+TEST_F(DefaultDisplayServerTestFixture, surface_types)
1113+{
1114+ struct ClientConfig : ClientConfigCommon
1115+ {
1116+ void exec()
1117+ {
1118+
1119+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
1120+
1121+ ASSERT_TRUE(connection != NULL);
1122+ EXPECT_TRUE(mir_connection_is_valid(connection));
1123+ EXPECT_STREQ(mir_connection_get_error_message(connection), "");
1124+
1125+ MirSurfaceParameters const request_params =
1126+ {
1127+ __PRETTY_FUNCTION__,
1128+ 640, 480,
1129+ mir_pixel_format_abgr_8888,
1130+ mir_buffer_usage_hardware
1131+ };
1132+
1133+ mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this));
1134+
1135+ ASSERT_TRUE(surface != NULL);
1136+ EXPECT_TRUE(mir_surface_is_valid(surface));
1137+ EXPECT_STREQ(mir_surface_get_error_message(surface), "");
1138+
1139+ EXPECT_EQ(mir_surface_get_type(surface), MIR_SURFACE_NORMAL);
1140+
1141+ mir_wait_for(mir_surface_set_type(surface, MIR_SURFACE_FREESTYLE));
1142+ EXPECT_EQ(mir_surface_get_type(surface), MIR_SURFACE_FREESTYLE);
1143+
1144+ mir_wait_for(mir_surface_set_type(surface,
1145+ static_cast<MirSurfaceType>(999)));
1146+ EXPECT_EQ(mir_surface_get_type(surface), MIR_SURFACE_FREESTYLE);
1147+
1148+ mir_wait_for(mir_surface_set_type(surface, MIR_SURFACE_DIALOG));
1149+ EXPECT_EQ(mir_surface_get_type(surface), MIR_SURFACE_DIALOG);
1150+
1151+ mir_wait_for(mir_surface_set_type(surface,
1152+ static_cast<MirSurfaceType>(888)));
1153+ EXPECT_EQ(mir_surface_get_type(surface), MIR_SURFACE_DIALOG);
1154+
1155+ // Stress-test synchronization logic with some flooding
1156+ for (int i = 0; i < 1000; i++)
1157+ {
1158+ mir_surface_set_type(surface, MIR_SURFACE_NORMAL);
1159+ mir_surface_set_type(surface, MIR_SURFACE_UTILITY);
1160+ mir_surface_set_type(surface, MIR_SURFACE_DIALOG);
1161+ mir_surface_set_type(surface, MIR_SURFACE_OVERLAY);
1162+ mir_surface_set_type(surface, MIR_SURFACE_FREESTYLE);
1163+ mir_wait_for(mir_surface_set_type(surface,
1164+ MIR_SURFACE_POPOVER));
1165+ ASSERT_EQ(mir_surface_get_type(surface), MIR_SURFACE_POPOVER);
1166+ }
1167+
1168+ mir_wait_for(mir_surface_release(surface, release_surface_callback,
1169+ this));
1170+
1171+ mir_connection_release(connection);
1172+ }
1173+ } client_config;
1174+
1175+ launch_client_process(client_config);
1176+}
1177+
1178 TEST_F(DefaultDisplayServerTestFixture, client_library_creates_multiple_surfaces)
1179 {
1180 int const n_surfaces = 13;
1181
1182=== modified file 'tests/acceptance-tests/test_focus_management_api.cpp'
1183--- tests/acceptance-tests/test_focus_management_api.cpp 2013-03-06 12:25:34 +0000
1184+++ tests/acceptance-tests/test_focus_management_api.cpp 2013-03-07 08:31:22 +0000
1185@@ -46,6 +46,8 @@
1186
1187 namespace mir
1188 {
1189+class Shell;
1190+
1191 namespace
1192 {
1193 struct ClientConfigCommon : TestingClientConfiguration
1194@@ -144,6 +146,8 @@
1195
1196 MOCK_METHOD0(shutdown, void ());
1197
1198+ MOCK_CONST_METHOD0(current_shell, std::shared_ptr<mir::Shell>());
1199+
1200 private:
1201 std::shared_ptr<shell::SessionStore> const impl;
1202 };
1203
1204=== modified file 'tests/behavior-tests/session_management_context.cpp'
1205--- tests/behavior-tests/session_management_context.cpp 2013-03-06 12:54:33 +0000
1206+++ tests/behavior-tests/session_management_context.cpp 2013-03-07 08:31:22 +0000
1207@@ -75,6 +75,11 @@
1208 {
1209 return std::shared_ptr<mc::Buffer>();
1210 }
1211+
1212+ virtual int configure(MirSurfaceAttrib, int)
1213+ {
1214+ return 0;
1215+ }
1216 };
1217
1218 struct SizedDummySurface : public DummySurface
1219
1220=== modified file 'tests/integration-tests/cucumber/test_session_management_context.cpp'
1221--- tests/integration-tests/cucumber/test_session_management_context.cpp 2013-03-06 16:48:33 +0000
1222+++ tests/integration-tests/cucumber/test_session_management_context.cpp 2013-03-07 08:31:22 +0000
1223@@ -59,6 +59,8 @@
1224 MOCK_METHOD1(focus_session_with_lightdm_id, void(int));
1225
1226 MOCK_METHOD0(shutdown, void());
1227+
1228+ MOCK_CONST_METHOD0(current_shell, std::shared_ptr<mir::Shell>());
1229 };
1230
1231 struct MockSession : public msh::Session
1232@@ -72,6 +74,8 @@
1233
1234 MOCK_METHOD0(hide, void());
1235 MOCK_METHOD0(show, void());
1236+
1237+ MOCK_METHOD3(configure_surface, int(msh::SurfaceId, MirSurfaceAttrib, int));
1238 };
1239
1240 struct MockSurface : public msh::Surface
1241@@ -85,6 +89,8 @@
1242 MOCK_CONST_METHOD0(size, mir::geometry::Size ());
1243 MOCK_CONST_METHOD0(pixel_format, mir::geometry::PixelFormat ());
1244 MOCK_CONST_METHOD0(client_buffer, std::shared_ptr<mc::Buffer> ());
1245+
1246+ MOCK_METHOD2(configure, int(MirSurfaceAttrib, int));
1247 };
1248
1249 MATCHER_P(NamedWindowWithNoGeometry, name, "")
1250
1251=== modified file 'tests/unit-tests/CMakeLists.txt'
1252--- tests/unit-tests/CMakeLists.txt 2013-03-04 15:54:45 +0000
1253+++ tests/unit-tests/CMakeLists.txt 2013-03-07 08:31:22 +0000
1254@@ -17,6 +17,7 @@
1255 endif()
1256 add_subdirectory(surfaces/)
1257 add_subdirectory(draw/)
1258+add_subdirectory(shell/)
1259
1260 add_executable(unit-tests ${UNIT_TEST_SOURCES})
1261
1262
1263=== modified file 'tests/unit-tests/client/CMakeLists.txt'
1264--- tests/unit-tests/client/CMakeLists.txt 2013-03-04 15:54:45 +0000
1265+++ tests/unit-tests/client/CMakeLists.txt 2013-03-07 08:31:22 +0000
1266@@ -3,6 +3,7 @@
1267 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_platform.cpp
1268 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_mir_surface.cpp
1269 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_connection.cpp
1270+ ${CMAKE_CURRENT_SOURCE_DIR}/test_wait_handle.cpp
1271 )
1272
1273 if(MIR_PLATFORM STREQUAL "android")
1274
1275=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
1276--- tests/unit-tests/client/test_client_mir_surface.cpp 2013-02-26 16:48:46 +0000
1277+++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-07 08:31:22 +0000
1278@@ -376,3 +376,22 @@
1279 EXPECT_EQ(pf, geom::PixelFormat::abgr_8888);
1280 }
1281
1282+TEST_F(MirClientSurfaceTest, default_surface_type)
1283+{
1284+ using namespace testing;
1285+ using namespace mir::protobuf;
1286+
1287+ EXPECT_CALL(*mock_depository, deposit_package_rv(_,_,_,_))
1288+ .Times(1);
1289+
1290+ auto surface = std::make_shared<MirSurface> (connection.get(),
1291+ *client_comm_channel,
1292+ logger,
1293+ mock_depository,
1294+ params,
1295+ &empty_callback,
1296+ (void*) NULL);
1297+ surface->get_create_wait_handle()->wait_for_result();
1298+
1299+ EXPECT_EQ(surface->attrib(MIR_SURFACE_TYPE), MIR_SURFACE_NORMAL);
1300+}
1301
1302=== added file 'tests/unit-tests/client/test_wait_handle.cpp'
1303--- tests/unit-tests/client/test_wait_handle.cpp 1970-01-01 00:00:00 +0000
1304+++ tests/unit-tests/client/test_wait_handle.cpp 2013-03-07 08:31:22 +0000
1305@@ -0,0 +1,114 @@
1306+/*
1307+ * Copyright © 2013 Canonical Ltd.
1308+ *
1309+ * This program is free software: you can redistribute it and/or modify
1310+ * it under the terms of the GNU General Public License version 3 as
1311+ * published by the Free Software Foundation.
1312+ *
1313+ * This program is distributed in the hope that it will be useful,
1314+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1315+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1316+ * GNU General Public License for more details.
1317+ *
1318+ * You should have received a copy of the GNU General Public License
1319+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1320+ *
1321+ * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
1322+ */
1323+
1324+#include <thread>
1325+#include <gtest/gtest.h>
1326+#include "src/client/mir_wait_handle.h"
1327+
1328+using namespace mir_toolkit;
1329+
1330+TEST(WaitHandle, symmetric_synchronous)
1331+{
1332+ MirWaitHandle w;
1333+
1334+ for (int i = 0; i < 100; i++)
1335+ {
1336+ w.result_received();
1337+ w.wait_for_result();
1338+ }
1339+
1340+ EXPECT_TRUE(true); // Failure would be hanging in the above loop
1341+}
1342+
1343+TEST(WaitHandle, asymmetric_synchronous)
1344+{
1345+ MirWaitHandle w;
1346+
1347+ for (int i = 1; i <= 100; i++)
1348+ {
1349+ for (int j = 1; j <= i; j++)
1350+ w.result_received();
1351+
1352+ w.wait_for_result();
1353+ }
1354+
1355+ EXPECT_TRUE(true); // Failure would be hanging in the above loop
1356+}
1357+
1358+namespace
1359+{
1360+ int symmetric_result = 0;
1361+
1362+ void symmetric_thread(MirWaitHandle *in, MirWaitHandle *out, int max)
1363+ {
1364+ for (int i = 1; i <= max; i++)
1365+ {
1366+ in->wait_for_result();
1367+ symmetric_result = i;
1368+ out->result_received();
1369+ }
1370+ }
1371+}
1372+
1373+TEST(WaitHandle, symmetric_asynchronous)
1374+{
1375+ const int max = 100;
1376+ MirWaitHandle in, out;
1377+ std::thread t(symmetric_thread, &in, &out, max);
1378+
1379+ for (int i = 1; i <= max; i++)
1380+ {
1381+ in.result_received();
1382+ out.wait_for_result();
1383+ ASSERT_EQ(symmetric_result, i);
1384+ }
1385+ t.join();
1386+}
1387+
1388+namespace
1389+{
1390+ int asymmetric_result = 0;
1391+
1392+ void asymmetric_thread(MirWaitHandle *in, MirWaitHandle *out, int max)
1393+ {
1394+ for (int i = 1; i <= max; i++)
1395+ {
1396+ in->wait_for_result();
1397+ asymmetric_result = i;
1398+ for (int j = 1; j <= i; j++)
1399+ out->result_received();
1400+ }
1401+ }
1402+}
1403+
1404+TEST(WaitHandle, asymmetric_asynchronous)
1405+{
1406+ const int max = 100;
1407+ MirWaitHandle in, out;
1408+ std::thread t(asymmetric_thread, &in, &out, max);
1409+
1410+ for (int i = 1; i <= max; i++)
1411+ {
1412+ in.result_received();
1413+ for (int j = 1; j <= i; j++)
1414+ out.expect_result();
1415+ out.wait_for_result();
1416+ ASSERT_EQ(asymmetric_result, i);
1417+ }
1418+ t.join();
1419+}
1420
1421=== modified file 'tests/unit-tests/frontend/test_application_mediator.cpp'
1422--- tests/unit-tests/frontend/test_application_mediator.cpp 2013-03-06 12:54:33 +0000
1423+++ tests/unit-tests/frontend/test_application_mediator.cpp 2013-03-07 08:31:22 +0000
1424@@ -112,6 +112,12 @@
1425 void tag_session_with_lightdm_id(std::shared_ptr<msh::Session> const&, int) {}
1426 void focus_session_with_lightdm_id(int) {}
1427
1428+ std::shared_ptr<mir::Shell> current_shell() const
1429+ {
1430+ std::shared_ptr<mir::Shell> noshell;
1431+ return noshell;
1432+ }
1433+
1434 std::shared_ptr<msh::SurfaceFactory> factory;
1435 };
1436
1437
1438=== modified file 'tests/unit-tests/frontend/test_application_mediator_gbm.cpp'
1439--- tests/unit-tests/frontend/test_application_mediator_gbm.cpp 2013-03-06 12:54:33 +0000
1440+++ tests/unit-tests/frontend/test_application_mediator_gbm.cpp 2013-03-07 08:31:22 +0000
1441@@ -83,6 +83,12 @@
1442 void tag_session_with_lightdm_id(std::shared_ptr<msh::Session> const&, int) {}
1443 void focus_session_with_lightdm_id(int) {}
1444
1445+ std::shared_ptr<mir::Shell> current_shell() const
1446+ {
1447+ std::shared_ptr<mir::Shell> noshell;
1448+ return noshell;
1449+ }
1450+
1451 std::shared_ptr<msh::SurfaceFactory> factory;
1452 };
1453
1454
1455=== modified file 'tests/unit-tests/sessions/test_application_session.cpp'
1456--- tests/unit-tests/sessions/test_application_session.cpp 2013-03-06 12:54:33 +0000
1457+++ tests/unit-tests/sessions/test_application_session.cpp 2013-03-07 08:31:22 +0000
1458@@ -64,6 +64,8 @@
1459 MOCK_CONST_METHOD0(pixel_format, mir::geometry::PixelFormat ());
1460 MOCK_CONST_METHOD0(client_buffer, std::shared_ptr<mc::Buffer> ());
1461
1462+ MOCK_METHOD2(configure, int(MirSurfaceAttrib, int));
1463+
1464 private:
1465 ms::BasicProxySurface impl;
1466 };
1467
1468=== added directory 'tests/unit-tests/shell'
1469=== added file 'tests/unit-tests/shell/CMakeLists.txt'
1470--- tests/unit-tests/shell/CMakeLists.txt 1970-01-01 00:00:00 +0000
1471+++ tests/unit-tests/shell/CMakeLists.txt 2013-03-07 08:31:22 +0000
1472@@ -0,0 +1,5 @@
1473+list (APPEND UNIT_TEST_SOURCES
1474+ ${CMAKE_CURRENT_SOURCE_DIR}/test_nullshell.cpp
1475+)
1476+
1477+set( UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE)
1478
1479=== added file 'tests/unit-tests/shell/test_nullshell.cpp'
1480--- tests/unit-tests/shell/test_nullshell.cpp 1970-01-01 00:00:00 +0000
1481+++ tests/unit-tests/shell/test_nullshell.cpp 2013-03-07 08:31:22 +0000
1482@@ -0,0 +1,53 @@
1483+/*
1484+ * Copyright © 2013 Canonical Ltd.
1485+ *
1486+ * This program is free software: you can redistribute it and/or modify
1487+ * it under the terms of the GNU General Public License version 3 as
1488+ * published by the Free Software Foundation.
1489+ *
1490+ * This program is distributed in the hope that it will be useful,
1491+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1492+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1493+ * GNU General Public License for more details.
1494+ *
1495+ * You should have received a copy of the GNU General Public License
1496+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1497+ *
1498+ * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
1499+ */
1500+
1501+#include "mir/shell/nullshell.h"
1502+#include <gtest/gtest.h>
1503+
1504+using namespace mir::shell;
1505+
1506+TEST(NullShell, surface_attribs)
1507+{
1508+ NullShell n;
1509+
1510+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE));
1511+ EXPECT_FALSE(n.supports(static_cast<MirSurfaceAttrib>(-1)));
1512+ EXPECT_FALSE(n.supports(static_cast<MirSurfaceAttrib>(99)));
1513+ EXPECT_FALSE(n.supports(MirSurfaceAttrib_ARRAYSIZE));
1514+}
1515+
1516+TEST(NullShell, surface_types)
1517+{
1518+ NullShell n;
1519+
1520+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_NORMAL));
1521+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_UTILITY));
1522+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_DIALOG));
1523+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_OVERLAY));
1524+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_FREESTYLE));
1525+ EXPECT_TRUE(n.supports(MIR_SURFACE_TYPE, MIR_SURFACE_POPOVER));
1526+ EXPECT_FALSE(n.supports(MIR_SURFACE_TYPE, MirSurfaceType_ARRAYSIZE));
1527+ EXPECT_FALSE(n.supports(MIR_SURFACE_TYPE, -1));
1528+ EXPECT_FALSE(n.supports(MIR_SURFACE_TYPE, 123));
1529+
1530+ EXPECT_FALSE(n.supports(static_cast<MirSurfaceAttrib>(-1),
1531+ MIR_SURFACE_NORMAL));
1532+ EXPECT_FALSE(n.supports(static_cast<MirSurfaceAttrib>(99),
1533+ MIR_SURFACE_NORMAL));
1534+ EXPECT_FALSE(n.supports(MirSurfaceAttrib_ARRAYSIZE, MIR_SURFACE_NORMAL));
1535+}
1536
1537=== modified file 'tests/unit-tests/surfaces/test_surface.cpp'
1538--- tests/unit-tests/surfaces/test_surface.cpp 2013-03-06 12:54:33 +0000
1539+++ tests/unit-tests/surfaces/test_surface.cpp 2013-03-07 08:31:22 +0000
1540@@ -306,3 +306,21 @@
1541
1542 EXPECT_EQ(alpha, ret_alpha);
1543 }
1544+
1545+TEST_F(SurfaceCreation, types)
1546+{
1547+ using namespace testing;
1548+
1549+ ms::Surface surf{surface_name, mock_buffer_bundle};
1550+
1551+ EXPECT_EQ(MIR_SURFACE_NORMAL, surf.type());
1552+
1553+ EXPECT_TRUE(surf.set_type(MIR_SURFACE_UTILITY));
1554+ EXPECT_EQ(surf.type(), MIR_SURFACE_UTILITY);
1555+
1556+ EXPECT_FALSE(surf.set_type(static_cast<MirSurfaceType>(999)));
1557+ EXPECT_EQ(surf.type(), MIR_SURFACE_UTILITY);
1558+
1559+ EXPECT_TRUE(surf.set_type(MIR_SURFACE_DIALOG));
1560+ EXPECT_EQ(surf.type(), MIR_SURFACE_DIALOG);
1561+}

Subscribers

People subscribed via source and target branches