Merge lp:~mir-team/mir/improve-attribute-protocol-and-normalize-getters into lp:mir
- improve-attribute-protocol-and-normalize-getters
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alexandros Frantzis |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1778 |
Proposed branch: | lp:~mir-team/mir/improve-attribute-protocol-and-normalize-getters |
Merge into: | lp:mir |
Diff against target: |
933 lines (+383/-171) 16 files modified
include/client/mir_toolkit/mir_surface.h (+14/-0) include/server/mir/frontend/surface.h (+1/-0) include/shared/mir_toolkit/common.h (+4/-0) include/test/mir_test_doubles/mock_frontend_surface.h (+1/-0) include/test/mir_test_doubles/stub_scene_surface.h (+1/-0) src/client/mir_surface.cpp (+6/-3) src/client/mir_surface.h (+3/-0) src/client/mir_surface_api.cpp (+49/-10) src/server/frontend/session_mediator.cpp (+9/-0) src/server/scene/basic_surface.cpp (+125/-62) src/server/scene/basic_surface.h (+9/-8) src/shared/protobuf/mir_protobuf.proto (+2/-0) tests/acceptance-tests/test_client_surface_visibility.cpp (+4/-1) tests/unit-tests/client/test_client_mir_surface.cpp (+38/-26) tests/unit-tests/scene/test_basic_surface.cpp (+117/-15) tests/unit-tests/scene/test_surface_impl.cpp (+0/-46) |
To merge this branch: | bzr merge lp:~mir-team/mir/improve-attribute-protocol-and-normalize-getters |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gerry Boland (community) | Approve | ||
Alexandros Frantzis (community) | Approve | ||
Daniel van Vugt | Abstain | ||
Chris Halse Rogers | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+225912@code.launchpad.net |
Commit message
Improve surface attribute protocol and add missing getters.
Description of the change
The motivation for this branch begins with attempting to address bug:
https:/
Seems simple enough at first but on investigation noticed a few irregularities in the surface attributes:
1. Some like focus, have no getter/persistent state.
2. Some like visibility have no getter.
3. Some like DPI have a getter on the client side, and thus support querying via the use of a "-1" value.
4. Some irregular observer behavior (missing observer calls, irregular behavior when values don't change).
5. Implementing client side getters requires use of a -1 value type trick, and leads to potentially blocking getters.
This branch sets out to clear up some of these abnormalities. You can see a series of tests instantiated for each attribute in test_basic_surface. There are a few small observer fixes, etc as mentioned. In order to make DPI behave normally (i.e. throw on invalid value rather than interpret as query), I've had to change surface attributes to be sent at surface creation time. This way the client library never has to query, it always has a value for each attribute.
Focus and visibility getters are added to the client library.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1741
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1741
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1743
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1748
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
Yay! Surface attributes populated on construction! I'm broadly in favour of this :)
Your API docs don't match the behaviour; they say you'll return -1 for invalid surfaces.
While we're at it, I thought that, waaaaay back in London, we were going to abort() when passed an invalid surface? I'm very much against silently pretending that everything's OK. Likewise, I cringe at all the
try { <something> }
catch(...)
{
//la di da! The client doesn't need to know about this...
}
in there (even though much of it is pre-existing).
Alexandros Frantzis (afrantzis) wrote : | # |
370 + if (!set_focus_
371 + BOOST_THROW_
372 + result = value;
373 break;
374 case mir_surface_
375 - allow_dropping = (value == 0);
376 - allow_framedrop
377 + if (!set_swap_
378 + BOOST_THROW_
379 result = value;
380 break;
381 case mir_surface_
382 - if (value >= 0 && !set_dpi(value)) // Negative means query only
383 + if (!set_dpi(value))
384 BOOST_THROW_
configure() is the only user of the set_* functions and it doesn't really need the return value. We might as well throw from the set_* functions instead of checking the return value and throwing in configure.
394 + switch (attrib)
395 + {
396 + case mir_surface_
397 + return type_value;
398 + case mir_surface_
399 + return state_value;
...
It seems like we storing the attributes in an array indexed by the attribute instead of separate variables would make life easier for BasicSurface.
Robert Carr (robertcarr) wrote : | # |
Refactored the set_ functions
Added attribute array (caught several more missing locks in the meantime).
Removed misleading comment.
Lets do something about client library errors...but not in this branch...was our plan in london written down? I'll see what I can remember over lunch...I don't remember each detail.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1751
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
Re: client errors - in one of those enthusiastic London days we decided that API constructors would never return NULL, but instead return an error object. Because this makes it very easy to write programs that fail in unexpected ways, we further decided that passing an error object into any API call that isn't explicitly a check for error status would die, so that developers get immediate and useful corefile-based feedback.
Chris Halse Rogers (raof) wrote : | # |
Bah. I was going to suggest std::array<int, > for the attrib array on the basis that operator[] would do nice bounds checking for us, but it doesn't because of silliness.
Daniel van Vugt (vanvugt) wrote : | # |
(4) Hmm, the protocol change uses "repeated" which actually appears to be backward compatible, so no ABI bump for libmirprotobuf is required after all;
https:/
(5) This single-use function doesn't need to exist. If you initialize your variables in the constructor then it's more obvious locking isn't required either...
ms::BasicSurfac
(6) I think the TODO comment is still valid and should not be deleted:
395 - /*
396 - * TODO: In future, query the shell implementation for the subset of
397 - * attributes/types it implements.
398 - */
Needs^H^
Chris Halse Rogers (raof) wrote : | # |
The protocol change is the sort of thing that we won't be able to get away with when used on the desktop, but because the phone reboots to do any package update it's ok (as long as libmirclient updates in lockstep with libmirserver!)
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
Nit:
260 + std::lock_
As mentioned by Daniel, locking is not currently needed.
Gerry Boland (gerboland) wrote : | # |
+ MirSurfaceType set_type(
+ MirSurfaceState set_state(
+ int set_dpi(int);
+ MirSurfaceVisib
+ int set_swap_
+ MirSurfaceFocus
these look weird to me - why returning the value set? Could a different value be set than what I asked for? I'd be suspicious of it, but it's private so meh.
LGTM otherwise
Daniel van Vugt (vanvugt) wrote : | # |
Gerry:
We return the value applied because it might be different to the requested value, in some restricted shells. That's the TODO I was referring to above in (6).
Preview Diff
1 | === modified file 'include/client/mir_toolkit/mir_surface.h' | |||
2 | --- include/client/mir_toolkit/mir_surface.h 2014-06-19 16:15:42 +0000 | |||
3 | +++ include/client/mir_toolkit/mir_surface.h 2014-07-09 21:43:55 +0000 | |||
4 | @@ -253,6 +253,20 @@ | |||
5 | 253 | * \return The DPI of the surface, or zero if unknown. | 253 | * \return The DPI of the surface, or zero if unknown. |
6 | 254 | */ | 254 | */ |
7 | 255 | int mir_surface_get_dpi(MirSurface* surface); | 255 | int mir_surface_get_dpi(MirSurface* surface); |
8 | 256 | |||
9 | 257 | /** | ||
10 | 258 | * Query the focus state for a surface. | ||
11 | 259 | * \param [in] surface The surface to operate on | ||
12 | 260 | * \return The focus state of said surface | ||
13 | 261 | */ | ||
14 | 262 | MirSurfaceFocusState mir_surface_get_focus(MirSurface *surface); | ||
15 | 263 | |||
16 | 264 | /** | ||
17 | 265 | * Query the visibility state for a surface. | ||
18 | 266 | * \param [in] surface The surface to operate on | ||
19 | 267 | * \return The visibility state of said surface | ||
20 | 268 | */ | ||
21 | 269 | MirSurfaceVisibility mir_surface_get_visibility(MirSurface *surface); | ||
22 | 256 | 270 | ||
23 | 257 | /** | 271 | /** |
24 | 258 | * Choose the cursor state for a surface: whether a cursor is shown, | 272 | * Choose the cursor state for a surface: whether a cursor is shown, |
25 | 259 | 273 | ||
26 | === modified file 'include/server/mir/frontend/surface.h' | |||
27 | --- include/server/mir/frontend/surface.h 2014-06-09 17:35:20 +0000 | |||
28 | +++ include/server/mir/frontend/surface.h 2014-07-09 21:43:55 +0000 | |||
29 | @@ -53,6 +53,7 @@ | |||
30 | 53 | virtual int client_input_fd() const = 0; | 53 | virtual int client_input_fd() const = 0; |
31 | 54 | 54 | ||
32 | 55 | virtual int configure(MirSurfaceAttrib attrib, int value) = 0; | 55 | virtual int configure(MirSurfaceAttrib attrib, int value) = 0; |
33 | 56 | virtual int query(MirSurfaceAttrib attrib) = 0; | ||
34 | 56 | 57 | ||
35 | 57 | virtual void set_cursor_image(std::shared_ptr<graphics::CursorImage> const& image) = 0; | 58 | virtual void set_cursor_image(std::shared_ptr<graphics::CursorImage> const& image) = 0; |
36 | 58 | 59 | ||
37 | 59 | 60 | ||
38 | === modified file 'include/shared/mir_toolkit/common.h' | |||
39 | --- include/shared/mir_toolkit/common.h 2014-06-23 02:57:39 +0000 | |||
40 | +++ include/shared/mir_toolkit/common.h 2014-07-09 21:43:55 +0000 | |||
41 | @@ -33,12 +33,14 @@ | |||
42 | 33 | */ | 33 | */ |
43 | 34 | typedef enum MirSurfaceAttrib | 34 | typedef enum MirSurfaceAttrib |
44 | 35 | { | 35 | { |
45 | 36 | /* Do not specify values...code relies on 0...N ordering. */ | ||
46 | 36 | mir_surface_attrib_type, | 37 | mir_surface_attrib_type, |
47 | 37 | mir_surface_attrib_state, | 38 | mir_surface_attrib_state, |
48 | 38 | mir_surface_attrib_swapinterval, | 39 | mir_surface_attrib_swapinterval, |
49 | 39 | mir_surface_attrib_focus, | 40 | mir_surface_attrib_focus, |
50 | 40 | mir_surface_attrib_dpi, | 41 | mir_surface_attrib_dpi, |
51 | 41 | mir_surface_attrib_visibility, | 42 | mir_surface_attrib_visibility, |
52 | 43 | /* Must be last */ | ||
53 | 42 | mir_surface_attribs | 44 | mir_surface_attribs |
54 | 43 | } MirSurfaceAttrib; | 45 | } MirSurfaceAttrib; |
55 | 44 | 46 | ||
56 | @@ -68,6 +70,8 @@ | |||
57 | 68 | mir_surface_states | 70 | mir_surface_states |
58 | 69 | } MirSurfaceState; | 71 | } MirSurfaceState; |
59 | 70 | 72 | ||
60 | 73 | /* TODO: MirSurfaceFocusState MirSurfaceVisibility and MirLifecycleState use an inconsistent | ||
61 | 74 | naming convention. */ | ||
62 | 71 | typedef enum MirSurfaceFocusState | 75 | typedef enum MirSurfaceFocusState |
63 | 72 | { | 76 | { |
64 | 73 | mir_surface_unfocused = 0, | 77 | mir_surface_unfocused = 0, |
65 | 74 | 78 | ||
66 | === modified file 'include/test/mir_test_doubles/mock_frontend_surface.h' | |||
67 | --- include/test/mir_test_doubles/mock_frontend_surface.h 2014-06-03 17:00:23 +0000 | |||
68 | +++ include/test/mir_test_doubles/mock_frontend_surface.h 2014-07-09 21:43:55 +0000 | |||
69 | @@ -50,6 +50,7 @@ | |||
70 | 50 | MOCK_METHOD1(set_cursor_image, void(std::shared_ptr<graphics::CursorImage> const&)); | 50 | MOCK_METHOD1(set_cursor_image, void(std::shared_ptr<graphics::CursorImage> const&)); |
71 | 51 | 51 | ||
72 | 52 | MOCK_METHOD2(configure, int(MirSurfaceAttrib, int)); | 52 | MOCK_METHOD2(configure, int(MirSurfaceAttrib, int)); |
73 | 53 | MOCK_METHOD1(query, int(MirSurfaceAttrib)); | ||
74 | 53 | }; | 54 | }; |
75 | 54 | } | 55 | } |
76 | 55 | } | 56 | } |
77 | 56 | 57 | ||
78 | === modified file 'include/test/mir_test_doubles/stub_scene_surface.h' | |||
79 | --- include/test/mir_test_doubles/stub_scene_surface.h 2014-06-23 22:25:17 +0000 | |||
80 | +++ include/test/mir_test_doubles/stub_scene_surface.h 2014-07-09 21:43:55 +0000 | |||
81 | @@ -96,6 +96,7 @@ | |||
82 | 96 | bool supports_input() const override { return true;} | 96 | bool supports_input() const override { return true;} |
83 | 97 | int client_input_fd() const override { return fd;} | 97 | int client_input_fd() const override { return fd;} |
84 | 98 | int configure(MirSurfaceAttrib, int) override { return 0; } | 98 | int configure(MirSurfaceAttrib, int) override { return 0; } |
85 | 99 | int query(MirSurfaceAttrib) override { return 0; } | ||
86 | 99 | void with_most_recent_buffer_do(std::function<void(graphics::Buffer&)> const& ) override {} | 100 | void with_most_recent_buffer_do(std::function<void(graphics::Buffer&)> const& ) override {} |
87 | 100 | }; | 101 | }; |
88 | 101 | 102 | ||
89 | 102 | 103 | ||
90 | === modified file 'src/client/mir_surface.cpp' | |||
91 | --- src/client/mir_surface.cpp 2014-06-23 02:57:39 +0000 | |||
92 | +++ src/client/mir_surface.cpp 2014-07-09 21:43:55 +0000 | |||
93 | @@ -67,9 +67,6 @@ | |||
94 | 67 | 67 | ||
95 | 68 | for (int i = 0; i < mir_surface_attribs; i++) | 68 | for (int i = 0; i < mir_surface_attribs; i++) |
96 | 69 | attrib_cache[i] = -1; | 69 | attrib_cache[i] = -1; |
97 | 70 | attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal; | ||
98 | 71 | attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown; | ||
99 | 72 | attrib_cache[mir_surface_attrib_swapinterval] = 1; | ||
100 | 73 | 70 | ||
101 | 74 | std::lock_guard<decltype(handle_mutex)> lock(handle_mutex); | 71 | std::lock_guard<decltype(handle_mutex)> lock(handle_mutex); |
102 | 75 | valid_surfaces.insert(this); | 72 | valid_surfaces.insert(this); |
103 | @@ -228,6 +225,12 @@ | |||
104 | 228 | 225 | ||
105 | 229 | process_incoming_buffer(); | 226 | process_incoming_buffer(); |
106 | 230 | accelerated_window = platform->create_egl_native_window(this); | 227 | accelerated_window = platform->create_egl_native_window(this); |
107 | 228 | |||
108 | 229 | for(int i = 0; i < surface.attributes_size(); i++) | ||
109 | 230 | { | ||
110 | 231 | auto const& attrib = surface.attributes(i); | ||
111 | 232 | attrib_cache[attrib.attrib()] = attrib.ivalue(); | ||
112 | 233 | } | ||
113 | 231 | } | 234 | } |
114 | 232 | 235 | ||
115 | 233 | connection->on_surface_created(id(), this); | 236 | connection->on_surface_created(id(), this); |
116 | 234 | 237 | ||
117 | === modified file 'src/client/mir_surface.h' | |||
118 | --- src/client/mir_surface.h 2014-06-23 02:57:39 +0000 | |||
119 | +++ src/client/mir_surface.h 2014-07-09 21:43:55 +0000 | |||
120 | @@ -86,7 +86,10 @@ | |||
121 | 86 | EGLNativeWindowType generate_native_window(); | 86 | EGLNativeWindowType generate_native_window(); |
122 | 87 | 87 | ||
123 | 88 | MirWaitHandle* configure(MirSurfaceAttrib a, int value); | 88 | MirWaitHandle* configure(MirSurfaceAttrib a, int value); |
124 | 89 | |||
125 | 90 | // Non-blocking | ||
126 | 89 | int attrib(MirSurfaceAttrib a) const; | 91 | int attrib(MirSurfaceAttrib a) const; |
127 | 92 | |||
128 | 90 | MirOrientation get_orientation() const; | 93 | MirOrientation get_orientation() const; |
129 | 91 | 94 | ||
130 | 92 | MirWaitHandle* configure_cursor(MirCursorConfiguration const* cursor); | 95 | MirWaitHandle* configure_cursor(MirCursorConfiguration const* cursor); |
131 | 93 | 96 | ||
132 | === modified file 'src/client/mir_surface_api.cpp' | |||
133 | --- src/client/mir_surface_api.cpp 2014-06-19 16:15:42 +0000 | |||
134 | +++ src/client/mir_surface_api.cpp 2014-07-09 21:43:55 +0000 | |||
135 | @@ -247,34 +247,73 @@ | |||
136 | 247 | 247 | ||
137 | 248 | int mir_surface_get_swapinterval(MirSurface* surf) | 248 | int mir_surface_get_swapinterval(MirSurface* surf) |
138 | 249 | { | 249 | { |
140 | 250 | return surf ? surf->attrib(mir_surface_attrib_swapinterval) : -1; | 250 | int swap_interval = -1; |
141 | 251 | |||
142 | 252 | try | ||
143 | 253 | { | ||
144 | 254 | swap_interval = surf ? surf->attrib(mir_surface_attrib_swapinterval) : -1; | ||
145 | 255 | } | ||
146 | 256 | catch (...) | ||
147 | 257 | { | ||
148 | 258 | } | ||
149 | 259 | |||
150 | 260 | return swap_interval; | ||
151 | 251 | } | 261 | } |
152 | 252 | 262 | ||
153 | 253 | int mir_surface_get_dpi(MirSurface* surf) | 263 | int mir_surface_get_dpi(MirSurface* surf) |
154 | 254 | { | 264 | { |
156 | 255 | int dpi = 0; | 265 | int dpi = -1; |
157 | 256 | 266 | ||
158 | 257 | try | 267 | try |
159 | 258 | { | 268 | { |
160 | 259 | if (surf) | 269 | if (surf) |
161 | 260 | { | 270 | { |
162 | 261 | dpi = surf->attrib(mir_surface_attrib_dpi); | 271 | dpi = surf->attrib(mir_surface_attrib_dpi); |
163 | 262 | if (dpi < 0) | ||
164 | 263 | { | ||
165 | 264 | // Officially we don't support setting DPI from the client. | ||
166 | 265 | // But this is a convenient way to query it on startup... | ||
167 | 266 | surf->configure(mir_surface_attrib_dpi, -1)->wait_for_all(); | ||
168 | 267 | dpi = surf->attrib(mir_surface_attrib_dpi); | ||
169 | 268 | } | ||
170 | 269 | } | 272 | } |
171 | 270 | } | 273 | } |
173 | 271 | catch (std::exception const&) | 274 | catch (...) |
174 | 272 | { | 275 | { |
175 | 273 | } | 276 | } |
176 | 274 | 277 | ||
177 | 275 | return dpi; | 278 | return dpi; |
178 | 276 | } | 279 | } |
179 | 277 | 280 | ||
180 | 281 | MirSurfaceFocusState mir_surface_get_focus(MirSurface* surf) | ||
181 | 282 | { | ||
182 | 283 | MirSurfaceFocusState state = mir_surface_unfocused; | ||
183 | 284 | |||
184 | 285 | try | ||
185 | 286 | { | ||
186 | 287 | if (surf) | ||
187 | 288 | { | ||
188 | 289 | state = static_cast<MirSurfaceFocusState>(surf->attrib(mir_surface_attrib_focus)); | ||
189 | 290 | } | ||
190 | 291 | } | ||
191 | 292 | catch (...) | ||
192 | 293 | { | ||
193 | 294 | } | ||
194 | 295 | |||
195 | 296 | return state; | ||
196 | 297 | } | ||
197 | 298 | |||
198 | 299 | MirSurfaceVisibility mir_surface_get_visibility(MirSurface* surf) | ||
199 | 300 | { | ||
200 | 301 | MirSurfaceVisibility state = static_cast<MirSurfaceVisibility>(mir_surface_visibility_occluded); | ||
201 | 302 | |||
202 | 303 | try | ||
203 | 304 | { | ||
204 | 305 | if (surf) | ||
205 | 306 | { | ||
206 | 307 | state = static_cast<MirSurfaceVisibility>(surf->attrib(mir_surface_attrib_visibility)); | ||
207 | 308 | } | ||
208 | 309 | } | ||
209 | 310 | catch (...) | ||
210 | 311 | { | ||
211 | 312 | } | ||
212 | 313 | |||
213 | 314 | return state; | ||
214 | 315 | } | ||
215 | 316 | |||
216 | 278 | MirWaitHandle* mir_surface_configure_cursor(MirSurface* surface, MirCursorConfiguration const* cursor) | 317 | MirWaitHandle* mir_surface_configure_cursor(MirSurface* surface, MirCursorConfiguration const* cursor) |
217 | 279 | { | 318 | { |
218 | 280 | MirWaitHandle *result = nullptr; | 319 | MirWaitHandle *result = nullptr; |
219 | 281 | 320 | ||
220 | === modified file 'src/server/frontend/session_mediator.cpp' | |||
221 | --- src/server/frontend/session_mediator.cpp 2014-07-09 10:48:47 +0000 | |||
222 | +++ src/server/frontend/session_mediator.cpp 2014-07-09 21:43:55 +0000 | |||
223 | @@ -196,6 +196,15 @@ | |||
224 | 196 | 196 | ||
225 | 197 | if (surface->supports_input()) | 197 | if (surface->supports_input()) |
226 | 198 | response->add_fd(surface->client_input_fd()); | 198 | response->add_fd(surface->client_input_fd()); |
227 | 199 | |||
228 | 200 | for (unsigned int i = 0; i < mir_surface_attribs; i++) | ||
229 | 201 | { | ||
230 | 202 | auto setting = response->add_attributes(); | ||
231 | 203 | |||
232 | 204 | setting->mutable_surfaceid()->set_value(surf_id.as_value()); | ||
233 | 205 | setting->set_attrib(i); | ||
234 | 206 | setting->set_ivalue(surface->query(static_cast<MirSurfaceAttrib>(i))); | ||
235 | 207 | } | ||
236 | 199 | 208 | ||
237 | 200 | advance_buffer(surf_id, *surface, | 209 | advance_buffer(surf_id, *surface, |
238 | 201 | [lock, this, response, done, session] | 210 | [lock, this, response, done, session] |
239 | 202 | 211 | ||
240 | === modified file 'src/server/scene/basic_surface.cpp' | |||
241 | --- src/server/scene/basic_surface.cpp 2014-07-09 07:54:29 +0000 | |||
242 | +++ src/server/scene/basic_surface.cpp 2014-07-09 21:43:55 +0000 | |||
243 | @@ -159,15 +159,24 @@ | |||
244 | 159 | input_sender(input_sender), | 159 | input_sender(input_sender), |
245 | 160 | configurator(configurator), | 160 | configurator(configurator), |
246 | 161 | cursor_image_(cursor_image), | 161 | cursor_image_(cursor_image), |
252 | 162 | report(report), | 162 | report(report) |
248 | 163 | type_value(mir_surface_type_normal), | ||
249 | 164 | state_value(mir_surface_state_restored), | ||
250 | 165 | visibility_value(mir_surface_visibility_exposed), | ||
251 | 166 | dpi_value(0) | ||
253 | 167 | { | 163 | { |
254 | 164 | initialize_attributes(); | ||
255 | 168 | report->surface_created(this, surface_name); | 165 | report->surface_created(this, surface_name); |
256 | 169 | } | 166 | } |
257 | 170 | 167 | ||
258 | 168 | void ms::BasicSurface::initialize_attributes() | ||
259 | 169 | { | ||
260 | 170 | std::lock_guard<std::mutex> lg(guard); | ||
261 | 171 | |||
262 | 172 | attrib_values[mir_surface_attrib_type] = mir_surface_type_normal; | ||
263 | 173 | attrib_values[mir_surface_attrib_state] = mir_surface_state_restored; | ||
264 | 174 | attrib_values[mir_surface_attrib_swapinterval] = 1; | ||
265 | 175 | attrib_values[mir_surface_attrib_focus] = mir_surface_unfocused; | ||
266 | 176 | attrib_values[mir_surface_attrib_dpi] = 0; | ||
267 | 177 | attrib_values[mir_surface_attrib_visibility] = mir_surface_visibility_exposed; | ||
268 | 178 | } | ||
269 | 179 | |||
270 | 171 | void ms::BasicSurface::force_requests_to_complete() | 180 | void ms::BasicSurface::force_requests_to_complete() |
271 | 172 | { | 181 | { |
272 | 173 | surface_buffer_stream->force_requests_to_complete(); | 182 | surface_buffer_stream->force_requests_to_complete(); |
273 | @@ -404,42 +413,94 @@ | |||
274 | 404 | 413 | ||
275 | 405 | 414 | ||
276 | 406 | MirSurfaceType ms::BasicSurface::type() const | 415 | MirSurfaceType ms::BasicSurface::type() const |
279 | 407 | { | 416 | { |
280 | 408 | return type_value; | 417 | std::unique_lock<std::mutex> lg(guard); |
281 | 418 | return static_cast<MirSurfaceType>(attrib_values[mir_surface_attrib_type]); | ||
282 | 409 | } | 419 | } |
283 | 410 | 420 | ||
285 | 411 | bool ms::BasicSurface::set_type(MirSurfaceType t) | 421 | MirSurfaceType ms::BasicSurface::set_type(MirSurfaceType t) |
286 | 412 | { | 422 | { |
296 | 413 | bool valid = false; | 423 | std::unique_lock<std::mutex> lg(guard); |
297 | 414 | 424 | ||
298 | 415 | if (t >= 0 && t < mir_surface_types) | 425 | if (t < 0 || t > mir_surface_types) |
299 | 416 | { | 426 | { |
300 | 417 | type_value = t; | 427 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " |
301 | 418 | valid = true; | 428 | "type.")); |
302 | 419 | } | 429 | } |
303 | 420 | 430 | ||
304 | 421 | return valid; | 431 | if (attrib_values[mir_surface_attrib_type] != t) |
305 | 432 | { | ||
306 | 433 | attrib_values[mir_surface_attrib_type] = t; | ||
307 | 434 | lg.unlock(); | ||
308 | 435 | |||
309 | 436 | observers.attrib_changed(mir_surface_attrib_type, attrib_values[mir_surface_attrib_type]); | ||
310 | 437 | } | ||
311 | 438 | |||
312 | 439 | return t; | ||
313 | 422 | } | 440 | } |
314 | 423 | 441 | ||
315 | 424 | MirSurfaceState ms::BasicSurface::state() const | 442 | MirSurfaceState ms::BasicSurface::state() const |
316 | 425 | { | 443 | { |
318 | 426 | return state_value; | 444 | std::unique_lock<std::mutex> lg(guard); |
319 | 445 | return static_cast<MirSurfaceState>(attrib_values[mir_surface_attrib_state]); | ||
320 | 427 | } | 446 | } |
321 | 428 | 447 | ||
323 | 429 | bool ms::BasicSurface::set_state(MirSurfaceState s) | 448 | MirSurfaceState ms::BasicSurface::set_state(MirSurfaceState s) |
324 | 430 | { | 449 | { |
326 | 431 | bool valid = false; | 450 | if (s < mir_surface_state_unknown || s > mir_surface_states) |
327 | 451 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state.")); | ||
328 | 432 | 452 | ||
331 | 433 | if (s > mir_surface_state_unknown && | 453 | std::unique_lock<std::mutex> lg(guard); |
332 | 434 | s < mir_surface_states) | 454 | if (attrib_values[mir_surface_attrib_state] != s) |
333 | 435 | { | 455 | { |
337 | 436 | state_value = s; | 456 | attrib_values[mir_surface_attrib_state] = s; |
338 | 437 | valid = true; | 457 | lg.unlock(); |
339 | 438 | 458 | ||
340 | 439 | observers.attrib_changed(mir_surface_attrib_state, s); | 459 | observers.attrib_changed(mir_surface_attrib_state, s); |
341 | 440 | } | 460 | } |
342 | 441 | 461 | ||
344 | 442 | return valid; | 462 | return s; |
345 | 463 | } | ||
346 | 464 | |||
347 | 465 | int ms::BasicSurface::set_swap_interval(int interval) | ||
348 | 466 | { | ||
349 | 467 | if (interval < 0) | ||
350 | 468 | { | ||
351 | 469 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid swapinterval")); | ||
352 | 470 | } | ||
353 | 471 | |||
354 | 472 | std::unique_lock<std::mutex> lg(guard); | ||
355 | 473 | if (attrib_values[mir_surface_attrib_swapinterval] != interval) | ||
356 | 474 | { | ||
357 | 475 | attrib_values[mir_surface_attrib_swapinterval] = interval; | ||
358 | 476 | bool allow_dropping = (interval == 0); | ||
359 | 477 | allow_framedropping(allow_dropping); | ||
360 | 478 | |||
361 | 479 | lg.unlock(); | ||
362 | 480 | observers.attrib_changed(mir_surface_attrib_swapinterval, interval); | ||
363 | 481 | } | ||
364 | 482 | |||
365 | 483 | return interval; | ||
366 | 484 | } | ||
367 | 485 | |||
368 | 486 | MirSurfaceFocusState ms::BasicSurface::set_focus_state(MirSurfaceFocusState new_state) | ||
369 | 487 | { | ||
370 | 488 | if (new_state != mir_surface_focused && | ||
371 | 489 | new_state != mir_surface_unfocused) | ||
372 | 490 | { | ||
373 | 491 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid focus state.")); | ||
374 | 492 | } | ||
375 | 493 | |||
376 | 494 | std::unique_lock<std::mutex> lg(guard); | ||
377 | 495 | if (attrib_values[mir_surface_attrib_focus] != new_state) | ||
378 | 496 | { | ||
379 | 497 | attrib_values[mir_surface_attrib_focus] = new_state; | ||
380 | 498 | |||
381 | 499 | lg.unlock(); | ||
382 | 500 | observers.attrib_changed(mir_surface_attrib_focus, new_state); | ||
383 | 501 | } | ||
384 | 502 | |||
385 | 503 | return new_state; | ||
386 | 443 | } | 504 | } |
387 | 444 | 505 | ||
388 | 445 | void ms::BasicSurface::take_input_focus(std::shared_ptr<msh::InputTargeter> const& targeter) | 506 | void ms::BasicSurface::take_input_focus(std::shared_ptr<msh::InputTargeter> const& targeter) |
389 | @@ -449,43 +510,26 @@ | |||
390 | 449 | 510 | ||
391 | 450 | int ms::BasicSurface::configure(MirSurfaceAttrib attrib, int value) | 511 | int ms::BasicSurface::configure(MirSurfaceAttrib attrib, int value) |
392 | 451 | { | 512 | { |
400 | 452 | bool allow_dropping = false; | 513 | int result = configurator->select_attribute_value(*this, attrib, value); |
394 | 453 | |||
395 | 454 | /* | ||
396 | 455 | * TODO: In future, query the shell implementation for the subset of | ||
397 | 456 | * attributes/types it implements. | ||
398 | 457 | */ | ||
399 | 458 | int result = value = configurator->select_attribute_value(*this, attrib, value); | ||
401 | 459 | switch (attrib) | 514 | switch (attrib) |
402 | 460 | { | 515 | { |
403 | 461 | case mir_surface_attrib_type: | 516 | case mir_surface_attrib_type: |
408 | 462 | if (!set_type(static_cast<MirSurfaceType>(value))) | 517 | result = set_type(static_cast<MirSurfaceType>(result)); |
405 | 463 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " | ||
406 | 464 | "type.")); | ||
407 | 465 | result = type(); | ||
409 | 466 | break; | 518 | break; |
410 | 467 | case mir_surface_attrib_state: | 519 | case mir_surface_attrib_state: |
415 | 468 | if (value != mir_surface_state_unknown && | 520 | result = set_state(static_cast<MirSurfaceState>(result)); |
412 | 469 | !set_state(static_cast<MirSurfaceState>(value))) | ||
413 | 470 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state.")); | ||
414 | 471 | result = state(); | ||
416 | 472 | break; | 521 | break; |
417 | 473 | case mir_surface_attrib_focus: | 522 | case mir_surface_attrib_focus: |
419 | 474 | observers.attrib_changed(attrib, value); | 523 | result = set_focus_state(static_cast<MirSurfaceFocusState>(result)); |
420 | 475 | break; | 524 | break; |
421 | 476 | case mir_surface_attrib_swapinterval: | 525 | case mir_surface_attrib_swapinterval: |
425 | 477 | allow_dropping = (value == 0); | 526 | result = set_swap_interval(result); |
423 | 478 | allow_framedropping(allow_dropping); | ||
424 | 479 | result = value; | ||
426 | 480 | break; | 527 | break; |
427 | 481 | case mir_surface_attrib_dpi: | 528 | case mir_surface_attrib_dpi: |
431 | 482 | if (value >= 0 && !set_dpi(value)) // Negative means query only | 529 | result = set_dpi(result); |
429 | 483 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid DPI value")); | ||
430 | 484 | result = dpi(); | ||
432 | 485 | break; | 530 | break; |
433 | 486 | case mir_surface_attrib_visibility: | 531 | case mir_surface_attrib_visibility: |
436 | 487 | set_visibility(static_cast<MirSurfaceVisibility>(value)); | 532 | result = set_visibility(static_cast<MirSurfaceVisibility>(result)); |
435 | 488 | result = visibility_value; | ||
437 | 489 | break; | 533 | break; |
438 | 490 | default: | 534 | default: |
439 | 491 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " | 535 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " |
440 | @@ -498,6 +542,16 @@ | |||
441 | 498 | return result; | 542 | return result; |
442 | 499 | } | 543 | } |
443 | 500 | 544 | ||
444 | 545 | int ms::BasicSurface::query(MirSurfaceAttrib attrib) | ||
445 | 546 | { | ||
446 | 547 | if (attrib < 0 || attrib > mir_surface_attribs) | ||
447 | 548 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " | ||
448 | 549 | "attribute.")); | ||
449 | 550 | |||
450 | 551 | std::unique_lock<std::mutex> lg(guard); | ||
451 | 552 | return attrib_values[attrib]; | ||
452 | 553 | } | ||
453 | 554 | |||
454 | 501 | void ms::BasicSurface::hide() | 555 | void ms::BasicSurface::hide() |
455 | 502 | { | 556 | { |
456 | 503 | set_hidden(true); | 557 | set_hidden(true); |
457 | @@ -528,24 +582,29 @@ | |||
458 | 528 | 582 | ||
459 | 529 | int ms::BasicSurface::dpi() const | 583 | int ms::BasicSurface::dpi() const |
460 | 530 | { | 584 | { |
462 | 531 | return dpi_value; | 585 | std::unique_lock<std::mutex> lock(guard); |
463 | 586 | return attrib_values[mir_surface_attrib_dpi]; | ||
464 | 532 | } | 587 | } |
465 | 533 | 588 | ||
467 | 534 | bool ms::BasicSurface::set_dpi(int new_dpi) | 589 | int ms::BasicSurface::set_dpi(int new_dpi) |
468 | 535 | { | 590 | { |
470 | 536 | bool valid = false; | 591 | if (new_dpi < 0) |
471 | 592 | { | ||
472 | 593 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid DPI value")); | ||
473 | 594 | } | ||
474 | 537 | 595 | ||
476 | 538 | if (new_dpi >= 0) | 596 | std::unique_lock<std::mutex> lg(guard); |
477 | 597 | if (attrib_values[mir_surface_attrib_dpi] != new_dpi) | ||
478 | 539 | { | 598 | { |
482 | 540 | dpi_value = new_dpi; | 599 | attrib_values[mir_surface_attrib_dpi] = new_dpi; |
483 | 541 | valid = true; | 600 | lg.unlock(); |
484 | 542 | observers.attrib_changed(mir_surface_attrib_dpi, dpi_value); | 601 | observers.attrib_changed(mir_surface_attrib_dpi, new_dpi); |
485 | 543 | } | 602 | } |
486 | 544 | 603 | ||
488 | 545 | return valid; | 604 | return new_dpi; |
489 | 546 | } | 605 | } |
490 | 547 | 606 | ||
492 | 548 | void ms::BasicSurface::set_visibility(MirSurfaceVisibility new_visibility) | 607 | MirSurfaceVisibility ms::BasicSurface::set_visibility(MirSurfaceVisibility new_visibility) |
493 | 549 | { | 608 | { |
494 | 550 | if (new_visibility != mir_surface_visibility_occluded && | 609 | if (new_visibility != mir_surface_visibility_occluded && |
495 | 551 | new_visibility != mir_surface_visibility_exposed) | 610 | new_visibility != mir_surface_visibility_exposed) |
496 | @@ -553,11 +612,15 @@ | |||
497 | 553 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid visibility value")); | 612 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid visibility value")); |
498 | 554 | } | 613 | } |
499 | 555 | 614 | ||
501 | 556 | if (visibility_value != new_visibility) | 615 | std::unique_lock<std::mutex> lg(guard); |
502 | 616 | if (attrib_values[mir_surface_attrib_visibility] != new_visibility) | ||
503 | 557 | { | 617 | { |
506 | 558 | visibility_value = new_visibility; | 618 | attrib_values[mir_surface_attrib_visibility] = new_visibility; |
507 | 559 | observers.attrib_changed(mir_surface_attrib_visibility, visibility_value); | 619 | lg.unlock(); |
508 | 620 | observers.attrib_changed(mir_surface_attrib_visibility, attrib_values[mir_surface_attrib_visibility]); | ||
509 | 560 | } | 621 | } |
510 | 622 | |||
511 | 623 | return new_visibility; | ||
512 | 561 | } | 624 | } |
513 | 562 | 625 | ||
514 | 563 | void ms::BasicSurface::add_observer(std::shared_ptr<SurfaceObserver> const& observer) | 626 | void ms::BasicSurface::add_observer(std::shared_ptr<SurfaceObserver> const& observer) |
515 | 564 | 627 | ||
516 | === modified file 'src/server/scene/basic_surface.h' | |||
517 | --- src/server/scene/basic_surface.h 2014-06-27 13:40:34 +0000 | |||
518 | +++ src/server/scene/basic_surface.h 2014-07-09 21:43:55 +0000 | |||
519 | @@ -139,6 +139,7 @@ | |||
520 | 139 | MirSurfaceState state() const override; | 139 | MirSurfaceState state() const override; |
521 | 140 | void take_input_focus(std::shared_ptr<shell::InputTargeter> const& targeter) override; | 140 | void take_input_focus(std::shared_ptr<shell::InputTargeter> const& targeter) override; |
522 | 141 | int configure(MirSurfaceAttrib attrib, int value) override; | 141 | int configure(MirSurfaceAttrib attrib, int value) override; |
523 | 142 | int query(MirSurfaceAttrib attrib) override; | ||
524 | 142 | void hide() override; | 143 | void hide() override; |
525 | 143 | void show() override; | 144 | void show() override; |
526 | 144 | 145 | ||
527 | @@ -152,10 +153,12 @@ | |||
528 | 152 | 153 | ||
529 | 153 | private: | 154 | private: |
530 | 154 | bool visible(std::unique_lock<std::mutex>&) const; | 155 | bool visible(std::unique_lock<std::mutex>&) const; |
535 | 155 | bool set_type(MirSurfaceType t); // Use configure() to make public changes | 156 | MirSurfaceType set_type(MirSurfaceType t); // Use configure() to make public changes |
536 | 156 | bool set_state(MirSurfaceState s); | 157 | MirSurfaceState set_state(MirSurfaceState s); |
537 | 157 | bool set_dpi(int); | 158 | int set_dpi(int); |
538 | 158 | void set_visibility(MirSurfaceVisibility v); | 159 | MirSurfaceVisibility set_visibility(MirSurfaceVisibility v); |
539 | 160 | int set_swap_interval(int); | ||
540 | 161 | MirSurfaceFocusState set_focus_state(MirSurfaceFocusState f); | ||
541 | 159 | 162 | ||
542 | 160 | SurfaceObservers observers; | 163 | SurfaceObservers observers; |
543 | 161 | std::mutex mutable guard; | 164 | std::mutex mutable guard; |
544 | @@ -175,10 +178,8 @@ | |||
545 | 175 | std::shared_ptr<graphics::CursorImage> cursor_image_; | 178 | std::shared_ptr<graphics::CursorImage> cursor_image_; |
546 | 176 | std::shared_ptr<SceneReport> const report; | 179 | std::shared_ptr<SceneReport> const report; |
547 | 177 | 180 | ||
552 | 178 | MirSurfaceType type_value; | 181 | void initialize_attributes(); |
553 | 179 | MirSurfaceState state_value; | 182 | int attrib_values[mir_surface_attribs]; |
550 | 180 | MirSurfaceVisibility visibility_value; | ||
551 | 181 | int dpi_value; | ||
554 | 182 | }; | 183 | }; |
555 | 183 | 184 | ||
556 | 184 | } | 185 | } |
557 | 185 | 186 | ||
558 | === modified file 'src/shared/protobuf/mir_protobuf.proto' | |||
559 | --- src/shared/protobuf/mir_protobuf.proto 2014-07-09 07:54:29 +0000 | |||
560 | +++ src/shared/protobuf/mir_protobuf.proto 2014-07-09 21:43:55 +0000 | |||
561 | @@ -103,6 +103,8 @@ | |||
562 | 103 | 103 | ||
563 | 104 | repeated sint32 fd = 7; | 104 | repeated sint32 fd = 7; |
564 | 105 | optional int32 fds_on_side_channel = 8; | 105 | optional int32 fds_on_side_channel = 8; |
565 | 106 | |||
566 | 107 | repeated SurfaceSetting attributes = 9; | ||
567 | 106 | 108 | ||
568 | 107 | optional string error = 127; | 109 | optional string error = 127; |
569 | 108 | } | 110 | } |
570 | 109 | 111 | ||
571 | === modified file 'tests/acceptance-tests/test_client_surface_visibility.cpp' | |||
572 | --- tests/acceptance-tests/test_client_surface_visibility.cpp 2014-06-23 17:19:22 +0000 | |||
573 | +++ tests/acceptance-tests/test_client_surface_visibility.cpp 2014-07-09 21:43:55 +0000 | |||
574 | @@ -293,7 +293,10 @@ | |||
575 | 293 | mt::WaitCondition event_received; | 293 | mt::WaitCondition event_received; |
576 | 294 | 294 | ||
577 | 295 | EXPECT_CALL(mock_visibility_callback, handle(surface, visibility)) | 295 | EXPECT_CALL(mock_visibility_callback, handle(surface, visibility)) |
579 | 296 | .WillOnce(mt::WakeUp(&event_received)); | 296 | .WillOnce(DoAll(Invoke([&visibility](MirSurface *s, MirSurfaceVisibility) |
580 | 297 | { | ||
581 | 298 | EXPECT_EQ(visibility, mir_surface_get_visibility(s)); | ||
582 | 299 | }), mt::WakeUp(&event_received))); | ||
583 | 297 | 300 | ||
584 | 298 | action(); | 301 | action(); |
585 | 299 | 302 | ||
586 | 300 | 303 | ||
587 | === modified file 'tests/unit-tests/client/test_client_mir_surface.cpp' | |||
588 | --- tests/unit-tests/client/test_client_mir_surface.cpp 2014-06-24 12:55:16 +0000 | |||
589 | +++ tests/unit-tests/client/test_client_mir_surface.cpp 2014-07-09 21:43:55 +0000 | |||
590 | @@ -36,11 +36,12 @@ | |||
591 | 36 | #include "mir_test/gmock_fixes.h" | 36 | #include "mir_test/gmock_fixes.h" |
592 | 37 | #include "mir_test/fake_shared.h" | 37 | #include "mir_test/fake_shared.h" |
593 | 38 | 38 | ||
594 | 39 | #include <cstring> | ||
595 | 40 | |||
596 | 41 | #include <gtest/gtest.h> | 39 | #include <gtest/gtest.h> |
597 | 42 | #include <gmock/gmock.h> | 40 | #include <gmock/gmock.h> |
598 | 43 | 41 | ||
599 | 42 | #include <cstring> | ||
600 | 43 | #include <map> | ||
601 | 44 | |||
602 | 44 | #include <fcntl.h> | 45 | #include <fcntl.h> |
603 | 45 | 46 | ||
604 | 46 | namespace mcl = mir::client; | 47 | namespace mcl = mir::client; |
605 | @@ -96,6 +97,8 @@ | |||
606 | 96 | int pf_sent; | 97 | int pf_sent; |
607 | 97 | int stride_sent; | 98 | int stride_sent; |
608 | 98 | 99 | ||
609 | 100 | static std::map<int, int> sent_surface_attributes; | ||
610 | 101 | |||
611 | 99 | private: | 102 | private: |
612 | 100 | void generate_unique_buffer() | 103 | void generate_unique_buffer() |
613 | 101 | { | 104 | { |
614 | @@ -143,16 +146,26 @@ | |||
615 | 143 | response->set_width(server_package.width); | 146 | response->set_width(server_package.width); |
616 | 144 | response->set_height(server_package.height); | 147 | response->set_height(server_package.height); |
617 | 145 | } | 148 | } |
619 | 146 | 149 | ||
620 | 147 | void create_surface_response(mir::protobuf::Surface* response) | 150 | void create_surface_response(mir::protobuf::Surface* response) |
621 | 148 | { | 151 | { |
622 | 152 | unsigned int const id = 2; | ||
623 | 153 | |||
624 | 149 | response->set_fds_on_side_channel(1); | 154 | response->set_fds_on_side_channel(1); |
625 | 150 | 155 | ||
627 | 151 | response->mutable_id()->set_value(2); | 156 | response->mutable_id()->set_value(id); |
628 | 152 | response->set_width(width_sent); | 157 | response->set_width(width_sent); |
629 | 153 | response->set_height(height_sent); | 158 | response->set_height(height_sent); |
630 | 154 | response->set_pixel_format(pf_sent); | 159 | response->set_pixel_format(pf_sent); |
631 | 155 | response->add_fd(input_fd); | 160 | response->add_fd(input_fd); |
632 | 161 | |||
633 | 162 | for (auto const& kv : sent_surface_attributes) | ||
634 | 163 | { | ||
635 | 164 | auto setting = response->add_attributes(); | ||
636 | 165 | setting->mutable_surfaceid()->set_value(id); | ||
637 | 166 | setting->set_attrib(kv.first); | ||
638 | 167 | setting->set_ivalue(kv.second); | ||
639 | 168 | } | ||
640 | 156 | 169 | ||
641 | 157 | create_buffer_response(response->mutable_buffer()); | 170 | create_buffer_response(response->mutable_buffer()); |
642 | 158 | } | 171 | } |
643 | @@ -167,6 +180,15 @@ | |||
644 | 167 | int global_buffer_id; | 180 | int global_buffer_id; |
645 | 168 | }; | 181 | }; |
646 | 169 | 182 | ||
647 | 183 | std::map<int, int> MockServerPackageGenerator::sent_surface_attributes = { | ||
648 | 184 | { mir_surface_attrib_type, mir_surface_type_normal }, | ||
649 | 185 | { mir_surface_attrib_state, mir_surface_state_restored }, | ||
650 | 186 | { mir_surface_attrib_swapinterval, 1 }, | ||
651 | 187 | { mir_surface_attrib_focus, mir_surface_focused }, | ||
652 | 188 | { mir_surface_attrib_dpi, 19 }, | ||
653 | 189 | { mir_surface_attrib_visibility, mir_surface_visibility_exposed } | ||
654 | 190 | }; | ||
655 | 191 | |||
656 | 170 | struct MockBuffer : public mcl::ClientBuffer | 192 | struct MockBuffer : public mcl::ClientBuffer |
657 | 171 | { | 193 | { |
658 | 172 | MockBuffer() | 194 | MockBuffer() |
659 | @@ -469,6 +491,18 @@ | |||
660 | 469 | create_and_wait_for_surface_with(*client_comm_channel, mock_buffer_factory); | 491 | create_and_wait_for_surface_with(*client_comm_channel, mock_buffer_factory); |
661 | 470 | } | 492 | } |
662 | 471 | 493 | ||
663 | 494 | TEST_F(MirClientSurfaceTest, attributes_set_on_surface_creation) | ||
664 | 495 | { | ||
665 | 496 | using namespace testing; | ||
666 | 497 | |||
667 | 498 | auto surface = create_and_wait_for_surface_with(*client_comm_channel, mock_buffer_factory); | ||
668 | 499 | |||
669 | 500 | for (int i = 0; i < mir_surface_attribs; i++) | ||
670 | 501 | { | ||
671 | 502 | EXPECT_EQ(MockServerPackageGenerator::sent_surface_attributes[i], surface->attrib(static_cast<MirSurfaceAttrib>(i))); | ||
672 | 503 | } | ||
673 | 504 | } | ||
674 | 505 | |||
675 | 472 | TEST_F(MirClientSurfaceTest, create_wait_handle_really_blocks) | 506 | TEST_F(MirClientSurfaceTest, create_wait_handle_really_blocks) |
676 | 473 | { | 507 | { |
677 | 474 | using namespace testing; | 508 | using namespace testing; |
678 | @@ -630,28 +664,6 @@ | |||
679 | 630 | EXPECT_THAT(after.height, Eq(new_height)); | 664 | EXPECT_THAT(after.height, Eq(new_height)); |
680 | 631 | } | 665 | } |
681 | 632 | 666 | ||
682 | 633 | TEST_F(MirClientSurfaceTest, default_surface_type) | ||
683 | 634 | { | ||
684 | 635 | using namespace testing; | ||
685 | 636 | |||
686 | 637 | auto const surface = create_and_wait_for_surface_with(*client_comm_channel, stub_buffer_factory); | ||
687 | 638 | |||
688 | 639 | EXPECT_THAT(surface->attrib(mir_surface_attrib_type), | ||
689 | 640 | Eq(mir_surface_type_normal)); | ||
690 | 641 | } | ||
691 | 642 | |||
692 | 643 | TEST_F(MirClientSurfaceTest, default_surface_state) | ||
693 | 644 | { | ||
694 | 645 | using namespace testing; | ||
695 | 646 | |||
696 | 647 | auto const surface = create_and_wait_for_surface_with(*client_comm_channel, stub_buffer_factory); | ||
697 | 648 | |||
698 | 649 | // Test the default cached state value. It is always unknown until we | ||
699 | 650 | // get a real answer from the server. | ||
700 | 651 | EXPECT_THAT(surface->attrib(mir_surface_attrib_state), | ||
701 | 652 | Eq(mir_surface_state_unknown)); | ||
702 | 653 | } | ||
703 | 654 | |||
704 | 655 | TEST_F(MirClientSurfaceTest, get_cpu_region_returns_correct_data) | 667 | TEST_F(MirClientSurfaceTest, get_cpu_region_returns_correct_data) |
705 | 656 | { | 668 | { |
706 | 657 | using namespace testing; | 669 | using namespace testing; |
707 | 658 | 670 | ||
708 | === modified file 'tests/unit-tests/scene/test_basic_surface.cpp' | |||
709 | --- tests/unit-tests/scene/test_basic_surface.cpp 2014-07-09 07:54:29 +0000 | |||
710 | +++ tests/unit-tests/scene/test_basic_surface.cpp 2014-07-09 21:43:55 +0000 | |||
711 | @@ -468,48 +468,150 @@ | |||
712 | 468 | EXPECT_EQ(mi::InputReceptionMode::receives_all_input, surface.reception_mode()); | 468 | EXPECT_EQ(mi::InputReceptionMode::receives_all_input, surface.reception_mode()); |
713 | 469 | } | 469 | } |
714 | 470 | 470 | ||
716 | 471 | TEST_F(BasicSurfaceTest, notifies_about_visibility_attrib_changes) | 471 | namespace |
717 | 472 | { | ||
718 | 473 | |||
719 | 474 | struct AttributeTestParameters | ||
720 | 475 | { | ||
721 | 476 | MirSurfaceAttrib attribute; | ||
722 | 477 | int default_value; | ||
723 | 478 | int a_valid_value; | ||
724 | 479 | int an_invalid_value; | ||
725 | 480 | }; | ||
726 | 481 | |||
727 | 482 | struct BasicSurfaceAttributeTest : public BasicSurfaceTest, | ||
728 | 483 | public ::testing::WithParamInterface<AttributeTestParameters> | ||
729 | 484 | { | ||
730 | 485 | }; | ||
731 | 486 | |||
732 | 487 | AttributeTestParameters const surface_visibility_test_parameters{ | ||
733 | 488 | mir_surface_attrib_visibility, | ||
734 | 489 | mir_surface_visibility_exposed, | ||
735 | 490 | mir_surface_visibility_occluded, | ||
736 | 491 | -1 | ||
737 | 492 | }; | ||
738 | 493 | |||
739 | 494 | AttributeTestParameters const surface_type_test_parameters{ | ||
740 | 495 | mir_surface_attrib_type, | ||
741 | 496 | mir_surface_type_normal, | ||
742 | 497 | mir_surface_type_freestyle, | ||
743 | 498 | -1 | ||
744 | 499 | }; | ||
745 | 500 | |||
746 | 501 | AttributeTestParameters const surface_state_test_parameters{ | ||
747 | 502 | mir_surface_attrib_state, | ||
748 | 503 | mir_surface_state_restored, | ||
749 | 504 | mir_surface_state_fullscreen, | ||
750 | 505 | 1178312 | ||
751 | 506 | }; | ||
752 | 507 | |||
753 | 508 | AttributeTestParameters const surface_swapinterval_test_parameters{ | ||
754 | 509 | mir_surface_attrib_swapinterval, | ||
755 | 510 | 1, | ||
756 | 511 | 0, | ||
757 | 512 | -1 | ||
758 | 513 | }; | ||
759 | 514 | |||
760 | 515 | AttributeTestParameters const surface_dpi_test_parameters{ | ||
761 | 516 | mir_surface_attrib_dpi, | ||
762 | 517 | 0, | ||
763 | 518 | 90, | ||
764 | 519 | -1 | ||
765 | 520 | }; | ||
766 | 521 | |||
767 | 522 | AttributeTestParameters const surface_focus_test_parameters{ | ||
768 | 523 | mir_surface_attrib_focus, | ||
769 | 524 | mir_surface_unfocused, | ||
770 | 525 | mir_surface_focused, | ||
771 | 526 | -1 | ||
772 | 527 | }; | ||
773 | 528 | |||
774 | 529 | } | ||
775 | 530 | |||
776 | 531 | TEST_P(BasicSurfaceAttributeTest, default_value) | ||
777 | 532 | { | ||
778 | 533 | auto const& params = GetParam(); | ||
779 | 534 | auto const& attribute = params.attribute; | ||
780 | 535 | auto const& default_value = params.default_value; | ||
781 | 536 | |||
782 | 537 | EXPECT_EQ(default_value, surface.query(attribute)); | ||
783 | 538 | } | ||
784 | 539 | |||
785 | 540 | TEST_P(BasicSurfaceAttributeTest, notifies_about_attrib_changes) | ||
786 | 472 | { | 541 | { |
787 | 473 | using namespace testing; | 542 | using namespace testing; |
788 | 543 | |||
789 | 544 | auto const& params = GetParam(); | ||
790 | 545 | auto const& attribute = params.attribute; | ||
791 | 546 | auto const& value1 = params.a_valid_value; | ||
792 | 547 | auto const& value2 = params.default_value; | ||
793 | 548 | |||
794 | 474 | MockSurfaceAttribObserver mock_surface_observer; | 549 | MockSurfaceAttribObserver mock_surface_observer; |
795 | 475 | 550 | ||
796 | 476 | InSequence s; | 551 | InSequence s; |
798 | 477 | EXPECT_CALL(mock_surface_observer, attrib_changed(mir_surface_attrib_visibility, mir_surface_visibility_occluded)) | 552 | EXPECT_CALL(mock_surface_observer, attrib_changed(attribute, value1)) |
799 | 478 | .Times(1); | 553 | .Times(1); |
801 | 479 | EXPECT_CALL(mock_surface_observer, attrib_changed(mir_surface_attrib_visibility, mir_surface_visibility_exposed)) | 554 | EXPECT_CALL(mock_surface_observer, attrib_changed(attribute, value2)) |
802 | 480 | .Times(1); | 555 | .Times(1); |
803 | 481 | 556 | ||
804 | 482 | surface.add_observer(mt::fake_shared(mock_surface_observer)); | 557 | surface.add_observer(mt::fake_shared(mock_surface_observer)); |
805 | 483 | 558 | ||
808 | 484 | surface.configure(mir_surface_attrib_visibility, mir_surface_visibility_occluded); | 559 | surface.configure(attribute, value1); |
809 | 485 | surface.configure(mir_surface_attrib_visibility, mir_surface_visibility_exposed); | 560 | surface.configure(attribute, value2); |
810 | 486 | } | 561 | } |
811 | 487 | 562 | ||
813 | 488 | TEST_F(BasicSurfaceTest, does_not_notify_if_visibility_attrib_is_unchanged) | 563 | TEST_P(BasicSurfaceAttributeTest, does_not_notify_if_attrib_is_unchanged) |
814 | 489 | { | 564 | { |
815 | 490 | using namespace testing; | 565 | using namespace testing; |
816 | 566 | |||
817 | 567 | auto const& params = GetParam(); | ||
818 | 568 | auto const& attribute = params.attribute; | ||
819 | 569 | auto const& default_value = params.default_value; | ||
820 | 570 | auto const& another_value = params.a_valid_value; | ||
821 | 571 | |||
822 | 491 | MockSurfaceAttribObserver mock_surface_observer; | 572 | MockSurfaceAttribObserver mock_surface_observer; |
823 | 492 | 573 | ||
825 | 493 | EXPECT_CALL(mock_surface_observer, attrib_changed(mir_surface_attrib_visibility, mir_surface_visibility_occluded)) | 574 | EXPECT_CALL(mock_surface_observer, attrib_changed(attribute, another_value)) |
826 | 494 | .Times(1); | 575 | .Times(1); |
827 | 495 | 576 | ||
828 | 496 | surface.add_observer(mt::fake_shared(mock_surface_observer)); | 577 | surface.add_observer(mt::fake_shared(mock_surface_observer)); |
829 | 497 | 578 | ||
833 | 498 | surface.configure(mir_surface_attrib_visibility, mir_surface_visibility_exposed); | 579 | surface.configure(attribute, default_value); |
834 | 499 | surface.configure(mir_surface_attrib_visibility, mir_surface_visibility_occluded); | 580 | surface.configure(attribute, another_value); |
835 | 500 | surface.configure(mir_surface_attrib_visibility, mir_surface_visibility_occluded); | 581 | surface.configure(attribute, another_value); |
836 | 501 | } | 582 | } |
837 | 502 | 583 | ||
839 | 503 | TEST_F(BasicSurfaceTest, throws_on_invalid_visibility_attrib_value) | 584 | TEST_P(BasicSurfaceAttributeTest, throws_on_invalid_value) |
840 | 504 | { | 585 | { |
841 | 505 | using namespace testing; | 586 | using namespace testing; |
843 | 506 | 587 | ||
844 | 588 | auto const& params = GetParam(); | ||
845 | 589 | auto const& attribute = params.attribute; | ||
846 | 590 | auto const& invalid_value = params.an_invalid_value; | ||
847 | 591 | |||
848 | 507 | EXPECT_THROW({ | 592 | EXPECT_THROW({ |
852 | 508 | surface.configure(mir_surface_attrib_visibility, | 593 | surface.configure(attribute, invalid_value); |
853 | 509 | static_cast<int>(mir_surface_visibility_exposed) + 1); | 594 | }, std::logic_error); |
851 | 510 | }, std::logic_error); | ||
854 | 511 | } | 595 | } |
855 | 512 | 596 | ||
856 | 597 | INSTANTIATE_TEST_CASE_P(SurfaceTypeAttributeTest, BasicSurfaceAttributeTest, | ||
857 | 598 | ::testing::Values(surface_type_test_parameters)); | ||
858 | 599 | |||
859 | 600 | INSTANTIATE_TEST_CASE_P(SurfaceVisibilityAttributeTest, BasicSurfaceAttributeTest, | ||
860 | 601 | ::testing::Values(surface_visibility_test_parameters)); | ||
861 | 602 | |||
862 | 603 | INSTANTIATE_TEST_CASE_P(SurfaceStateAttributeTest, BasicSurfaceAttributeTest, | ||
863 | 604 | ::testing::Values(surface_state_test_parameters)); | ||
864 | 605 | |||
865 | 606 | INSTANTIATE_TEST_CASE_P(SurfaceSwapintervalAttributeTest, BasicSurfaceAttributeTest, | ||
866 | 607 | ::testing::Values(surface_swapinterval_test_parameters)); | ||
867 | 608 | |||
868 | 609 | INSTANTIATE_TEST_CASE_P(SurfaceDPIAttributeTest, BasicSurfaceAttributeTest, | ||
869 | 610 | ::testing::Values(surface_dpi_test_parameters)); | ||
870 | 611 | |||
871 | 612 | INSTANTIATE_TEST_CASE_P(SurfaceFocusAttributeTest, BasicSurfaceAttributeTest, | ||
872 | 613 | ::testing::Values(surface_focus_test_parameters)); | ||
873 | 614 | |||
874 | 513 | TEST_F(BasicSurfaceTest, configure_returns_value_set_by_configurator) | 615 | TEST_F(BasicSurfaceTest, configure_returns_value_set_by_configurator) |
875 | 514 | { | 616 | { |
876 | 515 | using namespace testing; | 617 | using namespace testing; |
877 | 516 | 618 | ||
878 | === modified file 'tests/unit-tests/scene/test_surface_impl.cpp' | |||
879 | --- tests/unit-tests/scene/test_surface_impl.cpp 2014-06-23 22:25:17 +0000 | |||
880 | +++ tests/unit-tests/scene/test_surface_impl.cpp 2014-07-09 21:43:55 +0000 | |||
881 | @@ -186,52 +186,6 @@ | |||
882 | 186 | EXPECT_EQ(mir_surface_state_fullscreen, surf.state()); | 186 | EXPECT_EQ(mir_surface_state_fullscreen, surf.state()); |
883 | 187 | } | 187 | } |
884 | 188 | 188 | ||
885 | 189 | TEST_F(Surface, dpi_is_initialized) | ||
886 | 190 | { | ||
887 | 191 | using namespace testing; | ||
888 | 192 | |||
889 | 193 | ms::BasicSurface surf( | ||
890 | 194 | std::string("stub"), | ||
891 | 195 | geom::Rectangle{{},{}}, | ||
892 | 196 | false, | ||
893 | 197 | buffer_stream, | ||
894 | 198 | std::shared_ptr<mi::InputChannel>(), | ||
895 | 199 | stub_input_sender, | ||
896 | 200 | null_configurator, | ||
897 | 201 | std::shared_ptr<mg::CursorImage>(), | ||
898 | 202 | report); | ||
899 | 203 | |||
900 | 204 | EXPECT_EQ(0, surf.dpi()); // The current default. It will change. | ||
901 | 205 | } | ||
902 | 206 | |||
903 | 207 | TEST_F(Surface, dpi_changes) | ||
904 | 208 | { | ||
905 | 209 | using namespace testing; | ||
906 | 210 | |||
907 | 211 | ms::BasicSurface surf( | ||
908 | 212 | std::string("stub"), | ||
909 | 213 | geom::Rectangle{{},{}}, | ||
910 | 214 | false, | ||
911 | 215 | buffer_stream, | ||
912 | 216 | std::shared_ptr<mi::InputChannel>(), | ||
913 | 217 | stub_input_sender, | ||
914 | 218 | null_configurator, | ||
915 | 219 | std::shared_ptr<mg::CursorImage>(), | ||
916 | 220 | report); | ||
917 | 221 | |||
918 | 222 | EXPECT_EQ(123, surf.configure(mir_surface_attrib_dpi, 123)); | ||
919 | 223 | EXPECT_EQ(123, surf.dpi()); | ||
920 | 224 | |||
921 | 225 | EXPECT_EQ(456, surf.configure(mir_surface_attrib_dpi, 456)); | ||
922 | 226 | EXPECT_EQ(456, surf.dpi()); | ||
923 | 227 | |||
924 | 228 | surf.configure(mir_surface_attrib_dpi, -1); | ||
925 | 229 | EXPECT_EQ(456, surf.dpi()); | ||
926 | 230 | |||
927 | 231 | EXPECT_EQ(789, surf.configure(mir_surface_attrib_dpi, 789)); | ||
928 | 232 | EXPECT_EQ(789, surf.dpi()); | ||
929 | 233 | } | ||
930 | 234 | |||
931 | 235 | bool operator==(MirEvent const& a, MirEvent const& b) | 189 | bool operator==(MirEvent const& a, MirEvent const& b) |
932 | 236 | { | 190 | { |
933 | 237 | // We will always fill unused bytes with zero, so memcmp is accurate... | 191 | // We will always fill unused bytes with zero, so memcmp is accurate... |
Just some quick comments:
(1) This should be 0..N:
+ /* Do not specify values...code relies on 1...N ordering. */
(2) The suffix "_state" is unnecessary and potentially confusing with the attribute called "state": sState mir_surface_ get_focus_ state(MirSurfac e *surface); bility mir_surface_ get_visibility_ state(MirSurfac e *surface);
15 +MirSurfaceFocu
23 +MirSurfaceVisi
(3) Returning an integer value outside the range of an enum is a violation of the implicit contract that a well designed API will only return values of those enums: unfocused and mir_surface_ visibility_ occluded.
13 + * -1 if the surface is invalid.
21 + * -1 if the surface is invalid.
I think a more sensible fallback for invalid surfaces would be to return mir_surface_
(4) src/shared/ protobuf/ mir_protobuf. proto: Protocol ABI change!
Please either avoid protocol changes, or record the change explicitly with a bump of libmirprotobuf0 to libmirprotobuf1. Not ideal.