Mir

Merge lp:~kdub/mir/demo-stream-titlebars into lp:mir

Proposed by Kevin DuBois
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
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 CanonicalWindowManagerPolicy from using Surfaces to display titlebars to using Streams.

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 CanonicalWindowManagerPolicy from using Surfaces to display titlebars to using Streams.

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)

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3452
https://mir-jenkins.ubuntu.com/job/mir-ci/826/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/831
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/868
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/859
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/859
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/841
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/841/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/841
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/841/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/841
        deb: https://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
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/841
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/841/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/841
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/841/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/826/rebuild

review: Approve (continuous-integration)
Revision history for this message
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_client_multiwin

Expected: multiwin has bright (focussed) titlebars, terminal has dim (unfocussed) titlebars
Actual .: Both the terminal and multiwin have "focus" titlebars.

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

I don't see where this is being used.
640 + SurfaceCreationParameters& with_buffer_streams(std::vector<shell::StreamSpecification> const& streams);

why is it needed? Is there a followup branch?

review: Needs Information
Revision history for this message
Kevin DuBois (kdub) wrote :

> I don't see where this is being used.
> 640 + SurfaceCreationParameters&
> with_buffer_streams(std::vector<shell::StreamSpecification> const& streams);
>
> 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_usage(...)
    .with_buffer_streams(...);

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

> > I don't see where this is being used.
> > 640 + SurfaceCreationParameters&
> > with_buffer_streams(std::vector<shell::StreamSpecification> const& streams);
> >
> > 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_usage(...)
> .with_buffer_streams(...);

Ok I guess it sounds useful.

review: Approve
Revision history for this message
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://bugs.launchpad.net/mir/+bug/1569836/comments/1

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.

review: Abstain
Revision history for this message
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.

review: Approve
Revision history for this message
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.

Revision history for this message
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_buffer_stream()'

Revision history for this message
Kevin DuBois (kdub) wrote :

bit of bitrot while I did 0.23 testing and sync fence investigation, fixing up

Revision history for this message
Kevin DuBois (kdub) wrote :

back to WIP

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'examples/server_example_basic_window_manager.cpp'
--- examples/server_example_basic_window_manager.cpp 2015-11-27 13:58:54 +0000
+++ examples/server_example_basic_window_manager.cpp 2016-04-13 11:13:46 +0000
@@ -58,7 +58,7 @@
58 auto const surface = session->surface(result);58 auto const surface = session->surface(result);
59 surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params});59 surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params});
60 policy->handle_new_surface(session, surface);60 policy->handle_new_surface(session, surface);
61 policy->generate_decorations_for(session, surface, surface_info, build);61 policy->generate_decorations_for(session, surface);
62 return result;62 return result;
63}63}
6464
6565
=== modified file 'examples/server_example_basic_window_manager.h'
--- examples/server_example_basic_window_manager.h 2016-01-29 08:18:22 +0000
+++ examples/server_example_basic_window_manager.h 2016-04-13 11:13:46 +0000
@@ -104,9 +104,7 @@
104 virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value) = 0;104 virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirSurfaceState value) = 0;
105105
106 virtual void generate_decorations_for(106 virtual void generate_decorations_for(
107 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface,107 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) = 0;
108 SurfaceInfoMap& surface_info,
109 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build) = 0;
110108
111 virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0;109 virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0;
112110
113111
=== modified file 'examples/server_example_canonical_window_manager.cpp'
--- examples/server_example_canonical_window_manager.cpp 2016-04-12 14:10:00 +0000
+++ examples/server_example_canonical_window_manager.cpp 2016-04-13 11:13:46 +0000
@@ -30,6 +30,7 @@
3030
31namespace me = mir::examples;31namespace me = mir::examples;
32namespace ms = mir::scene;32namespace ms = mir::scene;
33namespace mg = mir::graphics;
33using namespace mir::geometry;34using namespace mir::geometry;
3435
35///\example server_example_canonical_window_manager.cpp36///\example server_example_canonical_window_manager.cpp
@@ -38,18 +39,95 @@
38namespace39namespace
39{40{
40int const title_bar_height = 10;41int const title_bar_height = 10;
42Displacement const titlebar_displacement { 0, -10 };
43
41Size titlebar_size_for_window(Size window_size)44Size titlebar_size_for_window(Size window_size)
42{45{
43 return {window_size.width, Height{title_bar_height}};46 return {window_size.width, Height{title_bar_height}};
44}47}
4548
46Point titlebar_position_for_window(Point window_position)49void constrain_input_to(std::vector<Rectangle>& rectangles, Rectangle constraint)
47{50{
48 return {51 auto surface_displacement = constraint.top_left - Point{0, 0};
49 window_position.x,52 for(auto& rect : rectangles)
50 window_position.y - DeltaY(title_bar_height)53 {
51 };54 rect.top_left = rect.top_left + surface_displacement;
52}55 rect = rect.intersection_with(constraint);
56 rect.top_left = rect.top_left - surface_displacement;
57 }
58}
59
60std::vector<Rectangle> input_content_area(me::SurfaceInfo& info, Rectangle surface_rect)
61{
62 std::vector<Rectangle> rectangles;
63 if (info.input_shape.is_set() && !info.input_shape.value().empty())
64 return info.input_shape.value();
65 else
66 return { { Point{0,0}, surface_rect.size } };
67}
68
69void apply_input_content_area(
70 me::SurfaceInfo& info, ms::Surface& surface, Rectangle surface_rect)
71{
72 surface.set_input_region(input_content_area(info, surface_rect));
73}
74
75void apply_input_titlebar_and_content_area(
76 me::SurfaceInfo& info, ms::Surface& surface,
77 Rectangle surface_rect)
78{
79 auto rectangles = input_content_area(info, surface_rect);
80 info.titlebar_input_shape =
81 { Point{0,0} + titlebar_displacement, titlebar_size_for_window(surface_rect.size) };
82 rectangles.emplace_back(info.titlebar_input_shape.value());
83 surface.set_input_region(rectangles);
84}
85
86void content_and_titlebar(me::SurfaceInfo& info, ms::Surface& surface, Size new_size)
87{
88 auto streams = info.streams.value();
89 auto titlebar = std::find_if(streams.begin(), streams.end(),
90 [&](mir::shell::StreamSpecification const& entry)
91 {
92 return entry.stream_id == info.titlebar_id;
93 });
94
95 if (titlebar == streams.end())
96 {
97 streams.push_back(
98 { info.titlebar_id, titlebar_displacement, {titlebar_size_for_window(new_size)}});
99 }
100 else
101 {
102 titlebar->size = titlebar_size_for_window(new_size);
103 }
104
105 if (auto session = info.session.lock())
106 session->configure_streams(surface, streams);
107
108 info.streams = streams;
109 info.visible_titlebar = true;
110}
111
112void content_only(me::SurfaceInfo& info, ms::Surface& surface)
113{
114 auto streams = info.streams.value();
115 for(auto it = streams.begin(); it != streams.end();)
116 {
117 if (it->stream_id == info.titlebar_id)
118 it = streams.erase(it);
119 else
120 it++;
121 }
122
123 if (auto session = info.session.lock())
124 session->configure_streams(surface, streams);
125
126 info.streams = streams;
127 info.visible_titlebar = false;
128}
129
130
53}131}
54132
55me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy(133me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy(
@@ -83,7 +161,7 @@
83161
84 display_layout->place_in_output(info.output_id.value(), rect);162 display_layout->place_in_output(info.output_id.value(), rect);
85 surface->move_to(rect.top_left);163 surface->move_to(rect.top_left);
86 surface->resize(rect.size);164 apply_resize(surface, rect.top_left, rect.size);
87 }165 }
88 }166 }
89}167}
@@ -103,9 +181,6 @@
103 auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_surface_type_normal;181 auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_surface_type_normal;
104 bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type);182 bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type);
105183
106 if (needs_titlebar)
107 parameters.size.height = parameters.size.height + DeltaY{title_bar_height};
108
109 if (!parameters.state.is_set())184 if (!parameters.state.is_set())
110 parameters.state = mir_surface_state_restored;185 parameters.state = mir_surface_state_restored;
111186
@@ -238,45 +313,34 @@
238 parameters.size.height = parameters.size.height - DeltaY{title_bar_height};313 parameters.size.height = parameters.size.height - DeltaY{title_bar_height};
239 }314 }
240315
316 if (parameters.input_shape.is_set())
317 {
318 auto rect = parameters.input_shape.value();
319 constrain_input_to(rect, {parameters.top_left, parameters.size});
320 parameters.input_shape = rect;
321 }
322
241 return parameters;323 return parameters;
242}324}
243325
244void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for(326void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for(
245 std::shared_ptr<scene::Session> const& session,327 std::shared_ptr<scene::Session> const& session,
246 std::shared_ptr<scene::Surface> const& surface,328 std::shared_ptr<scene::Surface> const& surface)
247 SurfaceInfoMap& surface_map,
248 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build)
249{329{
250 if (!SurfaceInfo::needs_titlebar(surface->type()))330 if (!SurfaceInfo::needs_titlebar(surface->type()))
251 return;331 return;
252332
253 auto format = mir_pixel_format_xrgb_8888;333 auto format = mir_pixel_format_xrgb_8888;
254 mir::graphics::BufferProperties properties(titlebar_size_for_window(surface->size()),334 auto size = titlebar_size_for_window(surface->size());
255 format, mir::graphics::BufferUsage::software);335 auto usage = mir::graphics::BufferUsage::software;
256 auto stream_id = session->create_buffer_stream(properties);
257 auto params = ms::a_surface()
258 .of_size(titlebar_size_for_window(surface->size()))
259 .of_name("decoration")
260 .of_pixel_format(format)
261 .of_buffer_usage(mir::graphics::BufferUsage::software)
262 .of_position(titlebar_position_for_window(surface->top_left()))
263 .of_type(mir_surface_type_gloss)
264 .with_buffer_stream(stream_id);
265 auto id = build(session, params);
266 auto titlebar = session->surface(id);
267 titlebar->set_alpha(0.9);
268
269 auto& surface_info = tools->info_for(surface);336 auto& surface_info = tools->info_for(surface);
270 surface_info.titlebar = titlebar;337 surface_info.has_titlebar = true;
271 surface_info.titlebar_id = id;338 surface_info.titlebar_id = session->create_buffer_stream(mg::BufferProperties{size, format, usage});
272 surface_info.titlebar_stream_id = stream_id;339 surface_info.init_titlebar(size);
273 surface_info.children.push_back(titlebar);340 surface_info.paint_titlebar(0xFF);
274341
275 SurfaceInfo& titlebar_info =342 content_and_titlebar(surface_info, *surface, size);
276 surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second;343 apply_input_titlebar_and_content_area(surface_info, *surface, {surface->top_left(), surface->size()});
277 titlebar_info.is_titlebar = true;
278 titlebar_info.parent = surface;
279 titlebar_info.init_titlebar(titlebar);
280}344}
281345
282void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface)346void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface)
@@ -289,18 +353,6 @@
289353
290 tools->info_for(session).surfaces.push_back(surface);354 tools->info_for(session).surfaces.push_back(surface);
291355
292 if (surface_info.can_be_active())
293 {
294 surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>(
295 [this](std::shared_ptr<scene::Session> const& /*session*/,
296 std::shared_ptr<scene::Surface> const& surface)
297 {
298 select_active_surface(surface);
299 },
300 session,
301 surface));
302 }
303
304 if (surface_info.state == mir_surface_state_fullscreen)356 if (surface_info.state == mir_surface_state_fullscreen)
305 fullscreen_surfaces.insert(surface);357 fullscreen_surfaces.insert(surface);
306}358}
@@ -362,6 +414,19 @@
362414
363 #undef COPY_IF_SET415 #undef COPY_IF_SET
364416
417 if (modifications.input_shape.is_set())
418 {
419 auto rects = modifications.input_shape.value();
420 constrain_input_to(rects, {surface->top_left(), surface->size()} );
421 surface_info.input_shape = rects;
422
423 std::vector<Rectangle> input_area;
424 if (surface_info.visible_titlebar)
425 apply_input_titlebar_and_content_area(surface_info, *surface, {surface->top_left(), surface->size()});
426 else
427 apply_input_content_area(surface_info, *surface, {surface->top_left(), surface->size()});
428 }
429
365 std::swap(surface_info, surface_info_old);430 std::swap(surface_info, surface_info_old);
366431
367 if (modifications.name.is_set())432 if (modifications.name.is_set())
@@ -394,7 +459,7 @@
394 false,459 false,
395 display_area);460 display_area);
396461
397 apply_resize(surface, surface_info.titlebar, top_left, new_size);462 apply_resize(surface, top_left, new_size);
398 }463 }
399464
400 if (modifications.input_shape.is_set())465 if (modifications.input_shape.is_set())
@@ -439,12 +504,8 @@
439 }504 }
440505
441 session->destroy_surface(surface);506 session->destroy_surface(surface);
442 if (info.titlebar)507 if (info.has_titlebar)
443 {508 session->destroy_buffer_stream(info.titlebar_id);
444 session->destroy_surface(info.titlebar_id);
445 session->destroy_buffer_stream(info.titlebar_stream_id);
446 tools->forget(info.titlebar);
447 }
448509
449 auto& surfaces = tools->info_for(session).surfaces;510 auto& surfaces = tools->info_for(session).surfaces;
450511
@@ -511,36 +572,28 @@
511 {572 {
512 case mir_surface_state_restored:573 case mir_surface_state_restored:
513 movement = info.restore_rect.top_left - old_pos;574 movement = info.restore_rect.top_left - old_pos;
514 surface->resize(info.restore_rect.size);575 info.visible_titlebar = true;
515 if (info.titlebar)576 apply_resize(surface, surface->top_left() + movement, info.restore_rect.size);
516 {
517 info.titlebar->resize(titlebar_size_for_window(info.restore_rect.size));
518 info.titlebar->show();
519 }
520 break;577 break;
521578
522 case mir_surface_state_maximized:579 case mir_surface_state_maximized:
523 movement = display_area.top_left - old_pos;580 movement = display_area.top_left - old_pos;
524 surface->resize(display_area.size);581 movement.dy = movement.dy - titlebar_displacement.dy;
525 if (info.titlebar)582 info.visible_titlebar = true;
526 info.titlebar->hide();583 apply_resize(surface, surface->top_left() + movement, display_area.size);
527 break;584 break;
528585
529 case mir_surface_state_horizmaximized:586 case mir_surface_state_horizmaximized:
530 movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos;587 movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos;
531 surface->resize({display_area.size.width, info.restore_rect.size.height});588 info.visible_titlebar = true;
532 if (info.titlebar)589 apply_resize(surface, surface->top_left() + movement, {display_area.size.width, info.restore_rect.size.height});
533 {
534 info.titlebar->resize(titlebar_size_for_window({display_area.size.width, info.restore_rect.size.height}));
535 info.titlebar->show();
536 }
537 break;590 break;
538591
539 case mir_surface_state_vertmaximized:592 case mir_surface_state_vertmaximized:
540 movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos;593 movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos;
541 surface->resize({info.restore_rect.size.width, display_area.size.height});594 movement.dy = movement.dy - titlebar_displacement.dy;
542 if (info.titlebar)595 info.visible_titlebar = true;
543 info.titlebar->hide();596 apply_resize(surface, surface->top_left() + movement, {info.restore_rect.size.width, display_area.size.height});
544 break;597 break;
545598
546 case mir_surface_state_fullscreen:599 case mir_surface_state_fullscreen:
@@ -557,14 +610,15 @@
557 }610 }
558611
559 movement = rect.top_left - old_pos;612 movement = rect.top_left - old_pos;
560 surface->resize(rect.size);613
614 //needs to be content only
615 info.visible_titlebar = false;
616 apply_resize(surface, surface->top_left() + movement, rect.size);
561 break;617 break;
562 }618 }
563619
564 case mir_surface_state_hidden:620 case mir_surface_state_hidden:
565 case mir_surface_state_minimized:621 case mir_surface_state_minimized:
566 if (info.titlebar)
567 info.titlebar->hide();
568 surface->hide();622 surface->hide();
569 return info.state = value;623 return info.state = value;
570624
@@ -572,11 +626,6 @@
572 break;626 break;
573 }627 }
574628
575 // TODO It is rather simplistic to move a tree WRT the top_left of the root
576 // TODO when resizing. But for more sophistication we would need to encode
577 // TODO some sensible layout rules.
578 move_tree(surface, movement);
579
580 info.state = value;629 info.state = value;
581630
582 if (info.is_visible())631 if (info.is_visible())
@@ -757,9 +806,9 @@
757 {806 {
758 if (mir_pointer_event_button_state(event, mir_pointer_button_primary))807 if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
759 {808 {
760 if (auto const possible_titlebar = tools->surface_at(old_cursor))809 if (auto const surface = tools->surface_at(old_cursor))
761 {810 {
762 if (tools->info_for(possible_titlebar).is_titlebar)811 if (old_cursor.y < surface->top_left().y)
763 {812 {
764 drag(cursor);813 drag(cursor);
765 consumes_event = true;814 consumes_event = true;
@@ -783,6 +832,7 @@
783832
784 auto const value = handle_set_state(surface, MirSurfaceState(state));833 auto const value = handle_set_state(surface, MirSurfaceState(state));
785 surface->configure(mir_surface_attrib_state, value);834 surface->configure(mir_surface_attrib_state, value);
835 handle_set_state(surface, state);
786 }836 }
787}837}
788838
@@ -795,10 +845,7 @@
795 {845 {
796 if (auto const active_surface = active_surface_.lock())846 if (auto const active_surface = active_surface_.lock())
797 {847 {
798 if (auto const titlebar = tools->info_for(active_surface).titlebar)848 tools->info_for(active_surface).paint_titlebar(0x3F);
799 {
800 tools->info_for(titlebar).paint_titlebar(0x3F);
801 }
802 }849 }
803850
804 if (active_surface_.lock())851 if (active_surface_.lock())
@@ -814,15 +861,9 @@
814 {861 {
815 if (auto const active_surface = active_surface_.lock())862 if (auto const active_surface = active_surface_.lock())
816 {863 {
817 if (auto const titlebar = tools->info_for(active_surface).titlebar)864 tools->info_for(active_surface).paint_titlebar(0x3F);
818 {865 }
819 tools->info_for(titlebar).paint_titlebar(0x3F);866 tools->info_for(surface).paint_titlebar(0xFF);
820 }
821 }
822 if (auto const titlebar = tools->info_for(surface).titlebar)
823 {
824 tools->info_for(titlebar).paint_titlebar(0xFF);
825 }
826 tools->set_focus_to(info_for.session.lock(), surface);867 tools->set_focus_to(info_for.session.lock(), surface);
827 tools->raise_tree(surface);868 tools->raise_tree(surface);
828 active_surface_ = surface;869 active_surface_ = surface;
@@ -852,7 +893,7 @@
852893
853bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds)894bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds)
854{895{
855 if (!surface || !surface->input_area_contains(old_cursor))896 if (!surface)
856 return false;897 return false;
857898
858 auto const top_left = surface->top_left();899 auto const top_left = surface->top_left();
@@ -883,27 +924,38 @@
883924
884 Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy;925 Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy;
885926
886
887 auto const& surface_info = tools->info_for(surface);927 auto const& surface_info = tools->info_for(surface);
888928
889 surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds);929 surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds);
890930
891 apply_resize(surface, surface_info.titlebar, new_pos, new_size);931 apply_resize(surface, new_pos, new_size);
892932
893 return true;933 return true;
894}934}
895935
896void me::CanonicalWindowManagerPolicyCopy::apply_resize(936void me::CanonicalWindowManagerPolicyCopy::apply_resize(
897 std::shared_ptr<ms::Surface> const& surface,937 std::shared_ptr<ms::Surface> const& surface,
898 std::shared_ptr<ms::Surface> const& titlebar,
899 Point const& new_pos,938 Point const& new_pos,
900 Size const& new_size) const939 Size const& new_size) const
901{940{
902 if (titlebar)941 auto& surface_info = tools->info_for(surface);
903 titlebar->resize({new_size.width, Height{title_bar_height}});942
943 if (surface_info.visible_titlebar)
944 {
945 apply_input_titlebar_and_content_area(surface_info, *surface, {new_pos, new_size});
946 content_and_titlebar(surface_info, *surface, new_size);
947 }
948 else
949 {
950 apply_input_content_area(surface_info, *surface, {new_pos, new_size});
951 content_only(surface_info, *surface);
952 }
904953
905 surface->resize(new_size);954 surface->resize(new_size);
906955
956 // TODO It is rather simplistic to move a tree WRT the top_left of the root
957 // TODO when resizing. But for more sophistication we would need to encode
958 // TODO some sensible layout rules.
907 move_tree(surface, new_pos-surface->top_left());959 move_tree(surface, new_pos-surface->top_left());
908}960}
909961
@@ -912,7 +964,7 @@
912 if (!surface)964 if (!surface)
913 return false;965 return false;
914966
915 if (!surface->input_area_contains(from) && !tools->info_for(surface).titlebar)967 if (!surface->input_area_contains(from))
916 return false;968 return false;
917969
918 auto movement = to - from;970 auto movement = to - from;
919971
=== modified file 'examples/server_example_canonical_window_manager.h'
--- examples/server_example_canonical_window_manager.h 2016-01-29 08:18:22 +0000
+++ examples/server_example_canonical_window_manager.h 2016-04-13 11:13:46 +0000
@@ -88,9 +88,7 @@
8888
89 void generate_decorations_for(89 void generate_decorations_for(
90 std::shared_ptr<scene::Session> const& session,90 std::shared_ptr<scene::Session> const& session,
91 std::shared_ptr<scene::Surface> const& surface,91 std::shared_ptr<scene::Surface> const& surface);
92 SurfaceInfoMap& surface_map,
93 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build);
9492
95private:93private:
96 static const int modifier_mask =94 static const int modifier_mask =
@@ -112,7 +110,6 @@
112 void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const;110 void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const;
113 void apply_resize(111 void apply_resize(
114 std::shared_ptr<mir::scene::Surface> const& surface,112 std::shared_ptr<mir::scene::Surface> const& surface,
115 std::shared_ptr<mir::scene::Surface> const& titlebar,
116 geometry::Point const& new_pos,113 geometry::Point const& new_pos,
117 geometry::Size const& new_size) const;114 geometry::Size const& new_size) const;
118115
119116
=== modified file 'examples/server_example_tiling_window_manager.cpp'
--- examples/server_example_tiling_window_manager.cpp 2016-01-29 08:18:22 +0000
+++ examples/server_example_tiling_window_manager.cpp 2016-04-13 11:13:46 +0000
@@ -138,9 +138,7 @@
138138
139void me::TilingWindowManagerPolicy::generate_decorations_for(139void me::TilingWindowManagerPolicy::generate_decorations_for(
140 std::shared_ptr<ms::Session> const&,140 std::shared_ptr<ms::Session> const&,
141 std::shared_ptr<ms::Surface> const&,141 std::shared_ptr<ms::Surface> const&)
142 SurfaceInfoMap&,
143 std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&)
144{142{
145}143}
146144
147145
=== modified file 'examples/server_example_tiling_window_manager.h'
--- examples/server_example_tiling_window_manager.h 2016-01-29 08:18:22 +0000
+++ examples/server_example_tiling_window_manager.h 2016-04-13 11:13:46 +0000
@@ -78,9 +78,7 @@
78 std::shared_ptr<scene::Surface> const& surface);78 std::shared_ptr<scene::Surface> const& surface);
7979
80 void generate_decorations_for(80 void generate_decorations_for(
81 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface,81 std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface);
82 SurfaceInfoMap& surface_info,
83 std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build);
8482
85private:83private:
86 static const int modifier_mask =84 static const int modifier_mask =
8785
=== modified file 'examples/server_example_window_management.cpp'
--- examples/server_example_window_management.cpp 2016-03-23 06:39:56 +0000
+++ examples/server_example_window_management.cpp 2016-04-13 11:13:46 +0000
@@ -105,10 +105,7 @@
105 }105 }
106106
107 void generate_decorations_for(107 void generate_decorations_for(
108 std::shared_ptr<ms::Session> const&,108 std::shared_ptr<ms::Session> const&, std::shared_ptr<ms::Surface> const&) override
109 std::shared_ptr<ms::Surface> const&,
110 SurfaceInfoMap&,
111 std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) override
112 {109 {
113 }110 }
114private:111private:
115112
=== modified file 'examples/server_example_window_management_info.cpp'
--- examples/server_example_window_management_info.cpp 2016-01-29 08:18:22 +0000
+++ examples/server_example_window_management_info.cpp 2016-04-13 11:13:46 +0000
@@ -19,6 +19,7 @@
19#include "server_example_window_management_info.h"19#include "server_example_window_management_info.h"
2020
21#include "mir/scene/surface.h"21#include "mir/scene/surface.h"
22#include "mir/scene/session.h"
22#include "mir/scene/surface_creation_parameters.h"23#include "mir/scene/surface_creation_parameters.h"
2324
24#include "mir/graphics/buffer.h"25#include "mir/graphics/buffer.h"
@@ -46,7 +47,9 @@
46 width_inc{params.width_inc},47 width_inc{params.width_inc},
47 height_inc{params.height_inc},48 height_inc{params.height_inc},
48 min_aspect{params.min_aspect},49 min_aspect{params.min_aspect},
49 max_aspect{params.max_aspect}50 max_aspect{params.max_aspect},
51 input_shape{params.input_shape.is_set() ? params.input_shape.value() : std::vector<Rectangle>{}},
52 streams{params.streams.is_set() ? params.streams.value() : std::vector<shell::StreamSpecification>{}}
50{53{
51 if (params.output_id != mir::graphics::DisplayConfigurationOutputId{0})54 if (params.output_id != mir::graphics::DisplayConfigurationOutputId{0})
52 output_id = params.output_id;55 output_id = params.output_id;
@@ -243,16 +246,19 @@
243 mg::BufferID back_buffer; 246 mg::BufferID back_buffer;
244};247};
245248
246void mir::examples::SurfaceInfo::init_titlebar(std::shared_ptr<scene::Surface> const& surface)249void mir::examples::SurfaceInfo::init_titlebar(Size titlebar_size)
247{250{
248 auto stream = surface->primary_buffer_stream();251 if (auto s = session.lock())
249 try252 {
250 {253 auto stream = s->get_buffer_stream(titlebar_id);
251 stream_painter = std::make_shared<AllocatingPainter>(stream, surface->size());254 try
252 }255 {
253 catch (...)256 stream_painter = std::make_shared<AllocatingPainter>(stream, titlebar_size);
254 {257 }
255 stream_painter = std::make_shared<SwappingPainter>(stream);258 catch (...)
259 {
260 stream_painter = std::make_shared<SwappingPainter>(stream);
261 }
256 }262 }
257}263}
258264
259265
=== modified file 'examples/server_example_window_management_info.h'
--- examples/server_example_window_management_info.h 2016-03-30 14:08:54 +0000
+++ examples/server_example_window_management_info.h 2016-04-13 11:13:46 +0000
@@ -63,10 +63,6 @@
63 std::weak_ptr <scene::Session> session;63 std::weak_ptr <scene::Session> session;
64 std::weak_ptr <scene::Surface> parent;64 std::weak_ptr <scene::Surface> parent;
65 std::vector <std::weak_ptr<scene::Surface>> children;65 std::vector <std::weak_ptr<scene::Surface>> children;
66 std::shared_ptr <scene::Surface> titlebar;
67 frontend::SurfaceId titlebar_id;
68 frontend::BufferStreamId titlebar_stream_id;
69 bool is_titlebar = false;
70 geometry::Width min_width;66 geometry::Width min_width;
71 geometry::Height min_height;67 geometry::Height min_height;
72 geometry::Width max_width;68 geometry::Width max_width;
@@ -76,8 +72,15 @@
76 mir::optional_value<shell::SurfaceAspectRatio> min_aspect;72 mir::optional_value<shell::SurfaceAspectRatio> min_aspect;
77 mir::optional_value<shell::SurfaceAspectRatio> max_aspect;73 mir::optional_value<shell::SurfaceAspectRatio> max_aspect;
78 mir::optional_value<graphics::DisplayConfigurationOutputId> output_id;74 mir::optional_value<graphics::DisplayConfigurationOutputId> output_id;
7975 mir::optional_value<std::vector<geometry::Rectangle>> input_shape;
80 void init_titlebar(std::shared_ptr <scene::Surface> const& surface);76 mir::optional_value<geometry::Rectangle> titlebar_input_shape;
77
78 mir::optional_value<std::vector<shell::StreamSpecification>> streams;
79 frontend::BufferStreamId titlebar_id;
80 bool has_titlebar = false;
81 bool visible_titlebar = false;
82
83 void init_titlebar(geometry::Size titlebar_size);
8184
82 void paint_titlebar(int intensity);85 void paint_titlebar(int intensity);
8386
8487
=== modified file 'include/server/mir/scene/surface_creation_parameters.h'
--- include/server/mir/scene/surface_creation_parameters.h 2016-03-29 16:30:22 +0000
+++ include/server/mir/scene/surface_creation_parameters.h 2016-04-13 11:13:46 +0000
@@ -72,6 +72,8 @@
7272
73 SurfaceCreationParameters& with_buffer_stream(frontend::BufferStreamId const& id);73 SurfaceCreationParameters& with_buffer_stream(frontend::BufferStreamId const& id);
7474
75 SurfaceCreationParameters& with_buffer_streams(std::vector<shell::StreamSpecification> const& streams);
76
75 std::string name;77 std::string name;
76 geometry::Size size;78 geometry::Size size;
77 geometry::Point top_left;79 geometry::Point top_left;
@@ -84,7 +86,6 @@
84 mir::optional_value<MirSurfaceType> type;86 mir::optional_value<MirSurfaceType> type;
85 mir::optional_value<MirOrientationMode> preferred_orientation;87 mir::optional_value<MirOrientationMode> preferred_orientation;
86 mir::optional_value<frontend::SurfaceId> parent_id;88 mir::optional_value<frontend::SurfaceId> parent_id;
87 mir::optional_value<frontend::BufferStreamId> content_id;
88 mir::optional_value<geometry::Rectangle> aux_rect;89 mir::optional_value<geometry::Rectangle> aux_rect;
89 mir::optional_value<MirEdgeAttachment> edge_attachment;90 mir::optional_value<MirEdgeAttachment> edge_attachment;
9091
9192
=== modified file 'include/server/mir/shell/surface_specification.h'
--- include/server/mir/shell/surface_specification.h 2016-03-23 06:39:56 +0000
+++ include/server/mir/shell/surface_specification.h 2016-04-13 11:13:46 +0000
@@ -45,6 +45,7 @@
45 geometry::Displacement displacement;45 geometry::Displacement displacement;
46 optional_value<geometry::Size> size;46 optional_value<geometry::Size> size;
47};47};
48bool operator==(StreamSpecification const& lhs, StreamSpecification const& rhs);
4849
49/// Specification of surface properties requested by client50/// Specification of surface properties requested by client
50struct SurfaceSpecification51struct SurfaceSpecification
5152
=== modified file 'src/server/frontend/session_mediator.cpp'
--- src/server/frontend/session_mediator.cpp 2016-04-12 14:10:00 +0000
+++ src/server/frontend/session_mediator.cpp 2016-04-13 11:13:46 +0000
@@ -287,10 +287,10 @@
287 #undef COPY_IF_SET287 #undef COPY_IF_SET
288288
289 mf::BufferStreamId buffer_stream_id;289 mf::BufferStreamId buffer_stream_id;
290 std::shared_ptr<mf::BufferStream> legacy_stream = nullptr;290 std::shared_ptr<mf::BufferStream> legacy_stream;
291 std::vector<msh::StreamSpecification> stream_spec;
291 if (request->stream_size() > 0)292 if (request->stream_size() > 0)
292 {293 {
293 std::vector<msh::StreamSpecification> stream_spec;
294 for (auto& stream : request->stream())294 for (auto& stream : request->stream())
295 {295 {
296 if (stream.has_width() && stream.has_height())296 if (stream.has_width() && stream.has_height())
@@ -310,16 +310,17 @@
310 {}});310 {}});
311 }311 }
312 }312 }
313 params.streams = std::move(stream_spec);
314 }313 }
315 else314 else
316 {315 {
317 buffer_stream_id = session->create_buffer_stream(316 buffer_stream_id = session->create_buffer_stream(
318 {params.size, params.pixel_format, params.buffer_usage});317 {params.size, params.pixel_format, params.buffer_usage});
319 legacy_stream = session->get_buffer_stream(buffer_stream_id);318 legacy_stream = session->get_buffer_stream(buffer_stream_id);
320 params.content_id = buffer_stream_id;319 stream_spec.emplace_back(msh::StreamSpecification{ {buffer_stream_id}, {0, 0}, {}});
321 }320 }
322321
322 params.streams = std::move(stream_spec);
323
323 if (request->has_min_aspect())324 if (request->has_min_aspect())
324 params.min_aspect = { request->min_aspect().width(), request->min_aspect().height()};325 params.min_aspect = { request->min_aspect().width(), request->min_aspect().height()};
325326
@@ -334,17 +335,16 @@
334 auto const surf_id = shell->create_surface(session, params, sink);335 auto const surf_id = shell->create_surface(session, params, sink);
335336
336 auto surface = session->get_surface(surf_id);337 auto surface = session->get_surface(surf_id);
337 auto stream = session->get_buffer_stream(buffer_stream_id);
338 auto const& client_size = surface->client_size();338 auto const& client_size = surface->client_size();
339 response->mutable_id()->set_value(surf_id.as_value());339 response->mutable_id()->set_value(surf_id.as_value());
340 response->set_width(client_size.width.as_uint32_t());340 response->set_width(client_size.width.as_uint32_t());
341 response->set_height(client_size.height.as_uint32_t());341 response->set_height(client_size.height.as_uint32_t());
342342
343 // TODO: Deprecate343 // TODO: Deprecate
344 response->set_pixel_format(stream->pixel_format());344 response->set_pixel_format(params.pixel_format);
345 response->set_buffer_usage(request->buffer_usage());345 response->set_buffer_usage(request->buffer_usage());
346346
347 response->mutable_buffer_stream()->set_pixel_format(stream->pixel_format());347 response->mutable_buffer_stream()->set_pixel_format(params.pixel_format);
348 response->mutable_buffer_stream()->set_buffer_usage(request->buffer_usage());348 response->mutable_buffer_stream()->set_buffer_usage(request->buffer_usage());
349349
350 if (surface->supports_input())350 if (surface->supports_input())
351351
=== modified file 'src/server/scene/application_session.cpp'
--- src/server/scene/application_session.cpp 2016-04-13 11:13:46 +0000
+++ src/server/scene/application_session.cpp 2016-04-13 11:13:46 +0000
@@ -94,19 +94,12 @@
94 //TODO: we take either the content_id or the first streams content for now.94 //TODO: we take either the content_id or the first streams content for now.
95 // Once the surface factory interface takes more than one stream,95 // Once the surface factory interface takes more than one stream,
96 // we can take all the streams as content.96 // we can take all the streams as content.
97 if (!((the_params.content_id.is_set()) ||97 if (!(the_params.streams.is_set() && the_params.streams.value().size() > 0))
98 (the_params.streams.is_set() && the_params.streams.value().size() > 0)))
99 {
100 BOOST_THROW_EXCEPTION(std::logic_error("surface must have content"));98 BOOST_THROW_EXCEPTION(std::logic_error("surface must have content"));
101 }
10299
103 auto params = the_params;100 auto params = the_params;
104101
105 mf::BufferStreamId stream_id;102 mf::BufferStreamId stream_id = params.streams.value()[0].stream_id;
106 if (params.content_id.is_set())
107 stream_id = params.content_id.value();
108 else
109 stream_id = params.streams.value()[0].stream_id;
110103
111 if (params.parent_id.is_set())104 if (params.parent_id.is_set())
112 params.parent = checked_find(the_params.parent_id.value())->second;105 params.parent = checked_find(the_params.parent_id.value())->second;
@@ -116,15 +109,8 @@
116 buffer_stream->resize(params.size);109 buffer_stream->resize(params.size);
117110
118 std::list<StreamInfo> streams;111 std::list<StreamInfo> streams;
119 if (the_params.content_id.is_set())112 for (auto& stream : params.streams.value())
120 {113 streams.push_back({checked_find(stream.stream_id)->second, stream.displacement, stream.size});
121 streams.push_back({checked_find(the_params.content_id.value())->second, {0,0}, {}});
122 }
123 else
124 {
125 for (auto& stream : params.streams.value())
126 streams.push_back({checked_find(stream.stream_id)->second, stream.displacement, stream.size});
127 }
128114
129 auto surface = surface_factory->create_surface(streams, params);115 auto surface = surface_factory->create_surface(streams, params);
130116
131117
=== modified file 'src/server/scene/surface_creation_parameters.cpp'
--- src/server/scene/surface_creation_parameters.cpp 2016-01-29 08:18:22 +0000
+++ src/server/scene/surface_creation_parameters.cpp 2016-04-13 11:13:46 +0000
@@ -130,7 +130,14 @@
130130
131ms::SurfaceCreationParameters& ms::SurfaceCreationParameters::with_buffer_stream(mf::BufferStreamId const& id)131ms::SurfaceCreationParameters& ms::SurfaceCreationParameters::with_buffer_stream(mf::BufferStreamId const& id)
132{132{
133 content_id = id;133 streams = std::vector<shell::StreamSpecification>{ {id, {}, {}} };
134 return *this;
135}
136
137ms::SurfaceCreationParameters& ms::SurfaceCreationParameters::with_buffer_streams(
138 std::vector<shell::StreamSpecification> const& s)
139{
140 streams = s;
134 return *this;141 return *this;
135}142}
136143
@@ -149,7 +156,7 @@
149 lhs.type == rhs.type &&156 lhs.type == rhs.type &&
150 lhs.preferred_orientation == rhs.preferred_orientation &&157 lhs.preferred_orientation == rhs.preferred_orientation &&
151 lhs.parent_id == rhs.parent_id &&158 lhs.parent_id == rhs.parent_id &&
152 lhs.content_id == rhs.content_id;159 lhs.streams == rhs.streams;
153}160}
154161
155bool ms::operator!=(162bool ms::operator!=(
156163
=== modified file 'src/server/shell/surface_specification.cpp'
--- src/server/shell/surface_specification.cpp 2015-10-15 04:20:44 +0000
+++ src/server/shell/surface_specification.cpp 2016-04-13 11:13:46 +0000
@@ -47,3 +47,10 @@
47 !parent.is_set() &&47 !parent.is_set() &&
48 !input_shape.is_set();48 !input_shape.is_set();
49}49}
50
51bool msh::operator==(StreamSpecification const& lhs, StreamSpecification const& rhs)
52{
53 return lhs.stream_id == rhs.stream_id &&
54 lhs.displacement == rhs.displacement &&
55 lhs.size == rhs.size;
56}
5057
=== modified file 'src/server/symbols.map'
--- src/server/symbols.map 2016-03-28 23:15:00 +0000
+++ src/server/symbols.map 2016-04-13 11:13:46 +0000
@@ -290,6 +290,7 @@
290 mir::shell::ShellWrapper::start_prompt_session_for*;290 mir::shell::ShellWrapper::start_prompt_session_for*;
291 mir::shell::ShellWrapper::stop_prompt_session*;291 mir::shell::ShellWrapper::stop_prompt_session*;
292 mir::shell::ShellWrapper::surface_at*;292 mir::shell::ShellWrapper::surface_at*;
293 mir::shell::StreamSpecification::operator*;
293 mir::shell::SurfaceReadyObserver::frame_posted*;294 mir::shell::SurfaceReadyObserver::frame_posted*;
294 mir::shell::SurfaceReadyObserver::?SurfaceReadyObserver*;295 mir::shell::SurfaceReadyObserver::?SurfaceReadyObserver*;
295 mir::shell::SurfaceReadyObserver::SurfaceReadyObserver*;296 mir::shell::SurfaceReadyObserver::SurfaceReadyObserver*;

Subscribers

People subscribed via source and target branches