Merge lp:~kdub/mir/demo-stream-titlebars into lp:mir
- demo-stream-titlebars
- Merge into development-branch
Status: | Work in progress |
---|---|
Proposed branch: | lp:~kdub/mir/demo-stream-titlebars |
Merge into: | lp:mir |
Prerequisite: | lp:~kdub/mir/fix-1563278 |
Diff against target: |
821 lines (+219/-167) 16 files modified
examples/server_example_basic_window_manager.cpp (+1/-1) examples/server_example_basic_window_manager.h (+1/-3) examples/server_example_canonical_window_manager.cpp (+157/-105) examples/server_example_canonical_window_manager.h (+1/-4) examples/server_example_tiling_window_manager.cpp (+1/-3) examples/server_example_tiling_window_manager.h (+1/-3) examples/server_example_window_management.cpp (+1/-4) examples/server_example_window_management_info.cpp (+16/-10) examples/server_example_window_management_info.h (+9/-6) include/server/mir/scene/surface_creation_parameters.h (+2/-1) include/server/mir/shell/surface_specification.h (+1/-0) src/server/frontend/session_mediator.cpp (+7/-7) src/server/scene/application_session.cpp (+4/-18) src/server/scene/surface_creation_parameters.cpp (+9/-2) src/server/shell/surface_specification.cpp (+7/-0) src/server/symbols.map (+1/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/demo-stream-titlebars |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Halse Rogers | Approve | ||
Daniel van Vugt | Abstain | ||
Cemil Azizoglu (community) | Approve | ||
Alan Griffiths | Needs Fixing | ||
Mir CI Bot | continuous-integration | Approve | |
Review via email: mp+291740@code.launchpad.net |
Commit message
demos: transition CanonicalWindow
Our "Surfaces" are really more like windows (content, input, and WM), and Streams are the content. Its better to have titlebars that are merely content than to have two "Surfaces/windows" and force the WM policy to tie the two windows together to make it look like one of the windows is a titlebar to the other.
I did intentionally change behavior in the case of vertmaximized to correct behavior of the shell according to my reading of the spec.
Fixes: LP: #1569836
Description of the change
demos: transition CanonicalWindow
Our "Surfaces" are really more like windows (content, input, and WM), and Streams are the content. Its better to have titlebars that are merely content than to have two "Surfaces/windows" and force the WM policy to tie the two windows together to make it look like one of the windows is a titlebar to the other.
I did intentionally change behavior in the case of vertmaximized to correct behavior of the shell according to my reading of the spec (LP: #1569836)
Mir CI Bot (mir-ci-bot) wrote : | # |
Alan Griffiths (alan-griffiths) wrote : | # |
This doesn't seem to get all the focus based repainting right:
$ bin/mir_demo_server
$ bin/mirrun gnome-terminal
...
in the terminal:
$ mir_demo_
Expected: multiwin has bright (focussed) titlebars, terminal has dim (unfocussed) titlebars
Actual .: Both the terminal and multiwin have "focus" titlebars.
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
I don't see where this is being used.
640 + SurfaceCreation
why is it needed? Is there a followup branch?
Kevin DuBois (kdub) wrote : | # |
> I don't see where this is being used.
> 640 + SurfaceCreation
> with_buffer_
>
> why is it needed? Is there a followup branch?
It is providing a similar way to set the stream fields, eg:
ms::a_surface()
.with_size(...)
.with_
.with_
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
> > I don't see where this is being used.
> > 640 + SurfaceCreation
> > with_buffer_
> >
> > why is it needed? Is there a followup branch?
>
> It is providing a similar way to set the stream fields, eg:
> ms::a_surface()
> .with_size(...)
> .with_bufer_
> .with_buffer_
Ok I guess it sounds useful.
Daniel van Vugt (vanvugt) wrote : | # |
I've made a few attempts on this topic over the years. Although I feel treating the titlebar as the only type of decoration is quite wrong, simultaneously ignoring the past and not looking to the future.
Please read:
https:/
Also consider how you would support a theme with:
* Window borders around the sides
* No titlebar
* Titlebar on the side
* Titlebar non-rectangular, or not the same length as the window
* Titlebar on the bottom
* A titlebar that is hidden and only pops up sometimes, maybe with floating buttons.
There is prior art for all of these. The only commonality really is that the client area is usually (but not always) rectangular. And decorations may be arbitrary.
I hesitate to disapprove, because the problem is also pre-existing. But we should be thinking about more generic solutions than this.
Chris Halse Rogers (raof) wrote : | # |
Looks reasonable to me, modulo Alan's needs-fixing.
This isn't code for actual Mir shell clients to use, and we don't need to implement fancy decorations in our demo server.
Kevin DuBois (kdub) wrote : | # |
hit some difficulty with "mirrun", so branch has been lingering. Trying to fix once again.
re the various examples, the location and appearance of the titlebar are controlled by the shell, so different shell logic could control these different locations.
Kevin DuBois (kdub) wrote : | # |
> Looks reasonable to me, modulo Alan's needs-fixing.
>
> This isn't code for actual Mir shell clients to use, and we don't need to
> implement fancy decorations in our demo server.
Right, this is just to stop giving an example of binding up a MirSurface to use as a titlebar, and to eliminate a use of the 'primary_
Kevin DuBois (kdub) wrote : | # |
bit of bitrot while I did 0.23 testing and sync fence investigation, fixing up
Unmerged revisions
- 3452. By Kevin DuBois
-
make sure to expose == operator for StreamSpecification
- 3451. By Kevin DuBois
-
port over changes that transition the CanonicalWM to using streams instead of surfaces for titlebars
Preview Diff
1 | === modified file 'examples/server_example_basic_window_manager.cpp' |
2 | --- examples/server_example_basic_window_manager.cpp 2015-11-27 13:58:54 +0000 |
3 | +++ examples/server_example_basic_window_manager.cpp 2016-04-13 11:13:46 +0000 |
4 | @@ -58,7 +58,7 @@ |
5 | auto const surface = session->surface(result); |
6 | surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params}); |
7 | policy->handle_new_surface(session, surface); |
8 | - policy->generate_decorations_for(session, surface, surface_info, build); |
9 | + policy->generate_decorations_for(session, surface); |
10 | return result; |
11 | } |
12 | |
13 | |
14 | === modified file 'examples/server_example_basic_window_manager.h' |
15 | --- examples/server_example_basic_window_manager.h 2016-01-29 08:18:22 +0000 |
16 | +++ examples/server_example_basic_window_manager.h 2016-04-13 11:13:46 +0000 |
17 | @@ -104,9 +104,7 @@ |
18 | virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value) = 0; |
19 | |
20 | virtual void generate_decorations_for( |
21 | - std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface, |
22 | - SurfaceInfoMap& surface_info, |
23 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build) = 0; |
24 | + std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) = 0; |
25 | |
26 | virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0; |
27 | |
28 | |
29 | === modified file 'examples/server_example_canonical_window_manager.cpp' |
30 | --- examples/server_example_canonical_window_manager.cpp 2016-04-12 14:10:00 +0000 |
31 | +++ examples/server_example_canonical_window_manager.cpp 2016-04-13 11:13:46 +0000 |
32 | @@ -30,6 +30,7 @@ |
33 | |
34 | namespace me = mir::examples; |
35 | namespace ms = mir::scene; |
36 | +namespace mg = mir::graphics; |
37 | using namespace mir::geometry; |
38 | |
39 | ///\example server_example_canonical_window_manager.cpp |
40 | @@ -38,18 +39,95 @@ |
41 | namespace |
42 | { |
43 | int const title_bar_height = 10; |
44 | +Displacement const titlebar_displacement { 0, -10 }; |
45 | + |
46 | Size titlebar_size_for_window(Size window_size) |
47 | { |
48 | return {window_size.width, Height{title_bar_height}}; |
49 | } |
50 | |
51 | -Point titlebar_position_for_window(Point window_position) |
52 | -{ |
53 | - return { |
54 | - window_position.x, |
55 | - window_position.y - DeltaY(title_bar_height) |
56 | - }; |
57 | -} |
58 | +void constrain_input_to(std::vector<Rectangle>& rectangles, Rectangle constraint) |
59 | +{ |
60 | + auto surface_displacement = constraint.top_left - Point{0, 0}; |
61 | + for(auto& rect : rectangles) |
62 | + { |
63 | + rect.top_left = rect.top_left + surface_displacement; |
64 | + rect = rect.intersection_with(constraint); |
65 | + rect.top_left = rect.top_left - surface_displacement; |
66 | + } |
67 | +} |
68 | + |
69 | +std::vector<Rectangle> input_content_area(me::SurfaceInfo& info, Rectangle surface_rect) |
70 | +{ |
71 | + std::vector<Rectangle> rectangles; |
72 | + if (info.input_shape.is_set() && !info.input_shape.value().empty()) |
73 | + return info.input_shape.value(); |
74 | + else |
75 | + return { { Point{0,0}, surface_rect.size } }; |
76 | +} |
77 | + |
78 | +void apply_input_content_area( |
79 | + me::SurfaceInfo& info, ms::Surface& surface, Rectangle surface_rect) |
80 | +{ |
81 | + surface.set_input_region(input_content_area(info, surface_rect)); |
82 | +} |
83 | + |
84 | +void apply_input_titlebar_and_content_area( |
85 | + me::SurfaceInfo& info, ms::Surface& surface, |
86 | + Rectangle surface_rect) |
87 | +{ |
88 | + auto rectangles = input_content_area(info, surface_rect); |
89 | + info.titlebar_input_shape = |
90 | + { Point{0,0} + titlebar_displacement, titlebar_size_for_window(surface_rect.size) }; |
91 | + rectangles.emplace_back(info.titlebar_input_shape.value()); |
92 | + surface.set_input_region(rectangles); |
93 | +} |
94 | + |
95 | +void content_and_titlebar(me::SurfaceInfo& info, ms::Surface& surface, Size new_size) |
96 | +{ |
97 | + auto streams = info.streams.value(); |
98 | + auto titlebar = std::find_if(streams.begin(), streams.end(), |
99 | + [&](mir::shell::StreamSpecification const& entry) |
100 | + { |
101 | + return entry.stream_id == info.titlebar_id; |
102 | + }); |
103 | + |
104 | + if (titlebar == streams.end()) |
105 | + { |
106 | + streams.push_back( |
107 | + { info.titlebar_id, titlebar_displacement, {titlebar_size_for_window(new_size)}}); |
108 | + } |
109 | + else |
110 | + { |
111 | + titlebar->size = titlebar_size_for_window(new_size); |
112 | + } |
113 | + |
114 | + if (auto session = info.session.lock()) |
115 | + session->configure_streams(surface, streams); |
116 | + |
117 | + info.streams = streams; |
118 | + info.visible_titlebar = true; |
119 | +} |
120 | + |
121 | +void content_only(me::SurfaceInfo& info, ms::Surface& surface) |
122 | +{ |
123 | + auto streams = info.streams.value(); |
124 | + for(auto it = streams.begin(); it != streams.end();) |
125 | + { |
126 | + if (it->stream_id == info.titlebar_id) |
127 | + it = streams.erase(it); |
128 | + else |
129 | + it++; |
130 | + } |
131 | + |
132 | + if (auto session = info.session.lock()) |
133 | + session->configure_streams(surface, streams); |
134 | + |
135 | + info.streams = streams; |
136 | + info.visible_titlebar = false; |
137 | +} |
138 | + |
139 | + |
140 | } |
141 | |
142 | me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy( |
143 | @@ -83,7 +161,7 @@ |
144 | |
145 | display_layout->place_in_output(info.output_id.value(), rect); |
146 | surface->move_to(rect.top_left); |
147 | - surface->resize(rect.size); |
148 | + apply_resize(surface, rect.top_left, rect.size); |
149 | } |
150 | } |
151 | } |
152 | @@ -103,9 +181,6 @@ |
153 | auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_surface_type_normal; |
154 | bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type); |
155 | |
156 | - if (needs_titlebar) |
157 | - parameters.size.height = parameters.size.height + DeltaY{title_bar_height}; |
158 | - |
159 | if (!parameters.state.is_set()) |
160 | parameters.state = mir_surface_state_restored; |
161 | |
162 | @@ -238,45 +313,34 @@ |
163 | parameters.size.height = parameters.size.height - DeltaY{title_bar_height}; |
164 | } |
165 | |
166 | + if (parameters.input_shape.is_set()) |
167 | + { |
168 | + auto rect = parameters.input_shape.value(); |
169 | + constrain_input_to(rect, {parameters.top_left, parameters.size}); |
170 | + parameters.input_shape = rect; |
171 | + } |
172 | + |
173 | return parameters; |
174 | } |
175 | |
176 | void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for( |
177 | std::shared_ptr<scene::Session> const& session, |
178 | - std::shared_ptr<scene::Surface> const& surface, |
179 | - SurfaceInfoMap& surface_map, |
180 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) |
181 | + std::shared_ptr<scene::Surface> const& surface) |
182 | { |
183 | if (!SurfaceInfo::needs_titlebar(surface->type())) |
184 | return; |
185 | |
186 | auto format = mir_pixel_format_xrgb_8888; |
187 | - mir::graphics::BufferProperties properties(titlebar_size_for_window(surface->size()), |
188 | - format, mir::graphics::BufferUsage::software); |
189 | - auto stream_id = session->create_buffer_stream(properties); |
190 | - auto params = ms::a_surface() |
191 | - .of_size(titlebar_size_for_window(surface->size())) |
192 | - .of_name("decoration") |
193 | - .of_pixel_format(format) |
194 | - .of_buffer_usage(mir::graphics::BufferUsage::software) |
195 | - .of_position(titlebar_position_for_window(surface->top_left())) |
196 | - .of_type(mir_surface_type_gloss) |
197 | - .with_buffer_stream(stream_id); |
198 | - auto id = build(session, params); |
199 | - auto titlebar = session->surface(id); |
200 | - titlebar->set_alpha(0.9); |
201 | - |
202 | + auto size = titlebar_size_for_window(surface->size()); |
203 | + auto usage = mir::graphics::BufferUsage::software; |
204 | auto& surface_info = tools->info_for(surface); |
205 | - surface_info.titlebar = titlebar; |
206 | - surface_info.titlebar_id = id; |
207 | - surface_info.titlebar_stream_id = stream_id; |
208 | - surface_info.children.push_back(titlebar); |
209 | + surface_info.has_titlebar = true; |
210 | + surface_info.titlebar_id = session->create_buffer_stream(mg::BufferProperties{size, format, usage}); |
211 | + surface_info.init_titlebar(size); |
212 | + surface_info.paint_titlebar(0xFF); |
213 | |
214 | - SurfaceInfo& titlebar_info = |
215 | - surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second; |
216 | - titlebar_info.is_titlebar = true; |
217 | - titlebar_info.parent = surface; |
218 | - titlebar_info.init_titlebar(titlebar); |
219 | + content_and_titlebar(surface_info, *surface, size); |
220 | + apply_input_titlebar_and_content_area(surface_info, *surface, {surface->top_left(), surface->size()}); |
221 | } |
222 | |
223 | void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface) |
224 | @@ -289,18 +353,6 @@ |
225 | |
226 | tools->info_for(session).surfaces.push_back(surface); |
227 | |
228 | - if (surface_info.can_be_active()) |
229 | - { |
230 | - surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>( |
231 | - [this](std::shared_ptr<scene::Session> const& /*session*/, |
232 | - std::shared_ptr<scene::Surface> const& surface) |
233 | - { |
234 | - select_active_surface(surface); |
235 | - }, |
236 | - session, |
237 | - surface)); |
238 | - } |
239 | - |
240 | if (surface_info.state == mir_surface_state_fullscreen) |
241 | fullscreen_surfaces.insert(surface); |
242 | } |
243 | @@ -362,6 +414,19 @@ |
244 | |
245 | #undef COPY_IF_SET |
246 | |
247 | + if (modifications.input_shape.is_set()) |
248 | + { |
249 | + auto rects = modifications.input_shape.value(); |
250 | + constrain_input_to(rects, {surface->top_left(), surface->size()} ); |
251 | + surface_info.input_shape = rects; |
252 | + |
253 | + std::vector<Rectangle> input_area; |
254 | + if (surface_info.visible_titlebar) |
255 | + apply_input_titlebar_and_content_area(surface_info, *surface, {surface->top_left(), surface->size()}); |
256 | + else |
257 | + apply_input_content_area(surface_info, *surface, {surface->top_left(), surface->size()}); |
258 | + } |
259 | + |
260 | std::swap(surface_info, surface_info_old); |
261 | |
262 | if (modifications.name.is_set()) |
263 | @@ -394,7 +459,7 @@ |
264 | false, |
265 | display_area); |
266 | |
267 | - apply_resize(surface, surface_info.titlebar, top_left, new_size); |
268 | + apply_resize(surface, top_left, new_size); |
269 | } |
270 | |
271 | if (modifications.input_shape.is_set()) |
272 | @@ -439,12 +504,8 @@ |
273 | } |
274 | |
275 | session->destroy_surface(surface); |
276 | - if (info.titlebar) |
277 | - { |
278 | - session->destroy_surface(info.titlebar_id); |
279 | - session->destroy_buffer_stream(info.titlebar_stream_id); |
280 | - tools->forget(info.titlebar); |
281 | - } |
282 | + if (info.has_titlebar) |
283 | + session->destroy_buffer_stream(info.titlebar_id); |
284 | |
285 | auto& surfaces = tools->info_for(session).surfaces; |
286 | |
287 | @@ -511,36 +572,28 @@ |
288 | { |
289 | case mir_surface_state_restored: |
290 | movement = info.restore_rect.top_left - old_pos; |
291 | - surface->resize(info.restore_rect.size); |
292 | - if (info.titlebar) |
293 | - { |
294 | - info.titlebar->resize(titlebar_size_for_window(info.restore_rect.size)); |
295 | - info.titlebar->show(); |
296 | - } |
297 | + info.visible_titlebar = true; |
298 | + apply_resize(surface, surface->top_left() + movement, info.restore_rect.size); |
299 | break; |
300 | |
301 | case mir_surface_state_maximized: |
302 | movement = display_area.top_left - old_pos; |
303 | - surface->resize(display_area.size); |
304 | - if (info.titlebar) |
305 | - info.titlebar->hide(); |
306 | + movement.dy = movement.dy - titlebar_displacement.dy; |
307 | + info.visible_titlebar = true; |
308 | + apply_resize(surface, surface->top_left() + movement, display_area.size); |
309 | break; |
310 | |
311 | case mir_surface_state_horizmaximized: |
312 | movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos; |
313 | - surface->resize({display_area.size.width, info.restore_rect.size.height}); |
314 | - if (info.titlebar) |
315 | - { |
316 | - info.titlebar->resize(titlebar_size_for_window({display_area.size.width, info.restore_rect.size.height})); |
317 | - info.titlebar->show(); |
318 | - } |
319 | + info.visible_titlebar = true; |
320 | + apply_resize(surface, surface->top_left() + movement, {display_area.size.width, info.restore_rect.size.height}); |
321 | break; |
322 | |
323 | case mir_surface_state_vertmaximized: |
324 | movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos; |
325 | - surface->resize({info.restore_rect.size.width, display_area.size.height}); |
326 | - if (info.titlebar) |
327 | - info.titlebar->hide(); |
328 | + movement.dy = movement.dy - titlebar_displacement.dy; |
329 | + info.visible_titlebar = true; |
330 | + apply_resize(surface, surface->top_left() + movement, {info.restore_rect.size.width, display_area.size.height}); |
331 | break; |
332 | |
333 | case mir_surface_state_fullscreen: |
334 | @@ -557,14 +610,15 @@ |
335 | } |
336 | |
337 | movement = rect.top_left - old_pos; |
338 | - surface->resize(rect.size); |
339 | + |
340 | + //needs to be content only |
341 | + info.visible_titlebar = false; |
342 | + apply_resize(surface, surface->top_left() + movement, rect.size); |
343 | break; |
344 | } |
345 | |
346 | case mir_surface_state_hidden: |
347 | case mir_surface_state_minimized: |
348 | - if (info.titlebar) |
349 | - info.titlebar->hide(); |
350 | surface->hide(); |
351 | return info.state = value; |
352 | |
353 | @@ -572,11 +626,6 @@ |
354 | break; |
355 | } |
356 | |
357 | - // TODO It is rather simplistic to move a tree WRT the top_left of the root |
358 | - // TODO when resizing. But for more sophistication we would need to encode |
359 | - // TODO some sensible layout rules. |
360 | - move_tree(surface, movement); |
361 | - |
362 | info.state = value; |
363 | |
364 | if (info.is_visible()) |
365 | @@ -757,9 +806,9 @@ |
366 | { |
367 | if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) |
368 | { |
369 | - if (auto const possible_titlebar = tools->surface_at(old_cursor)) |
370 | + if (auto const surface = tools->surface_at(old_cursor)) |
371 | { |
372 | - if (tools->info_for(possible_titlebar).is_titlebar) |
373 | + if (old_cursor.y < surface->top_left().y) |
374 | { |
375 | drag(cursor); |
376 | consumes_event = true; |
377 | @@ -783,6 +832,7 @@ |
378 | |
379 | auto const value = handle_set_state(surface, MirSurfaceState(state)); |
380 | surface->configure(mir_surface_attrib_state, value); |
381 | + handle_set_state(surface, state); |
382 | } |
383 | } |
384 | |
385 | @@ -795,10 +845,7 @@ |
386 | { |
387 | if (auto const active_surface = active_surface_.lock()) |
388 | { |
389 | - if (auto const titlebar = tools->info_for(active_surface).titlebar) |
390 | - { |
391 | - tools->info_for(titlebar).paint_titlebar(0x3F); |
392 | - } |
393 | + tools->info_for(active_surface).paint_titlebar(0x3F); |
394 | } |
395 | |
396 | if (active_surface_.lock()) |
397 | @@ -814,15 +861,9 @@ |
398 | { |
399 | if (auto const active_surface = active_surface_.lock()) |
400 | { |
401 | - if (auto const titlebar = tools->info_for(active_surface).titlebar) |
402 | - { |
403 | - tools->info_for(titlebar).paint_titlebar(0x3F); |
404 | - } |
405 | - } |
406 | - if (auto const titlebar = tools->info_for(surface).titlebar) |
407 | - { |
408 | - tools->info_for(titlebar).paint_titlebar(0xFF); |
409 | - } |
410 | + tools->info_for(active_surface).paint_titlebar(0x3F); |
411 | + } |
412 | + tools->info_for(surface).paint_titlebar(0xFF); |
413 | tools->set_focus_to(info_for.session.lock(), surface); |
414 | tools->raise_tree(surface); |
415 | active_surface_ = surface; |
416 | @@ -852,7 +893,7 @@ |
417 | |
418 | bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds) |
419 | { |
420 | - if (!surface || !surface->input_area_contains(old_cursor)) |
421 | + if (!surface) |
422 | return false; |
423 | |
424 | auto const top_left = surface->top_left(); |
425 | @@ -883,27 +924,38 @@ |
426 | |
427 | Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy; |
428 | |
429 | - |
430 | auto const& surface_info = tools->info_for(surface); |
431 | |
432 | surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds); |
433 | |
434 | - apply_resize(surface, surface_info.titlebar, new_pos, new_size); |
435 | + apply_resize(surface, new_pos, new_size); |
436 | |
437 | return true; |
438 | } |
439 | |
440 | void me::CanonicalWindowManagerPolicyCopy::apply_resize( |
441 | std::shared_ptr<ms::Surface> const& surface, |
442 | - std::shared_ptr<ms::Surface> const& titlebar, |
443 | Point const& new_pos, |
444 | Size const& new_size) const |
445 | { |
446 | - if (titlebar) |
447 | - titlebar->resize({new_size.width, Height{title_bar_height}}); |
448 | + auto& surface_info = tools->info_for(surface); |
449 | + |
450 | + if (surface_info.visible_titlebar) |
451 | + { |
452 | + apply_input_titlebar_and_content_area(surface_info, *surface, {new_pos, new_size}); |
453 | + content_and_titlebar(surface_info, *surface, new_size); |
454 | + } |
455 | + else |
456 | + { |
457 | + apply_input_content_area(surface_info, *surface, {new_pos, new_size}); |
458 | + content_only(surface_info, *surface); |
459 | + } |
460 | |
461 | surface->resize(new_size); |
462 | |
463 | + // TODO It is rather simplistic to move a tree WRT the top_left of the root |
464 | + // TODO when resizing. But for more sophistication we would need to encode |
465 | + // TODO some sensible layout rules. |
466 | move_tree(surface, new_pos-surface->top_left()); |
467 | } |
468 | |
469 | @@ -912,7 +964,7 @@ |
470 | if (!surface) |
471 | return false; |
472 | |
473 | - if (!surface->input_area_contains(from) && !tools->info_for(surface).titlebar) |
474 | + if (!surface->input_area_contains(from)) |
475 | return false; |
476 | |
477 | auto movement = to - from; |
478 | |
479 | === modified file 'examples/server_example_canonical_window_manager.h' |
480 | --- examples/server_example_canonical_window_manager.h 2016-01-29 08:18:22 +0000 |
481 | +++ examples/server_example_canonical_window_manager.h 2016-04-13 11:13:46 +0000 |
482 | @@ -88,9 +88,7 @@ |
483 | |
484 | void generate_decorations_for( |
485 | std::shared_ptr<scene::Session> const& session, |
486 | - std::shared_ptr<scene::Surface> const& surface, |
487 | - SurfaceInfoMap& surface_map, |
488 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build); |
489 | + std::shared_ptr<scene::Surface> const& surface); |
490 | |
491 | private: |
492 | static const int modifier_mask = |
493 | @@ -112,7 +110,6 @@ |
494 | void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const; |
495 | void apply_resize( |
496 | std::shared_ptr<mir::scene::Surface> const& surface, |
497 | - std::shared_ptr<mir::scene::Surface> const& titlebar, |
498 | geometry::Point const& new_pos, |
499 | geometry::Size const& new_size) const; |
500 | |
501 | |
502 | === modified file 'examples/server_example_tiling_window_manager.cpp' |
503 | --- examples/server_example_tiling_window_manager.cpp 2016-01-29 08:18:22 +0000 |
504 | +++ examples/server_example_tiling_window_manager.cpp 2016-04-13 11:13:46 +0000 |
505 | @@ -138,9 +138,7 @@ |
506 | |
507 | void me::TilingWindowManagerPolicy::generate_decorations_for( |
508 | std::shared_ptr<ms::Session> const&, |
509 | - std::shared_ptr<ms::Surface> const&, |
510 | - SurfaceInfoMap&, |
511 | - std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) |
512 | + std::shared_ptr<ms::Surface> const&) |
513 | { |
514 | } |
515 | |
516 | |
517 | === modified file 'examples/server_example_tiling_window_manager.h' |
518 | --- examples/server_example_tiling_window_manager.h 2016-01-29 08:18:22 +0000 |
519 | +++ examples/server_example_tiling_window_manager.h 2016-04-13 11:13:46 +0000 |
520 | @@ -78,9 +78,7 @@ |
521 | std::shared_ptr<scene::Surface> const& surface); |
522 | |
523 | void generate_decorations_for( |
524 | - std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface, |
525 | - SurfaceInfoMap& surface_info, |
526 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build); |
527 | + std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface); |
528 | |
529 | private: |
530 | static const int modifier_mask = |
531 | |
532 | === modified file 'examples/server_example_window_management.cpp' |
533 | --- examples/server_example_window_management.cpp 2016-03-23 06:39:56 +0000 |
534 | +++ examples/server_example_window_management.cpp 2016-04-13 11:13:46 +0000 |
535 | @@ -105,10 +105,7 @@ |
536 | } |
537 | |
538 | void generate_decorations_for( |
539 | - std::shared_ptr<ms::Session> const&, |
540 | - std::shared_ptr<ms::Surface> const&, |
541 | - SurfaceInfoMap&, |
542 | - std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) override |
543 | + std::shared_ptr<ms::Session> const&, std::shared_ptr<ms::Surface> const&) override |
544 | { |
545 | } |
546 | private: |
547 | |
548 | === modified file 'examples/server_example_window_management_info.cpp' |
549 | --- examples/server_example_window_management_info.cpp 2016-01-29 08:18:22 +0000 |
550 | +++ examples/server_example_window_management_info.cpp 2016-04-13 11:13:46 +0000 |
551 | @@ -19,6 +19,7 @@ |
552 | #include "server_example_window_management_info.h" |
553 | |
554 | #include "mir/scene/surface.h" |
555 | +#include "mir/scene/session.h" |
556 | #include "mir/scene/surface_creation_parameters.h" |
557 | |
558 | #include "mir/graphics/buffer.h" |
559 | @@ -46,7 +47,9 @@ |
560 | width_inc{params.width_inc}, |
561 | height_inc{params.height_inc}, |
562 | min_aspect{params.min_aspect}, |
563 | - max_aspect{params.max_aspect} |
564 | + max_aspect{params.max_aspect}, |
565 | + input_shape{params.input_shape.is_set() ? params.input_shape.value() : std::vector<Rectangle>{}}, |
566 | + streams{params.streams.is_set() ? params.streams.value() : std::vector<shell::StreamSpecification>{}} |
567 | { |
568 | if (params.output_id != mir::graphics::DisplayConfigurationOutputId{0}) |
569 | output_id = params.output_id; |
570 | @@ -243,16 +246,19 @@ |
571 | mg::BufferID back_buffer; |
572 | }; |
573 | |
574 | -void mir::examples::SurfaceInfo::init_titlebar(std::shared_ptr<scene::Surface> const& surface) |
575 | +void mir::examples::SurfaceInfo::init_titlebar(Size titlebar_size) |
576 | { |
577 | - auto stream = surface->primary_buffer_stream(); |
578 | - try |
579 | - { |
580 | - stream_painter = std::make_shared<AllocatingPainter>(stream, surface->size()); |
581 | - } |
582 | - catch (...) |
583 | - { |
584 | - stream_painter = std::make_shared<SwappingPainter>(stream); |
585 | + if (auto s = session.lock()) |
586 | + { |
587 | + auto stream = s->get_buffer_stream(titlebar_id); |
588 | + try |
589 | + { |
590 | + stream_painter = std::make_shared<AllocatingPainter>(stream, titlebar_size); |
591 | + } |
592 | + catch (...) |
593 | + { |
594 | + stream_painter = std::make_shared<SwappingPainter>(stream); |
595 | + } |
596 | } |
597 | } |
598 | |
599 | |
600 | === modified file 'examples/server_example_window_management_info.h' |
601 | --- examples/server_example_window_management_info.h 2016-03-30 14:08:54 +0000 |
602 | +++ examples/server_example_window_management_info.h 2016-04-13 11:13:46 +0000 |
603 | @@ -63,10 +63,6 @@ |
604 | std::weak_ptr <scene::Session> session; |
605 | std::weak_ptr <scene::Surface> parent; |
606 | std::vector <std::weak_ptr<scene::Surface>> children; |
607 | - std::shared_ptr <scene::Surface> titlebar; |
608 | - frontend::SurfaceId titlebar_id; |
609 | - frontend::BufferStreamId titlebar_stream_id; |
610 | - bool is_titlebar = false; |
611 | geometry::Width min_width; |
612 | geometry::Height min_height; |
613 | geometry::Width max_width; |
614 | @@ -76,8 +72,15 @@ |
615 | mir::optional_value<shell::SurfaceAspectRatio> min_aspect; |
616 | mir::optional_value<shell::SurfaceAspectRatio> max_aspect; |
617 | mir::optional_value<graphics::DisplayConfigurationOutputId> output_id; |
618 | - |
619 | - void init_titlebar(std::shared_ptr <scene::Surface> const& surface); |
620 | + mir::optional_value<std::vector<geometry::Rectangle>> input_shape; |
621 | + mir::optional_value<geometry::Rectangle> titlebar_input_shape; |
622 | + |
623 | + mir::optional_value<std::vector<shell::StreamSpecification>> streams; |
624 | + frontend::BufferStreamId titlebar_id; |
625 | + bool has_titlebar = false; |
626 | + bool visible_titlebar = false; |
627 | + |
628 | + void init_titlebar(geometry::Size titlebar_size); |
629 | |
630 | void paint_titlebar(int intensity); |
631 | |
632 | |
633 | === modified file 'include/server/mir/scene/surface_creation_parameters.h' |
634 | --- include/server/mir/scene/surface_creation_parameters.h 2016-03-29 16:30:22 +0000 |
635 | +++ include/server/mir/scene/surface_creation_parameters.h 2016-04-13 11:13:46 +0000 |
636 | @@ -72,6 +72,8 @@ |
637 | |
638 | SurfaceCreationParameters& with_buffer_stream(frontend::BufferStreamId const& id); |
639 | |
640 | + SurfaceCreationParameters& with_buffer_streams(std::vector<shell::StreamSpecification> const& streams); |
641 | + |
642 | std::string name; |
643 | geometry::Size size; |
644 | geometry::Point top_left; |
645 | @@ -84,7 +86,6 @@ |
646 | mir::optional_value<MirSurfaceType> type; |
647 | mir::optional_value<MirOrientationMode> preferred_orientation; |
648 | mir::optional_value<frontend::SurfaceId> parent_id; |
649 | - mir::optional_value<frontend::BufferStreamId> content_id; |
650 | mir::optional_value<geometry::Rectangle> aux_rect; |
651 | mir::optional_value<MirEdgeAttachment> edge_attachment; |
652 | |
653 | |
654 | === modified file 'include/server/mir/shell/surface_specification.h' |
655 | --- include/server/mir/shell/surface_specification.h 2016-03-23 06:39:56 +0000 |
656 | +++ include/server/mir/shell/surface_specification.h 2016-04-13 11:13:46 +0000 |
657 | @@ -45,6 +45,7 @@ |
658 | geometry::Displacement displacement; |
659 | optional_value<geometry::Size> size; |
660 | }; |
661 | +bool operator==(StreamSpecification const& lhs, StreamSpecification const& rhs); |
662 | |
663 | /// Specification of surface properties requested by client |
664 | struct SurfaceSpecification |
665 | |
666 | === modified file 'src/server/frontend/session_mediator.cpp' |
667 | --- src/server/frontend/session_mediator.cpp 2016-04-12 14:10:00 +0000 |
668 | +++ src/server/frontend/session_mediator.cpp 2016-04-13 11:13:46 +0000 |
669 | @@ -287,10 +287,10 @@ |
670 | #undef COPY_IF_SET |
671 | |
672 | mf::BufferStreamId buffer_stream_id; |
673 | - std::shared_ptr<mf::BufferStream> legacy_stream = nullptr; |
674 | + std::shared_ptr<mf::BufferStream> legacy_stream; |
675 | + std::vector<msh::StreamSpecification> stream_spec; |
676 | if (request->stream_size() > 0) |
677 | { |
678 | - std::vector<msh::StreamSpecification> stream_spec; |
679 | for (auto& stream : request->stream()) |
680 | { |
681 | if (stream.has_width() && stream.has_height()) |
682 | @@ -310,16 +310,17 @@ |
683 | {}}); |
684 | } |
685 | } |
686 | - params.streams = std::move(stream_spec); |
687 | } |
688 | else |
689 | { |
690 | buffer_stream_id = session->create_buffer_stream( |
691 | {params.size, params.pixel_format, params.buffer_usage}); |
692 | legacy_stream = session->get_buffer_stream(buffer_stream_id); |
693 | - params.content_id = buffer_stream_id; |
694 | + stream_spec.emplace_back(msh::StreamSpecification{ {buffer_stream_id}, {0, 0}, {}}); |
695 | } |
696 | |
697 | + params.streams = std::move(stream_spec); |
698 | + |
699 | if (request->has_min_aspect()) |
700 | params.min_aspect = { request->min_aspect().width(), request->min_aspect().height()}; |
701 | |
702 | @@ -334,17 +335,16 @@ |
703 | auto const surf_id = shell->create_surface(session, params, sink); |
704 | |
705 | auto surface = session->get_surface(surf_id); |
706 | - auto stream = session->get_buffer_stream(buffer_stream_id); |
707 | auto const& client_size = surface->client_size(); |
708 | response->mutable_id()->set_value(surf_id.as_value()); |
709 | response->set_width(client_size.width.as_uint32_t()); |
710 | response->set_height(client_size.height.as_uint32_t()); |
711 | |
712 | // TODO: Deprecate |
713 | - response->set_pixel_format(stream->pixel_format()); |
714 | + response->set_pixel_format(params.pixel_format); |
715 | response->set_buffer_usage(request->buffer_usage()); |
716 | |
717 | - response->mutable_buffer_stream()->set_pixel_format(stream->pixel_format()); |
718 | + response->mutable_buffer_stream()->set_pixel_format(params.pixel_format); |
719 | response->mutable_buffer_stream()->set_buffer_usage(request->buffer_usage()); |
720 | |
721 | if (surface->supports_input()) |
722 | |
723 | === modified file 'src/server/scene/application_session.cpp' |
724 | --- src/server/scene/application_session.cpp 2016-04-13 11:13:46 +0000 |
725 | +++ src/server/scene/application_session.cpp 2016-04-13 11:13:46 +0000 |
726 | @@ -94,19 +94,12 @@ |
727 | //TODO: we take either the content_id or the first streams content for now. |
728 | // Once the surface factory interface takes more than one stream, |
729 | // we can take all the streams as content. |
730 | - if (!((the_params.content_id.is_set()) || |
731 | - (the_params.streams.is_set() && the_params.streams.value().size() > 0))) |
732 | - { |
733 | + if (!(the_params.streams.is_set() && the_params.streams.value().size() > 0)) |
734 | BOOST_THROW_EXCEPTION(std::logic_error("surface must have content")); |
735 | - } |
736 | |
737 | auto params = the_params; |
738 | |
739 | - mf::BufferStreamId stream_id; |
740 | - if (params.content_id.is_set()) |
741 | - stream_id = params.content_id.value(); |
742 | - else |
743 | - stream_id = params.streams.value()[0].stream_id; |
744 | + mf::BufferStreamId stream_id = params.streams.value()[0].stream_id; |
745 | |
746 | if (params.parent_id.is_set()) |
747 | params.parent = checked_find(the_params.parent_id.value())->second; |
748 | @@ -116,15 +109,8 @@ |
749 | buffer_stream->resize(params.size); |
750 | |
751 | std::list<StreamInfo> streams; |
752 | - if (the_params.content_id.is_set()) |
753 | - { |
754 | - streams.push_back({checked_find(the_params.content_id.value())->second, {0,0}, {}}); |
755 | - } |
756 | - else |
757 | - { |
758 | - for (auto& stream : params.streams.value()) |
759 | - streams.push_back({checked_find(stream.stream_id)->second, stream.displacement, stream.size}); |
760 | - } |
761 | + for (auto& stream : params.streams.value()) |
762 | + streams.push_back({checked_find(stream.stream_id)->second, stream.displacement, stream.size}); |
763 | |
764 | auto surface = surface_factory->create_surface(streams, params); |
765 | |
766 | |
767 | === modified file 'src/server/scene/surface_creation_parameters.cpp' |
768 | --- src/server/scene/surface_creation_parameters.cpp 2016-01-29 08:18:22 +0000 |
769 | +++ src/server/scene/surface_creation_parameters.cpp 2016-04-13 11:13:46 +0000 |
770 | @@ -130,7 +130,14 @@ |
771 | |
772 | ms::SurfaceCreationParameters& ms::SurfaceCreationParameters::with_buffer_stream(mf::BufferStreamId const& id) |
773 | { |
774 | - content_id = id; |
775 | + streams = std::vector<shell::StreamSpecification>{ {id, {}, {}} }; |
776 | + return *this; |
777 | +} |
778 | + |
779 | +ms::SurfaceCreationParameters& ms::SurfaceCreationParameters::with_buffer_streams( |
780 | + std::vector<shell::StreamSpecification> const& s) |
781 | +{ |
782 | + streams = s; |
783 | return *this; |
784 | } |
785 | |
786 | @@ -149,7 +156,7 @@ |
787 | lhs.type == rhs.type && |
788 | lhs.preferred_orientation == rhs.preferred_orientation && |
789 | lhs.parent_id == rhs.parent_id && |
790 | - lhs.content_id == rhs.content_id; |
791 | + lhs.streams == rhs.streams; |
792 | } |
793 | |
794 | bool ms::operator!=( |
795 | |
796 | === modified file 'src/server/shell/surface_specification.cpp' |
797 | --- src/server/shell/surface_specification.cpp 2015-10-15 04:20:44 +0000 |
798 | +++ src/server/shell/surface_specification.cpp 2016-04-13 11:13:46 +0000 |
799 | @@ -47,3 +47,10 @@ |
800 | !parent.is_set() && |
801 | !input_shape.is_set(); |
802 | } |
803 | + |
804 | +bool msh::operator==(StreamSpecification const& lhs, StreamSpecification const& rhs) |
805 | +{ |
806 | + return lhs.stream_id == rhs.stream_id && |
807 | + lhs.displacement == rhs.displacement && |
808 | + lhs.size == rhs.size; |
809 | +} |
810 | |
811 | === modified file 'src/server/symbols.map' |
812 | --- src/server/symbols.map 2016-03-28 23:15:00 +0000 |
813 | +++ src/server/symbols.map 2016-04-13 11:13:46 +0000 |
814 | @@ -290,6 +290,7 @@ |
815 | mir::shell::ShellWrapper::start_prompt_session_for*; |
816 | mir::shell::ShellWrapper::stop_prompt_session*; |
817 | mir::shell::ShellWrapper::surface_at*; |
818 | + mir::shell::StreamSpecification::operator*; |
819 | mir::shell::SurfaceReadyObserver::frame_posted*; |
820 | mir::shell::SurfaceReadyObserver::?SurfaceReadyObserver*; |
821 | mir::shell::SurfaceReadyObserver::SurfaceReadyObserver*; |
PASSED: Continuous integration, rev:3452 /mir-jenkins. ubuntu. com/job/ mir-ci/ 826/ /mir-jenkins. ubuntu. com/job/ build-mir/ 831 /mir-jenkins. ubuntu. com/job/ build-0- fetch/868 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 859 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 859 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 841 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 841/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 841 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 841/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 841 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 841/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 841 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 841/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 841 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 841/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 826/rebuild
https:/