Mir

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

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 526
Proposed branch: lp:~vanvugt/mir/surface-types
Merge into: lp:~mir-team/mir/trunk
Diff against target: 854 lines (+460/-1)
30 files modified
debian/control (+12/-0)
debian/mircommon-dev.install (+1/-0)
include/client/mir_toolkit/mir_client_library.h (+19/-0)
include/server/mir/frontend/session.h (+3/-0)
include/server/mir/frontend/session_mediator.h (+5/-0)
include/server/mir/frontend/session_mediator_report.h (+4/-0)
include/server/mir/frontend/surface.h (+3/-0)
include/server/mir/logging/session_mediator_report.h (+2/-0)
include/server/mir/shell/application_session.h (+2/-0)
include/shared/mir_toolkit/common.h (+49/-0)
include/test/mir_test_doubles/mock_session.h (+2/-0)
include/test/mir_test_doubles/mock_surface.h (+2/-0)
include/test/mir_test_doubles/stub_session.h (+4/-0)
include/test/mir_test_doubles/stub_surface.h (+5/-0)
src/client/mir_client_library.cpp (+22/-0)
src/client/mir_surface.cpp (+47/-0)
src/client/mir_surface.h (+11/-0)
src/server/frontend/null_session_mediator_report.cpp (+4/-0)
src/server/frontend/protobuf_message_processor.cpp (+4/-0)
src/server/frontend/session_mediator.cpp (+27/-0)
src/server/logging/session_mediator_report.cpp (+5/-0)
src/server/shell/application_session.cpp (+10/-0)
src/server/shell/surface.cpp (+45/-1)
src/server/shell/surface.h (+8/-0)
src/shared/CMakeLists.txt (+10/-0)
src/shared/protobuf/mir_protobuf.proto (+10/-0)
tests/acceptance-tests/test_client_library.cpp (+74/-0)
tests/integration-tests/cucumber/test_session_management_context.cpp (+2/-0)
tests/unit-tests/client/test_client_mir_surface.cpp (+20/-0)
tests/unit-tests/shell/test_surface.cpp (+48/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/surface-types
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Robert Carr (community) Needs Fixing
Alan Griffiths Approve
Robert Ancell Approve
Review via email: mp+154261@code.launchpad.net

This proposal supersedes a proposal from 2013-03-15.

Commit message

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

This work will also form the foundation of supporting surface states.

Description of the change

Fixed conflicts from nightly upstream landings. Also moved type out of surfaces::Surface and into shell::Surface.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:554
http://jenkins.qa.ubuntu.com/job/mir-ci/69/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/70//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/69//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I don't think that surfaces::Surface needs configure(MirSurfaceAttrib attrib, int value) - AFICS attributes are a feature of shell::Surface. (And, as discussed elsewhere, surfaces::ProxySurface belongs in shell, possibly as shell::Window.)

~~~~

90 +

Trailing whitespace.

~~~~

216 === added file 'include/shared/mir/common.h'

This is not the place for parts of the toolkit API - this is for namespace mir

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Is there a clear distinction between SurfaceSetting and SurfaceParameters? (And is it worth supplying SurfaceSetting to create_surface and avoiding a round-trip?)

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

the new surface type get/set for client api looks ok to me

The acceptance test takes quite a while on the galaxy nexus, perhaps it can be shortened by using less iterations in line 757?
[ RUN ] DefaultDisplayServerTestFixture.surface_types
[ OK ] DefaultDisplayServerTestFixture.surface_types (1384 ms)
(i see about 180ms on my desktop)

small nit but with
615 +int ms::Surface::configure(MirSurfaceAttrib attrib, int value)
the name 'configure' didn't make it obvious what is going on in the function.

Also with this function, (related to the comment in it) is the surface type something that mir cares about, or the shell? This is tricky to talk about without a 'shell api', but its still a bit hazy to me what our requirements for tracking the data that the shell cares about.

although the tests look good, they do have multiple testing expectations in them because they are long.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Alan,

Extraneous "configure" methods:
I only added methods where I absolutely needed to, to make the code compile and run. However that was many revisions ago so I'll check to see if it's still required...

Trailing whitespace at line 90:
Will fix now.

216 === added file 'include/shared/mir/common.h'
"common.h" is not part of the "toolkit". It is used by the client toolkit and in the server.

SurfaceSetting vs SurfaceParameters
Yes they will always be different. SurfaceParameters are required information to create a surface. SurfaceSetting is something you might optionally change later; like type, state, hidden, width, height (most of which are not implemented yet but require this branch to land first).

Kevin,

Stress test takes too long:
I think 1.3 seconds is OK for a stress test, but I can shorten it if you really want.

"configure" is not self explanatory:
I kind of agree but have not yet thought of a better method name other than "set_attribute" (making the protocol call something like "set_surface_attribute"). I prefer "configure_surface". More suggestions?

Who cares about surface type?...
You're absolutely right that surface type is something only the shell will care about and act upon. However for consistency between different shells and avoiding duplication, it is reasonable for the server to store the type value in each server surface instance. Even though it will only be used by the shell. This will change as new attributes are added like "state" which will potentially be used by the server directly.

Test length:
Yes, I will always make code as concise as possible without hurting readability.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Minor fixes done.

Alan -
I can put "common.h" anywhere of course. Just remember:
  1. It's not part of the "toolkit". "toolkit" means client-only but "common.h" is also used in the server and shell.
  2. common.h has to be installed under "include/mir/..." to make it clear to external users that it's part of mir. And it is implicitly in the "mir" namespace by virtue of the "Mir" type prefixes. We can't use "namespace mir" however because it is C code, not C++.

Alan & Kevin -
I agree that "type" is not a deep server-level attribute. It only makes sense at the shell level. I could move it out of surfaces::Surface now, and into a proxy class. However I think that should be done later because the "Proxy" classes clearly need some refactoring, everyone seems to agree. I'd rather not make assumptions about what form that will take and move any members into *ProxySurface until that's done.

Also keep in mind that _most_ future configurable attributes (state, hidden, width, height etc) will be low-level and live in the server surfaces::Surface rather than the shell.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> Minor fixes done.
>
> Alan -
> I can put "common.h" anywhere of course. Just remember:
> 1. It's not part of the "toolkit". "toolkit" means client-only but
> "common.h" is also used in the server and shell.
> 2. common.h has to be installed under "include/mir/..." to make it clear to
> external users that it's part of mir. And it is implicitly in the "mir"
> namespace by virtue of the "Mir" type prefixes. We can't use "namespace mir"
> however because it is C code, not C++.

As it is included by toolkit I think it is part of toolkit. If it were really "part of mir", then there would be no reason for it to be C code. (Is it part of some hypothetical "common" that we've just identified - if so, is "common.h" isn't a good name.)

> Alan & Kevin -
> I agree that "type" is not a deep server-level attribute. It only makes sense
> at the shell level. I could move it out of surfaces::Surface now, and into a
> proxy class. However I think that should be done later because the "Proxy"
> classes clearly need some refactoring, everyone seems to agree. I'd rather not
> make assumptions about what form that will take and move any members into
> *ProxySurface until that's done.

Perhaps it is best to wait on that refactoring and reassess after that?

> Also keep in mind that _most_ future configurable attributes (state, hidden,
> width, height etc) will be low-level and live in the server surfaces::Surface
> rather than the shell.

Are you envisaging using the same mechanism?

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Absolutely, all attributes that can be changed after construction will use configure() eventually.

Please consider landing this branch before any ProxySurface refactoring. I am tired of fixing conflicts and refactoring it every day.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Also, these arguments are blocking me from starting on two other deliverables which will depend on this work.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> Absolutely, all attributes that can be changed after construction will use
> configure() eventually.

Does that imply that e.g. you see resizing happening by setting the width and height in two configure calls? I'm not sure that is a good plan.

Why wouldn't there be a single resize(graphics::Size) call?

> Please consider landing this branch before any ProxySurface refactoring. I am
> tired of fixing conflicts and refactoring it every day.

I'm equally tired of reviewing it every day - there has to be a better way to communicate.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Good point. Width/height are bad examples. But I will reuse configure() for surface states soon.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I tried moving common.h to: include/shared/mir_toolkit/common.h
But that fails for reasons alluded to earlier. That is such common headers need to have the same relative path in the source tree as in the install tree. Because mir_client_library.h has to be able to find common.h in both situations.

Any suggestions?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> I tried moving common.h to: include/shared/mir_toolkit/common.h
> But that fails for reasons alluded to earlier. That is such common headers
> need to have the same relative path in the source tree as in the install tree.
> Because mir_client_library.h has to be able to find common.h in both
> situations.
>
> Any suggestions?

I guess this comes as part of the various problems with directory names.

IMO include/shared/mir_toolkit and include/client/mir_toolkit should be installed to <target>/mir_toolkit - and that would facilitate #include <mir_toolkit/common.h>

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

>
> I guess this comes as part of the various problems with directory names.
>
> IMO include/shared/mir_toolkit and include/client/mir_toolkit should be
> installed to <target>/mir_toolkit - and that would facilitate #include
> <mir_toolkit/common.h>

+1

Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

== include/shared/mir vs include/shared/mir_toolkit ==

The concept is that whatever is under */mir_toolkit (and only that) will be part of the toolkit interface. Since a toolkit/client needs this, mir_toolkit is the way to go. Keep in mind that this is still under shared/.

So, this is how I see things currently:

1. server/*, client/*, shared/* => which mir components need to access the definitions in the file
2. */mir, */mir_toolkit => whether the definitions are internal to mir, or (also) exposed to the toolkit API

== surfaces::Surface::set_type(),type() ==

I agree that this doesn't belong there. I don't have a problem putting it there *temporarily* to unblock work, if the related surface refactorings aren't expected to be done soon.

== configure() ==

At the Surface level, and for the limited number of attributes I am aware of, I would prefer to have explicit calls : app_session->set_surface_state(id, ...) or app_session->surface(id)->set_state(...) (since we are already exposing the surface) etc

At the RPC level: one approach is to use configure(attrib, value), another is to have <attrib>(value) calls. A third approach (not neccessarily preferable for this use case, just mentioning it for completeness) is to have, e.g.:

message SurfaceSettings {
    optional SurfaceId surfaceid = 1;
    optional int32 type = 2;
    optional int32 state = 3;
    optional bool visible = 4;
    ...
}

The frontend could then act depending on which values are actually included in the message. This method allows the client to set and retrieve all of the settings in one go.

For the number of attributes and the use cases I am aware of, my preference would be once again to be explicit, and have separate calls <attrib>().

Marking as "Needs information" => "Needs discussion"

review: Needs Information
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I thought it was implicit that having two different top-level include directories:
  <mir/foo>
  <mir_toolkit/bar>
was obviously a bad idea. I thought that was obvious but clearly it's just my opinion now. I think eventually everything should be under "mir/" for consistency:
  <mir/foo>
  <mir/toolkit/bar>
But that's a cleanup for a another day and a different proposal.

Alexandros:
configure() needs to be generic because there are so many layers of classes in the Mir code, it does not scale to add a new function for every attribute at every layer. When I added configure() I was surprised at how many classes I had to modify. It becomes unmaintainable and excessively over-complicated if you have to do that again and again for each new attribute. Consider also reporting -- we don't want to change every type of report to add new methods to those every time a new attribute is added.
Also, we should not assume to have designed all the required attributes any time soon. New attributes will be added and some even removed over time. We don't want to go changing the protocol and half a dozen foundational classes each time.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I've now been working on this branch for a month and it's been under review for two weeks. It has worked perfectly without bugs for the entire duration. Remember we're only arguing about style issues that can be fixed later.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

8 +Package: mircommon-dev

I don't think this is right as it stands - but that is probably part of a pre-existing problem with the install packages and directory structure.

We need to be able to install the client process toolkit headers. (shared/mir_toolkit/* + client/mir_toolkit/*)

We need to be able to install the server process toolkit headers. (shared/mir_toolkit/* + server/mir_toolkit/*)

We need to be able to install for building against the library headers. (shared/mir/* + server/mir/* + shared/mir_toolkit/common.h)

I don't have a better proposal to hand, but something needs fixing.

~~~~

As I've said before I don't think that surfaces::Surface needs configure(MirSurfaceAttrib attrib, int value) - AFICS attributes are a feature of shell::Surface.

But I guess we can delete it a few minutes after it lands.

review: Abstain
Revision history for this message
Robert Ancell (robert-ancell) wrote : Posted in a previous version of this proposal

I'm unsure about why we have mircommon, but that can be solved outside of this.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I might be able to install "common.h" twice; for client and server. Thus eliminating the mircommon-dev package. If you want me to give it a go?.. But there's obviously redundancy doing that.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I think we need a discussion about the different user code targets we want to support and organizing headers to support them. But this MP isn't the place for it.

I'd still prefer not putting attributes that belong on shell::Surface onto surface::Surface.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Work in progress again. As happens every day, there are conflicts from upstream I need to resolve.

I will also re-visit the shell::Surface discussion now that shell::Surface actually exists.

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 :

I'm not sure if these are consistent:

316 + // I assume the type can only change from the client side. Otherwise
317 + // we would have to send off a message to retrieve the latest...
...
619 + bool set_type(MirSurfaceType t);

This is a public member function - that suggest that it could, potentially, be called other than as the result of a call from a client process.

Also, given the expectation of using a graphics toolkit within the server process is "client side" the right terminology?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

820 + EXPECT_EQ(surf.configure(mir_surface_attrib_type,
821 + mir_surface_type_popover),
822 + mir_surface_type_popover);

Expected and actual reversed

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

Alan's concerns addressed.

And if you want to be that pedantic about gtest syntax, see bug 1149157.

Revision history for this message
Robert Ancell (robert-ancell) :
review: Approve
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 :

> Alan's concerns addressed.
>
> And if you want to be that pedantic about gtest syntax, see bug 1149157.

My "concern" is about getting clear output from a test failure.

If I wanted to be pedantic I'd "Need Fixing" the tests that don't test a single thing described by the test name.

review: Approve
Revision history for this message
Robert Carr (robertcarr) wrote :

Looks good! excited to get surface attributes in.

Some minor style nits:

>>+/**
>>+ * Set the type (purpose) of a surface. This is not guaranteed to always work
>>+ * with some shell types (e.g. phone/tablet UIs). As such, you may have to
>>+ * wait on the function and check the result using mir_surface_get_type.
>>+ * \param [in] surface The surface to operate on
>>+ * \param [in] type The new type of the surface
>>+ * \return A wait handle that can be passed to mir_wait_for
>>+ */

Only nitting here because it's public header. I found this a little confusing to read (i.e. mention of phone/tablet is a little distracting). I would write it like this:

"Set the type (role) of a surface. Success of this operation is dependent on server policy. As such, you may have to wait on the function and check the result using mir_suface_get_type"

>>+ mir_surface_type_arraysize_
Do we do this elsewhere (trailing underscore), should we?

>> 427:
I find the continuous mention in comments and the variable attrib_cache of "cache" confusing. In this sense of the word cache, mir_toolkit:MirSurface itself is a cache of the latest Surface state returned from the server. Reading cache here makes me think there is some extra caching behavior going on, whereas really it's no different than surface geometry!

Revision history for this message
Robert Carr (robertcarr) wrote :

>> 477:
I can't find the test for this

review: Needs Information
Revision history for this message
Robert Carr (robertcarr) wrote :

>> 305:
Whitespace

>> 821:

This would be more in line with the rest of the code style if there were a few tests:

TEST_F(ShellSurface, default_surface_type_is_normal)
TEST_F(ShellSurface, takes_surface_type_from_configure)
TEST_F(ShellSurface, invalid_surface_type_throw_behavior)

This would improve the failure output significantly I think

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

racarr,

comment confusion: Yeah easy to fix, later.

mir_surface_type_arraysize_: This is similar to a convention I have used for a long time. There is no precedent in the mir source AFAIK. It is adapted from the original version I proposed 3 weeks ago: "MirSurfaceType_ARRAYSIZE" which is the style Google uses in protobuf.

427: Comments can be clarified. But not worth a reproposal.

477: The test for the whole configure_surface stack is covered by:
TEST_F(DefaultDisplayServerTestFixture, surface_types)

305: That indentation is no mistake. I moved it to stay within 80 columns.

821: I am adjusting my style to suit you guys. It won't happen over night but it is happening. I don't think this is a blocker.

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

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-12 03:50:42 +0000
3+++ debian/control 2013-03-21 04:05:24 +0000
4@@ -58,11 +58,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@@ -86,6 +97,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=== added file 'debian/mircommon-dev.install'
37--- debian/mircommon-dev.install 1970-01-01 00:00:00 +0000
38+++ debian/mircommon-dev.install 2013-03-21 04:05:24 +0000
39@@ -0,0 +1,1 @@
40+usr/include/mir_toolkit/*.h
41
42=== modified file 'include/client/mir_toolkit/mir_client_library.h'
43--- include/client/mir_toolkit/mir_client_library.h 2013-03-20 10:26:48 +0000
44+++ include/client/mir_toolkit/mir_client_library.h 2013-03-21 04:05:24 +0000
45@@ -18,6 +18,8 @@
46 #ifndef MIR_CLIENT_LIBRARY_H
47 #define MIR_CLIENT_LIBRARY_H
48
49+#include <mir_toolkit/common.h>
50+
51 #ifdef __cplusplus
52 /** The C client API
53 */
54@@ -358,6 +360,23 @@
55 */
56 int mir_debug_surface_id(MirSurface *surface);
57
58+/**
59+ * Set the type (purpose) of a surface. This is not guaranteed to always work
60+ * with some shell types (e.g. phone/tablet UIs). As such, you may have to
61+ * wait on the function and check the result using mir_surface_get_type.
62+ * \param [in] surface The surface to operate on
63+ * \param [in] type The new type of the surface
64+ * \return A wait handle that can be passed to mir_wait_for
65+ */
66+MirWaitHandle* mir_surface_set_type(MirSurface *surface, MirSurfaceType type);
67+
68+/**
69+ * Get the type (purpose) of a surface.
70+ * \param [in] surface The surface to query
71+ * \return The type of the surface
72+ */
73+MirSurfaceType mir_surface_get_type(MirSurface *surface);
74+
75 #ifdef __cplusplus
76 }
77 }
78
79=== modified file 'include/server/mir/frontend/session.h'
80--- include/server/mir/frontend/session.h 2013-03-19 03:05:30 +0000
81+++ include/server/mir/frontend/session.h 2013-03-21 04:05:24 +0000
82@@ -19,6 +19,7 @@
83 #ifndef MIR_FRONTEND_SESSION_H_
84 #define MIR_FRONTEND_SESSION_H_
85
86+#include "mir_toolkit/common.h"
87 #include "mir/frontend/surface_id.h"
88
89 #include <mutex>
90@@ -49,6 +50,8 @@
91 virtual void hide() = 0;
92 virtual void show() = 0;
93
94+ virtual int configure_surface(SurfaceId id, MirSurfaceAttrib attrib, int value) = 0;
95+
96 protected:
97 Session() = default;
98 Session(Session const&) = delete;
99
100=== modified file 'include/server/mir/frontend/session_mediator.h'
101--- include/server/mir/frontend/session_mediator.h 2013-03-19 03:05:30 +0000
102+++ include/server/mir/frontend/session_mediator.h 2013-03-21 04:05:24 +0000
103@@ -100,6 +100,11 @@
104 mir::protobuf::DRMAuthMagicStatus* response,
105 google::protobuf::Closure* done);
106
107+ void configure_surface(google::protobuf::RpcController* controller,
108+ const mir::protobuf::SurfaceSetting*,
109+ mir::protobuf::SurfaceSetting*,
110+ google::protobuf::Closure* done);
111+
112 private:
113 std::shared_ptr<Shell> const shell;
114 std::shared_ptr<graphics::Platform> const graphics_platform;
115
116=== modified file 'include/server/mir/frontend/session_mediator_report.h'
117--- include/server/mir/frontend/session_mediator_report.h 2013-03-19 03:05:30 +0000
118+++ include/server/mir/frontend/session_mediator_report.h 2013-03-21 04:05:24 +0000
119@@ -42,6 +42,8 @@
120
121 virtual void session_drm_auth_magic_called(std::string const& app_name) = 0;
122
123+ virtual void session_configure_surface_called(std::string const& app_name) = 0;
124+
125 virtual void session_error(
126 std::string const& app_name,
127 char const* method,
128@@ -63,6 +65,8 @@
129
130 virtual void session_drm_auth_magic_called(std::string const& app_name);
131
132+ virtual void session_configure_surface_called(std::string const& app_name);
133+
134 virtual void session_error(
135 std::string const& app_name,
136 char const* method,
137
138=== modified file 'include/server/mir/frontend/surface.h'
139--- include/server/mir/frontend/surface.h 2013-03-20 10:56:07 +0000
140+++ include/server/mir/frontend/surface.h 2013-03-21 04:05:24 +0000
141@@ -23,6 +23,7 @@
142 #include "mir/geometry/pixel_format.h"
143 #include "mir/geometry/point.h"
144 #include "mir/geometry/size.h"
145+#include "mir_toolkit/common.h"
146
147 #include <memory>
148
149@@ -60,6 +61,8 @@
150 virtual bool supports_input() const = 0;
151 virtual int client_input_fd() const = 0;
152
153+ virtual int configure(MirSurfaceAttrib attrib, int value) = 0;
154+
155 protected:
156 Surface() = default;
157 Surface(Surface const&) = delete;
158
159=== modified file 'include/server/mir/logging/session_mediator_report.h'
160--- include/server/mir/logging/session_mediator_report.h 2013-03-19 03:05:30 +0000
161+++ include/server/mir/logging/session_mediator_report.h 2013-03-21 04:05:24 +0000
162@@ -47,6 +47,8 @@
163
164 virtual void session_drm_auth_magic_called(std::string const& app_name);
165
166+ virtual void session_configure_surface_called(std::string const& app_name);
167+
168 virtual void session_error(
169 std::string const& app_name,
170 char const* method,
171
172=== modified file 'include/server/mir/shell/application_session.h'
173--- include/server/mir/shell/application_session.h 2013-03-20 10:56:07 +0000
174+++ include/server/mir/shell/application_session.h 2013-03-21 04:05:24 +0000
175@@ -47,6 +47,8 @@
176 void hide();
177 void show();
178
179+ int configure_surface(frontend::SurfaceId id, MirSurfaceAttrib attrib, int value);
180+
181 protected:
182 ApplicationSession(ApplicationSession const&) = delete;
183 ApplicationSession& operator=(ApplicationSession const&) = delete;
184
185=== added file 'include/shared/mir_toolkit/common.h'
186--- include/shared/mir_toolkit/common.h 1970-01-01 00:00:00 +0000
187+++ include/shared/mir_toolkit/common.h 2013-03-21 04:05:24 +0000
188@@ -0,0 +1,49 @@
189+/*
190+ * Simple definitions common to client and server.
191+ *
192+ * Copyright © 2013 Canonical Ltd.
193+ *
194+ * This program is free software: you can redistribute it and/or modify
195+ * it under the terms of the GNU Lesser General Public License version 3 as
196+ * published by the Free Software Foundation.
197+ *
198+ * This program is distributed in the hope that it will be useful,
199+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
200+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201+ * GNU Lesser General Public License for more details.
202+ *
203+ * You should have received a copy of the GNU Lesser General Public License
204+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
205+ *
206+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
207+ */
208+
209+#ifndef MIR_COMMON_H_
210+#define MIR_COMMON_H_
211+
212+/* This is C code. Not C++. */
213+
214+/*
215+ * Attributes of a surface that the client and server/shell may wish to
216+ * get or set over the wire.
217+ */
218+typedef enum MirSurfaceAttrib
219+{
220+ mir_surface_attrib_type,
221+ mir_surface_attrib_arraysize_
222+} MirSurfaceAttrib;
223+
224+typedef enum MirSurfaceType
225+{
226+ mir_surface_type_normal,
227+ mir_surface_type_utility,
228+ mir_surface_type_dialog,
229+ mir_surface_type_overlay,
230+ mir_surface_type_freestyle,
231+ mir_surface_type_popover,
232+ mir_surface_type_arraysize_
233+} MirSurfaceType;
234+
235+/* TODO: Surface states here */
236+
237+#endif
238
239=== modified file 'include/test/mir_test_doubles/mock_session.h'
240--- include/test/mir_test_doubles/mock_session.h 2013-03-19 03:05:30 +0000
241+++ include/test/mir_test_doubles/mock_session.h 2013-03-21 04:05:24 +0000
242@@ -41,6 +41,8 @@
243
244 MOCK_METHOD0(hide, void());
245 MOCK_METHOD0(show, void());
246+
247+ MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int));
248 };
249
250 }
251
252=== modified file 'include/test/mir_test_doubles/mock_surface.h'
253--- include/test/mir_test_doubles/mock_surface.h 2013-03-20 10:56:07 +0000
254+++ include/test/mir_test_doubles/mock_surface.h 2013-03-21 04:05:24 +0000
255@@ -49,6 +49,8 @@
256
257 MOCK_CONST_METHOD0(supports_input, bool());
258 MOCK_CONST_METHOD0(client_input_fd, int());
259+
260+ MOCK_METHOD2(configure, int(MirSurfaceAttrib, int));
261 };
262
263 }
264
265=== modified file 'include/test/mir_test_doubles/stub_session.h'
266--- include/test/mir_test_doubles/stub_session.h 2013-03-19 03:05:30 +0000
267+++ include/test/mir_test_doubles/stub_session.h 2013-03-21 04:05:24 +0000
268@@ -54,6 +54,10 @@
269 void show()
270 {
271 }
272+ int configure_surface(frontend::SurfaceId, MirSurfaceAttrib, int)
273+ {
274+ return 0;
275+ }
276 };
277
278 }
279
280=== modified file 'include/test/mir_test_doubles/stub_surface.h'
281--- include/test/mir_test_doubles/stub_surface.h 2013-03-18 15:43:58 +0000
282+++ include/test/mir_test_doubles/stub_surface.h 2013-03-21 04:05:24 +0000
283@@ -53,6 +53,11 @@
284 {
285 return std::shared_ptr<compositor::Buffer>();
286 }
287+
288+ virtual int configure(MirSurfaceAttrib, int)
289+ {
290+ return 0;
291+ }
292
293 virtual bool supports_input() const
294 {
295
296=== modified file 'src/client/mir_client_library.cpp'
297--- src/client/mir_client_library.cpp 2013-03-20 05:11:57 +0000
298+++ src/client/mir_client_library.cpp 2013-03-21 04:05:24 +0000
299@@ -272,3 +272,25 @@
300 {
301 // Ignore
302 }
303+
304+mir_toolkit::MirWaitHandle* mir_toolkit::mir_surface_set_type(MirSurface *surf,
305+ MirSurfaceType type)
306+{
307+ return surf ? surf->configure(mir_surface_attrib_type, type) : NULL;
308+}
309+
310+MirSurfaceType mir_toolkit::mir_surface_get_type(MirSurface *surf)
311+{
312+ MirSurfaceType type = mir_surface_type_normal;
313+
314+ if (surf)
315+ {
316+ // Only the client will ever change the type of a surface so it is
317+ // safe to get the type from a local cache surf->attrib().
318+
319+ int t = surf->attrib(mir_surface_attrib_type);
320+ type = static_cast<MirSurfaceType>(t);
321+ }
322+
323+ return type;
324+}
325
326=== modified file 'src/client/mir_surface.cpp'
327--- src/client/mir_surface.cpp 2013-03-07 08:04:05 +0000
328+++ src/client/mir_surface.cpp 2013-03-21 04:05:24 +0000
329@@ -50,6 +50,10 @@
330 message.set_buffer_usage(params.buffer_usage);
331
332 server.create_surface(0, &message, &surface, gp::NewCallback(this, &MirSurface::created, callback, context));
333+
334+ for (int i = 0; i < mir_surface_attrib_arraysize_; i++)
335+ attrib_cache[i] = -1;
336+ attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal;
337 }
338
339 mir_toolkit::MirSurface::~MirSurface()
340@@ -226,3 +230,46 @@
341 {
342 return *accelerated_window;
343 }
344+
345+MirWaitHandle* MirSurface::configure(MirSurfaceAttrib at, int value)
346+{
347+ mp::SurfaceSetting setting;
348+ setting.mutable_surfaceid()->CopyFrom(surface.id());
349+ setting.set_attrib(at);
350+ setting.set_ivalue(value);
351+
352+ configure_wait_handle.expect_result();
353+ server.configure_surface(0, &setting, &configure_result,
354+ google::protobuf::NewCallback(this, &MirSurface::on_configured));
355+
356+ return &configure_wait_handle;
357+}
358+
359+void MirSurface::on_configured()
360+{
361+ if (configure_result.has_surfaceid() &&
362+ configure_result.surfaceid().value() == surface.id().value() &&
363+ configure_result.has_attrib())
364+ {
365+ switch (configure_result.attrib())
366+ {
367+ case mir_surface_attrib_type:
368+ if (configure_result.has_ivalue())
369+ {
370+ int t = configure_result.ivalue();
371+ attrib_cache[mir_surface_attrib_type] = t;
372+ } // else error is probably set due to an unsupported attrib/value
373+ break;
374+ default:
375+ assert(false);
376+ break;
377+ }
378+
379+ configure_wait_handle.result_received();
380+ }
381+}
382+
383+int MirSurface::attrib(MirSurfaceAttrib at) const
384+{
385+ return attrib_cache[at];
386+}
387
388=== modified file 'src/client/mir_surface.h'
389--- src/client/mir_surface.h 2013-03-15 07:40:59 +0000
390+++ src/client/mir_surface.h 2013-03-21 04:05:24 +0000
391@@ -23,6 +23,7 @@
392 #include "mir/geometry/pixel_format.h"
393 #include "mir/geometry/dimensions.h"
394 #include "mir_toolkit/mir_client_library.h"
395+#include "mir_toolkit/common.h"
396 #include "client_buffer_depository.h"
397 #include "mir_wait_handle.h"
398 #include "mir_client_surface.h"
399@@ -72,7 +73,11 @@
400 void release_cpu_region();
401 EGLNativeWindowType generate_native_window();
402
403+ MirWaitHandle* configure(MirSurfaceAttrib a, int value);
404+ int attrib(MirSurfaceAttrib a) const;
405+
406 private:
407+ void on_configured();
408 void process_incoming_buffer();
409 void populate(MirBufferPackage& buffer_package);
410 void created(mir_surface_lifecycle_callback callback, void * context);
411@@ -88,6 +93,7 @@
412 MirConnection *connection;
413 MirWaitHandle create_wait_handle;
414 MirWaitHandle next_buffer_wait_handle;
415+ MirWaitHandle configure_wait_handle;
416
417 int last_buffer_id;
418
419@@ -96,6 +102,11 @@
420
421 std::shared_ptr<mir::client::Logger> logger;
422 std::shared_ptr<EGLNativeWindowType> accelerated_window;
423+
424+ mir::protobuf::SurfaceSetting configure_result;
425+
426+ // Cache of latest SurfaceSettings returned from the server
427+ int attrib_cache[mir_surface_attrib_arraysize_];
428 };
429
430 #endif /* MIR_CLIENT_PRIVATE_MIR_WAIT_HANDLE_H_ */
431
432=== modified file 'src/server/frontend/null_session_mediator_report.cpp'
433--- src/server/frontend/null_session_mediator_report.cpp 2013-03-19 03:05:30 +0000
434+++ src/server/frontend/null_session_mediator_report.cpp 2013-03-21 04:05:24 +0000
435@@ -42,6 +42,10 @@
436 {
437 }
438
439+void mir::frontend::NullSessionMediatorReport::session_configure_surface_called(std::string const&)
440+{
441+}
442+
443 void mir::frontend::NullSessionMediatorReport::session_error(
444 std::string const&,
445 char const* ,
446
447=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
448--- src/server/frontend/protobuf_message_processor.cpp 2013-03-07 08:04:05 +0000
449+++ src/server/frontend/protobuf_message_processor.cpp 2013-03-21 04:05:24 +0000
450@@ -176,6 +176,10 @@
451 {
452 invoke(&protobuf::DisplayServer::select_focus_by_lightdm_id, invocation);
453 }
454+ else if ("configure_surface" == invocation.method_name())
455+ {
456+ invoke(&protobuf::DisplayServer::configure_surface, invocation);
457+ }
458 else if ("disconnect" == invocation.method_name())
459 {
460 invoke(&protobuf::DisplayServer::disconnect, invocation);
461
462=== modified file 'src/server/frontend/session_mediator.cpp'
463--- src/server/frontend/session_mediator.cpp 2013-03-20 05:11:57 +0000
464+++ src/server/frontend/session_mediator.cpp 2013-03-21 04:05:24 +0000
465@@ -23,6 +23,7 @@
466 #include "mir/frontend/surface.h"
467 #include "mir/frontend/surface_creation_parameters.h"
468 #include "mir/frontend/resource_cache.h"
469+#include "mir_toolkit/common.h"
470 #include "mir/compositor/buffer_ipc_package.h"
471 #include "mir/compositor/buffer_id.h"
472 #include "mir/compositor/buffer.h"
473@@ -220,3 +221,29 @@
474 done->Run();
475 }
476
477+void mir::frontend::SessionMediator::configure_surface(
478+ google::protobuf::RpcController*, // controller,
479+ const mir::protobuf::SurfaceSetting* request,
480+ mir::protobuf::SurfaceSetting* response,
481+ google::protobuf::Closure* done)
482+{
483+ MirSurfaceAttrib attrib = static_cast<MirSurfaceAttrib>(request->attrib());
484+
485+ // Required response fields:
486+ response->mutable_surfaceid()->CopyFrom(request->surfaceid());
487+ response->set_attrib(attrib);
488+
489+ if (session.get() == nullptr)
490+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
491+
492+ report->session_configure_surface_called(session->name());
493+
494+ auto const id = frontend::SurfaceId(request->surfaceid().value());
495+ int value = request->ivalue();
496+ int newvalue = session->configure_surface(id, attrib, value);
497+
498+ response->set_ivalue(newvalue);
499+
500+ done->Run();
501+}
502+
503
504=== modified file 'src/server/logging/session_mediator_report.cpp'
505--- src/server/logging/session_mediator_report.cpp 2013-03-19 03:05:30 +0000
506+++ src/server/logging/session_mediator_report.cpp 2013-03-21 04:05:24 +0000
507@@ -63,6 +63,11 @@
508 log->log<Logger::informational>("session_drm_auth_magic_called(\"" + app_name + "\")", component);
509 }
510
511+void ml::SessionMediatorReport::session_configure_surface_called(std::string const& app_name)
512+{
513+ log->log<Logger::informational>("session_configure_surface_called(\"" + app_name + "\")", component);
514+}
515+
516 void ml::SessionMediatorReport::session_error(
517 std::string const& app_name,
518 char const* method,
519
520=== modified file 'src/server/shell/application_session.cpp'
521--- src/server/shell/application_session.cpp 2013-03-20 10:56:07 +0000
522+++ src/server/shell/application_session.cpp 2013-03-21 04:05:24 +0000
523@@ -122,3 +122,13 @@
524 id_s.second->show();
525 }
526 }
527+
528+int msh::ApplicationSession::configure_surface(mf::SurfaceId id,
529+ MirSurfaceAttrib attrib,
530+ int value)
531+{
532+ std::unique_lock<std::mutex> lock(surfaces_mutex);
533+ std::shared_ptr<mf::Surface> surf(checked_find(id)->second);
534+
535+ return surf->configure(attrib, value);
536+}
537
538=== modified file 'src/server/shell/surface.cpp'
539--- src/server/shell/surface.cpp 2013-03-19 03:05:30 +0000
540+++ src/server/shell/surface.cpp 2013-03-21 04:05:24 +0000
541@@ -35,7 +35,8 @@
542 std::shared_ptr<input::InputChannel> const& input_channel)
543 : builder(builder),
544 input_channel(input_channel),
545- surface(builder->create_surface(params))
546+ surface(builder->create_surface(params)),
547+ type_value(mir_surface_type_normal)
548 {
549 }
550
551@@ -133,3 +134,46 @@
552 BOOST_THROW_EXCEPTION(std::logic_error("Surface does not support input"));
553 return input_channel->client_fd();
554 }
555+
556+int msh::Surface::configure(MirSurfaceAttrib attrib, int value)
557+{
558+ int result = 0;
559+
560+ /*
561+ * TODO: In future, query the shell implementation for the subset of
562+ * attributes/types it implements.
563+ */
564+ switch (attrib)
565+ {
566+ case mir_surface_attrib_type:
567+ if (!set_type(static_cast<MirSurfaceType>(value)))
568+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface "
569+ "type."));
570+ result = type();
571+ break;
572+ default:
573+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface "
574+ "attribute."));
575+ break;
576+ }
577+
578+ return result;
579+}
580+
581+MirSurfaceType msh::Surface::type() const
582+{
583+ return type_value;
584+}
585+
586+bool msh::Surface::set_type(MirSurfaceType t)
587+{
588+ bool valid = false;
589+
590+ if (t >= 0 && t < mir_surface_type_arraysize_)
591+ {
592+ type_value = t;
593+ valid = true;
594+ }
595+
596+ return valid;
597+}
598
599=== modified file 'src/server/shell/surface.h'
600--- src/server/shell/surface.h 2013-03-20 10:56:07 +0000
601+++ src/server/shell/surface.h 2013-03-21 04:05:24 +0000
602@@ -22,6 +22,7 @@
603
604 #include "mir/frontend/surface.h"
605 #include "mir/surfaces/surface.h"
606+#include "mir_toolkit/common.h"
607
608 namespace mir
609 {
610@@ -66,10 +67,17 @@
611 virtual bool supports_input() const;
612 virtual int client_input_fd() const;
613
614+ virtual int configure(MirSurfaceAttrib attrib, int value);
615+ virtual MirSurfaceType type() const;
616+
617 private:
618+ bool set_type(MirSurfaceType t); // Use configure() to make public changes
619+
620 std::shared_ptr<SurfaceBuilder> const builder;
621 std::shared_ptr<mir::input::InputChannel> const input_channel;
622 std::weak_ptr<mir::surfaces::Surface> const surface;
623+
624+ MirSurfaceType type_value;
625 };
626 }
627 }
628
629=== modified file 'src/shared/CMakeLists.txt'
630--- src/shared/CMakeLists.txt 2013-03-13 17:54:59 +0000
631+++ src/shared/CMakeLists.txt 2013-03-21 04:05:24 +0000
632@@ -5,3 +5,13 @@
633 MIR_GENERATED_INCLUDE_DIRECTORIES
634 ${MIR_GENERATED_INCLUDE_DIRECTORIES}
635 PARENT_SCOPE)
636+
637+# Some headers contain common definitions required for both client and
638+# server development...
639+set (MIR_COMMON_HEADERS
640+ ${CMAKE_SOURCE_DIR}/include/shared/mir_toolkit/common.h
641+)
642+
643+# TODO: Find a more elegant include/ structure. Ideally one in which everything
644+# lives under "include/mir/".
645+install (FILES ${MIR_COMMON_HEADERS} DESTINATION "include/mir_toolkit/")
646
647=== modified file 'src/shared/protobuf/mir_protobuf.proto'
648--- src/shared/protobuf/mir_protobuf.proto 2013-03-19 03:05:30 +0000
649+++ src/shared/protobuf/mir_protobuf.proto 2013-03-21 04:05:24 +0000
650@@ -114,6 +114,14 @@
651 optional string error = 127;
652 }
653
654+message SurfaceSetting {
655+ optional SurfaceId surfaceid = 1;
656+ optional int32 attrib = 2;
657+ optional int32 ivalue = 3;
658+ // optional string svalue = 4; // Expected for future use
659+ optional string error = 127;
660+}
661+
662 service DisplayServer {
663 // Platform independent requests
664 rpc connect(ConnectParameters) returns (Connection);
665@@ -127,5 +135,7 @@
666 rpc drm_auth_magic(DRMMagic) returns (DRMAuthMagicStatus);
667
668 rpc test_file_descriptors(Void) returns (Buffer);
669+
670+ rpc configure_surface(SurfaceSetting) returns (SurfaceSetting);
671 }
672
673
674=== modified file 'tests/acceptance-tests/test_client_library.cpp'
675--- tests/acceptance-tests/test_client_library.cpp 2013-03-20 05:11:57 +0000
676+++ tests/acceptance-tests/test_client_library.cpp 2013-03-21 04:05:24 +0000
677@@ -205,6 +205,80 @@
678 launch_client_process(client_config);
679 }
680
681+TEST_F(DefaultDisplayServerTestFixture, surface_types)
682+{
683+ struct ClientConfig : ClientConfigCommon
684+ {
685+ void exec()
686+ {
687+
688+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
689+
690+ ASSERT_TRUE(connection != NULL);
691+ EXPECT_TRUE(mir_connection_is_valid(connection));
692+ EXPECT_STREQ(mir_connection_get_error_message(connection), "");
693+
694+ MirSurfaceParameters const request_params =
695+ {
696+ __PRETTY_FUNCTION__,
697+ 640, 480,
698+ mir_pixel_format_abgr_8888,
699+ mir_buffer_usage_hardware
700+ };
701+
702+ mir_wait_for(mir_surface_create(connection, &request_params, create_surface_callback, this));
703+
704+ ASSERT_TRUE(surface != NULL);
705+ EXPECT_TRUE(mir_surface_is_valid(surface));
706+ EXPECT_STREQ(mir_surface_get_error_message(surface), "");
707+
708+ EXPECT_EQ(mir_surface_type_normal,
709+ mir_surface_get_type(surface));
710+
711+ mir_wait_for(mir_surface_set_type(surface,
712+ mir_surface_type_freestyle));
713+ EXPECT_EQ(mir_surface_type_freestyle,
714+ mir_surface_get_type(surface));
715+
716+ mir_wait_for(mir_surface_set_type(surface,
717+ static_cast<MirSurfaceType>(999)));
718+ EXPECT_EQ(mir_surface_type_freestyle,
719+ mir_surface_get_type(surface));
720+
721+ mir_wait_for(mir_surface_set_type(surface,
722+ mir_surface_type_dialog));
723+ EXPECT_EQ(mir_surface_type_dialog,
724+ mir_surface_get_type(surface));
725+
726+ mir_wait_for(mir_surface_set_type(surface,
727+ static_cast<MirSurfaceType>(888)));
728+ EXPECT_EQ(mir_surface_type_dialog,
729+ mir_surface_get_type(surface));
730+
731+ // Stress-test synchronization logic with some flooding
732+ for (int i = 0; i < 100; i++)
733+ {
734+ mir_surface_set_type(surface, mir_surface_type_normal);
735+ mir_surface_set_type(surface, mir_surface_type_utility);
736+ mir_surface_set_type(surface, mir_surface_type_dialog);
737+ mir_surface_set_type(surface, mir_surface_type_overlay);
738+ mir_surface_set_type(surface, mir_surface_type_freestyle);
739+ mir_wait_for(mir_surface_set_type(surface,
740+ mir_surface_type_popover));
741+ ASSERT_EQ(mir_surface_type_popover,
742+ mir_surface_get_type(surface));
743+ }
744+
745+ mir_wait_for(mir_surface_release(surface, release_surface_callback,
746+ this));
747+
748+ mir_connection_release(connection);
749+ }
750+ } client_config;
751+
752+ launch_client_process(client_config);
753+}
754+
755 TEST_F(DefaultDisplayServerTestFixture, client_library_creates_multiple_surfaces)
756 {
757 int const n_surfaces = 13;
758
759=== modified file 'tests/integration-tests/cucumber/test_session_management_context.cpp'
760--- tests/integration-tests/cucumber/test_session_management_context.cpp 2013-03-20 05:11:57 +0000
761+++ tests/integration-tests/cucumber/test_session_management_context.cpp 2013-03-21 04:05:24 +0000
762@@ -64,6 +64,8 @@
763 MOCK_CONST_METHOD0(pixel_format, mir::geometry::PixelFormat ());
764 MOCK_CONST_METHOD0(client_buffer, std::shared_ptr<mc::Buffer> ());
765
766+ MOCK_METHOD2(configure, int(MirSurfaceAttrib, int));
767+
768 MOCK_CONST_METHOD0(supports_input, bool());
769 MOCK_CONST_METHOD0(client_input_fd, int());
770 };
771
772=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
773--- tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-07 08:04:05 +0000
774+++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-21 04:05:24 +0000
775@@ -376,3 +376,23 @@
776 EXPECT_EQ(pf, geom::PixelFormat::abgr_8888);
777 }
778
779+TEST_F(MirClientSurfaceTest, default_surface_type)
780+{
781+ using namespace testing;
782+ using namespace mir::protobuf;
783+
784+ EXPECT_CALL(*mock_depository, deposit_package_rv(_,_,_,_))
785+ .Times(1);
786+
787+ auto surface = std::make_shared<MirSurface> (connection.get(),
788+ *client_comm_channel,
789+ logger,
790+ mock_depository,
791+ params,
792+ &empty_callback,
793+ (void*) NULL);
794+ surface->get_create_wait_handle()->wait_for_result();
795+
796+ EXPECT_EQ(mir_surface_type_normal,
797+ surface->attrib(mir_surface_attrib_type));
798+}
799
800=== modified file 'tests/unit-tests/shell/test_surface.cpp'
801--- tests/unit-tests/shell/test_surface.cpp 2013-03-20 05:11:57 +0000
802+++ tests/unit-tests/shell/test_surface.cpp 2013-03-21 04:05:24 +0000
803@@ -307,3 +307,51 @@
804 }, std::logic_error);
805 }
806
807+TEST_F(ShellSurface, attributes)
808+{
809+ using namespace testing;
810+
811+ msh::Surface surf(
812+ mt::fake_shared(surface_builder),
813+ mf::a_surface(),
814+ null_input_channel);
815+
816+ EXPECT_THROW({
817+ surf.configure(static_cast<MirSurfaceAttrib>(111), 222);
818+ }, std::logic_error);
819+}
820+
821+TEST_F(ShellSurface, types)
822+{
823+ using namespace testing;
824+
825+ msh::Surface surf(
826+ mt::fake_shared(surface_builder),
827+ mf::a_surface(),
828+ null_input_channel);
829+
830+ EXPECT_EQ(mir_surface_type_normal, surf.type());
831+
832+ EXPECT_EQ(mir_surface_type_utility,
833+ surf.configure(mir_surface_attrib_type,
834+ mir_surface_type_utility));
835+ EXPECT_EQ(mir_surface_type_utility, surf.type());
836+
837+ EXPECT_THROW({
838+ surf.configure(mir_surface_attrib_type, 999);
839+ }, std::logic_error);
840+ EXPECT_THROW({
841+ surf.configure(mir_surface_attrib_type, -1);
842+ }, std::logic_error);
843+ EXPECT_EQ(mir_surface_type_utility, surf.type());
844+
845+ EXPECT_EQ(mir_surface_type_dialog,
846+ surf.configure(mir_surface_attrib_type,
847+ mir_surface_type_dialog));
848+ EXPECT_EQ(mir_surface_type_dialog, surf.type());
849+
850+ EXPECT_EQ(mir_surface_type_freestyle,
851+ surf.configure(mir_surface_attrib_type,
852+ mir_surface_type_freestyle));
853+ EXPECT_EQ(mir_surface_type_freestyle, surf.type());
854+}

Subscribers

People subscribed via source and target branches