Mir

Merge lp:mir/0.22 into lp:mir/ubuntu

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: 3481
Merged at revision: 1273
Proposed branch: lp:mir/0.22
Merge into: lp:mir/ubuntu
Diff against target: 22899 lines (+8398/-3474)
369 files modified
3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h (+0/-6)
3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp (+0/-29)
CMakeLists.txt (+1/-1)
cmake/FindLibHardware.cmake (+1/-1)
cmake/MirCommon.cmake (+1/-1)
cross-compile-chroot.sh (+6/-3)
debian/changelog (+61/-0)
debian/control (+9/-9)
debian/libmirserver39.install (+1/-1)
debian/mir-platform-graphics-android9.install (+1/-1)
debian/mir-platform-graphics-mesa-kms9.install (+1/-1)
debian/mir-platform-graphics-mesa-x9.install (+1/-1)
debian/mir-test-tools.install (+1/-0)
debian/mir-utils.install (+1/-0)
doc/dso_versioning_guide.md (+6/-8)
examples/CMakeLists.txt (+1/-7)
examples/render_surfaces.cpp (+7/-1)
examples/scroll.cpp (+17/-166)
examples/server_example.cpp (+6/-1)
examples/server_example_canonical_window_manager.cpp (+23/-8)
examples/server_example_input_device_config.cpp (+28/-16)
examples/server_example_input_filter.cpp (+38/-3)
examples/server_example_test_client.cpp (+7/-3)
examples/server_example_window_management_info.h (+1/-0)
examples/target.c (+56/-15)
include/client/mir_toolkit/client_types.h (+37/-2)
include/client/mir_toolkit/events/event.h (+1/-1)
include/client/mir_toolkit/mir_client_library.h (+1/-0)
include/client/mir_toolkit/mir_connection.h (+64/-0)
include/client/mir_toolkit/mir_display_configuration.h (+71/-0)
include/client/mir_toolkit/mir_error.h (+55/-0)
include/client/mir_toolkit/mir_screencast.h (+108/-5)
include/common/mir/optional_value.h (+1/-1)
include/common/mir_toolkit/common.h (+8/-0)
include/platform/mir/graphics/display_buffer.h (+11/-0)
include/platform/mir/graphics/display_configuration.h (+2/-1)
include/renderers/gl/mir/renderer/gl/render_target.h (+5/-1)
include/server/mir/frontend/session.h (+2/-0)
include/server/mir/frontend/session_mediator_report.h (+4/-2)
include/server/mir/input/input_manager.h (+0/-7)
include/server/mir/scene/session.h (+1/-2)
include/server/mir/scene/surface.h (+2/-0)
include/server/mir/scene/surface_creation_parameters.h (+1/-0)
include/server/mir/scene/surface_factory.h (+3/-1)
include/server/mir/shell/surface_specification.h (+1/-0)
include/server/mir/time/alarm_factory.h (+1/-1)
include/test/mir/test/display_config_matchers.h (+1/-0)
include/test/mir/test/doubles/null_display_buffer.h (+1/-0)
include/test/mir/test/doubles/stub_session.h (+1/-1)
include/test/mir/test/event_matchers.h (+8/-3)
include/test/mir/test/signal.h (+13/-0)
include/test/mir/test/wait_condition.h (+0/-84)
include/test/mir_test_framework/interprocess_client_server_test.h (+2/-0)
include/test/mir_test_framework/process.h (+3/-0)
playground/demo-shell/demo_compositor.cpp (+1/-1)
playground/mir_demo_client_prerendered_frames.c (+1/-6)
src/client/CMakeLists.txt (+4/-0)
src/client/buffer.cpp (+29/-7)
src/client/buffer.h (+5/-0)
src/client/buffer_stream.cpp (+43/-16)
src/client/buffer_stream.h (+2/-1)
src/client/buffer_vault.cpp (+130/-49)
src/client/buffer_vault.h (+25/-19)
src/client/client_buffer_depository.cpp (+8/-1)
src/client/client_buffer_depository.h (+3/-0)
src/client/display_configuration_api.cpp (+8/-0)
src/client/event.cpp (+37/-42)
src/client/events/CMakeLists.txt (+0/-1)
src/client/events/event_builders.cpp (+144/-129)
src/client/events/make_empty_event.cpp (+0/-42)
src/client/events/make_empty_event.h (+0/-32)
src/client/events/serialization.cpp (+2/-81)
src/client/input/android/event_conversion_helpers.cpp (+9/-8)
src/client/input/input_event.cpp (+49/-99)
src/client/input/xkb_mapper.cpp (+6/-6)
src/client/mir_connection.cpp (+76/-2)
src/client/mir_connection.h (+10/-1)
src/client/mir_connection_api.cpp (+55/-1)
src/client/mir_error.cpp (+35/-0)
src/client/mir_error.h (+37/-0)
src/client/mir_error_api.cpp (+30/-0)
src/client/mir_screencast.cpp (+128/-48)
src/client/mir_screencast.h (+30/-11)
src/client/mir_screencast_api.cpp (+79/-44)
src/client/presentation_chain.cpp (+6/-4)
src/client/rpc/mir_display_server.cpp (+14/-7)
src/client/rpc/mir_display_server.h (+8/-4)
src/client/rpc/mir_protobuf_rpc_channel.cpp (+7/-7)
src/client/screencast_stream.cpp (+28/-30)
src/client/screencast_stream.h (+2/-2)
src/client/symbols.map (+28/-0)
src/common/CMakeLists.txt (+2/-0)
src/common/events/CMakeLists.txt (+40/-0)
src/common/events/close_surface_event.cpp (+34/-0)
src/common/events/event.cpp (+237/-0)
src/common/events/input_configuration_event.cpp (+54/-0)
src/common/events/input_event.cpp (+47/-0)
src/common/events/keyboard_event.cpp (+105/-0)
src/common/events/keymap_event.cpp (+164/-0)
src/common/events/motion_event.cpp (+340/-0)
src/common/events/orientation_event.cpp (+44/-0)
src/common/events/prompt_session_event.cpp (+34/-0)
src/common/events/resize_event.cpp (+54/-0)
src/common/events/surface_event.cpp (+54/-0)
src/common/events/surface_output_event.cpp (+74/-0)
src/common/symbols.map (+135/-0)
src/cookie/authority.cpp (+12/-51)
src/include/common/mir/client_visible_error.h (+55/-0)
src/include/common/mir/events/close_surface_event.h (+35/-0)
src/include/common/mir/events/event.h (+133/-0)
src/include/common/mir/events/event_private.h (+13/-173)
src/include/common/mir/events/input_configuration_event.h (+46/-0)
src/include/common/mir/events/input_event.h (+39/-0)
src/include/common/mir/events/keyboard_event.h (+69/-0)
src/include/common/mir/events/keymap_event.h (+60/-0)
src/include/common/mir/events/motion_event.h (+151/-0)
src/include/common/mir/events/orientation_event.h (+39/-0)
src/include/common/mir/events/prompt_session_event.h (+35/-0)
src/include/common/mir/events/resize_event.h (+43/-0)
src/include/common/mir/events/surface_event.h (+43/-0)
src/include/common/mir/events/surface_output_event.h (+54/-0)
src/include/common/mir/protobuf/display_server.h (+8/-4)
src/include/server/mir/compositor/buffer_stream.h (+1/-1)
src/include/server/mir/compositor/frame_dropping_policy_factory.h (+1/-1)
src/include/server/mir/compositor/renderer.h (+3/-1)
src/include/server/mir/frontend/client_buffers.h (+0/-1)
src/include/server/mir/frontend/display_changer.h (+7/-0)
src/include/server/mir/frontend/screencast.h (+3/-1)
src/include/server/mir/frontend/template_protobuf_message_processor.h (+11/-0)
src/include/server/mir/glib_main_loop.h (+1/-1)
src/include/server/mir/lockable_callback_wrapper.h (+3/-3)
src/platforms/CMakeLists.txt (+2/-2)
src/platforms/android/server/device_quirks.cpp (+7/-3)
src/platforms/android/server/display_buffer.cpp (+9/-0)
src/platforms/android/server/display_buffer.h (+2/-0)
src/platforms/android/server/display_configuration.cpp (+1/-1)
src/platforms/android/server/display_resource_factory.h (+1/-0)
src/platforms/android/server/hwc_layers.cpp (+2/-0)
src/platforms/android/server/hwc_loggers.cpp (+1/-0)
src/platforms/android/server/resource_factory.cpp (+1/-0)
src/platforms/evdev/libinput_device.cpp (+4/-5)
src/platforms/mesa/server/kms/display_buffer.cpp (+9/-0)
src/platforms/mesa/server/kms/display_buffer.h (+2/-0)
src/platforms/mesa/server/kms/kms_page_flipper.h (+2/-2)
src/platforms/mesa/server/kms/real_kms_output.h (+16/-16)
src/platforms/mesa/server/x11/graphics/display.cpp (+27/-20)
src/platforms/mesa/server/x11/graphics/display.h (+2/-2)
src/platforms/mesa/server/x11/graphics/display_buffer.cpp (+9/-0)
src/platforms/mesa/server/x11/graphics/display_buffer.h (+2/-0)
src/protobuf/CMakeLists.txt (+4/-3)
src/protobuf/mir_protobuf.proto (+29/-0)
src/protobuf/symbols.map (+25/-0)
src/renderers/gl/renderer.cpp (+63/-22)
src/renderers/gl/renderer.h (+6/-4)
src/server/CMakeLists.txt (+3/-1)
src/server/compositor/CMakeLists.txt (+2/-0)
src/server/compositor/buffer_bundle.h (+8/-0)
src/server/compositor/buffer_map.cpp (+0/-7)
src/server/compositor/buffer_map.h (+0/-1)
src/server/compositor/buffer_queue.cpp (+18/-10)
src/server/compositor/buffer_queue.h (+5/-1)
src/server/compositor/buffer_stream_surfaces.cpp (+3/-3)
src/server/compositor/buffer_stream_surfaces.h (+1/-1)
src/server/compositor/compositing_screencast.cpp (+52/-57)
src/server/compositor/compositing_screencast.h (+8/-4)
src/server/compositor/default_display_buffer_compositor.cpp (+1/-1)
src/server/compositor/multi_monitor_arbiter.h (+1/-7)
src/server/compositor/screencast_display_buffer.cpp (+82/-17)
src/server/compositor/screencast_display_buffer.h (+54/-10)
src/server/compositor/stream.cpp (+23/-6)
src/server/compositor/stream.h (+5/-2)
src/server/compositor/timeout_frame_dropping_policy_factory.cpp (+5/-5)
src/server/compositor/timeout_frame_dropping_policy_factory.h (+1/-1)
src/server/frontend/CMakeLists.txt (+1/-0)
src/server/frontend/authorizing_display_changer.cpp (+51/-0)
src/server/frontend/authorizing_display_changer.h (+8/-0)
src/server/frontend/buffer_stream_tracker.cpp (+24/-0)
src/server/frontend/buffer_stream_tracker.h (+7/-0)
src/server/frontend/protobuf_message_processor.cpp (+15/-5)
src/server/frontend/screencast_buffer_tracker.cpp (+41/-0)
src/server/frontend/screencast_buffer_tracker.h (+67/-0)
src/server/frontend/session_mediator.cpp (+152/-53)
src/server/frontend/session_mediator.h (+12/-5)
src/server/frontend/unauthorized_screencast.cpp (+3/-3)
src/server/frontend/unauthorized_screencast.h (+5/-3)
src/server/glib_main_loop.cpp (+5/-5)
src/server/graphics/nested/display_buffer.cpp (+17/-6)
src/server/graphics/nested/display_buffer.h (+2/-0)
src/server/graphics/offscreen/display_buffer.cpp (+9/-0)
src/server/graphics/offscreen/display_buffer.h (+2/-0)
src/server/input/CMakeLists.txt (+2/-0)
src/server/input/android/CMakeLists.txt (+0/-2)
src/server/input/android/input_sender.cpp (+3/-3)
src/server/input/channel.cpp (+45/-30)
src/server/input/channel.h (+14/-25)
src/server/input/channel_factory.cpp (+5/-6)
src/server/input/channel_factory.h (+10/-12)
src/server/input/default_configuration.cpp (+11/-6)
src/server/input/default_event_builder.cpp (+6/-2)
src/server/input/default_input_manager.cpp (+5/-32)
src/server/input/default_input_manager.h (+1/-7)
src/server/input/key_repeat_dispatcher.cpp (+18/-25)
src/server/input/key_repeat_dispatcher.h (+4/-4)
src/server/input/null_input_manager.h (+0/-3)
src/server/input/seat_input_device_tracker.cpp (+11/-9)
src/server/input/seat_input_device_tracker.h (+4/-1)
src/server/input/surface_input_dispatcher.cpp (+15/-13)
src/server/input/validator.cpp (+12/-13)
src/server/lockable_callback_wrapper.cpp (+4/-4)
src/server/report/logging/session_mediator_report.cpp (+10/-5)
src/server/report/logging/session_mediator_report.h (+4/-2)
src/server/report/logging/shell_report.cpp (+51/-22)
src/server/report/logging/shell_report.h (+28/-28)
src/server/report/lttng/session_mediator_report.cpp (+2/-1)
src/server/report/lttng/session_mediator_report.h (+2/-1)
src/server/report/lttng/session_mediator_report_tp.h (+2/-0)
src/server/report/null/session_mediator_report.cpp (+8/-4)
src/server/report/null/session_mediator_report.h (+4/-2)
src/server/scene/application_session.cpp (+42/-26)
src/server/scene/application_session.h (+3/-1)
src/server/scene/basic_surface.cpp (+35/-20)
src/server/scene/basic_surface.h (+2/-2)
src/server/scene/default_configuration.cpp (+2/-1)
src/server/scene/mediating_display_changer.cpp (+63/-2)
src/server/scene/mediating_display_changer.h (+18/-1)
src/server/scene/session_manager.cpp (+1/-1)
src/server/scene/surface_allocator.cpp (+3/-5)
src/server/scene/surface_allocator.h (+1/-1)
src/server/server.cpp (+1/-2)
src/server/shell/canonical_window_manager.cpp (+13/-5)
src/server/symbols.map (+44/-49)
src/utils/CMakeLists.txt (+3/-0)
src/utils/out.c (+1/-0)
src/utils/run.cpp (+143/-0)
tests/CMakeLists.txt (+1/-1)
tests/acceptance-tests/server_signal_handling.cpp (+8/-2)
tests/acceptance-tests/test_client_cookie.cpp (+5/-5)
tests/acceptance-tests/test_client_focus_notification.cpp (+1/-1)
tests/acceptance-tests/test_client_input.cpp (+105/-42)
tests/acceptance-tests/test_client_logging.cpp (+0/-1)
tests/acceptance-tests/test_client_scaling.cpp (+0/-9)
tests/acceptance-tests/test_client_screencast.cpp (+10/-12)
tests/acceptance-tests/test_client_surface_visibility.cpp (+83/-55)
tests/acceptance-tests/test_client_surfaces.cpp (+5/-5)
tests/acceptance-tests/test_custom_input_dispatcher.cpp (+5/-5)
tests/acceptance-tests/test_display_configuration.cpp (+4/-4)
tests/acceptance-tests/test_input_device_hub.cpp (+6/-6)
tests/acceptance-tests/test_latency.cpp (+11/-15)
tests/acceptance-tests/test_nested_input.cpp (+10/-9)
tests/acceptance-tests/test_nested_mir.cpp (+101/-99)
tests/acceptance-tests/test_new_display_configuration.cpp (+210/-4)
tests/acceptance-tests/test_server_shutdown.cpp (+5/-5)
tests/acceptance-tests/test_server_startup.cpp (+1/-1)
tests/acceptance-tests/test_session_mediator_report.cpp (+2/-1)
tests/acceptance-tests/test_surface_raise.cpp (+5/-5)
tests/acceptance-tests/throwback/test_client_cursor_api.cpp (+15/-15)
tests/acceptance-tests/throwback/test_client_library_errors.cpp (+21/-6)
tests/acceptance-tests/throwback/test_presentation_chain.cpp (+1/-2)
tests/include/mir/test/death.h (+49/-0)
tests/include/mir/test/doubles/fake_alarm_factory.h (+1/-1)
tests/include/mir/test/doubles/mock_buffer_bundle.h (+1/-0)
tests/include/mir/test/doubles/mock_buffer_stream.h (+2/-1)
tests/include/mir/test/doubles/mock_display_buffer.h (+1/-0)
tests/include/mir/test/doubles/mock_display_changer.h (+4/-0)
tests/include/mir/test/doubles/mock_frame_dropping_policy_factory.h (+11/-5)
tests/include/mir/test/doubles/mock_gl_display_buffer.h (+1/-0)
tests/include/mir/test/doubles/mock_input_manager.h (+0/-1)
tests/include/mir/test/doubles/mock_main_loop.h (+6/-1)
tests/include/mir/test/doubles/mock_renderer.h (+1/-1)
tests/include/mir/test/doubles/mock_scene_session.h (+2/-1)
tests/include/mir/test/doubles/mock_screencast.h (+4/-2)
tests/include/mir/test/doubles/mock_surface.h (+4/-2)
tests/include/mir/test/doubles/mock_timer.h (+1/-1)
tests/include/mir/test/doubles/null_display_changer.h (+11/-0)
tests/include/mir/test/doubles/null_screencast.h (+3/-1)
tests/include/mir/test/doubles/stub_buffer_stream.h (+1/-1)
tests/include/mir/test/doubles/stub_display_server.h (+8/-0)
tests/include/mir/test/doubles/stub_frame_dropping_policy_factory.h (+1/-1)
tests/include/mir/test/doubles/stub_gl_display_buffer.h (+1/-0)
tests/include/mir/test/doubles/stub_renderer.h (+3/-11)
tests/include/mir/test/doubles/stub_surface_factory.h (+1/-1)
tests/include/mir/test/stub_server_tool.h (+6/-6)
tests/include/mir/test/test_protobuf_client.h (+6/-6)
tests/integration-tests/compositor/test_buffer_stream.cpp (+1/-1)
tests/integration-tests/input/test_cursor_listener.cpp (+4/-4)
tests/integration-tests/session_management.cpp (+7/-2)
tests/integration-tests/surface_composition.cpp (+5/-4)
tests/integration-tests/test_buffer_scheduling.cpp (+38/-5)
tests/integration-tests/test_client_screencast.cpp (+68/-7)
tests/integration-tests/test_display_server_main_loop_events.cpp (+4/-4)
tests/integration-tests/test_error_reporting.cpp (+1/-1)
tests/integration-tests/test_exchange_buffer.cpp (+1/-0)
tests/integration-tests/test_protobuf.cpp (+7/-7)
tests/integration-tests/test_protobuf.proto (+7/-1)
tests/integration-tests/test_server_client_types.cpp (+2/-0)
tests/integration-tests/test_session.cpp (+11/-6)
tests/integration-tests/test_surface_stack_with_compositor.cpp (+13/-9)
tests/integration-tests/test_surfaceloop.cpp (+5/-5)
tests/mir_test_doubles/fake_alarm_factory.cpp (+1/-1)
tests/mir_test_doubles/mock_frame_dropping_policy_factory.cpp (+3/-3)
tests/mir_test_doubles/mock_timer.cpp (+12/-11)
tests/mir_test_doubles/mock_x11.cpp (+4/-2)
tests/mir_test_doubles/test_protobuf_client.cpp (+11/-12)
tests/mir_test_framework/input_testing_server_options.cpp (+5/-5)
tests/mir_test_framework/interprocess_client_server_test.cpp (+11/-0)
tests/mir_test_framework/process.cpp (+5/-0)
tests/mir_test_framework/stub_session.cpp (+1/-1)
tests/privileged-tests/test_input_events.cpp (+5/-5)
tests/test-clients/CMakeLists.txt (+2/-0)
tests/test-clients/impolite-shutdown/CMakeLists.txt (+15/-0)
tests/test-clients/impolite-shutdown/scroll.cpp (+198/-0)
tests/unit-tests/client/CMakeLists.txt (+1/-0)
tests/unit-tests/client/input/test_android_input_receiver.cpp (+34/-41)
tests/unit-tests/client/input/test_xkb_mapper.cpp (+1/-1)
tests/unit-tests/client/test_buffer_vault.cpp (+161/-100)
tests/unit-tests/client/test_client_mir_error.cpp (+42/-0)
tests/unit-tests/client/test_event_distributor.cpp (+15/-19)
tests/unit-tests/client/test_mir_buffer.cpp (+18/-6)
tests/unit-tests/client/test_mir_screencast.cpp (+55/-65)
tests/unit-tests/compositor/test_buffer_queue.cpp (+31/-0)
tests/unit-tests/compositor/test_buffer_stream.cpp (+1/-1)
tests/unit-tests/compositor/test_client_buffers.cpp (+3/-34)
tests/unit-tests/compositor/test_compositing_screencast.cpp (+98/-21)
tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+11/-4)
tests/unit-tests/compositor/test_screencast_display_buffer.cpp (+84/-38)
tests/unit-tests/compositor/test_stream.cpp (+5/-8)
tests/unit-tests/compositor/test_temporary_buffers.cpp (+1/-0)
tests/unit-tests/compositor/test_timeout_frame_dropping_policy.cpp (+8/-8)
tests/unit-tests/dispatch/test_threaded_dispatcher.cpp (+24/-6)
tests/unit-tests/frontend/test_authorizing_display_changer.cpp (+40/-0)
tests/unit-tests/frontend/test_protobuf_surface_apis.cpp (+1/-1)
tests/unit-tests/frontend/test_published_socket_connector.cpp (+13/-16)
tests/unit-tests/frontend/test_session_mediator.cpp (+156/-130)
tests/unit-tests/graphics/android/hwc_struct_helpers.cpp (+1/-0)
tests/unit-tests/graphics/android/hwc_struct_helpers.h (+3/-0)
tests/unit-tests/graphics/android/test_display_group.cpp (+1/-0)
tests/unit-tests/graphics/android/test_hwc_layers.cpp (+2/-0)
tests/unit-tests/graphics/android/test_resource_factory.cpp (+17/-1)
tests/unit-tests/graphics/mesa/kms/test_real_kms_output.cpp (+2/-2)
tests/unit-tests/graphics/offscreen/test_offscreen_display.cpp (+1/-0)
tests/unit-tests/input/CMakeLists.txt (+1/-0)
tests/unit-tests/input/android/CMakeLists.txt (+0/-1)
tests/unit-tests/input/android/test_android_communication_package.cpp (+4/-5)
tests/unit-tests/input/android/test_android_input_sender.cpp (+2/-3)
tests/unit-tests/input/android/test_input_consumer.cpp (+3/-2)
tests/unit-tests/input/evdev/test_libinput_device.cpp (+14/-0)
tests/unit-tests/input/test_input_channel_factory.cpp (+6/-6)
tests/unit-tests/input/test_input_event.cpp (+45/-53)
tests/unit-tests/input/test_key_repeat_dispatcher.cpp (+3/-4)
tests/unit-tests/input/test_seat_input_device_tracker.cpp (+17/-0)
tests/unit-tests/input/test_surface_input_dispatcher.cpp (+3/-3)
tests/unit-tests/input/test_validator.cpp (+34/-34)
tests/unit-tests/scene/test_abstract_shell.cpp (+48/-23)
tests/unit-tests/scene/test_application_session.cpp (+133/-107)
tests/unit-tests/scene/test_basic_surface.cpp (+44/-69)
tests/unit-tests/scene/test_mediating_display_changer.cpp (+180/-4)
tests/unit-tests/scene/test_session_manager.cpp (+6/-2)
tests/unit-tests/scene/test_surface.cpp (+6/-11)
tests/unit-tests/scene/test_surface_impl.cpp (+24/-12)
tests/unit-tests/scene/test_surface_stack.cpp (+78/-89)
tests/unit-tests/scene/test_threaded_snapshot_strategy.cpp (+7/-7)
tests/unit-tests/test_fatal.cpp (+7/-5)
tests/unit-tests/test_glib_main_loop.cpp (+5/-5)
tests/unit-tests/test_lockable_callback.cpp (+5/-5)
tests/unit-tests/test_mir_cookie.cpp (+2/-2)
tests/unit-tests/test_thread_name.cpp (+7/-7)
tests/unit-tests/test_thread_safe_list.cpp (+8/-8)
tests/unit-tests/test_udev_wrapper.cpp (+5/-4)
tools/valgrind_suppressions_glibc_2.23 (+60/-48)
To merge this branch: bzr merge lp:mir/0.22
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir CI Bot continuous-integration Approve
Daniel van Vugt Approve
Cemil Azizoglu (community) Approve
Review via email: mp+292571@code.launchpad.net

Commit message

Mir 0.22 release

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

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

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

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

PS Jenkins bot is alive?

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

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

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

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

lgtm

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3476
https://mir-jenkins.ubuntu.com/job/mir-ubuntu-ci/23/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/917/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/956
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/947
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/947
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/927/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/927/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/927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/927/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/927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/927/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/927/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The mir-ci-bot failure is bug 1556045, which we marked as fixed in 0.22.0. I guess it's not.

The PS Jenkins failure is weird. But isn't PS Jenkins retired?
ERROR: Dynamic exception type: St12system_error
std::exception::what: Enable multithreading to use std::thread: Operation not permitted

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

I wonder if this could break some C++ ABI that passes a MirEvent pointer/ref as a parameter?

diff -r 0.21/include/client/mir_toolkit/events/event.h 0.22/include/client/mir_toolkit/events/event.h
63c63
< typedef union MirEvent MirEvent;
---
> typedef struct MirEvent MirEvent;

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

^^^
Changing MirEvent to a struct may represent a platform ABI break too:

include/platform/mir/input/event_builder.h: virtual void add_touch(MirEvent& event, MirTouchId touch_id, MirTouchAction action, MirTouchTooltype tooltype,
include/platform/mir/input/input_sink.h: virtual void handle_input(MirEvent& event) = 0;

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

Nope, apparently not an ABI break. The typedef apparently means users of MirEvent& are not sensitive to its actual type changing, which you can see here:

   _ZN3mir6events9add_touchER8MirEventi14MirTouchAction16MirTouchTooltypeffffff
   mir::events::add_touch(MirEvent&, int, MirTouchAction, MirTouchTooltype, float, float, float, float, float, float)

Both Mir 0.21 and 0.22 view MirEvent& as the same thing.

Incidentally, 'struct MirEvent' is still private. So referring to a reference of that type in libmirclient's ABI doesn't seem quite right. We maintain ABI safety only by:
   ptr = created_opaquely
   add_touch(*ptr, ...)
So it should not be a reference (in future when we do eventually break the ABI).

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

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

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

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h'
2--- 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2016-01-29 08:18:22 +0000
3+++ 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2016-04-27 09:08:17 +0000
4@@ -141,12 +141,6 @@
5 public:
6 InputChannel(const String8& name, int fd);
7
8- /* Creates a pair of input channels.
9- *
10- * Returns OK on success.
11- */
12- static status_t openInputFdPair(int& server_fd, int& client_fd);
13-
14 inline String8 getName() const { return mName; }
15 inline int getFd() const { return mFd; }
16
17
18=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp'
19--- 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2016-03-16 06:59:01 +0000
20+++ 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2016-04-27 09:08:17 +0000
21@@ -32,12 +32,6 @@
22
23 namespace android {
24
25-// Socket buffer size. The default is typically about 128KB, which is much larger than
26-// we really need. So we make it smaller. It just needs to be big enough to hold
27-// a few dozen large multi-finger motion events in the case where an application gets
28-// behind processing touches.
29-static const size_t SOCKET_BUFFER_SIZE = 32 * 1024;
30-
31 // Nanoseconds per milliseconds.
32 static constexpr const std::chrono::nanoseconds NANOS_PER_MS = std::chrono::nanoseconds(1000000);
33
34@@ -117,29 +111,6 @@
35 #endif
36 }
37
38-status_t InputChannel::openInputFdPair(int& server_fd, int& client_fd) {
39- int sockets[2];
40- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
41- status_t result = -errno;
42- ALOGE("InputChannel ~ Could not create socket pair. errno=%d",
43- errno);
44- server_fd = client_fd = 0;
45-
46- return result;
47- }
48-
49- int bufferSize = SOCKET_BUFFER_SIZE;
50- setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
51- setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
52- setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
53- setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
54-
55- server_fd = sockets[0];
56- client_fd = sockets[1];
57-
58- return OK;
59-}
60-
61 status_t InputChannel::sendMessage(const InputMessage* msg) {
62 size_t msgLength = msg->size();
63 ssize_t nWrite;
64
65=== modified file 'CMakeLists.txt'
66--- CMakeLists.txt 2016-03-25 15:08:27 +0000
67+++ CMakeLists.txt 2016-04-27 09:08:17 +0000
68@@ -28,7 +28,7 @@
69 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
70
71 set(MIR_VERSION_MAJOR 0)
72-set(MIR_VERSION_MINOR 21)
73+set(MIR_VERSION_MINOR 22)
74 set(MIR_VERSION_PATCH 0)
75
76 add_definitions(-DMIR_VERSION_MAJOR=${MIR_VERSION_MAJOR})
77
78=== modified file 'cmake/FindLibHardware.cmake'
79--- cmake/FindLibHardware.cmake 2016-03-16 06:59:01 +0000
80+++ cmake/FindLibHardware.cmake 2016-04-27 09:08:17 +0000
81@@ -7,7 +7,7 @@
82 INCLUDE(FindPackageHandleStandardArgs)
83
84 find_package( PkgConfig )
85-pkg_search_module(ANDROID_HEADERS REQUIRED android-headers)
86+pkg_search_module(ANDROID_HEADERS REQUIRED android-headers-23)
87 set(LIBHARDWARE_INCLUDE_DIRS ${ANDROID_HEADERS_INCLUDE_DIRS})
88
89 find_library(LIBHARDWARE_LIBRARY
90
91=== modified file 'cmake/MirCommon.cmake'
92--- cmake/MirCommon.cmake 2016-03-16 06:59:01 +0000
93+++ cmake/MirCommon.cmake 2016-04-27 09:08:17 +0000
94@@ -28,7 +28,7 @@
95 set(VALGRIND_CMD ${VALGRIND_CMD} "--track-fds=yes")
96 set(VALGRIND_CMD ${VALGRIND_CMD} "--num-callers=128")
97 set(VALGRIND_CMD ${VALGRIND_CMD} "--suppressions=${CMAKE_SOURCE_DIR}/tools/valgrind_suppressions_generic")
98- set(VALGRIND_CMD ${VALGRIND_CMD} "--suppressions=${CMAKE_SOURCE_DIR}/tools/valgrind_suppressions_glibc_2.21")
99+ set(VALGRIND_CMD ${VALGRIND_CMD} "--suppressions=${CMAKE_SOURCE_DIR}/tools/valgrind_suppressions_glibc_2.23")
100 if (TARGET_ARCH STREQUAL "arm-linux-gnueabihf")
101 set(VALGRIND_CMD ${VALGRIND_CMD} "--suppressions=${CMAKE_SOURCE_DIR}/tools/valgrind_suppressions_armhf")
102 endif()
103
104=== modified file 'cross-compile-chroot.sh'
105--- cross-compile-chroot.sh 2016-03-16 06:59:01 +0000
106+++ cross-compile-chroot.sh 2016-04-27 09:08:17 +0000
107@@ -26,10 +26,10 @@
108 dist=vivid
109 clean=0
110 update_build_dir=0
111-
112+enable_tests=yes
113 target_arch=armhf
114
115-while getopts "a:cd:hu" OPTNAME
116+while getopts "a:cd:hut:" OPTNAME
117 do
118 case $OPTNAME in
119 a )
120@@ -55,6 +55,9 @@
121 usage
122 exit 1;
123 ;;
124+ t )
125+ enable_tests=${OPTARG}
126+ ;;
127 * )
128 echo "invalid option specified"
129 usage
130@@ -162,7 +165,7 @@
131 echo "Using PKG_CONFIG_PATH: $PKG_CONFIG_PATH"
132 echo "Using PKG_CONFIG_EXECUTABLE: $PKG_CONFIG_EXECUTABLE"
133 cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/LinuxCrossCompile.cmake \
134- -DMIR_PLATFORM=${mir_platform} \
135+ -DMIR_PLATFORM=${mir_platform} -DMIR_ENABLE_TESTS=${enable_tests}\
136 ..
137
138 make -j${NUM_JOBS} $@
139
140=== modified file 'debian/changelog'
141--- debian/changelog 2016-03-30 00:23:20 +0000
142+++ debian/changelog 2016-04-27 09:08:17 +0000
143@@ -1,3 +1,64 @@
144+mir (0.22.0) UNRELEASED; urgency=medium
145+
146+ * New upstream release 0.22.0 (https://launchpad.net/mir/+milestone/0.22.0)
147+ - ABI summary: Only servers need rebuilding
148+ . mirclient ABI unchanged at 9
149+ . mirserver ABI bumped to 39
150+ . mircommon ABI unchanged at 5
151+ . mirplatform ABI unchanged at 11
152+ . mirprotobuf ABI unchanged at 3
153+ . mirplatformgraphics ABI bumped to 9
154+ . mirclientplatform ABI unchanged at 5
155+ . mirinputplatform ABI unchanged at 5
156+ - Enhancements:
157+ . New screencast creation API which allows a client to specify
158+ number of capture buffers and mirroring mode
159+ . HWC 1.5 support for android based platforms
160+ - Bug fixes:
161+ . [regression] Black screen: Mir hangs and then crashes on startup/login
162+ due to reading from /dev/random (LP: #1536662)
163+ . CI test failures on xenial amd64 due to valgrind errors following system
164+ upgrade to ld-2.23 (LP: #1560415)
165+ . [regression] failure in CI on ThreadedDispatcherSignalTest.keeps_
166+ dispatching_after_signal_interruption under Valgrind (LP: #1499229)
167+ . [regression] Cursor mostly does not move at all in response to slow
168+ mouse movement, but then sometimes jumps (LP: #1528109)
169+ . Sometimes devices don't suspend - display turns back on immediately
170+ (LP: #1549701)
171+ . CI failure in NestedServer.display_orientation_changes_are_forwarded_to_
172+ host (LP: #1555074)
173+ . NBS fullscreen overlay benchmark performance is much lower than
174+ BufferQueue (LP: #1557962)
175+ . server crashes when shutting down in smoke tests (LP: #1560900)
176+ . [regression] [OTA-10] Spread animation stutters badly with only a few
177+ apps opened (LP: #1563287)
178+ . nested mir_demo_server crashes on startup (LP: #1570362)
179+ . mir_acceptance_tests & mir_unit_tests dump core files (even when
180+ everything passes) (LP: #1342092)
181+ . [regression] Tests fail with: std::exception::what: Failed to read from
182+ device: /dev/random after: 30 seconds (LP: #1541188)
183+ . [testsfail] ClientLatency.throttled_input_rate_yields_lower_latency
184+ (LP: #1554572)
185+ . NBS causes sudden loss of performance after un-fullscreening a swap
186+ interval zero client (LP: #1557442)
187+ . surface creation with non-default buffer streams is ignored by server
188+ (LP: #1563278)
189+ . [regression] mir_integration_tests take significantly longer (27x
190+ longer) when running with ctest (LP: #1568966)
191+ . CI failure in TestClientInput.receives_one_touch_event_per_frame
192+ (LP: #1570698)
193+ . Racy shutdown in mir_demo_client_scroll causes SEGFAULT (LP: #1560943)
194+ . mir_demo_client_target does not quit after SIGTERM/SIGINT (LP: #1562340)
195+ . ClientLogging.reports_performance fails under moderate load, is badly
196+ named (LP: #1563148)
197+ . nested mir_demo_server crashes on mouse move when --print-input-events
198+ active (LP: #1570357)
199+ . Virtual output is not removed when screencast client disappears
200+ (LP: #1573572)
201+ . Virtual display output configuration is set to LVDS (LP: #1573782)
202+
203+ -- Alberto Aguirre <alberto.aguirre@canonical.com> Thu, 21 Apr 2016 00:54:23 -0500
204+
205 mir (0.21.0+16.04.20160330-0ubuntu1) xenial; urgency=medium
206
207 [ Alberto Aguirre ]
208
209=== modified file 'debian/control'
210--- debian/control 2016-03-18 19:40:56 +0000
211+++ debian/control 2016-04-27 09:08:17 +0000
212@@ -23,7 +23,7 @@
213 libglm-dev,
214 libprotobuf-dev,
215 pkg-config,
216- android-headers (>=4.4.2) [i386 amd64 armhf],
217+ android-headers-23,
218 libhardware-dev [i386 amd64 armhf],
219 libandroid-properties-dev [i386 amd64 armhf],
220 libgoogle-glog-dev,
221@@ -67,7 +67,7 @@
222
223 #TODO: Packaging infrastructure for better dependency generation,
224 # ala pkg-xorg's xviddriver:Provides and ABI detection.
225-Package: libmirserver38
226+Package: libmirserver39
227 Section: libs
228 Architecture: linux-any
229 Multi-Arch: same
230@@ -133,7 +133,7 @@
231 Architecture: linux-any
232 Multi-Arch: same
233 Pre-Depends: ${misc:Pre-Depends}
234-Depends: libmirserver38 (= ${binary:Version}),
235+Depends: libmirserver39 (= ${binary:Version}),
236 libmirplatform-dev (= ${binary:Version}),
237 libmircommon-dev (= ${binary:Version}),
238 libglm-dev,
239@@ -301,7 +301,7 @@
240 Contains the shared libraries required for the Mir server and client.
241
242 # Longer-term these drivers should move out-of-tree
243-Package: mir-platform-graphics-mesa-x8
244+Package: mir-platform-graphics-mesa-x9
245 Section: libs
246 Architecture: linux-any
247 Multi-Arch: same
248@@ -315,7 +315,7 @@
249 Contains the shared libraries required for the Mir server to interact with
250 the X11 platform using the Mesa drivers.
251
252-Package: mir-platform-graphics-mesa-kms8
253+Package: mir-platform-graphics-mesa-kms9
254 Section: libs
255 Architecture: linux-any
256 Multi-Arch: same
257@@ -329,7 +329,7 @@
258 Contains the shared libraries required for the Mir server to interact with
259 the hardware platform using the Mesa drivers.
260
261-Package: mir-platform-graphics-android8
262+Package: mir-platform-graphics-android9
263 Section: libs
264 Architecture: i386 amd64 armhf
265 Multi-Arch: same
266@@ -405,8 +405,8 @@
267 Multi-Arch: same
268 Pre-Depends: ${misc:Pre-Depends}
269 Depends: ${misc:Depends},
270- mir-platform-graphics-mesa-kms8,
271- mir-platform-graphics-mesa-x8,
272+ mir-platform-graphics-mesa-kms9,
273+ mir-platform-graphics-mesa-x9,
274 mir-client-platform-mesa5,
275 mir-platform-input-evdev5,
276 Description: Display server for Ubuntu - desktop driver metapackage
277@@ -422,7 +422,7 @@
278 Multi-Arch: same
279 Pre-Depends: ${misc:Pre-Depends}
280 Depends: ${misc:Depends},
281- mir-platform-graphics-android8,
282+ mir-platform-graphics-android9,
283 mir-client-platform-android5,
284 mir-platform-input-evdev5,
285 Description: Display server for Ubuntu - android driver metapackage
286
287=== renamed file 'debian/libmirserver38.install' => 'debian/libmirserver39.install'
288--- debian/libmirserver38.install 2016-03-16 06:59:01 +0000
289+++ debian/libmirserver39.install 2016-04-27 09:08:17 +0000
290@@ -1,1 +1,1 @@
291-usr/lib/*/libmirserver.so.38
292+usr/lib/*/libmirserver.so.39
293
294=== renamed file 'debian/mir-platform-graphics-android8.install' => 'debian/mir-platform-graphics-android9.install'
295--- debian/mir-platform-graphics-android8.install 2016-02-02 16:03:37 +0000
296+++ debian/mir-platform-graphics-android9.install 2016-04-27 09:08:17 +0000
297@@ -1,1 +1,1 @@
298-usr/lib/*/mir/server-platform/graphics-android.so.8
299+usr/lib/*/mir/server-platform/graphics-android.so.9
300
301=== renamed file 'debian/mir-platform-graphics-mesa-kms8.install' => 'debian/mir-platform-graphics-mesa-kms9.install'
302--- debian/mir-platform-graphics-mesa-kms8.install 2016-02-02 16:03:37 +0000
303+++ debian/mir-platform-graphics-mesa-kms9.install 2016-04-27 09:08:17 +0000
304@@ -1,1 +1,1 @@
305-usr/lib/*/mir/server-platform/graphics-mesa-kms.so.8
306+usr/lib/*/mir/server-platform/graphics-mesa-kms.so.9
307
308=== renamed file 'debian/mir-platform-graphics-mesa-x8.install' => 'debian/mir-platform-graphics-mesa-x9.install'
309--- debian/mir-platform-graphics-mesa-x8.install 2016-02-02 16:03:37 +0000
310+++ debian/mir-platform-graphics-mesa-x9.install 2016-04-27 09:08:17 +0000
311@@ -1,1 +1,1 @@
312-usr/lib/*/mir/server-platform/server-mesa-x11.so.8
313+usr/lib/*/mir/server-platform/server-mesa-x11.so.9
314
315=== modified file 'debian/mir-test-tools.install'
316--- debian/mir-test-tools.install 2016-03-16 06:59:01 +0000
317+++ debian/mir-test-tools.install 2016-04-27 09:08:17 +0000
318@@ -7,6 +7,7 @@
319 usr/bin/mir_performance_tests
320 usr/bin/mir_privileged_tests
321 usr/bin/mir_test_reload_protobuf
322+usr/bin/mir_test_client_*
323 usr/lib/*/mir/tools/libmirclientlttng.so
324 usr/lib/*/mir/tools/libmirserverlttng.so
325 usr/lib/*/mir/server-platform/graphics-dummy.so
326
327=== modified file 'debian/mir-utils.install'
328--- debian/mir-utils.install 2016-03-14 10:13:49 +0000
329+++ debian/mir-utils.install 2016-04-27 09:08:17 +0000
330@@ -3,3 +3,4 @@
331 usr/bin/mirin
332 usr/bin/mirscreencast
333 usr/bin/mirbacklight
334+usr/bin/mirrun
335
336=== modified file 'doc/dso_versioning_guide.md'
337--- doc/dso_versioning_guide.md 2016-01-29 08:18:22 +0000
338+++ doc/dso_versioning_guide.md 2016-04-27 09:08:17 +0000
339@@ -6,13 +6,11 @@
340
341 There are more detailed descriptions below, but as a general rule:
342
343- - If you add a new symbol, add it to the `*_unreleased` version stanza,
344- like `MIR_CLIENT_unreleased`, `MIR_PLATFORM_unreleased`, etc.
345+ - If you add a new symbol, add it to a `*_NEXTSERIES` version stanza,
346+ like `MIR_CLIENT_0.22`, `MIR_PLATFORM_0.22`, etc representing the
347+ next future Mir series in which the new symbol will first be released.
348 - If you change the behaviour or signature of a symbol _and_ wish to preserve
349 backward compatibility, see "Change symbols without breaking ABI" below.
350- - At release time, rename the current `*_unversioned` stanzas to have the
351- version of the current release, like `MIR_CLIENT_0.17`, `MIR_PLATFORM_0.17`,
352- etc.
353
354 Can I have some details?
355 ------------------------
356@@ -95,7 +93,7 @@
357 /* Other symbols go here */
358 };
359
360- MIR_CLIENT_unreleased {
361+ MIR_CLIENT_0.18 {
362 global:
363 mir_connect_new_symbol;
364 local:
365@@ -138,7 +136,7 @@
366 /* The old implementation */
367
368 /* The @@ specifies that this is the default version */
369- __asm__(".symver mir_connection_create_surface,mir_connection_create_surface@@@MIR_CLIENT_unreleased");
370+ __asm__(".symver mir_connection_create_surface,mir_connection_create_surface@@@MIR_CLIENT_0.18");
371 MirWaitHandle* mir_connection_create_surface(...)
372 /* The new implementation */
373
374@@ -151,7 +149,7 @@
375 ...
376 };
377
378- MIR_CLIENT_unreleased {
379+ MIR_CLIENT_0.18 {
380 global:
381 ...
382 mir_connection_create_surface;
383
384=== modified file 'examples/CMakeLists.txt'
385--- examples/CMakeLists.txt 2016-03-16 06:59:01 +0000
386+++ examples/CMakeLists.txt 2016-04-27 09:08:17 +0000
387@@ -166,14 +166,8 @@
388 )
389
390 target_link_libraries(mir_demo_client_scroll
391+ eglapp
392 mirdraw
393- mirclient
394-
395- ${Boost_LIBRARIES}
396- ${CMAKE_THREAD_LIBS_INIT}
397- ${EGL_LIBRARIES}
398- ${GLESv2_LIBRARIES}
399-
400 )
401
402 mir_add_wrapped_executable(mir_demo_client_prompt_session prompt_session.c)
403
404=== modified file 'examples/render_surfaces.cpp'
405--- examples/render_surfaces.cpp 2016-03-16 06:59:01 +0000
406+++ examples/render_surfaces.cpp 2016-04-27 09:08:17 +0000
407@@ -333,6 +333,7 @@
408
409 // New function to initialize moveables with surfaces
410 void create_surfaces()
411+ try
412 {
413 moveables.resize(get_options()->get<int>(surfaces_to_render));
414 std::cout << "Rendering " << moveables.size() << " surfaces" << std::endl;
415@@ -376,7 +377,7 @@
416
417 auto const stream = buffer_stream_factory->create_buffer_stream(
418 mf::BufferStreamId{}, std::make_shared<NullBufferSink>(), properties);
419- auto const surface = surface_factory->create_surface(stream, params);
420+ auto const surface = surface_factory->create_surface({ ms::StreamInfo{ stream, {0, 0}, {} } }, params);
421 surface_stack->add_surface(surface, params.input_mode);
422
423 {
424@@ -416,6 +417,11 @@
425
426 created = true;
427 }
428+ catch (...)
429+ {
430+ mir::report_exception();
431+ exit(EXIT_FAILURE);
432+ }
433
434 private:
435 std::vector<Moveable> moveables;
436
437=== modified file 'examples/scroll.cpp'
438--- examples/scroll.cpp 2016-03-15 08:14:23 +0000
439+++ examples/scroll.cpp 2016-04-27 09:08:17 +0000
440@@ -16,183 +16,34 @@
441 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
442 */
443
444-#include "mir_toolkit/mir_client_library.h"
445+#include "eglapp.h"
446 #include "graphics.h"
447
448-#ifdef NDEBUG
449-// We have no error handling so rely on assert() always being present.
450-#undef NDEBUG
451-#endif
452-#include <assert.h>
453-#include <signal.h>
454-#include <string.h>
455-#include <stdio.h>
456-#include <stdlib.h>
457-#include <unistd.h>
458-#include <getopt.h>
459-#include <EGL/egl.h>
460-#include <GLES2/gl2.h>
461-
462-#include <thread>
463-
464-static char const *socket_file = NULL;
465-static EGLDisplay disp;
466-
467-
468-void create_and_run_scroll_surface(MirConnection *connection)
469+#include <exception>
470+#include <iostream>
471+
472+int main(int argc, char* argv[])
473+try
474 {
475- /* egl setup */
476- int major, minor, n, rc;
477- EGLContext context;
478- EGLSurface egl_surface;
479- EGLConfig egl_config;
480- EGLint attribs[] = {
481- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
482- EGL_RED_SIZE, 8,
483- EGL_GREEN_SIZE, 8,
484- EGL_BLUE_SIZE, 8,
485- EGL_ALPHA_SIZE, 8,
486- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
487- EGL_NONE };
488- EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
489-
490- rc = eglInitialize(disp, &major, &minor);
491- assert(rc == EGL_TRUE);
492- assert(major == 1);
493- assert(minor == 4);
494-
495- rc = eglChooseConfig(disp, attribs, &egl_config, 1, &n);
496- assert(rc == EGL_TRUE);
497- assert(n == 1);
498-
499- MirPixelFormat pixel_format =
500- mir_connection_get_egl_pixel_format(connection, disp, egl_config);
501-
502- printf("Mir chose pixel format %d\n", pixel_format);
503-
504- auto deleter = [](MirSurfaceSpec *spec) { mir_surface_spec_release(spec); };
505- std::unique_ptr<MirSurfaceSpec, decltype(deleter)> spec{
506- mir_connection_create_spec_for_normal_surface(connection, 640, 480,
507- pixel_format),
508- deleter
509- };
510-
511- assert(spec != nullptr);
512-
513- mir_surface_spec_set_name(spec.get(), __PRETTY_FUNCTION__);
514- mir_surface_spec_set_buffer_usage(spec.get(), mir_buffer_usage_hardware);
515-
516- MirSurface *surface = mir_surface_create_sync(spec.get());
517- spec.reset();
518-
519- assert(surface != NULL);
520- assert(mir_surface_is_valid(surface));
521- assert(strcmp(mir_surface_get_error_message(surface), "") == 0);
522- puts("Surface created");
523-
524- EGLNativeWindowType native_window =
525- (EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(
526- mir_surface_get_buffer_stream(surface));
527- assert(native_window != (EGLNativeWindowType)NULL);
528-
529- egl_surface = eglCreateWindowSurface(disp, egl_config, native_window, NULL);
530- assert(egl_surface != EGL_NO_SURFACE);
531-
532- context = eglCreateContext(disp, egl_config, EGL_NO_CONTEXT, context_attribs);
533- assert(context != EGL_NO_CONTEXT);
534-
535- rc = eglMakeCurrent(disp, egl_surface, egl_surface, context);
536- assert(rc == EGL_TRUE);
537+ unsigned int width = 640, height = 480;
538+ if (!mir_eglapp_init(argc, argv, &width, &height))
539+ return 1;
540
541 mir::draw::glAnimationBasic gl_animation;
542 gl_animation.init_gl();
543
544- for(;;)
545+ while (mir_eglapp_running())
546 {
547 gl_animation.render_gl();
548- rc = eglSwapBuffers(disp, egl_surface);
549- assert(rc == EGL_TRUE);
550+ mir_eglapp_swap_buffers();
551 gl_animation.step();
552 }
553
554- eglDestroySurface(disp, egl_surface);
555- eglDestroyContext(disp, context);
556-
557- mir_surface_release_sync(surface);
558- puts("Surface released");
559-}
560-
561-static void shutdown(int signum)
562-{
563- // Exiting without closing surfaces and connection is impolite but should
564- // not kill the server. It actually did kill the server prior to -r 3385.
565- // Running this example in CI acts as a smoke test for that failure.
566- printf("Signal %d received. Good night.\n", signum);
567- exit(EXIT_SUCCESS);
568-}
569-
570-int main(int argc, char* argv[])
571-{
572- MirConnection *connection = 0;
573- unsigned num_windows = 1;
574- int arg;
575- opterr = 0;
576- while ((arg = getopt (argc, argv, "hm:w:")) != -1)
577- {
578- switch (arg)
579- {
580- case 'm':
581- socket_file = optarg;
582- break;
583- case 'w':
584- num_windows = atoi(optarg);
585- break;
586- case '?':
587- case 'h':
588- default:
589- puts(argv[0]);
590- puts("Usage:");
591- puts(" -m <Mir server socket>");
592- puts(" -w <Number of windows to create>:");
593- puts(" -h: this help text");
594- return -1;
595- }
596- }
597-
598- puts("Starting");
599-
600- signal(SIGINT, shutdown);
601- signal(SIGTERM, shutdown);
602- signal(SIGHUP, shutdown);
603-
604- connection = mir_connect_sync(socket_file, __PRETTY_FUNCTION__);
605- assert(connection != NULL);
606- assert(mir_connection_is_valid(connection));
607- assert(strcmp(mir_connection_get_error_message(connection), "") == 0);
608- puts("Connected");
609-
610- EGLNativeDisplayType native_display = (EGLNativeDisplayType) mir_connection_get_egl_native_display(connection);
611- disp = eglGetDisplay(native_display);
612- assert(disp != EGL_NO_DISPLAY);
613-
614- if (num_windows == 1)
615- {
616- create_and_run_scroll_surface(connection);
617- }
618- else
619- {
620- for (unsigned i = 0; i < num_windows; i++) std::thread(create_and_run_scroll_surface, connection).detach();
621- for(;;) {}
622- }
623-
624-
625- eglTerminate(disp);
626-
627- mir_connection_release(connection);
628- puts("Connection released");
629-
630+ mir_eglapp_shutdown();
631 return 0;
632 }
633-
634-
635-
636+catch(std::exception& e)
637+{
638+ std::cerr << "error : " << e.what() << std::endl;
639+ return 1;
640+}
641
642=== modified file 'examples/server_example.cpp'
643--- examples/server_example.cpp 2016-03-16 06:59:01 +0000
644+++ examples/server_example.cpp 2016-04-27 09:08:17 +0000
645@@ -71,7 +71,12 @@
646 {
647 auto const j = find(i, end(value), '&');
648
649- auto const cmd = "MIR_SOCKET=" + connection(server.open_client_socket()) + " " + std::string{i, j} + "&";
650+ auto const cmd ="DISPLAY= " // Discourage toolkits from using X11
651+ "GDK_BACKEND=mir " // configure GTK to use Mir
652+ "QT_QPA_PLATFORM=ubuntumirclient " // configure Qt to use Mir
653+ "SDL_VIDEODRIVER=mir " // configure SDL to use Mir
654+ "MIR_SOCKET=" + connection(server.open_client_socket()) + " " +
655+ std::string{i, j} + "&";
656
657 auto ignore = std::system(cmd.c_str());
658 (void)(ignore);
659
660=== modified file 'examples/server_example_canonical_window_manager.cpp'
661--- examples/server_example_canonical_window_manager.cpp 2016-01-29 08:18:22 +0000
662+++ examples/server_example_canonical_window_manager.cpp 2016-04-27 09:08:17 +0000
663@@ -251,13 +251,17 @@
664 return;
665
666 auto format = mir_pixel_format_xrgb_8888;
667- ms::SurfaceCreationParameters params;
668- params.of_size(titlebar_size_for_window(surface->size()))
669+ mir::graphics::BufferProperties properties(titlebar_size_for_window(surface->size()),
670+ format, mir::graphics::BufferUsage::software);
671+ auto stream_id = session->create_buffer_stream(properties);
672+ auto params = ms::a_surface()
673+ .of_size(titlebar_size_for_window(surface->size()))
674 .of_name("decoration")
675 .of_pixel_format(format)
676 .of_buffer_usage(mir::graphics::BufferUsage::software)
677 .of_position(titlebar_position_for_window(surface->top_left()))
678- .of_type(mir_surface_type_gloss);
679+ .of_type(mir_surface_type_gloss)
680+ .with_buffer_stream(stream_id);
681 auto id = build(session, params);
682 auto titlebar = session->surface(id);
683 titlebar->set_alpha(0.9);
684@@ -265,6 +269,7 @@
685 auto& surface_info = tools->info_for(surface);
686 surface_info.titlebar = titlebar;
687 surface_info.titlebar_id = id;
688+ surface_info.titlebar_stream_id = stream_id;
689 surface_info.children.push_back(titlebar);
690
691 SurfaceInfo& titlebar_info =
692@@ -369,11 +374,6 @@
693 session->configure_streams(*surface, l);
694 }
695
696- if (modifications.input_shape.is_set())
697- {
698- surface->set_input_region(modifications.input_shape.value());
699- }
700-
701 if (modifications.width.is_set() || modifications.height.is_set())
702 {
703 auto new_size = surface->size();
704@@ -397,6 +397,20 @@
705 apply_resize(surface, surface_info.titlebar, top_left, new_size);
706 }
707
708+ if (modifications.input_shape.is_set())
709+ {
710+ auto rectangles = modifications.input_shape.value();
711+ auto displacement = surface->top_left() - Point{0, 0};
712+ for(auto& rect : rectangles)
713+ {
714+ rect.top_left = rect.top_left + displacement;
715+ rect = rect.intersection_with({surface->top_left(), surface->size()});
716+ rect.top_left = rect.top_left - displacement;
717+ }
718+ surface->set_input_region(rectangles);
719+ }
720+
721+
722 if (modifications.state.is_set())
723 {
724 auto const state = handle_set_state(surface, modifications.state.value());
725@@ -428,6 +442,7 @@
726 if (info.titlebar)
727 {
728 session->destroy_surface(info.titlebar_id);
729+ session->destroy_buffer_stream(info.titlebar_stream_id);
730 tools->forget(info.titlebar);
731 }
732
733
734=== modified file 'examples/server_example_input_device_config.cpp'
735--- examples/server_example_input_device_config.cpp 2016-01-29 08:18:22 +0000
736+++ examples/server_example_input_device_config.cpp 2016-04-27 09:08:17 +0000
737@@ -157,25 +157,37 @@
738 {
739 if (contains(device->capabilities(), mi::DeviceCapability::touchpad))
740 {
741- mi::PointerConfiguration pointer_config( device->pointer_configuration().value() );
742- pointer_config.cursor_acceleration_bias = touchpad_cursor_acceleration_bias;
743- pointer_config.vertical_scroll_scale = touchpad_scroll_speed_scale;
744- pointer_config.horizontal_scroll_scale = touchpad_scroll_speed_scale;
745- device->apply_pointer_configuration(pointer_config);
746+ auto optional_pointer_config = device->pointer_configuration();
747+ if (optional_pointer_config.is_set())
748+ {
749+ mi::PointerConfiguration pointer_config( optional_pointer_config.value() );
750+ pointer_config.cursor_acceleration_bias = touchpad_cursor_acceleration_bias;
751+ pointer_config.vertical_scroll_scale = touchpad_scroll_speed_scale;
752+ pointer_config.horizontal_scroll_scale = touchpad_scroll_speed_scale;
753+ device->apply_pointer_configuration(pointer_config);
754+ }
755
756- mi::TouchpadConfiguration touch_config( device->touchpad_configuration().value() );
757- touch_config.disable_while_typing = disable_while_typing;
758- touch_config.click_mode = click_mode;
759- touch_config.scroll_mode = scroll_mode;
760- device->apply_touchpad_configuration(touch_config);
761+ auto optional_touchpad_config = device->touchpad_configuration();
762+ if (optional_touchpad_config.is_set())
763+ {
764+ mi::TouchpadConfiguration touch_config( optional_touchpad_config.value() );
765+ touch_config.disable_while_typing = disable_while_typing;
766+ touch_config.click_mode = click_mode;
767+ touch_config.scroll_mode = scroll_mode;
768+ device->apply_touchpad_configuration(touch_config);
769+ }
770 }
771 else if (contains(device->capabilities(), mi::DeviceCapability::pointer))
772 {
773- mi::PointerConfiguration pointer_config( device->pointer_configuration().value() );
774- pointer_config.acceleration = mouse_profile;
775- pointer_config.cursor_acceleration_bias = mouse_cursor_acceleration_bias;
776- pointer_config.vertical_scroll_scale = mouse_scroll_speed_scale;
777- pointer_config.horizontal_scroll_scale = mouse_scroll_speed_scale;
778- device->apply_pointer_configuration(pointer_config);
779+ auto optional_pointer_config = device->pointer_configuration();
780+ if (optional_pointer_config.is_set())
781+ {
782+ mi::PointerConfiguration pointer_config( optional_pointer_config.value() );
783+ pointer_config.acceleration = mouse_profile;
784+ pointer_config.cursor_acceleration_bias = mouse_cursor_acceleration_bias;
785+ pointer_config.vertical_scroll_scale = mouse_scroll_speed_scale;
786+ pointer_config.horizontal_scroll_scale = mouse_scroll_speed_scale;
787+ device->apply_pointer_configuration(pointer_config);
788+ }
789 }
790 }
791
792=== modified file 'examples/server_example_input_filter.cpp'
793--- examples/server_example_input_filter.cpp 2015-06-17 05:20:42 +0000
794+++ examples/server_example_input_filter.cpp 2016-04-27 09:08:17 +0000
795@@ -56,7 +56,7 @@
796 auto tev = mir_input_event_get_touch_event(ev);
797 auto tc = mir_touch_event_point_count(tev);
798
799- std::cout << "Handline touch event time=" << event_time
800+ std::cout << "Handling touch event time=" << event_time
801 << " touch_count=" << tc << std::endl;
802 for (unsigned i = 0; i < tc; i++)
803 {
804@@ -72,6 +72,38 @@
805 std::cout << "----------------" << std::endl << std::endl;
806 }
807
808+void print_pointer_event(MirInputEvent const* ev)
809+{
810+ auto event_time = mir_input_event_get_event_time(ev);
811+ auto pev = mir_input_event_get_pointer_event(ev);
812+ auto action = mir_pointer_event_action(pev);
813+
814+ std::cout << "Handling pointer event time=" << event_time
815+ << " action=";
816+ switch(action)
817+ {
818+ case mir_pointer_action_motion:
819+ std::cout << "motion";
820+ break;
821+ case mir_pointer_action_button_up:
822+ std::cout << "up";
823+ break;
824+ case mir_pointer_action_button_down:
825+ std::cout << "down";
826+ break;
827+ default:
828+ break;
829+ }
830+
831+ std::cout << " "
832+ << " pos=(" << mir_pointer_event_axis_value(pev, mir_pointer_axis_x) << ", "
833+ << mir_pointer_event_axis_value(pev, mir_pointer_axis_y) << ")"
834+ << " relative=(" << mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x) << ", "
835+ << mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y) << ")" << std::endl;
836+ std::cout << "----------------" << std::endl << std::endl;
837+}
838+
839+
840 struct PrintingEventFilter : public mi::EventFilter
841 {
842 bool handle(MirEvent const& ev) override
843@@ -88,8 +120,12 @@
844 case mir_input_event_type_touch:
845 print_touch_event(input_event);
846 break;
847+ case mir_input_event_type_pointer:
848+ print_pointer_event(input_event);
849+ break;
850 default:
851- abort();
852+ std::cout << "unkown input event type: " << mir_input_event_get_type(input_event) << std::endl;
853+ break;
854 }
855
856 return false;
857@@ -220,4 +256,3 @@
858
859 return screen_rotation_filter;
860 }
861-
862
863=== modified file 'examples/server_example_test_client.cpp'
864--- examples/server_example_test_client.cpp 2016-03-16 06:59:01 +0000
865+++ examples/server_example_test_client.cpp 2016-04-27 09:08:17 +0000
866@@ -46,6 +46,7 @@
867 {
868 ml::log(ml::Severity::informational, "Terminating client", component);
869 kill(pid, SIGKILL);
870+ return false;
871 }
872 else if (wait_rc != pid)
873 {
874@@ -55,7 +56,12 @@
875 else if (WIFEXITED(status))
876 {
877 auto const exit_status = WEXITSTATUS(status);
878- if (exit_status != EXIT_SUCCESS)
879+ if (exit_status == EXIT_SUCCESS)
880+ {
881+ ml::log(ml::Severity::informational, "Client exited successfully", component);
882+ return true;
883+ }
884+ else
885 {
886 char const format[] = "Client has exited with status %d";
887 char buffer[sizeof format + 10];
888@@ -78,8 +84,6 @@
889 ml::log(ml::Severity::informational, "Client died mysteriously", component);
890 return false;
891 }
892-
893- return true;
894 }
895 }
896
897
898=== modified file 'examples/server_example_window_management_info.h'
899--- examples/server_example_window_management_info.h 2016-01-29 08:18:22 +0000
900+++ examples/server_example_window_management_info.h 2016-04-27 09:08:17 +0000
901@@ -65,6 +65,7 @@
902 std::vector <std::weak_ptr<scene::Surface>> children;
903 std::shared_ptr <scene::Surface> titlebar;
904 frontend::SurfaceId titlebar_id;
905+ frontend::BufferStreamId titlebar_stream_id;
906 bool is_titlebar = false;
907 geometry::Width min_width;
908 geometry::Height min_height;
909
910=== modified file 'examples/target.c'
911--- examples/target.c 2015-06-10 07:48:27 +0000
912+++ examples/target.c 2016-04-27 09:08:17 +0000
913@@ -52,9 +52,11 @@
914
915 typedef struct
916 {
917+ sigset_t sigs;
918 pthread_mutex_t mutex;
919- pthread_cond_t change;
920+ pthread_cond_t change_cv;
921 bool changed;
922+ bool running;
923
924 bool resized;
925 TouchState touch;
926@@ -198,17 +200,32 @@
927 state->resized = true;
928 break;
929 case mir_event_type_close_surface:
930- // TODO: eglapp.h needs a quit() function or different behaviour of
931- // mir_eglapp_shutdown().
932- raise(SIGTERM); // handled by eglapp
933+ state->running = false;
934 break;
935 default:
936 break;
937 }
938
939 state->changed = true;
940- pthread_cond_signal(&state->change);
941- pthread_mutex_unlock(&state->mutex);
942+ pthread_cond_signal(&state->change_cv);
943+ pthread_mutex_unlock(&state->mutex);
944+}
945+
946+static void* shutdown_handler(void* context)
947+{
948+ State *state = (State*)context;
949+
950+ int signum;
951+ sigwait(&state->sigs, &signum);
952+ printf("Signal %d received. Good night.\n", signum);
953+
954+ pthread_mutex_lock(&state->mutex);
955+ state->running = false;
956+ state->changed = true;
957+ pthread_cond_signal(&state->change_cv);
958+ pthread_mutex_unlock(&state->mutex);
959+
960+ return NULL;
961 }
962
963 int main(int argc, char *argv[])
964@@ -241,6 +258,13 @@
965 " gl_FragColor = f;\n"
966 "}\n";
967
968+ sigset_t sigs;
969+ sigemptyset(&sigs);
970+ sigaddset(&sigs, SIGINT);
971+ sigaddset(&sigs, SIGTERM);
972+ sigaddset(&sigs, SIGHUP);
973+ pthread_sigmask(SIG_BLOCK, &sigs, NULL);
974+
975 // Disable Mir's input resampling. We do our own here, in a way that
976 // has even lower latency than Mir's default algorithm.
977 // TODO: Make a proper client API function for this:
978@@ -311,22 +335,38 @@
979
980 State state =
981 {
982- PTHREAD_MUTEX_INITIALIZER,
983- PTHREAD_COND_INITIALIZER,
984- true,
985- true,
986- {0, {{0, {{0.0f, 0.0f}}}}}
987+ .mutex = PTHREAD_MUTEX_INITIALIZER,
988+ .change_cv = PTHREAD_COND_INITIALIZER,
989+ .changed = true,
990+ .running = true,
991+ .resized = true,
992+ .touch = {0, {{0, {{0.0f, 0.0f}}}}}
993 };
994+ state.sigs = sigs;
995+
996+ pthread_t shutdown_handler_thread;
997+ if (pthread_create(&shutdown_handler_thread, NULL, &shutdown_handler, &state))
998+ {
999+ printf("Failed creating shutdown handling thread\n");
1000+ return 3;
1001+ }
1002+
1003 MirSurface *surface = mir_eglapp_native_surface();
1004 mir_surface_set_event_handler(surface, on_event, &state);
1005
1006- while (mir_eglapp_running())
1007+ while (true)
1008 {
1009 pthread_mutex_lock(&state.mutex);
1010
1011- while (mir_eglapp_running() && !state.changed)
1012- pthread_cond_wait(&state.change, &state.mutex);
1013-
1014+ while (state.running && !state.changed)
1015+ pthread_cond_wait(&state.change_cv, &state.mutex);
1016+
1017+ if (!state.running)
1018+ {
1019+ pthread_mutex_unlock(&state.mutex);
1020+ break;
1021+ }
1022+
1023 if (state.resized)
1024 {
1025 // mir_eglapp_swap_buffers updates the viewport for us...
1026@@ -384,5 +424,6 @@
1027 mir_surface_set_event_handler(surface, NULL, NULL);
1028 mir_eglapp_shutdown();
1029
1030+ pthread_join(shutdown_handler_thread, NULL);
1031 return 0;
1032 }
1033
1034=== modified file 'include/client/mir_toolkit/client_types.h'
1035--- include/client/mir_toolkit/client_types.h 2016-03-14 10:13:49 +0000
1036+++ include/client/mir_toolkit/client_types.h 2016-04-27 09:08:17 +0000
1037@@ -41,11 +41,14 @@
1038 typedef struct MirSurface MirSurface;
1039 typedef struct MirSurfaceSpec MirSurfaceSpec;
1040 typedef struct MirScreencast MirScreencast;
1041+typedef struct MirScreencastSpec MirScreencastSpec;
1042 typedef struct MirPromptSession MirPromptSession;
1043 typedef struct MirBufferStream MirBufferStream;
1044 typedef struct MirPersistentId MirPersistentId;
1045 typedef struct MirBlob MirBlob;
1046 typedef struct MirDisplayConfig MirDisplayConfig;
1047+typedef struct MirError MirError;
1048+
1049
1050 /**
1051 * Descriptor for an output connection.
1052@@ -278,7 +281,8 @@
1053 mir_display_output_type_hdmia,
1054 mir_display_output_type_hdmib,
1055 mir_display_output_type_tv,
1056- mir_display_output_type_edp
1057+ mir_display_output_type_edp,
1058+ mir_display_output_type_virtual
1059 } MirDisplayOutputType;
1060
1061 typedef enum MirOutputType
1062@@ -297,7 +301,8 @@
1063 mir_output_type_hdmia,
1064 mir_output_type_hdmib,
1065 mir_output_type_tv,
1066- mir_output_type_edp
1067+ mir_output_type_edp,
1068+ mir_output_type_virtual
1069 } MirOutputType;
1070
1071 typedef enum MirOutputConnectionState
1072@@ -443,6 +448,36 @@
1073 typedef void (*mir_input_config_callback)(
1074 MirConnection* connection, void* context);
1075
1076+/**
1077+ * Specifies the origin of an error.
1078+ *
1079+ * This is required to interpret the other aspects of a MirError.
1080+ */
1081+typedef enum MirErrorDomain
1082+{
1083+ /**
1084+ * Errors relating to display configuration.
1085+ *
1086+ * Associated error codes are found in \ref MirDisplayConfigurationError.
1087+ */
1088+ mir_error_domain_display_configuration,
1089+} MirErrorDomain;
1090+
1091+/**
1092+ * Errors from the \ref mir_error_domain_display_configuration \ref MirErrorDomain
1093+ */
1094+typedef enum MirDisplayConfigurationError {
1095+ /**
1096+ * Client is not permitted to change global display configuration
1097+ */
1098+ mir_display_configuration_error_unauthorized,
1099+} MirDisplayConfigurationError;
1100+
1101+typedef void (*mir_error_callback)(
1102+ MirConnection* connection,
1103+ MirError const* error,
1104+ void* context);
1105+
1106 #ifdef __cplusplus
1107 }
1108 /**@}*/
1109
1110=== modified file 'include/client/mir_toolkit/events/event.h'
1111--- include/client/mir_toolkit/events/event.h 2016-03-14 10:13:49 +0000
1112+++ include/client/mir_toolkit/events/event.h 2016-04-27 09:08:17 +0000
1113@@ -60,7 +60,7 @@
1114
1115 typedef struct MirCookie MirCookie;
1116
1117-typedef union MirEvent MirEvent;
1118+typedef struct MirEvent MirEvent;
1119
1120 #ifdef __cplusplus
1121 }
1122
1123=== modified file 'include/client/mir_toolkit/mir_client_library.h'
1124--- include/client/mir_toolkit/mir_client_library.h 2016-03-14 10:13:49 +0000
1125+++ include/client/mir_toolkit/mir_client_library.h 2016-04-27 09:08:17 +0000
1126@@ -28,5 +28,6 @@
1127 #include <mir_toolkit/mir_cookie.h>
1128 #include <mir_toolkit/mir_display_configuration.h>
1129 #include <mir_toolkit/mir_input_device.h>
1130+#include <mir_toolkit/mir_error.h>
1131
1132 #endif /* MIR_CLIENT_LIBRARY_H */
1133
1134=== modified file 'include/client/mir_toolkit/mir_connection.h'
1135--- include/client/mir_toolkit/mir_connection.h 2016-03-14 10:13:49 +0000
1136+++ include/client/mir_toolkit/mir_connection.h 2016-04-27 09:08:17 +0000
1137@@ -226,6 +226,59 @@
1138 MirConnection* connection,
1139 MirDisplayConfiguration const* display_configuration);
1140
1141+
1142+/**
1143+ * Preview a new base display configuration
1144+ *
1145+ * The base display configuration is the configuration the server applies when
1146+ * there is no active per-connection configuration.
1147+ *
1148+ * The display configuration will automatically revert to the previous
1149+ * settings after timeout_seconds unless confirmed by a call to
1150+ * mir_connection_confirm_base_display_configuration().
1151+ *
1152+ * If this request succeeds a configuration change event is sent to the
1153+ * client. Clients should register a callback with
1154+ * mir_connection_set_display_config_change_callback() in order to determine
1155+ * when this call succeeds.
1156+ *
1157+ * If the configuration is not confirmed before timeout_seconds have elapsed
1158+ * a second configuration change event is sent, with the old config.
1159+ *
1160+ * \param [in] connection The connection
1161+ * \param [in] configuration The MirDisplayConfig to set as base
1162+ * \param [in] timeout_seconds The time the server should wait, in seconds,
1163+ * for the change to be confirmed before
1164+ * reverting to the previous configuration.
1165+ */
1166+void mir_connection_preview_base_display_configuration(
1167+ MirConnection* connection,
1168+ MirDisplayConfig const* configuration,
1169+ int timeout_seconds);
1170+
1171+/**
1172+ * Confirm a base configuration change initiated by mir_connection_preview_base_display_configuration()
1173+ *
1174+ * The base display configuration is the configuration the server applies when
1175+ * there is no active per-connection configuration.
1176+ *
1177+ * If this request succeeds a second configuration change event is sent to the
1178+ * client, identical to the one sent after
1179+ * mir_connection_preview_base_display_configuration(). Clients should
1180+ * register a callback with mir_connection_set_display_config_change_callback()
1181+ * in order to determine when this call succeeds.
1182+ *
1183+ * The MirDisplayConfig must be the same as the one passed to
1184+ * mir_connection_preview_base_display_configuration().
1185+ *
1186+ * \param [in] connection The connection
1187+ * \param [in] configuration The MirDisplayConfig to confirm as base
1188+ * configuration.
1189+ */
1190+void mir_connection_confirm_base_display_configuration(
1191+ MirConnection* connection,
1192+ MirDisplayConfig const* configuration);
1193+
1194 /**
1195 * Get a display type that can be used for OpenGL ES 2.0 acceleration.
1196 * \param [in] connection The connection
1197@@ -311,6 +364,17 @@
1198 MirConnection* connection,
1199 mir_input_config_callback callback, void* context);
1200
1201+/**
1202+ * Register a callback to be called on non-fatal errors
1203+ *
1204+ * \param [in] connection The connection
1205+ * \param [in] callback The function to be called when an error occurs
1206+ * \param [in,out] context User data passed to the callback function
1207+ */
1208+void mir_connection_set_error_callback(
1209+ MirConnection* connection,
1210+ mir_error_callback callback,
1211+ void* context);
1212
1213 #ifdef __cplusplus
1214 }
1215
1216=== modified file 'include/client/mir_toolkit/mir_display_configuration.h'
1217--- include/client/mir_toolkit/mir_display_configuration.h 2016-03-14 10:13:49 +0000
1218+++ include/client/mir_toolkit/mir_display_configuration.h 2016-04-27 09:08:17 +0000
1219@@ -93,6 +93,19 @@
1220 size_t index);
1221
1222 /**
1223+ * Get a modifyable handle to the index 'th output of this configuration
1224+ *
1225+ * \note The MirOutput handle is only valid while config is valid.
1226+ * \pre 0 <= index < mir_display_config_get_num_outputs(config)
1227+ * \param [in] config The configuration to query
1228+ * \param [in] index The index of the output to get
1229+ * \returns A handle to a MirOutput within config which is valid
1230+ * until mir_display_config_release(config) is called.
1231+ */
1232+MirOutput* mir_display_config_get_mutable_output(MirDisplayConfig* config,
1233+ size_t index);
1234+
1235+/**
1236 * Get the number of modes in the supported mode list of this output.
1237 *
1238 * The list of supported modes is retrieved from the hardware, possibly modified
1239@@ -153,6 +166,14 @@
1240 MirOutputMode const* mir_output_get_current_mode(MirOutput const* output);
1241
1242 /**
1243+ * Set the current mode of an output.
1244+ *
1245+ * \param [in] output The MirOutput to mutate
1246+ * \param [in] mode The MirOutputMode to set as the current mode.
1247+ */
1248+void mir_output_set_current_mode(MirOutput* output, MirOutputMode const* mode);
1249+
1250+/**
1251 * Get the number of pixel formats supported by this output
1252 *
1253 * \param [in] output The MirOutput to query
1254@@ -245,6 +266,24 @@
1255 int mir_output_get_position_y(MirOutput const* output);
1256
1257 /**
1258+ * Set the coordinates of the top-left point of the output in the virtual
1259+ * display space.
1260+ *
1261+ * Outputs can be thought of as viewports into a virtual display space. They may
1262+ * freely overlap, coincide, or be disjoint as desired.
1263+ *
1264+ * Output orientation changes the orientation of the output rectangle in virtual
1265+ * display space, but does not change its top-left corner.
1266+ *
1267+ * \param [in] output The MirOutput to mutate
1268+ * \param [in] x The new x coordinate of the top-left point of the
1269+ * output in virtual display space.
1270+ * \param [in] y The new y coordinate of the top-left point of the
1271+ * output in virtual display space.
1272+ */
1273+void mir_output_set_position(MirOutput* output, int x, int y);
1274+
1275+/**
1276 * Get whether there is a display physically connected to the output.
1277 *
1278 * This gives a best-effort determination of whether or not enabling this output
1279@@ -277,6 +316,20 @@
1280 bool mir_output_is_enabled(MirOutput const* output);
1281
1282 /**
1283+ * Enable this output
1284+ *
1285+ * \param [in] output the MirOutput to enable
1286+ */
1287+void mir_output_enable(MirOutput* output);
1288+
1289+/**
1290+ * Disable this output
1291+ *
1292+ * \param [in] output the MirOutput to disable
1293+ */
1294+void mir_output_disable(MirOutput* output);
1295+
1296+/**
1297 * Get the physical width of the connected display, in millimetres.
1298 *
1299 * A best-effort report of the physical width of the display connected to this
1300@@ -318,6 +371,16 @@
1301 MirPowerMode mir_output_get_power_mode(MirOutput const* output);
1302
1303 /**
1304+ * Set the power state of a connected display.
1305+ *
1306+ * It is undefined what power state is set if the output is not connected.
1307+ *
1308+ * \param [in] output The MirOutput to mutate
1309+ * \param [in] mode The new MirPowerMode for output
1310+ */
1311+void mir_output_set_power_mode(MirOutput* output, MirPowerMode mode);
1312+
1313+/**
1314 * Get the orientation of a display.
1315 *
1316 * \param [in] output The MirOutput to query
1317@@ -326,6 +389,14 @@
1318 MirOrientation mir_output_get_orientation(MirOutput const* output);
1319
1320 /**
1321+ * Set the orientation of a display.
1322+ *
1323+ * \param [in] output The MirOutput to mutate
1324+ * \param [in] orientation The new MirOrientation for output
1325+ */
1326+void mir_output_set_orientation(MirOutput* output, MirOrientation orientation);
1327+
1328+/**
1329 * Get the scale-factor of a display
1330 *
1331 * The scale-factor specifies the conversion between logical pixels and physical pixels on this output.
1332
1333=== added file 'include/client/mir_toolkit/mir_error.h'
1334--- include/client/mir_toolkit/mir_error.h 1970-01-01 00:00:00 +0000
1335+++ include/client/mir_toolkit/mir_error.h 2016-04-27 09:08:17 +0000
1336@@ -0,0 +1,55 @@
1337+/*
1338+ * Copyright © 2016 Canonical Ltd.
1339+ *
1340+ * This program is free software: you can redistribute it and/or modify it
1341+ * under the terms of the GNU Lesser General Public License version 3,
1342+ * as published by the Free Software Foundation.
1343+ *
1344+ * This program is distributed in the hope that it will be useful,
1345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1347+ * GNU Lesser General Public License for more details.
1348+ *
1349+ * You should have received a copy of the GNU Lesser General Public License
1350+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1351+ *
1352+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1353+ */
1354+
1355+#ifndef MIR_TOOLKIT_MIR_ERROR_H_
1356+#define MIR_TOOLKIT_MIR_ERROR_H_
1357+
1358+#ifdef __cplusplus
1359+/**
1360+ * \addtogroup mir_toolkit
1361+ * @{
1362+ */
1363+extern "C" {
1364+#endif
1365+
1366+#include "client_types.h"
1367+
1368+/**
1369+ * Get the domain of a MirError.
1370+ *
1371+ * The error domain is required to interpret the rest of the error details.
1372+ *
1373+ * \param [in] error The MirError to query
1374+ * \returns The MirErrorDomain that this error belongs to.
1375+ */
1376+MirErrorDomain mir_error_get_domain(MirError const* error);
1377+
1378+/**
1379+ * Get the domain-specific error code of a MirError.
1380+ *
1381+ * \param [in] error The MirError to query
1382+ * \returns The domain-specific error code
1383+ */
1384+uint32_t mir_error_get_code(MirError const* error);
1385+
1386+#ifdef __cplusplus
1387+}
1388+/**@}*/
1389+#endif
1390+
1391+#endif // MIR_TOOLKIT_MIR_ERROR_H_
1392
1393=== modified file 'include/client/mir_toolkit/mir_screencast.h'
1394--- include/client/mir_toolkit/mir_screencast.h 2015-06-17 05:20:42 +0000
1395+++ include/client/mir_toolkit/mir_screencast.h 2016-04-27 09:08:17 +0000
1396@@ -28,6 +28,109 @@
1397 #endif
1398
1399 /**
1400+ * Create a screencast specification.
1401+ *
1402+ * \remark For use with mir_screencast_create() at the width, height,
1403+ * pixel format and capture region must be set.
1404+ *
1405+ * \param [in] connection a valid mir connection
1406+ * \return A handle that can ultimately be passed to
1407+ * mir_surface_create() or mir_surface_apply_spec()
1408+ */
1409+MirScreencastSpec* mir_create_screencast_spec(MirConnection* connection);
1410+
1411+/**
1412+ * Set the requested width, in pixels
1413+ *
1414+ * \param [in] spec Specification to mutate
1415+ * \param [in] width Requested width.
1416+ *
1417+ */
1418+void mir_screencast_spec_set_width(MirScreencastSpec* spec, unsigned int width);
1419+
1420+/**
1421+ * Set the requested height, in pixels
1422+ *
1423+ * \param [in] spec Specification to mutate
1424+ * \param [in] height Requested height.
1425+ *
1426+ */
1427+void mir_screencast_spec_set_height(MirScreencastSpec* spec, unsigned int height);
1428+
1429+/**
1430+ * Set the requested pixel format.
1431+ *
1432+ * \param [in] spec Specification to mutate
1433+ * \param [in] format Requested pixel format
1434+ *
1435+ */
1436+void mir_screencast_spec_set_pixel_format(MirScreencastSpec* spec, MirPixelFormat format);
1437+
1438+
1439+/**
1440+ * Set the rectangular region to capture.
1441+ *
1442+ * \param [in] spec Specification to mutate
1443+ * \param [in] region The rectangular region of the screen to capture
1444+ * specified in virtual screen space coordinates
1445+ *
1446+ */
1447+void mir_screencast_spec_set_capture_region(MirScreencastSpec* spec, MirRectangle const* region);
1448+
1449+/**
1450+ * Set the requested mirror mode.
1451+ *
1452+ * \param [in] spec Specification to mutate
1453+ * \param [in] mode The mirroring mode to apply when screencasting
1454+ *
1455+ */
1456+void mir_screencast_spec_set_mirror_mode(MirScreencastSpec* spec, MirMirrorMode mode);
1457+
1458+/**
1459+ * Set the requested number of buffers to use.
1460+ *
1461+ * \param [in] spec Specification to mutate
1462+ * \param [in] nbuffers The number of buffers to allocate for screencasting
1463+ *
1464+ */
1465+void mir_screencast_spec_set_number_of_buffers(MirScreencastSpec* spec, unsigned int nbuffers);
1466+
1467+/**
1468+ * Release the resources held by a MirScreencastSpec.
1469+ *
1470+ * \param [in] spec Specification to release
1471+ */
1472+void mir_screencast_spec_release(MirScreencastSpec* spec);
1473+
1474+/**
1475+ * Create a screencast from a given specification
1476+ *
1477+ * \param [in] spec Specification of the screencast attributes
1478+ * \return The resulting screencast
1479+ */
1480+MirScreencast* mir_screencast_create_sync(MirScreencastSpec* spec);
1481+
1482+/**
1483+ * Test for a valid screencast
1484+ *
1485+ * \param [in] screencast The screencast to verify
1486+ * \return True if the supplied screencast is valid, false otherwise.
1487+ */
1488+bool mir_screencast_is_valid(MirScreencast *screencast);
1489+
1490+/**
1491+ * Retrieve a text description of the error. The returned string is owned by
1492+ * the library and remains valid until the screencast or the associated
1493+ * connection has been released.
1494+ *
1495+ * \param [in] screencast The screencast
1496+ * \return A text description of any error resulting in an
1497+ * invalid screencast, or the empty string "" if the
1498+ * screencast is valid.
1499+ */
1500+char const *mir_screencast_get_error_message(MirScreencast *screencast);
1501+
1502+/**
1503 * Create a screencast on the supplied connection.
1504 *
1505 * A screencast allows clients to read the contents of the screen.
1506@@ -37,16 +140,16 @@
1507 * \param [in] parameters The screencast parameters
1508 * \return The resulting screencast
1509 */
1510-MirScreencast *mir_connection_create_screencast_sync(
1511- MirConnection *connection,
1512- MirScreencastParameters *parameters);
1513+MirScreencast* mir_connection_create_screencast_sync(
1514+ MirConnection* connection,
1515+ MirScreencastParameters* parameters);
1516
1517 /**
1518 * Release the specified screencast.
1519 * \param [in] screencast The screencast to be released
1520 */
1521 void mir_screencast_release_sync(
1522- MirScreencast *screencast);
1523+ MirScreencast* screencast);
1524
1525 /**
1526 * Retrieve the MirBufferStream associated with a screencast
1527@@ -54,7 +157,7 @@
1528 *
1529 * \param[in] screencast The screencast
1530 */
1531-MirBufferStream* mir_screencast_get_buffer_stream(MirScreencast *screencast);
1532+MirBufferStream* mir_screencast_get_buffer_stream(MirScreencast* screencast);
1533
1534 #ifdef __cplusplus
1535 }
1536
1537=== modified file 'include/common/mir/optional_value.h'
1538--- include/common/mir/optional_value.h 2016-01-29 08:18:22 +0000
1539+++ include/common/mir/optional_value.h 2016-04-27 09:08:17 +0000
1540@@ -29,7 +29,7 @@
1541 {
1542 public:
1543 optional_value() = default;
1544- optional_value(T const& value) : value_{value}, is_set_{true} {}
1545+ optional_value(T const& value) : value_(value), is_set_{true} {}
1546
1547 optional_value& operator=(T const& value)
1548 {
1549
1550=== modified file 'include/common/mir_toolkit/common.h'
1551--- include/common/mir_toolkit/common.h 2016-01-29 08:18:22 +0000
1552+++ include/common/mir_toolkit/common.h 2016-04-27 09:08:17 +0000
1553@@ -169,6 +169,14 @@
1554 mir_orientation_right = 270
1555 } MirOrientation;
1556
1557+/** Mirroring axis relative to the "natural" orientation of the display */
1558+typedef enum MirMirrorMode
1559+{
1560+ mir_mirror_mode_none,
1561+ mir_mirror_mode_vertical,
1562+ mir_mirror_mode_horizontal
1563+} MirMirrorMode;
1564+
1565 typedef enum MirOrientationMode
1566 {
1567 mir_orientation_mode_portrait = 1 << 0,
1568
1569=== modified file 'include/platform/mir/graphics/display_buffer.h'
1570--- include/platform/mir/graphics/display_buffer.h 2016-01-29 08:18:22 +0000
1571+++ include/platform/mir/graphics/display_buffer.h 2016-04-27 09:08:17 +0000
1572@@ -79,6 +79,17 @@
1573 */
1574 virtual MirOrientation orientation() const = 0;
1575
1576+ /** Returns the mirror mode of the display buffer relative to orientation
1577+ *
1578+ * If your DisplayBuffer can do the mirroring itself then this will
1579+ * always return mir_mirror_mode_none. If the DisplayBuffer does not
1580+ * implement the mirroring itself then this function will return the
1581+ * mirror mode the renderer must do after rotation to make things
1582+ * "look right".
1583+ *
1584+ */
1585+ virtual MirMirrorMode mirror_mode() const = 0;
1586+
1587 /** Returns a pointer to the native display buffer object backing this
1588 * display buffer.
1589 *
1590
1591=== modified file 'include/platform/mir/graphics/display_configuration.h'
1592--- include/platform/mir/graphics/display_configuration.h 2016-01-29 08:18:22 +0000
1593+++ include/platform/mir/graphics/display_configuration.h 2016-04-27 09:08:17 +0000
1594@@ -66,7 +66,8 @@
1595 hdmia,
1596 hdmib,
1597 tv,
1598- edp
1599+ edp,
1600+ virt,
1601 };
1602
1603 /**
1604
1605=== modified file 'include/renderers/gl/mir/renderer/gl/render_target.h'
1606--- include/renderers/gl/mir/renderer/gl/render_target.h 2015-10-01 08:58:30 +0000
1607+++ include/renderers/gl/mir/renderer/gl/render_target.h 2016-04-27 09:08:17 +0000
1608@@ -31,7 +31,7 @@
1609 public:
1610 virtual ~RenderTarget() = default;
1611
1612- /** Makes the the current GL render target. */
1613+ /** Makes GL render target current to calling thread */
1614 virtual void make_current() = 0;
1615 /** Releases the current GL render target. */
1616 virtual void release_current() = 0;
1617@@ -41,6 +41,10 @@
1618 * free GL-related resources such as textures and buffers.
1619 */
1620 virtual void swap_buffers() = 0;
1621+ /** Binds any necessary resources (fbos, textures if any)
1622+ * in preparation for drawing.
1623+ */
1624+ virtual void bind() = 0;
1625
1626 protected:
1627 RenderTarget() = default;
1628
1629=== modified file 'include/server/mir/frontend/session.h'
1630--- include/server/mir/frontend/session.h 2016-01-29 08:18:22 +0000
1631+++ include/server/mir/frontend/session.h 2016-04-27 09:08:17 +0000
1632@@ -52,6 +52,8 @@
1633
1634 virtual std::string name() const = 0;
1635
1636+ virtual void send_display_config(graphics::DisplayConfiguration const&) = 0;
1637+
1638 protected:
1639 Session() = default;
1640 Session(Session const&) = delete;
1641
1642=== modified file 'include/server/mir/frontend/session_mediator_report.h'
1643--- include/server/mir/frontend/session_mediator_report.h 2016-01-29 08:18:22 +0000
1644+++ include/server/mir/frontend/session_mediator_report.h 2016-04-27 09:08:17 +0000
1645@@ -38,8 +38,6 @@
1646
1647 virtual void session_create_surface_called(std::string const& app_name) = 0;
1648
1649- virtual void session_next_buffer_called(std::string const& app_name) = 0;
1650-
1651 virtual void session_exchange_buffer_called(std::string const& app_name) = 0;
1652
1653 virtual void session_submit_buffer_called(std::string const& app_name) = 0;
1654@@ -60,6 +58,10 @@
1655
1656 virtual void session_set_base_display_configuration_called(std::string const& app_name) = 0;
1657
1658+ virtual void session_preview_base_display_configuration_called(std::string const& app_name) = 0;
1659+
1660+ virtual void session_confirm_base_display_configuration_called(std::string const& app_name) = 0;
1661+
1662 virtual void session_start_prompt_session_called(std::string const& app_name, pid_t application_process) = 0;
1663
1664 virtual void session_stop_prompt_session_called(std::string const& app_name) = 0;
1665
1666=== modified file 'include/server/mir/input/input_manager.h'
1667--- include/server/mir/input/input_manager.h 2016-03-14 10:13:49 +0000
1668+++ include/server/mir/input/input_manager.h 2016-04-27 09:08:17 +0000
1669@@ -21,20 +21,13 @@
1670 #ifndef MIR_INPUT_INPUT_MANAGER_H_
1671 #define MIR_INPUT_INPUT_MANAGER_H_
1672
1673-#include <memory>
1674-
1675 namespace mir
1676 {
1677 namespace input
1678 {
1679-class Platform;
1680-
1681 class InputManager
1682 {
1683 public:
1684- // TODO Remove add_platform() when we next break mirserver ABI
1685- __attribute__ ((deprecated))
1686- virtual void add_platform(std::shared_ptr<Platform> const& platform) = 0;
1687 virtual void start() = 0;
1688 virtual void stop() = 0;
1689
1690
1691=== modified file 'include/server/mir/scene/session.h'
1692--- include/server/mir/scene/session.h 2016-01-29 08:18:22 +0000
1693+++ include/server/mir/scene/session.h 2016-04-27 09:08:17 +0000
1694@@ -38,13 +38,12 @@
1695 class Session : public frontend::Session
1696 {
1697 public:
1698- virtual void force_requests_to_complete() = 0;
1699+ virtual void drop_outstanding_requests() = 0;
1700 virtual pid_t process_id() const = 0;
1701
1702 virtual void take_snapshot(SnapshotCallback const& snapshot_taken) = 0;
1703 virtual std::shared_ptr<Surface> default_surface() const = 0;
1704 virtual void set_lifecycle_state(MirLifecycleState state) = 0;
1705- virtual void send_display_config(graphics::DisplayConfiguration const&) = 0;
1706
1707 virtual void hide() = 0;
1708 virtual void show() = 0;
1709
1710=== modified file 'include/server/mir/scene/surface.h'
1711--- include/server/mir/scene/surface.h 2016-03-18 15:26:47 +0000
1712+++ include/server/mir/scene/surface.h 2016-04-27 09:08:17 +0000
1713@@ -23,6 +23,7 @@
1714 #include "mir/input/surface.h"
1715 #include "mir/frontend/surface.h"
1716 #include "mir/compositor/compositor_id.h"
1717+#include "mir/optional_value.h"
1718
1719 #include <vector>
1720 #include <list>
1721@@ -40,6 +41,7 @@
1722 {
1723 std::shared_ptr<compositor::BufferStream> stream;
1724 geometry::Displacement displacement;
1725+ optional_value<geometry::Size> size;
1726 };
1727
1728 class SurfaceObserver;
1729
1730=== modified file 'include/server/mir/scene/surface_creation_parameters.h'
1731--- include/server/mir/scene/surface_creation_parameters.h 2016-01-29 08:18:22 +0000
1732+++ include/server/mir/scene/surface_creation_parameters.h 2016-04-27 09:08:17 +0000
1733@@ -101,6 +101,7 @@
1734
1735 mir::optional_value<std::vector<geometry::Rectangle>> input_shape;
1736 mir::optional_value<MirShellChrome> shell_chrome;
1737+ mir::optional_value<std::vector<shell::StreamSpecification>> streams;
1738 };
1739
1740 bool operator==(const SurfaceCreationParameters& lhs, const SurfaceCreationParameters& rhs);
1741
1742=== modified file 'include/server/mir/scene/surface_factory.h'
1743--- include/server/mir/scene/surface_factory.h 2015-06-17 05:20:42 +0000
1744+++ include/server/mir/scene/surface_factory.h 2016-04-27 09:08:17 +0000
1745@@ -21,6 +21,7 @@
1746
1747 #include "mir/scene/surface_creation_parameters.h"
1748 #include <memory>
1749+#include <list>
1750
1751 namespace mir
1752 {
1753@@ -28,6 +29,7 @@
1754 namespace scene
1755 {
1756 class Surface;
1757+class StreamInfo;
1758
1759 class SurfaceFactory
1760 {
1761@@ -36,7 +38,7 @@
1762 virtual ~SurfaceFactory() = default;
1763
1764 virtual std::shared_ptr<Surface> create_surface(
1765- std::shared_ptr<compositor::BufferStream> const&,
1766+ std::list<scene::StreamInfo> const& streams,
1767 SurfaceCreationParameters const& params) = 0;
1768
1769 private:
1770
1771=== modified file 'include/server/mir/shell/surface_specification.h'
1772--- include/server/mir/shell/surface_specification.h 2016-03-18 15:26:47 +0000
1773+++ include/server/mir/shell/surface_specification.h 2016-04-27 09:08:17 +0000
1774@@ -43,6 +43,7 @@
1775 {
1776 frontend::BufferStreamId stream_id;
1777 geometry::Displacement displacement;
1778+ optional_value<geometry::Size> size;
1779 };
1780
1781 /// Specification of surface properties requested by client
1782
1783=== modified file 'include/server/mir/time/alarm_factory.h'
1784--- include/server/mir/time/alarm_factory.h 2015-06-17 05:20:42 +0000
1785+++ include/server/mir/time/alarm_factory.h 2016-04-27 09:08:17 +0000
1786@@ -62,7 +62,7 @@
1787 * \param callback Function to call when the Alarm signals
1788 * \return A handle to an Alarm that can later be scheduled
1789 */
1790- virtual std::unique_ptr<Alarm> create_alarm(std::shared_ptr<LockableCallback> const& callback) = 0;
1791+ virtual std::unique_ptr<Alarm> create_alarm(std::unique_ptr<LockableCallback> callback) = 0;
1792
1793 protected:
1794 AlarmFactory() = default;
1795
1796=== modified file 'include/test/mir/test/display_config_matchers.h'
1797--- include/test/mir/test/display_config_matchers.h 2016-03-14 10:13:49 +0000
1798+++ include/test/mir/test/display_config_matchers.h 2016-04-27 09:08:17 +0000
1799@@ -23,6 +23,7 @@
1800
1801 #include <gmock/gmock.h>
1802
1803+
1804 //avoid a valgrind complaint by defining printer for this type
1805 static void PrintTo(MirDisplayConfiguration const&, ::std::ostream*) __attribute__ ((unused));
1806 void PrintTo(MirDisplayConfiguration const&, ::std::ostream*)
1807
1808=== modified file 'include/test/mir/test/doubles/null_display_buffer.h'
1809--- include/test/mir/test/doubles/null_display_buffer.h 2016-01-29 08:18:22 +0000
1810+++ include/test/mir/test/doubles/null_display_buffer.h 2016-04-27 09:08:17 +0000
1811@@ -34,6 +34,7 @@
1812 geometry::Rectangle view_area() const override { return geometry::Rectangle(); }
1813 bool post_renderables_if_optimizable(graphics::RenderableList const&) override { return false; }
1814 MirOrientation orientation() const override { return mir_orientation_normal; }
1815+ MirMirrorMode mirror_mode() const override { return mir_mirror_mode_none; }
1816 NativeDisplayBuffer* native_display_buffer() override { return this; }
1817 };
1818
1819
1820=== modified file 'include/test/mir/test/doubles/stub_session.h'
1821--- include/test/mir/test/doubles/stub_session.h 2016-01-29 08:18:22 +0000
1822+++ include/test/mir/test/doubles/stub_session.h 2016-04-27 09:08:17 +0000
1823@@ -37,7 +37,7 @@
1824
1825 std::string name() const override;
1826
1827- void force_requests_to_complete() override;
1828+ void drop_outstanding_requests() override;
1829
1830 pid_t process_id() const override;
1831
1832
1833=== modified file 'include/test/mir/test/event_matchers.h'
1834--- include/test/mir/test/event_matchers.h 2016-03-16 06:59:01 +0000
1835+++ include/test/mir/test/event_matchers.h 2016-04-27 09:08:17 +0000
1836@@ -383,16 +383,21 @@
1837 return false;
1838 }
1839
1840-MATCHER_P2(PointerEventWithDiff, dx, dy, "")
1841+MATCHER_P2(PointerEventWithDiff, expect_dx, expect_dy, "")
1842 {
1843 auto pev = maybe_pointer_event(to_address(arg));
1844 if (pev == nullptr)
1845 return false;
1846 if (mir_pointer_event_action(pev) != mir_pointer_action_motion)
1847 return false;
1848- if (mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x) != dx)
1849+ auto const error = 0.00001f;
1850+ auto const actual_dx = mir_pointer_event_axis_value(pev,
1851+ mir_pointer_axis_relative_x);
1852+ if (std::abs(expect_dx - actual_dx) > error)
1853 return false;
1854- if (mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y) != dy)
1855+ auto const actual_dy = mir_pointer_event_axis_value(pev,
1856+ mir_pointer_axis_relative_y);
1857+ if (std::abs(expect_dy - actual_dy) > error)
1858 return false;
1859 return true;
1860 }
1861
1862=== modified file 'include/test/mir/test/signal.h'
1863--- include/test/mir/test/signal.h 2016-01-29 08:18:22 +0000
1864+++ include/test/mir/test/signal.h 2016-04-27 09:08:17 +0000
1865@@ -19,6 +19,8 @@
1866 #ifndef MIR_TEST_SIGNAL_H_
1867 #define MIR_TEST_SIGNAL_H_
1868
1869+#include <gmock/gmock.h>
1870+
1871 #include <condition_variable>
1872 #include <chrono>
1873 #include <mutex>
1874@@ -57,6 +59,17 @@
1875 std::condition_variable cv;
1876 bool signalled{false};
1877 };
1878+
1879+ACTION_P(ReturnFalseAndWakeUp, signal)
1880+{
1881+ signal->raise();
1882+ return false;
1883+}
1884+ACTION_P(WakeUp, signal)
1885+{
1886+ signal->raise();
1887+}
1888+
1889 }
1890 }
1891
1892
1893=== removed file 'include/test/mir/test/wait_condition.h'
1894--- include/test/mir/test/wait_condition.h 2016-03-09 06:39:14 +0000
1895+++ include/test/mir/test/wait_condition.h 1970-01-01 00:00:00 +0000
1896@@ -1,84 +0,0 @@
1897-/*
1898- * Copyright © 2012 Canonical Ltd.
1899- *
1900- * This program is free software: you can redistribute it and/or modify it
1901- * under the terms of the GNU General Public License version 3,
1902- * as published by the Free Software Foundation.
1903- *
1904- * This program is distributed in the hope that it will be useful,
1905- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1906- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1907- * GNU General Public License for more details.
1908- *
1909- * You should have received a copy of the GNU General Public License
1910- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1911- *
1912- * Authored by: Thomas Voß <thomas.voss@canonical.com>
1913- */
1914-
1915-#ifndef MIR_TEST_WAIT_CONDITION_H_
1916-#define MIR_TEST_WAIT_CONDITION_H_
1917-
1918-#include <gmock/gmock.h>
1919-
1920-#include <chrono>
1921-#include <mutex>
1922-#include <condition_variable>
1923-
1924-namespace mir
1925-{
1926-namespace test
1927-{
1928-struct WaitCondition
1929-{
1930- WaitCondition() : woken_(false) {}
1931-
1932- void wait_for_at_most_seconds(std::chrono::seconds const& seconds)
1933- {
1934- std::unique_lock<std::mutex> ul(guard);
1935- condition.wait_for(ul, seconds,
1936- [this] { return woken_; });
1937- }
1938-
1939- void wait_for_at_most_seconds(int seconds)
1940- {
1941- wait_for_at_most_seconds(std::chrono::seconds(seconds));
1942- }
1943-
1944- void wake_up_everyone()
1945- {
1946- std::unique_lock<std::mutex> ul(guard);
1947- woken_ = true;
1948- condition.notify_all();
1949- }
1950-
1951- bool woken()
1952- {
1953- std::unique_lock<std::mutex> ul(guard);
1954- return woken_;
1955- }
1956-
1957- void reset()
1958- {
1959- std::lock_guard<std::mutex> ul(guard);
1960- woken_ = false;
1961- }
1962-
1963- std::mutex guard;
1964- std::condition_variable condition;
1965- bool woken_;
1966-};
1967-
1968-ACTION_P(ReturnFalseAndWakeUp, wait_condition)
1969-{
1970- wait_condition->wake_up_everyone();
1971- return false;
1972-}
1973-ACTION_P(WakeUp, wait_condition)
1974-{
1975- wait_condition->wake_up_everyone();
1976-}
1977-}
1978-}
1979-
1980-#endif // MIR_TEST_WAIT_CONDITION_H_
1981
1982=== modified file 'include/test/mir_test_framework/interprocess_client_server_test.h'
1983--- include/test/mir_test_framework/interprocess_client_server_test.h 2016-01-29 08:18:22 +0000
1984+++ include/test/mir_test_framework/interprocess_client_server_test.h 2016-04-27 09:08:17 +0000
1985@@ -37,6 +37,8 @@
1986 void init_server(std::function<void()> const& init_code);
1987
1988 void run_in_server(std::function<void()> const& exec_code);
1989+ void run_in_server_and_disable_core_dump(
1990+ std::function<void()> const& exec_code);
1991
1992 void run_in_client(std::function<void()> const& client_code);
1993
1994
1995=== modified file 'include/test/mir_test_framework/process.h'
1996--- include/test/mir_test_framework/process.h 2016-01-29 08:18:22 +0000
1997+++ include/test/mir_test_framework/process.h 2016-04-27 09:08:17 +0000
1998@@ -54,6 +54,9 @@
1999 // Was the process terminated by a signal?
2000 bool signalled() const;
2001
2002+ // Was the process terminated normally?
2003+ bool exited_normally() const;
2004+
2005 TerminationReason reason;
2006 int exit_code;
2007 int signal;
2008
2009=== modified file 'playground/demo-shell/demo_compositor.cpp'
2010--- playground/demo-shell/demo_compositor.cpp 2016-01-29 08:18:22 +0000
2011+++ playground/demo-shell/demo_compositor.cpp 2016-04-27 09:08:17 +0000
2012@@ -125,7 +125,7 @@
2013 }
2014 else
2015 {
2016- renderer.set_rotation(display_buffer.orientation());
2017+ renderer.set_output_transform(display_buffer.orientation(), display_buffer.mirror_mode());
2018 renderer.set_viewport(viewport);
2019 renderer.begin(std::move(decorated));
2020 renderer.render(renderable_list);
2021
2022=== modified file 'playground/mir_demo_client_prerendered_frames.c'
2023--- playground/mir_demo_client_prerendered_frames.c 2016-03-16 16:49:59 +0000
2024+++ playground/mir_demo_client_prerendered_frames.c 2016-04-27 09:08:17 +0000
2025@@ -159,14 +159,9 @@
2026 }
2027
2028 MirSurfaceSpec* spec = mir_connection_create_spec_for_normal_surface(connection, width, height, format);
2029- MirSurface* surface = mir_surface_create_sync(spec);
2030- mir_surface_spec_release(spec);
2031-
2032- //reassociate for advanced control
2033- spec = mir_create_surface_spec(connection);
2034 mir_surface_spec_add_presentation_chain(
2035 spec, width, height, displacement_x, displacement_y, chain);
2036- mir_surface_apply_spec(surface, spec);
2037+ MirSurface* surface = mir_surface_create_sync(spec);
2038 mir_surface_spec_release(spec);
2039
2040 int num_prerendered_frames = 20;
2041
2042=== modified file 'src/client/CMakeLists.txt'
2043--- src/client/CMakeLists.txt 2016-03-16 13:45:00 +0000
2044+++ src/client/CMakeLists.txt 2016-04-27 09:08:17 +0000
2045@@ -85,9 +85,13 @@
2046 display_configuration_api.cpp
2047 protobuf_to_native_buffer.cpp
2048 buffer_factory.cpp
2049+ mir_error.cpp
2050+ mir_error.h
2051+ mir_error_api.cpp
2052 ${MIR_CLIENT_SOURCES}
2053 ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/events/surface_output_event.h
2054 ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/mir_display_configuration.h
2055+ ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/mir_error.h
2056 )
2057
2058 # Ensure protobuf C++ headers have been produced before
2059
2060=== modified file 'src/client/buffer.cpp'
2061--- src/client/buffer.cpp 2016-03-16 13:45:00 +0000
2062+++ src/client/buffer.cpp 2016-04-27 09:08:17 +0000
2063@@ -32,11 +32,10 @@
2064 cb_context(context),
2065 buffer_id(buffer_id),
2066 buffer(buffer),
2067- owned(true),
2068+ owned(false),
2069 chain(chain),
2070 usage(usage)
2071 {
2072- cb(nullptr, reinterpret_cast<MirBuffer*>(this), cb_context);
2073 }
2074
2075 int mcl::Buffer::rpc_id() const
2076@@ -49,19 +48,33 @@
2077 std::lock_guard<decltype(mutex)> lk(mutex);
2078 if (!owned)
2079 BOOST_THROW_EXCEPTION(std::logic_error("cannot submit unowned buffer"));
2080+ buffer->mark_as_submitted();
2081 mapped_region.reset();
2082 owned = false;
2083 }
2084
2085+void mcl::Buffer::received()
2086+{
2087+ {
2088+ std::lock_guard<decltype(mutex)> lk(mutex);
2089+ if (!owned)
2090+ owned = true;
2091+ }
2092+ cb(nullptr, reinterpret_cast<MirBuffer*>(this), cb_context);
2093+
2094+}
2095+
2096 void mcl::Buffer::received(MirBufferPackage const& update_package)
2097 {
2098- std::lock_guard<decltype(mutex)> lk(mutex);
2099- if (!owned)
2100 {
2101- owned = true;
2102- buffer->update_from(update_package);
2103- cb(nullptr, reinterpret_cast<MirBuffer*>(this), cb_context);
2104+ std::lock_guard<decltype(mutex)> lk(mutex);
2105+ if (!owned)
2106+ {
2107+ owned = true;
2108+ buffer->update_from(update_package);
2109+ }
2110 }
2111+ cb(nullptr, reinterpret_cast<MirBuffer*>(this), cb_context);
2112 }
2113
2114 MirGraphicsRegion mcl::Buffer::map_region()
2115@@ -116,3 +129,12 @@
2116 {
2117 return buffer->size();
2118 }
2119+std::shared_ptr<mcl::ClientBuffer> mcl::Buffer::client_buffer() const
2120+{
2121+ return buffer;
2122+}
2123+
2124+void mcl::Buffer::increment_age()
2125+{
2126+ buffer->increment_age();
2127+}
2128
2129=== modified file 'src/client/buffer.h'
2130--- src/client/buffer.h 2016-03-16 13:45:00 +0000
2131+++ src/client/buffer.h 2016-04-27 09:08:17 +0000
2132@@ -20,6 +20,7 @@
2133 #define MIR_CLIENT_BUFFER_H
2134
2135 #include "mir_toolkit/mir_buffer.h"
2136+#include "mir/geometry/size.h"
2137 #include <memory>
2138 #include <chrono>
2139 #include <mutex>
2140@@ -43,9 +44,11 @@
2141 int rpc_id() const;
2142
2143 void submitted();
2144+ void received();
2145 void received(MirBufferPackage const& update_message);
2146
2147 MirNativeBuffer* as_mir_native_buffer() const;
2148+ std::shared_ptr<ClientBuffer> client_buffer() const;
2149 MirGraphicsRegion map_region();
2150
2151 void set_fence(MirNativeFence*, MirBufferAccess);
2152@@ -57,6 +60,8 @@
2153 geometry::Size size() const;
2154
2155 MirPresentationChain* allocating_chain() const;
2156+
2157+ void increment_age();
2158 private:
2159 mir_buffer_callback cb;
2160 void* cb_context;
2161
2162=== modified file 'src/client/buffer_stream.cpp'
2163--- src/client/buffer_stream.cpp 2016-03-16 13:45:00 +0000
2164+++ src/client/buffer_stream.cpp 2016-04-27 09:08:17 +0000
2165@@ -19,6 +19,8 @@
2166 #define MIR_LOG_COMPONENT "MirBufferStream"
2167
2168 #include "buffer_stream.h"
2169+#include "buffer.h"
2170+#include "buffer_factory.h"
2171 #include "make_protobuf_object.h"
2172 #include "mir_connection.h"
2173 #include "perf_report.h"
2174@@ -27,6 +29,7 @@
2175 #include "mir_protobuf.pb.h"
2176 #include "buffer_vault.h"
2177 #include "protobuf_to_native_buffer.h"
2178+#include "connection_surface_map.h"
2179
2180 #include "mir/log.h"
2181 #include "mir/client_platform.h"
2182@@ -63,6 +66,7 @@
2183 virtual void lost_connection() = 0;
2184 virtual void set_size(geom::Size) = 0;
2185 virtual MirWaitHandle* set_scale(float, mf::BufferStreamId) = 0;
2186+ virtual void set_interval(int interval) = 0;
2187 virtual ~ServerBufferSemantics() = default;
2188 ServerBufferSemantics() = default;
2189 ServerBufferSemantics(ServerBufferSemantics const&) = delete;
2190@@ -196,6 +200,10 @@
2191 return &scale_wait_handle;
2192 }
2193
2194+ void set_interval(int) override
2195+ {
2196+ }
2197+
2198 std::mutex mutex;
2199 mcl::ClientBufferDepository wrapped;
2200 mir::protobuf::DisplayServer& display_server;
2201@@ -245,11 +253,11 @@
2202 google::protobuf::NewCallback(Requests::ignore_response, protobuf_void));
2203 }
2204
2205- void submit_buffer(int id, mcl::ClientBuffer&) override
2206+ void submit_buffer(mcl::Buffer& buffer) override
2207 {
2208 mp::BufferRequest request;
2209 request.mutable_id()->set_value(stream_id);
2210- request.mutable_buffer()->set_buffer_id(id);
2211+ request.mutable_buffer()->set_buffer_id(buffer.rpc_id());
2212
2213 //note, NewCallback will trigger on exception, deleting this object there
2214 auto protobuf_void = new mp::Void;
2215@@ -272,10 +280,12 @@
2216 {
2217 NewBufferSemantics(
2218 std::shared_ptr<mcl::ClientBufferFactory> const& factory,
2219+ std::shared_ptr<mcl::AsyncBufferFactory> const& mirbuffer_factory,
2220 std::shared_ptr<mcl::ServerBufferRequests> const& requests,
2221+ std::weak_ptr<mcl::SurfaceMap> const& surface_map,
2222 geom::Size size, MirPixelFormat format, int usage,
2223 unsigned int initial_nbuffers) :
2224- vault(factory, requests, size, format, usage, initial_nbuffers)
2225+ vault(factory, mirbuffer_factory, requests, surface_map, size, format, usage, initial_nbuffers)
2226 {
2227 }
2228
2229@@ -295,30 +305,30 @@
2230 std::shared_ptr<mir::client::ClientBuffer> current_buffer() override
2231 {
2232 std::unique_lock<std::mutex> lk(mutex);
2233- if (!current.buffer)
2234+ if (!current)
2235 advance_current_buffer(lk);
2236- return current.buffer;
2237+ return current->client_buffer();
2238 }
2239
2240 uint32_t current_buffer_id() override
2241 {
2242 std::unique_lock<std::mutex> lk(mutex);
2243- if (!current.buffer)
2244+ if (!current)
2245 advance_current_buffer(lk);
2246- return current.id;
2247+ return current->rpc_id();
2248 }
2249
2250 MirWaitHandle* submit(std::function<void()> const& done, geom::Size, MirPixelFormat, int) override
2251 {
2252 std::unique_lock<std::mutex> lk(mutex);
2253- if (!current.buffer)
2254+ if (!current)
2255 advance_current_buffer(lk);
2256 lk.unlock();
2257
2258- vault.deposit(current.buffer);
2259+ vault.deposit(current);
2260
2261 next_buffer_wait_handle.expect_result();
2262- vault.wire_transfer_outbound(current.buffer);
2263+ vault.wire_transfer_outbound(current);
2264 next_buffer_wait_handle.result_received();
2265
2266 lk.lock();
2267@@ -349,11 +359,25 @@
2268 return &scale_wait_handle;
2269 }
2270
2271+ void set_interval(int interval) override
2272+ {
2273+ std::unique_lock<decltype(mutex)> lk(mutex);
2274+ interval = std::max(0, std::min(1, interval));
2275+ if (current_swap_interval == interval)
2276+ return;
2277+ if (interval == 0)
2278+ vault.increase_buffer_count();
2279+ else
2280+ vault.decrease_buffer_count();
2281+ current_swap_interval = interval;
2282+ }
2283+
2284 mcl::BufferVault vault;
2285 std::mutex mutex;
2286- mcl::BufferInfo current{nullptr, 0};
2287+ std::shared_ptr<mcl::Buffer> current{nullptr};
2288 MirWaitHandle next_buffer_wait_handle;
2289 MirWaitHandle scale_wait_handle;
2290+ int current_swap_interval = 1;
2291 };
2292
2293 }
2294@@ -377,7 +401,8 @@
2295 protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()},
2296 ideal_buffer_size(ideal_size),
2297 nbuffers(nbuffers),
2298- creation_wait_handle(creation_wait_handle)
2299+ creation_wait_handle(creation_wait_handle),
2300+ surface_map(std::make_shared<mcl::ConnectionSurfaceMap>())
2301 {
2302 init_swap_interval();
2303 if (!protobuf_bs->has_id())
2304@@ -406,8 +431,8 @@
2305 {
2306 cached_buffer_size = ideal_buffer_size;
2307 buffer_depository = std::make_unique<NewBufferSemantics>(
2308- client_platform->create_buffer_factory(),
2309- std::make_shared<Requests>(display_server, protobuf_bs->id().value()),
2310+ client_platform->create_buffer_factory(), std::make_shared<mcl::BufferFactory>(),
2311+ std::make_shared<Requests>(display_server, protobuf_bs->id().value()), surface_map,
2312 ideal_buffer_size, static_cast<MirPixelFormat>(protobuf_bs->pixel_format()),
2313 protobuf_bs->buffer_usage(), nbuffers);
2314 }
2315@@ -490,8 +515,8 @@
2316 else
2317 {
2318 buffer_depository = std::make_unique<NewBufferSemantics>(
2319- client_platform->create_buffer_factory(),
2320- std::make_shared<Requests>(display_server, protobuf_bs->id().value()),
2321+ client_platform->create_buffer_factory(), std::make_shared<mcl::BufferFactory>(),
2322+ std::make_shared<Requests>(display_server, protobuf_bs->id().value()), surface_map,
2323 ideal_buffer_size, static_cast<MirPixelFormat>(protobuf_bs->pixel_format()), 0, nbuffers);
2324 }
2325 }
2326@@ -638,6 +663,8 @@
2327 configuration.mutable_id()->set_value(protobuf_bs->id().value());
2328 configuration.set_swapinterval(interval);
2329
2330+ buffer_depository->set_interval(interval);
2331+
2332 interval_wait_handle.expect_result();
2333 display_server.configure_buffer_stream(&configuration, protobuf_void.get(),
2334 google::protobuf::NewCallback(this, &mcl::BufferStream::on_swap_interval_set, interval));
2335
2336=== modified file 'src/client/buffer_stream.h'
2337--- src/client/buffer_stream.h 2016-03-16 06:59:01 +0000
2338+++ src/client/buffer_stream.h 2016-04-27 09:08:17 +0000
2339@@ -64,7 +64,7 @@
2340 class ClientPlatform;
2341 class PerfReport;
2342 struct MemoryRegion;
2343-
2344+class SurfaceMap;
2345 class ServerBufferSemantics;
2346 class BufferStream : public EGLNativeSurface, public ClientBufferStream
2347 {
2348@@ -161,6 +161,7 @@
2349 size_t const nbuffers;
2350 std::string error_message;
2351 std::shared_ptr<MirWaitHandle> creation_wait_handle;
2352+ std::shared_ptr<SurfaceMap> const surface_map;
2353 };
2354
2355 }
2356
2357=== modified file 'src/client/buffer_vault.cpp'
2358--- src/client/buffer_vault.cpp 2016-03-16 13:45:00 +0000
2359+++ src/client/buffer_vault.cpp 2016-04-27 09:08:17 +0000
2360@@ -19,6 +19,9 @@
2361 #include "mir/client_buffer_factory.h"
2362 #include "mir/client_buffer.h"
2363 #include "buffer_vault.h"
2364+#include "buffer.h"
2365+#include "buffer_factory.h"
2366+#include "surface_map.h"
2367 #include "mir_protobuf.pb.h"
2368 #include "protobuf_to_native_buffer.h"
2369 #include <algorithm>
2370@@ -32,23 +35,38 @@
2371 enum class mcl::BufferVault::Owner
2372 {
2373 Server,
2374+ Self,
2375 ContentProducer,
2376- Self
2377+ SelfWithContent
2378 };
2379
2380+namespace
2381+{
2382+void ignore(MirPresentationChain*, MirBuffer*, void*)
2383+{
2384+}
2385+}
2386+
2387 mcl::BufferVault::BufferVault(
2388- std::shared_ptr<ClientBufferFactory> const& client_buffer_factory,
2389+ std::shared_ptr<ClientBufferFactory> const& platform_factory,
2390+ std::shared_ptr<AsyncBufferFactory> const& buffer_factory,
2391 std::shared_ptr<ServerBufferRequests> const& server_requests,
2392+ std::weak_ptr<SurfaceMap> const& surface_map,
2393 geom::Size size, MirPixelFormat format, int usage, unsigned int initial_nbuffers) :
2394- factory(client_buffer_factory),
2395+ platform_factory(platform_factory),
2396+ buffer_factory(buffer_factory),
2397 server_requests(server_requests),
2398+ surface_map(surface_map),
2399 format(format),
2400 usage(usage),
2401 size(size),
2402- disconnected_(false)
2403+ disconnected_(false),
2404+ current_buffer_count(initial_nbuffers),
2405+ needed_buffer_count(initial_nbuffers),
2406+ initial_buffer_count(initial_nbuffers)
2407 {
2408- for (auto i = 0u; i < initial_nbuffers; i++)
2409- server_requests->allocate_buffer(size, format, usage);
2410+ for (auto i = 0u; i < initial_buffer_count; i++)
2411+ alloc_buffer(size, format, usage);
2412 }
2413
2414 mcl::BufferVault::~BufferVault()
2415@@ -59,26 +77,57 @@
2416 for (auto& it : buffers)
2417 try
2418 {
2419- server_requests->free_buffer(it.first);
2420+ free_buffer(it.first);
2421 }
2422 catch (...)
2423 {
2424 }
2425 }
2426
2427-mcl::NoTLSFuture<mcl::BufferInfo> mcl::BufferVault::withdraw()
2428+void mcl::BufferVault::alloc_buffer(geom::Size size, MirPixelFormat format, int usage)
2429+{
2430+ buffer_factory->expect_buffer(platform_factory, nullptr, size, format, (MirBufferUsage)usage, ignore, nullptr);
2431+ server_requests->allocate_buffer(size, format, usage);
2432+}
2433+
2434+void mcl::BufferVault::free_buffer(int free_id)
2435+{
2436+ server_requests->free_buffer(free_id);
2437+}
2438+
2439+void mcl::BufferVault::realloc_buffer(int free_id, geom::Size size, MirPixelFormat format, int usage)
2440+{
2441+ free_buffer(free_id);
2442+ alloc_buffer(size, format, usage);
2443+}
2444+
2445+std::shared_ptr<mcl::Buffer> mcl::BufferVault::checked_buffer_from_map(int id)
2446+{
2447+ auto map = surface_map.lock();
2448+ if (!map)
2449+ BOOST_THROW_EXCEPTION(std::logic_error("connection resources lost; cannot access buffer"));
2450+
2451+ if (auto buffer = map->buffer(id))
2452+ return buffer;
2453+ else
2454+ BOOST_THROW_EXCEPTION(std::logic_error("no buffer in map"));
2455+}
2456+
2457+mcl::NoTLSFuture<std::shared_ptr<mcl::Buffer>> mcl::BufferVault::withdraw()
2458 {
2459 std::lock_guard<std::mutex> lk(mutex);
2460- mcl::NoTLSPromise<mcl::BufferInfo> promise;
2461+ mcl::NoTLSPromise<std::shared_ptr<mcl::Buffer>> promise;
2462 auto it = std::find_if(buffers.begin(), buffers.end(),
2463- [this](std::pair<int, BufferEntry> const& entry) {
2464- return ((entry.second.owner == Owner::Self) && (size == entry.second.buffer->size())); });
2465+ [this](std::pair<int, Owner> const& entry) {
2466+ return ((entry.second == Owner::Self) &&
2467+ (checked_buffer_from_map(entry.first)->size() == size));
2468+ });
2469
2470 auto future = promise.get_future();
2471 if (it != buffers.end())
2472 {
2473- it->second.owner = Owner::ContentProducer;
2474- promise.set_value({it->second.buffer, it->first});
2475+ it->second = Owner::ContentProducer;
2476+ promise.set_value(checked_buffer_from_map(it->first));
2477 }
2478 else
2479 {
2480@@ -87,40 +136,34 @@
2481 return future;
2482 }
2483
2484-void mcl::BufferVault::deposit(std::shared_ptr<mcl::ClientBuffer> const& buffer)
2485+void mcl::BufferVault::deposit(std::shared_ptr<mcl::Buffer> const& buffer)
2486 {
2487 std::lock_guard<std::mutex> lk(mutex);
2488- auto it = std::find_if(buffers.begin(), buffers.end(),
2489- [&buffer](std::pair<int, BufferEntry> const& entry) { return buffer == entry.second.buffer; });
2490- if (it == buffers.end() || it->second.owner != Owner::ContentProducer)
2491+ auto it = buffers.find(buffer->rpc_id());
2492+ if (it == buffers.end() || it->second != Owner::ContentProducer)
2493 BOOST_THROW_EXCEPTION(std::logic_error("buffer cannot be deposited"));
2494
2495- it->second.owner = Owner::Self;
2496- it->second.buffer->increment_age();
2497+ it->second = Owner::SelfWithContent;
2498+ checked_buffer_from_map(it->first)->increment_age();
2499 }
2500
2501-void mcl::BufferVault::wire_transfer_outbound(std::shared_ptr<mcl::ClientBuffer> const& buffer)
2502+void mcl::BufferVault::wire_transfer_outbound(std::shared_ptr<mcl::Buffer> const& buffer)
2503 {
2504- int id;
2505- std::shared_ptr<mcl::ClientBuffer> submit_buffer;
2506 std::unique_lock<std::mutex> lk(mutex);
2507- auto it = std::find_if(buffers.begin(), buffers.end(),
2508- [&buffer](std::pair<int, BufferEntry> const& entry) { return buffer == entry.second.buffer; });
2509- if (it == buffers.end() || it->second.owner != Owner::Self)
2510+ auto it = buffers.find(buffer->rpc_id());
2511+ if (it == buffers.end() || it->second != Owner::SelfWithContent)
2512 BOOST_THROW_EXCEPTION(std::logic_error("buffer cannot be transferred"));
2513-
2514- it->second.owner = Owner::Server;
2515- it->second.buffer->mark_as_submitted();
2516- submit_buffer = it->second.buffer;
2517- id = it->first;
2518+ it->second = Owner::Server;
2519 lk.unlock();
2520- server_requests->submit_buffer(id, *submit_buffer);
2521+
2522+ buffer->submitted();
2523+ server_requests->submit_buffer(*buffer);
2524 }
2525
2526 void mcl::BufferVault::wire_transfer_inbound(mp::Buffer const& protobuf_buffer)
2527 {
2528 std::shared_ptr<MirBufferPackage> package = mcl::protobuf_to_native_buffer(protobuf_buffer);
2529-
2530+ std::shared_ptr<mcl::Buffer> buffer;
2531 std::unique_lock<std::mutex> lk(mutex);
2532 auto it = buffers.find(protobuf_buffer.buffer_id());
2533 if (it == buffers.end())
2534@@ -129,39 +172,50 @@
2535 if (sz != size)
2536 {
2537 lk.unlock();
2538- server_requests->free_buffer(protobuf_buffer.buffer_id());
2539 for (int i = 0; i != package->fd_items; ++i)
2540 close(package->fd[i]);
2541
2542- server_requests->allocate_buffer(size, format, usage);
2543+ realloc_buffer(protobuf_buffer.buffer_id(), size, format, usage);
2544 return;
2545 }
2546
2547- buffers[protobuf_buffer.buffer_id()] =
2548- BufferEntry{ factory->create_buffer(package, sz, format), Owner::Self };
2549+ buffer = buffer_factory->generate_buffer(protobuf_buffer);
2550+ if (auto map = surface_map.lock())
2551+ map->insert(protobuf_buffer.buffer_id(), buffer);
2552+ else
2553+ BOOST_THROW_EXCEPTION(std::logic_error("connection resources lost; cannot access buffer"));
2554+
2555+ buffers[protobuf_buffer.buffer_id()] = Owner::Self;
2556+ buffer->received();
2557 }
2558 else
2559 {
2560- it->second.buffer->update_from(*package);
2561- if (size == it->second.buffer->size())
2562- {
2563- it->second.owner = Owner::Self;
2564- }
2565- else
2566+ buffer = checked_buffer_from_map(protobuf_buffer.buffer_id());
2567+ buffer->received(*package);
2568+ auto should_decrease_count = (current_buffer_count > needed_buffer_count);
2569+ if (size != buffer->size() || should_decrease_count)
2570 {
2571 int id = it->first;
2572 buffers.erase(it);
2573 lk.unlock();
2574- server_requests->free_buffer(id);
2575- server_requests->allocate_buffer(size, format, usage);
2576+
2577+ free_buffer(id);
2578+ if (should_decrease_count)
2579+ current_buffer_count--;
2580+ else
2581+ alloc_buffer(size, format, usage);
2582 return;
2583 }
2584+ else
2585+ {
2586+ it->second = Owner::Self;
2587+ }
2588 }
2589
2590 if (!promises.empty())
2591 {
2592- buffers[protobuf_buffer.buffer_id()].owner = Owner::ContentProducer;
2593- promises.front().set_value({buffers[protobuf_buffer.buffer_id()].buffer, protobuf_buffer.buffer_id()});
2594+ buffers[protobuf_buffer.buffer_id()] = Owner::ContentProducer;
2595+ promises.front().set_value(buffer);
2596 promises.pop_front();
2597 }
2598 }
2599@@ -192,7 +246,8 @@
2600 size = new_size;
2601 for (auto it = buffers.begin(); it != buffers.end();)
2602 {
2603- if ((it->second.owner == Owner::Self) && (it->second.buffer->size() != size))
2604+ auto buffer = checked_buffer_from_map(it->first);
2605+ if ((it->second == Owner::Self) && (buffer->size() != size))
2606 {
2607 free_ids.push_back(it->first);
2608 it = buffers.erase(it);
2609@@ -205,8 +260,34 @@
2610 lk.unlock();
2611
2612 for(auto& id : free_ids)
2613+ realloc_buffer(id, new_size, format, usage);
2614+}
2615+
2616+void mcl::BufferVault::increase_buffer_count()
2617+{
2618+ std::unique_lock<std::mutex> lk(mutex);
2619+ current_buffer_count++;
2620+ needed_buffer_count++;
2621+ lk.unlock();
2622+
2623+ alloc_buffer(size, format, usage);
2624+}
2625+
2626+void mcl::BufferVault::decrease_buffer_count()
2627+{
2628+ std::unique_lock<std::mutex> lk(mutex);
2629+ if (current_buffer_count == initial_buffer_count)
2630+ return;
2631+ needed_buffer_count--;
2632+
2633+ auto it = std::find_if(buffers.begin(), buffers.end(),
2634+ [](auto const& entry) { return entry.second == Owner::Self; });
2635+ if (it != buffers.end())
2636 {
2637- server_requests->allocate_buffer(new_size, format, usage);
2638- server_requests->free_buffer(id);
2639+ current_buffer_count--;
2640+ int free_id = it->first;
2641+ buffers.erase(it);
2642+ lk.unlock();
2643+ free_buffer(free_id);
2644 }
2645 }
2646
2647=== modified file 'src/client/buffer_vault.h'
2648--- src/client/buffer_vault.h 2016-03-14 10:13:49 +0000
2649+++ src/client/buffer_vault.h 2016-04-27 09:08:17 +0000
2650@@ -33,12 +33,16 @@
2651 namespace client
2652 {
2653 class ClientBuffer;
2654+class Buffer;
2655+class AsyncBufferFactory;
2656+class SurfaceMap;
2657+
2658 class ServerBufferRequests
2659 {
2660 public:
2661 virtual void allocate_buffer(geometry::Size size, MirPixelFormat format, int usage) = 0;
2662 virtual void free_buffer(int buffer_id) = 0;
2663- virtual void submit_buffer(int buffer_id, ClientBuffer&) = 0;
2664+ virtual void submit_buffer(Buffer&) = 0;
2665 virtual ~ServerBufferRequests() = default;
2666 protected:
2667 ServerBufferRequests() = default;
2668@@ -48,48 +52,50 @@
2669
2670 class ClientBufferFactory;
2671
2672-struct BufferInfo
2673-{
2674- std::shared_ptr<ClientBuffer> buffer;
2675- int id;
2676-};
2677-
2678 class BufferVault
2679 {
2680 public:
2681 BufferVault(
2682 std::shared_ptr<ClientBufferFactory> const&,
2683+ std::shared_ptr<AsyncBufferFactory> const&,
2684 std::shared_ptr<ServerBufferRequests> const&,
2685+ std::weak_ptr<SurfaceMap> const&,
2686 geometry::Size size, MirPixelFormat format, int usage,
2687 unsigned int initial_nbuffers);
2688 ~BufferVault();
2689
2690- NoTLSFuture<BufferInfo> withdraw();
2691- void deposit(std::shared_ptr<ClientBuffer> const& buffer);
2692+ NoTLSFuture<std::shared_ptr<Buffer>> withdraw();
2693+ void deposit(std::shared_ptr<Buffer> const& buffer);
2694 void wire_transfer_inbound(protobuf::Buffer const&);
2695- void wire_transfer_outbound(std::shared_ptr<ClientBuffer> const& buffer);
2696+ void wire_transfer_outbound(std::shared_ptr<Buffer> const& buffer);
2697 void set_size(geometry::Size);
2698 void disconnected();
2699 void set_scale(float scale);
2700+ void increase_buffer_count();
2701+ void decrease_buffer_count();
2702
2703 private:
2704- std::shared_ptr<ClientBufferFactory> const factory;
2705+ void alloc_buffer(geometry::Size size, MirPixelFormat format, int usage);
2706+ void free_buffer(int free_id);
2707+ void realloc_buffer(int free_id, geometry::Size size, MirPixelFormat format, int usage);
2708+ std::shared_ptr<Buffer> checked_buffer_from_map(int id);
2709+
2710+ std::shared_ptr<ClientBufferFactory> const platform_factory;
2711+ std::shared_ptr<AsyncBufferFactory> const buffer_factory;
2712 std::shared_ptr<ServerBufferRequests> const server_requests;
2713+ std::weak_ptr<SurfaceMap> const surface_map;
2714 MirPixelFormat const format;
2715 int const usage;
2716
2717 enum class Owner;
2718- struct BufferEntry
2719- {
2720- std::shared_ptr<ClientBuffer> buffer;
2721- Owner owner;
2722- };
2723-
2724 std::mutex mutex;
2725- std::map<int, BufferEntry> buffers;
2726- std::deque<NoTLSPromise<BufferInfo>> promises;
2727+ std::map<int, Owner> buffers;
2728+ std::deque<NoTLSPromise<std::shared_ptr<Buffer>>> promises;
2729 geometry::Size size;
2730 bool disconnected_;
2731+ size_t current_buffer_count;
2732+ size_t needed_buffer_count;
2733+ size_t const initial_buffer_count;
2734 };
2735 }
2736 }
2737
2738=== modified file 'src/client/client_buffer_depository.cpp'
2739--- src/client/client_buffer_depository.cpp 2015-06-17 05:20:42 +0000
2740+++ src/client/client_buffer_depository.cpp 2016-04-27 09:08:17 +0000
2741@@ -36,6 +36,13 @@
2742 set_max_buffers(max_buffers);
2743 }
2744
2745+mcl::ClientBufferDepository::ClientBufferDepository(
2746+ std::shared_ptr<ClientBufferFactory> const& factory) :
2747+ factory(factory),
2748+ max_buffers(0)
2749+{
2750+}
2751+
2752 void mcl::ClientBufferDepository::deposit_package(std::shared_ptr<MirBufferPackage> const& package, int id, geometry::Size size, MirPixelFormat pf)
2753 {
2754 auto existing_buffer_id_pair = buffers.end();
2755@@ -61,7 +68,7 @@
2756 buffers.erase(existing_buffer_id_pair);
2757 }
2758
2759- if (buffers.size() > max_buffers)
2760+ if (max_buffers != 0 && buffers.size() > max_buffers)
2761 buffers.pop_back();
2762 }
2763
2764
2765=== modified file 'src/client/client_buffer_depository.h'
2766--- src/client/client_buffer_depository.h 2015-06-17 05:20:42 +0000
2767+++ src/client/client_buffer_depository.h 2016-04-27 09:08:17 +0000
2768@@ -56,6 +56,9 @@
2769 /// passing. As such, this number needs to be shared between the server and client libraries.
2770 ClientBufferDepository(std::shared_ptr<ClientBufferFactory> const& factory, int max_buffers);
2771
2772+ /// Creates a depository with no explicit limit
2773+ ClientBufferDepository(std::shared_ptr<ClientBufferFactory> const& factory);
2774+
2775 /// Construct a ClientBuffer from the IPC data, and use it as the current buffer.
2776
2777 /// This also marks the previous current buffer (if any) as being submitted to the server.
2778
2779=== modified file 'src/client/display_configuration_api.cpp'
2780--- src/client/display_configuration_api.cpp 2016-03-14 10:13:49 +0000
2781+++ src/client/display_configuration_api.cpp 2016-04-27 09:08:17 +0000
2782@@ -291,6 +291,14 @@
2783 return static_cast<MirOrientation>(output->orientation());
2784 }
2785
2786+void mir_output_set_orientation(MirOutput* client_output, MirOrientation orientation)
2787+{
2788+ auto output = client_to_output(client_output);
2789+
2790+ output->set_orientation(orientation);
2791+}
2792+
2793+
2794 float mir_output_get_scale_factor(MirOutput const* client_output)
2795 {
2796 auto output = client_to_output(client_output);
2797
2798=== modified file 'src/client/event.cpp'
2799--- src/client/event.cpp 2016-01-29 08:18:22 +0000
2800+++ src/client/event.cpp 2016-04-27 09:08:17 +0000
2801@@ -39,10 +39,10 @@
2802 template <typename EventType>
2803 void expect_event_type(EventType const* ev, MirEventType t)
2804 {
2805- if (ev->type != t)
2806+ if (ev->type() != t)
2807 {
2808 mir::log_critical("Expected " + mir::event_type_to_string(t) + " but event is of type " +
2809- mir::event_type_to_string(ev->type));
2810+ mir::event_type_to_string(ev->type()));
2811 abort();
2812 }
2813 }
2814@@ -76,82 +76,82 @@
2815
2816 MirEventType mir_event_get_type(MirEvent const* ev)
2817 {
2818- switch (ev->type)
2819+ switch (ev->type())
2820 {
2821 case mir_event_type_key:
2822 case mir_event_type_motion:
2823 return mir_event_type_input;
2824 default:
2825- return ev->type;
2826+ return ev->type();
2827 }
2828 }
2829
2830 MirInputEvent const* mir_event_get_input_event(MirEvent const* ev)
2831 {
2832- if (ev->type != mir_event_type_key && ev->type != mir_event_type_motion)
2833+ if (ev->type() != mir_event_type_key && ev->type() != mir_event_type_motion)
2834 {
2835 mir::log_critical("Expected input event but event is of type " +
2836- mir::event_type_to_string(ev->type));
2837+ mir::event_type_to_string(ev->type()));
2838 abort();
2839 }
2840
2841- return reinterpret_cast<MirInputEvent const*>(ev);
2842+ return ev->to_input();
2843 }
2844
2845 MirSurfaceEvent const* mir_event_get_surface_event(MirEvent const* ev)
2846 {
2847 expect_event_type(ev, mir_event_type_surface);
2848
2849- return &ev->surface;
2850+ return ev->to_surface();
2851 }
2852
2853 MirResizeEvent const* mir_event_get_resize_event(MirEvent const* ev)
2854 {
2855 expect_event_type(ev, mir_event_type_resize);
2856
2857- return &ev->resize;
2858+ return ev->to_resize();
2859 }
2860
2861 MirPromptSessionEvent const* mir_event_get_prompt_session_event(MirEvent const* ev)
2862 {
2863 expect_event_type(ev, mir_event_type_prompt_session_state_change);
2864
2865- return &ev->prompt_session;
2866+ return ev->to_prompt_session();
2867 }
2868
2869 MirOrientationEvent const* mir_event_get_orientation_event(MirEvent const* ev)
2870 {
2871 expect_event_type(ev, mir_event_type_orientation);
2872
2873- return &ev->orientation;
2874+ return ev->to_orientation();
2875 }
2876
2877 MirCloseSurfaceEvent const* mir_event_get_close_surface_event(MirEvent const* ev)
2878 {
2879 expect_event_type(ev, mir_event_type_close_surface);
2880
2881- return &ev->close_surface;
2882+ return ev->to_close_surface();
2883 }
2884
2885 MirKeymapEvent const* mir_event_get_keymap_event(MirEvent const* ev)
2886 {
2887 expect_event_type(ev, mir_event_type_keymap);
2888
2889- return &ev->keymap;
2890+ return ev->to_keymap();
2891 }
2892
2893 MirInputConfigurationEvent const* mir_event_get_input_configuration_event(MirEvent const* ev)
2894 {
2895 expect_event_type(ev, mir_event_type_input_configuration);
2896
2897- return &ev->input_configuration;
2898+ return ev->to_input_configuration();
2899 }
2900
2901 MirSurfaceOutputEvent const* mir_event_get_surface_output_event(MirEvent const* ev)
2902 {
2903 expect_event_type(ev, mir_event_type_surface_output);
2904
2905- return &ev->surface_output;
2906+ return ev->to_surface_output();
2907 }
2908
2909 /* Surface event accessors */
2910@@ -160,14 +160,14 @@
2911 {
2912 expect_event_type(ev, mir_event_type_surface);
2913
2914- return ev->attrib;
2915+ return ev->attrib();
2916 }
2917
2918 int mir_surface_event_get_attribute_value(MirSurfaceEvent const* ev)
2919 {
2920 expect_event_type(ev, mir_event_type_surface);
2921
2922- return ev->value;
2923+ return ev->value();
2924 }
2925
2926 /* Resize event accessors */
2927@@ -175,13 +175,13 @@
2928 int mir_resize_event_get_width(MirResizeEvent const* ev)
2929 {
2930 expect_event_type(ev, mir_event_type_resize);
2931- return ev->width;
2932+ return ev->width();
2933 }
2934
2935 int mir_resize_event_get_height(MirResizeEvent const* ev)
2936 {
2937 expect_event_type(ev, mir_event_type_resize);
2938- return ev->height;
2939+ return ev->height();
2940 }
2941
2942 /* Prompt session event accessors */
2943@@ -189,7 +189,7 @@
2944 MirPromptSessionState mir_prompt_session_event_get_state(MirPromptSessionEvent const* ev)
2945 {
2946 expect_event_type(ev, mir_event_type_prompt_session_state_change);
2947- return ev->new_state;
2948+ return ev->new_state();
2949 }
2950
2951 /* Orientation event accessors */
2952@@ -197,7 +197,7 @@
2953 MirOrientation mir_orientation_event_get_direction(MirOrientationEvent const* ev)
2954 {
2955 expect_event_type(ev, mir_event_type_orientation);
2956- return ev->direction;
2957+ return ev->direction();
2958 }
2959
2960 /* Keymap event accessors */
2961@@ -206,15 +206,15 @@
2962 {
2963 expect_event_type(ev, mir_event_type_keymap);
2964
2965- *buffer = ev->buffer;
2966- *length = ev->size;
2967+ *buffer = ev->buffer();
2968+ *length = ev->size();
2969 }
2970
2971 MirInputDeviceId mir_keymap_event_get_device_id(MirKeymapEvent const* ev)
2972 {
2973 expect_event_type(ev, mir_event_type_keymap);
2974
2975- return ev->device_id;
2976+ return ev->device_id();
2977 }
2978
2979 /* Input configuration event accessors */
2980@@ -222,19 +222,19 @@
2981 MirInputConfigurationAction mir_input_configuration_event_get_action(MirInputConfigurationEvent const* ev)
2982 {
2983 expect_event_type(ev, mir_event_type_input_configuration);
2984- return ev->action;
2985+ return ev->action();
2986 }
2987
2988 int64_t mir_input_configuration_event_get_time(MirInputConfigurationEvent const* ev)
2989 {
2990 expect_event_type(ev, mir_event_type_input_configuration);
2991- return ev->when.count();
2992+ return ev->when().count();
2993 }
2994
2995 MirInputDeviceId mir_input_configuration_event_get_device_id(MirInputConfigurationEvent const* ev)
2996 {
2997 expect_event_type(ev, mir_event_type_input_configuration);
2998- return ev->id;
2999+ return ev->id();
3000 }
3001
3002 /* Surface output event accessors */
3003@@ -242,45 +242,40 @@
3004 int mir_surface_output_event_get_dpi(MirSurfaceOutputEvent const* ev)
3005 {
3006 expect_event_type(ev, mir_event_type_surface_output);
3007- return ev->dpi;
3008+ return ev->dpi();
3009 }
3010
3011 MirFormFactor mir_surface_output_event_get_form_factor(MirSurfaceOutputEvent const* ev)
3012 {
3013 expect_event_type(ev, mir_event_type_surface_output);
3014- return ev->form_factor;
3015+ return ev->form_factor();
3016 }
3017
3018 float mir_surface_output_event_get_scale(MirSurfaceOutputEvent const* ev)
3019 {
3020 expect_event_type(ev, mir_event_type_surface_output);
3021- return ev->scale;
3022+ return ev->scale();
3023 }
3024
3025 uint32_t mir_surface_output_event_get_output_id(MirSurfaceOutputEvent const *ev)
3026 {
3027 expect_event_type(ev, mir_event_type_surface_output);
3028- return ev->output_id;
3029+ return ev->output_id();
3030 }
3031
3032 // TODO: Until we opaquify the MirEvent structure and add
3033 // a ref count ref is implemented as copy.
3034 MirEvent const* mir_event_ref(MirEvent const* ev)
3035 {
3036- MirEvent *new_ev = new MirEvent;
3037- memcpy(new_ev, ev, sizeof(MirEvent));
3038-
3039- if (mir_event_get_type(new_ev) == mir_event_type_keymap)
3040- {
3041- // malloc to match xkbcommons allocation behavior
3042- auto buffer = static_cast<char*>(malloc(new_ev->keymap.size));
3043- std::memcpy(buffer, ev->keymap.buffer, new_ev->keymap.size);
3044- new_ev->keymap.buffer = buffer;
3045- }
3046- return new_ev;
3047+ return ev->clone();
3048 }
3049
3050 void mir_event_unref(MirEvent const* ev)
3051 {
3052+ if (mir_event_get_type(ev) == mir_event_type_keymap)
3053+ {
3054+ const_cast<MirEvent*>(ev)->to_keymap()->free_buffer();
3055+ }
3056+
3057 delete const_cast<MirEvent*>(ev);
3058 }
3059
3060=== modified file 'src/client/events/CMakeLists.txt'
3061--- src/client/events/CMakeLists.txt 2016-01-22 16:40:15 +0000
3062+++ src/client/events/CMakeLists.txt 2016-04-27 09:08:17 +0000
3063@@ -17,7 +17,6 @@
3064 list(APPEND MIR_CLIENT_SOURCES
3065 ${CMAKE_CURRENT_SOURCE_DIR}/event_builders.cpp
3066 ${CMAKE_CURRENT_SOURCE_DIR}/serialization.cpp
3067- ${CMAKE_CURRENT_SOURCE_DIR}/make_empty_event.cpp
3068 )
3069
3070 set(MIR_CLIENT_SOURCES ${MIR_CLIENT_SOURCES} PARENT_SCOPE)
3071
3072=== modified file 'src/client/events/event_builders.cpp'
3073--- src/client/events/event_builders.cpp 2016-01-29 08:18:22 +0000
3074+++ src/client/events/event_builders.cpp 2016-04-27 09:08:17 +0000
3075@@ -20,8 +20,6 @@
3076
3077 #include "mir/log.h"
3078
3079-#include "make_empty_event.h"
3080-
3081 #include "mir/events/event_builders.h"
3082 #include "mir/events/event_private.h"
3083 #include "mir/cookie/blob.h"
3084@@ -56,56 +54,71 @@
3085
3086 return blob;
3087 }
3088+
3089+template <class T>
3090+T* new_event()
3091+{
3092+ T* t = new T;
3093+
3094+ return t;
3095+}
3096+
3097+template <class T>
3098+mir::EventUPtr make_uptr_event(T* e)
3099+{
3100+ return mir::EventUPtr(e, ([](MirEvent* e) { delete reinterpret_cast<T*>(e); }));
3101+}
3102+
3103 }
3104
3105 mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id, MirOrientation orientation)
3106 {
3107- auto e = make_empty_event();
3108-
3109- e->type = mir_event_type_orientation;
3110- e->orientation.surface_id = surface_id.as_value();
3111- e->orientation.direction = orientation;
3112- return e;
3113+ auto e = new_event<MirOrientationEvent>();
3114+
3115+ e->set_surface_id(surface_id.as_value());
3116+ e->set_direction(orientation);
3117+
3118+ return make_uptr_event(e);
3119 }
3120
3121 mir::EventUPtr mev::make_event(MirPromptSessionState state)
3122 {
3123- auto e = make_empty_event();
3124-
3125- e->type = mir_event_type_prompt_session_state_change;
3126- e->prompt_session.new_state = state;
3127- return e;
3128+ auto e = new_event<MirPromptSessionEvent>();
3129+
3130+ e->set_new_state(state);
3131+
3132+ return make_uptr_event(e);
3133 }
3134
3135 mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id, geom::Size const& size)
3136 {
3137- auto e = make_empty_event();
3138-
3139- e->type = mir_event_type_resize;
3140- e->resize.surface_id = surface_id.as_value();
3141- e->resize.width = size.width.as_int();
3142- e->resize.height = size.height.as_int();
3143- return e;
3144+ auto e = new_event<MirResizeEvent>();
3145+
3146+ e->set_surface_id(surface_id.as_value());
3147+ e->set_width(size.width.as_int());
3148+ e->set_height(size.height.as_int());
3149+
3150+ return make_uptr_event(e);
3151 }
3152
3153 mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id, MirSurfaceAttrib attribute, int value)
3154 {
3155- auto e = make_empty_event();
3156-
3157- e->type = mir_event_type_surface;
3158- e->surface.id = surface_id.as_value();
3159- e->surface.attrib = attribute;
3160- e->surface.value = value;
3161- return e;
3162+ auto e = new_event<MirSurfaceEvent>();
3163+
3164+ e->set_id(surface_id.as_value());
3165+ e->set_attrib(attribute);
3166+ e->set_value(value);
3167+
3168+ return make_uptr_event(e);
3169 }
3170
3171 mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id)
3172 {
3173- auto e = make_empty_event();
3174-
3175- e->type = mir_event_type_close_surface;
3176- e->close_surface.surface_id = surface_id.as_value();
3177- return e;
3178+ auto e = new_event<MirCloseSurfaceEvent>();
3179+
3180+ e->set_surface_id(surface_id.as_value());
3181+
3182+ return make_uptr_event(e);
3183 }
3184
3185 mir::EventUPtr mev::make_event(
3186@@ -115,16 +128,15 @@
3187 MirFormFactor form_factor,
3188 uint32_t output_id)
3189 {
3190- auto e = make_empty_event();
3191-
3192- e->type = mir_event_type_surface_output;
3193- e->surface_output.surface_id = surface_id.as_value();
3194- e->surface_output.dpi = dpi;
3195- e->surface_output.scale = scale;
3196- e->surface_output.form_factor = form_factor;
3197- e->surface_output.output_id = output_id;
3198-
3199- return e;
3200+ auto e = new_event<MirSurfaceOutputEvent>();
3201+
3202+ e->set_surface_id(surface_id.as_value());
3203+ e->set_dpi(dpi);
3204+ e->set_scale(scale);
3205+ e->set_form_factor(form_factor);
3206+ e->set_output_id(output_id);
3207+
3208+ return make_uptr_event(e);
3209 }
3210
3211 namespace
3212@@ -162,36 +174,34 @@
3213 std::vector<uint8_t> const& cookie, MirKeyboardAction action, xkb_keysym_t key_code,
3214 int scan_code, MirInputEventModifiers modifiers)
3215 {
3216- auto e = make_empty_event();
3217-
3218- e->type = mir_event_type_key;
3219- auto& kev = e->key;
3220- kev.device_id = device_id;
3221- kev.source_id = AINPUT_SOURCE_KEYBOARD;
3222- kev.event_time = timestamp;
3223- kev.cookie = vector_to_cookie_as_blob(cookie);
3224- kev.action = action;
3225- kev.key_code = key_code;
3226- kev.scan_code = scan_code;
3227- kev.modifiers = modifiers;
3228-
3229- return e;
3230+ auto e = new_event<MirKeyboardEvent>();
3231+
3232+ e->set_device_id(device_id);
3233+ e->set_source_id(AINPUT_SOURCE_KEYBOARD);
3234+ e->set_event_time(timestamp);
3235+ e->set_cookie(vector_to_cookie_as_blob(cookie));
3236+ e->set_action(action);
3237+ e->set_key_code(key_code);
3238+ e->set_scan_code(scan_code);
3239+ e->set_modifiers(modifiers);
3240+
3241+ return make_uptr_event(e);
3242 }
3243
3244 void mev::set_modifier(MirEvent& event, MirInputEventModifiers modifiers)
3245 {
3246- switch(event.type)
3247+ switch(event.type())
3248 {
3249 case mir_event_type_key:
3250 {
3251- auto& kev = event.key;
3252- kev.modifiers = modifiers;
3253+ auto& kev = *event.to_input()->to_keyboard();
3254+ kev.set_modifiers(modifiers);
3255 break;
3256 }
3257 case mir_event_type_motion:
3258 {
3259- auto& mev = event.motion;
3260- mev.modifiers = modifiers;
3261+ auto& mev = *event.to_input()->to_motion();
3262+ mev.set_modifiers(modifiers);
3263 break;
3264 }
3265 default:
3266@@ -201,23 +211,23 @@
3267
3268 void mev::set_cursor_position(MirEvent& event, mir::geometry::Point const& pos)
3269 {
3270- if (event.type != mir_event_type_motion &&
3271- event.motion.source_id != AINPUT_SOURCE_MOUSE &&
3272- event.motion.pointer_count == 1)
3273+ if (event.type() != mir_event_type_motion &&
3274+ event.to_input()->to_motion()->source_id() != AINPUT_SOURCE_MOUSE &&
3275+ event.to_input()->to_motion()->pointer_count() == 1)
3276 BOOST_THROW_EXCEPTION(std::invalid_argument("Cursor position is only valid for pointer events."));
3277
3278- event.motion.pointer_coordinates[0].x = pos.x.as_float();
3279- event.motion.pointer_coordinates[0].y = pos.y.as_float();
3280+ event.to_input()->to_motion()->set_x(0, pos.x.as_float());
3281+ event.to_input()->to_motion()->set_y(0, pos.y.as_float());
3282 }
3283
3284 void mev::set_button_state(MirEvent& event, MirPointerButtons button_state)
3285 {
3286- if (event.type != mir_event_type_motion &&
3287- event.motion.source_id != AINPUT_SOURCE_MOUSE &&
3288- event.motion.pointer_count == 1)
3289+ if (event.type() != mir_event_type_motion &&
3290+ event.to_input()->to_motion()->source_id() != AINPUT_SOURCE_MOUSE &&
3291+ event.to_input()->to_motion()->pointer_count() == 1)
3292 BOOST_THROW_EXCEPTION(std::invalid_argument("Cursor position is only valid for pointer events."));
3293
3294- event.motion.buttons = button_state;
3295+ event.to_input()->to_motion()->set_buttons(button_state);
3296 }
3297
3298 // Deprecated version with uint64_t mac
3299@@ -239,17 +249,15 @@
3300 mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
3301 std::vector<uint8_t> const& cookie, MirInputEventModifiers modifiers)
3302 {
3303- auto e = make_empty_event();
3304-
3305- e->type = mir_event_type_motion;
3306- auto& mev = e->motion;
3307- mev.device_id = device_id;
3308- mev.event_time = timestamp;
3309- mev.cookie = vector_to_cookie_as_blob(cookie);
3310- mev.modifiers = modifiers;
3311- mev.source_id = AINPUT_SOURCE_TOUCHSCREEN;
3312-
3313- return e;
3314+ auto e = new_event<MirMotionEvent>();
3315+
3316+ e->set_device_id(device_id);
3317+ e->set_event_time(timestamp);
3318+ e->set_cookie(vector_to_cookie_as_blob(cookie));
3319+ e->set_modifiers(modifiers);
3320+ e->set_source_id(AINPUT_SOURCE_TOUCHSCREEN);
3321+
3322+ return make_uptr_event(e);
3323 }
3324
3325 // Deprecated version with uint64_t mac
3326@@ -270,17 +278,19 @@
3327 MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,
3328 float pressure_value, float touch_major_value, float touch_minor_value, float size_value)
3329 {
3330- auto& mev = event.motion;
3331- auto& pc = mev.pointer_coordinates[mev.pointer_count++];
3332- pc.id = touch_id;
3333- pc.tool_type = tooltype;
3334- pc.x = x_axis_value;
3335- pc.y = y_axis_value;
3336- pc.pressure = pressure_value;
3337- pc.touch_major = touch_major_value;
3338- pc.touch_minor = touch_minor_value;
3339- pc.size = size_value;
3340- pc.action = action;
3341+ auto mev = event.to_input()->to_motion();
3342+ auto current_index = mev->pointer_count();
3343+ mev->set_pointer_count(current_index + 1);
3344+
3345+ mev->set_id(current_index, touch_id);
3346+ mev->set_tool_type(current_index, tooltype);
3347+ mev->set_x(current_index, x_axis_value);
3348+ mev->set_y(current_index, y_axis_value);
3349+ mev->set_pressure(current_index, pressure_value);
3350+ mev->set_touch_major(current_index, touch_major_value);
3351+ mev->set_touch_minor(current_index, touch_minor_value);
3352+ mev->set_size(current_index, size_value);
3353+ mev->set_action(current_index, action);
3354 }
3355
3356 mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
3357@@ -290,28 +300,26 @@
3358 float hscroll_value, float vscroll_value,
3359 float relative_x_value, float relative_y_value)
3360 {
3361- auto e = make_empty_event();
3362-
3363- e->type = mir_event_type_motion;
3364- auto& mev = e->motion;
3365- mev.device_id = device_id;
3366- mev.event_time = timestamp;
3367- mev.cookie = vector_to_cookie_as_blob(cookie);
3368- mev.modifiers = modifiers;
3369- mev.source_id = AINPUT_SOURCE_MOUSE;
3370- mev.buttons = buttons_pressed;
3371-
3372- mev.pointer_count = 1;
3373- auto& pc = mev.pointer_coordinates[0];
3374- mev.pointer_coordinates[0].action = action;
3375- pc.x = x_axis_value;
3376- pc.y = y_axis_value;
3377- pc.dx = relative_x_value;
3378- pc.dy = relative_y_value;
3379- pc.hscroll = hscroll_value;
3380- pc.vscroll = vscroll_value;
3381-
3382- return e;
3383+ auto e = new_event<MirMotionEvent>();
3384+
3385+ auto& mev = *e->to_input()->to_motion();
3386+ mev.set_device_id(device_id);
3387+ mev.set_event_time(timestamp);
3388+ mev.set_cookie(vector_to_cookie_as_blob(cookie));
3389+ mev.set_modifiers(modifiers);
3390+ mev.set_source_id(AINPUT_SOURCE_MOUSE);
3391+ mev.set_buttons(buttons_pressed);
3392+
3393+ mev.set_pointer_count(1);
3394+ mev.set_action(0, action);
3395+ mev.set_x(0, x_axis_value);
3396+ mev.set_y(0, y_axis_value);
3397+ mev.set_dx(0, relative_x_value);
3398+ mev.set_dy(0, relative_y_value);
3399+ mev.set_hscroll(0, hscroll_value);
3400+ mev.set_vscroll(0, vscroll_value);
3401+
3402+ return make_uptr_event(e);
3403 }
3404
3405 // Deprecated version with uint64_t mac
3406@@ -365,7 +373,16 @@
3407 mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id, MirInputDeviceId id, std::string const& model,
3408 std::string const& layout, std::string const& variant, std::string const& options)
3409 {
3410- auto e = make_empty_event();
3411+ auto e = new_event<MirKeymapEvent>();
3412+ auto ep = mir::EventUPtr(e, [](MirEvent* e) {
3413+ // xkbcommon creates the keymap through malloc
3414+ if (e && e->type() == mir_event_type_keymap)
3415+ {
3416+ e->to_keymap()->free_buffer();
3417+ }
3418+
3419+ delete e;
3420+ });
3421
3422 auto ctx = mi::make_unique_context();
3423 auto map = mi::make_unique_keymap(ctx.get(), model, layout, variant, options);
3424@@ -373,24 +390,22 @@
3425 if (!map.get())
3426 BOOST_THROW_EXCEPTION(std::runtime_error("failed to assemble keymap from given parameters"));
3427
3428- e->type = mir_event_type_keymap;
3429- e->keymap.surface_id = surface_id.as_value();
3430- e->keymap.device_id = id;
3431+ e->set_surface_id(surface_id.as_value());
3432+ e->set_device_id(id);
3433 // TODO consider caching compiled keymaps
3434- e->keymap.buffer = xkb_keymap_get_as_string(map.get(), XKB_KEYMAP_FORMAT_TEXT_V1);
3435- e->keymap.size = strlen(e->keymap.buffer);
3436+ e->set_buffer(xkb_keymap_get_as_string(map.get(), XKB_KEYMAP_FORMAT_TEXT_V1));
3437+ e->set_size(strlen(e->to_keymap()->buffer()));
3438
3439- return e;
3440+ return ep;
3441 }
3442
3443 mir::EventUPtr mev::make_event(MirInputConfigurationAction action, MirInputDeviceId id, std::chrono::nanoseconds time)
3444 {
3445- auto e = make_empty_event();
3446-
3447- e->type = mir_event_type_input_configuration;
3448- e->input_configuration.action = action;
3449- e->input_configuration.when = time;
3450- e->input_configuration.id = id;
3451-
3452- return e;
3453+ auto e = new_event<MirInputConfigurationEvent>();
3454+
3455+ e->set_action(action);
3456+ e->set_when(time);
3457+ e->set_id(id);
3458+
3459+ return make_uptr_event(e);
3460 }
3461
3462=== removed file 'src/client/events/make_empty_event.cpp'
3463--- src/client/events/make_empty_event.cpp 2016-01-22 16:40:15 +0000
3464+++ src/client/events/make_empty_event.cpp 1970-01-01 00:00:00 +0000
3465@@ -1,42 +0,0 @@
3466-/*
3467- * Copyright © 2016 Canonical Ltd.
3468- *
3469- * This program is free software: you can redistribute it and/or modify it
3470- * under the terms of the GNU Lesser General Public License version 3,
3471- * as published by the Free Software Foundation.
3472- *
3473- * This program is distributed in the hope that it will be useful,
3474- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3475- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3476- * GNU Lesser General Public License for more details.
3477- *
3478- * You should have received a copy of the GNU Lesser General Public License
3479- * along with this program. If not, see <http://www.gnu.org/licenses/>.
3480- *
3481- * Author: Andreas Pokorny <andreas.pokorny@canonical.com>
3482- */
3483-
3484-#include "make_empty_event.h"
3485-#include "mir/events/event_private.h"
3486-
3487-#include <cstring>
3488-#include <cstdlib>
3489-
3490-namespace mev = mir::events;
3491-namespace
3492-{
3493- void delete_event(MirEvent *e)
3494- {
3495- // xkbcommon creates the keymap through malloc
3496- if (e && e->type == mir_event_type_keymap)
3497- std::free(const_cast<char*>(e->keymap.buffer));
3498- delete e;
3499- }
3500-}
3501-
3502-mir::EventUPtr mev::make_empty_event()
3503-{
3504- auto e = new MirEvent;
3505- std::memset(e, 0, sizeof (MirEvent));
3506- return mir::EventUPtr(e, delete_event);
3507-}
3508
3509=== removed file 'src/client/events/make_empty_event.h'
3510--- src/client/events/make_empty_event.h 2016-01-22 16:40:15 +0000
3511+++ src/client/events/make_empty_event.h 1970-01-01 00:00:00 +0000
3512@@ -1,32 +0,0 @@
3513-/*
3514- * Copyright © 2016 Canonical Ltd.
3515- *
3516- * This program is free software: you can redistribute it and/or modify it
3517- * under the terms of the GNU Lesser General Public License version 3,
3518- * as published by the Free Software Foundation.
3519- *
3520- * This program is distributed in the hope that it will be useful,
3521- * but WITHOUT ANY WARRANTY; without even the implied warranty of
3522- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3523- * GNU Lesser General Public License for more details.
3524- *
3525- * You should have received a copy of the GNU Lesser General Public License
3526- * along with this program. If not, see <http://www.gnu.org/licenses/>.
3527- *
3528- * Author: Andreas Pokorny <andreas.pokorny@canonical.com>
3529- */
3530-
3531-#ifndef MIR_EVENTS_MAKE_EMPTY_EVENTS_H_
3532-#define MIR_EVENTS_MAKE_EMPTY_EVENTS_H_
3533-
3534-#include "mir/events/event_builders.h"
3535-
3536-namespace mir
3537-{
3538-namespace events
3539-{
3540-mir::EventUPtr make_empty_event();
3541-}
3542-}
3543-
3544-#endif
3545
3546=== modified file 'src/client/events/serialization.cpp'
3547--- src/client/events/serialization.cpp 2016-01-22 16:40:15 +0000
3548+++ src/client/events/serialization.cpp 2016-04-27 09:08:17 +0000
3549@@ -16,96 +16,17 @@
3550 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
3551 */
3552
3553-#include "make_empty_event.h"
3554 #include "mir/events/serialization.h"
3555 #include "mir/events/event_private.h"
3556
3557-#include <boost/throw_exception.hpp>
3558-#include <cstring>
3559-
3560 namespace mev = mir::events;
3561
3562-namespace
3563-{
3564-template<typename Data>
3565-char const* consume(char const* pos, Data& data)
3566-{
3567- std::memcpy(&data, pos, sizeof data);
3568- return pos + sizeof data;
3569-}
3570-
3571-template<typename Data>
3572-void encode(std::string& encoded, Data const& data)
3573-{
3574- encoded.append(reinterpret_cast<char const*>(&data), sizeof data);
3575-}
3576-}
3577-
3578 std::string mev::serialize_event(MirEvent const& event)
3579 {
3580- auto type = mir_event_get_type(&event);
3581-
3582- switch (type)
3583- {
3584- case mir_event_type_keymap:
3585- {
3586- std::string encoded;
3587- auto const& keymap = event.keymap;
3588- encoded.reserve(sizeof event.type +
3589- sizeof keymap.surface_id +
3590- sizeof keymap.device_id +
3591- sizeof keymap.size +
3592- keymap.size);
3593- encode(encoded, event.type);
3594- encode(encoded, keymap.surface_id);
3595- encode(encoded, keymap.device_id);
3596- encode(encoded, keymap.size);
3597- encoded.append(keymap.buffer, keymap.size);
3598- return encoded;
3599- }
3600- default:
3601- return {reinterpret_cast<char const*>(&event), sizeof event};
3602- }
3603+ return MirEvent::serialize(&event);
3604 }
3605
3606 mir::EventUPtr mev::deserialize_event(std::string const& raw)
3607 {
3608- auto ev = make_empty_event();
3609- auto& event = *ev;
3610- auto minimal_event_size = sizeof event.type;
3611- auto const stream_size = raw.size();
3612- if (stream_size < minimal_event_size)
3613- BOOST_THROW_EXCEPTION(std::runtime_error("Failed to deserialize event"));
3614-
3615- char const* pos = consume(raw.data(), event.type);
3616-
3617- switch (event.type)
3618- {
3619- case mir_event_type_keymap:
3620- {
3621- auto& keymap = event.keymap;
3622- minimal_event_size += sizeof keymap.surface_id + sizeof keymap.device_id + sizeof keymap.size;
3623-
3624- if (stream_size < minimal_event_size)
3625- BOOST_THROW_EXCEPTION(std::runtime_error("Failed to deserialize event"));
3626- pos = consume(pos, keymap.surface_id);
3627- pos = consume(pos, keymap.device_id);
3628- pos = consume(pos, keymap.size);
3629-
3630- minimal_event_size += keymap.size;
3631-
3632- if (stream_size < minimal_event_size)
3633- BOOST_THROW_EXCEPTION(std::runtime_error("Failed to deserialize event"));
3634-
3635- auto buffer = static_cast<char*>(malloc(keymap.size));
3636- std::memcpy(buffer, pos, keymap.size);
3637- keymap.buffer = buffer;
3638- break;
3639- }
3640- default:
3641- consume(raw.data(), event);
3642- break;
3643- }
3644-
3645- return ev;
3646+ return MirEvent::deserialize(raw);
3647 }
3648
3649=== modified file 'src/client/input/android/event_conversion_helpers.cpp'
3650--- src/client/input/android/event_conversion_helpers.cpp 2016-03-17 22:23:47 +0000
3651+++ src/client/input/android/event_conversion_helpers.cpp 2016-04-27 09:08:17 +0000
3652@@ -201,11 +201,11 @@
3653 int32_t mia::extract_masked_android_action_from(MirEvent const& ev)
3654 {
3655 int index_with_action = -1;
3656- auto const& mev = ev.motion;
3657+ auto const& mev = *ev.to_input()->to_motion();
3658
3659- for (unsigned i = 0; i < mev.pointer_count; i++)
3660+ for (unsigned i = 0; i < mev.pointer_count(); i++)
3661 {
3662- if (mev.pointer_coordinates[i].action == mir_touch_action_change)
3663+ if (mev.action(i) == mir_touch_action_change)
3664 continue;
3665 index_with_action = i;
3666 }
3667@@ -213,16 +213,16 @@
3668 return AMOTION_EVENT_ACTION_MOVE;
3669
3670 int masked_action = AMOTION_EVENT_ACTION_MASK;
3671- switch (mev.pointer_coordinates[index_with_action].action)
3672+ switch (mev.action(index_with_action))
3673 {
3674 case mir_touch_action_up:
3675- if (mev.pointer_count != 1)
3676+ if (mev.pointer_count() != 1)
3677 masked_action &= AMOTION_EVENT_ACTION_POINTER_UP;
3678 else
3679 masked_action &= AMOTION_EVENT_ACTION_UP;
3680 break;
3681 case mir_touch_action_down:
3682- if (mev.pointer_count != 1)
3683+ if (mev.pointer_count() != 1)
3684 masked_action &= AMOTION_EVENT_ACTION_POINTER_DOWN;
3685 else
3686 masked_action &= AMOTION_EVENT_ACTION_DOWN;
3687@@ -275,10 +275,11 @@
3688
3689 int32_t mia::extract_android_action_from(MirEvent const& event)
3690 {
3691- if (mia::android_source_id_is_pointer_device(event.motion.source_id))
3692+ auto& mev = *event.to_input()->to_motion();
3693+ if (mia::android_source_id_is_pointer_device(mev.source_id()))
3694 {
3695 return mia::android_pointer_action_from_mir(
3696- static_cast<MirPointerAction>(event.motion.pointer_coordinates[0].action), event.motion.buttons);
3697+ static_cast<MirPointerAction>(mev.action(0)), mev.buttons());
3698 }
3699 else
3700 {
3701
3702=== modified file 'src/client/input/input_event.cpp'
3703--- src/client/input/input_event.cpp 2016-03-17 22:23:47 +0000
3704+++ src/client/input/input_event.cpp 2016-04-27 09:08:17 +0000
3705@@ -33,16 +33,6 @@
3706
3707 namespace
3708 {
3709-void expect_old_event_type(MirEvent const* ev, MirEventType t)
3710-{
3711- if (ev->type != t)
3712- {
3713- mir::log_critical("Expected " + mir::event_type_to_string(t) + " but event is of type " +
3714- mir::event_type_to_string(ev->type));
3715- abort();
3716- }
3717-}
3718-
3719 std::string input_event_type_to_string(MirInputEventType input_event_type)
3720 {
3721 switch (input_event_type)
3722@@ -84,25 +74,6 @@
3723 AINPUT_SOURCE_ANY = 0xffffff00
3724 };
3725
3726-MirEvent const* old_ev_from_new(MirInputEvent const* ev)
3727-{
3728- return reinterpret_cast<MirEvent const*>(ev);
3729-}
3730-
3731-MirMotionEvent const& old_mev_from_new(MirTouchEvent const* ev)
3732-{
3733- auto old_ev = reinterpret_cast<MirEvent const*>(ev);
3734- expect_old_event_type(old_ev, mir_event_type_motion);
3735- return old_ev->motion;
3736-}
3737-
3738-MirMotionEvent const& old_mev_from_new(MirPointerEvent const* ev)
3739-{
3740- auto old_ev = reinterpret_cast<MirEvent const*>(ev);
3741- expect_old_event_type(old_ev, mir_event_type_motion);
3742- return old_ev->motion;
3743-}
3744-
3745 // Differentiate between MirTouchEvents and MirPointerEvents based on old device class
3746 MirInputEventType type_from_device_class(int32_t source_class)
3747 {
3748@@ -122,20 +93,18 @@
3749
3750 MirInputEventType mir_input_event_get_type(MirInputEvent const* ev)
3751 {
3752- auto old_ev = old_ev_from_new(ev);
3753-
3754- if (old_ev->type != mir_event_type_key && old_ev->type != mir_event_type_motion)
3755+ if (ev->type() != mir_event_type_key && ev->type() != mir_event_type_motion)
3756 {
3757- mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
3758+ mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(ev->type()));
3759 abort();
3760 }
3761
3762- switch (old_ev->type)
3763+ switch (ev->type())
3764 {
3765 case mir_event_type_key:
3766 return mir_input_event_type_key;
3767 case mir_event_type_motion:
3768- return type_from_device_class(old_ev->motion.source_id);
3769+ return type_from_device_class(ev->to_motion()->source_id());
3770 default:
3771 abort();
3772 }
3773@@ -143,20 +112,18 @@
3774
3775 MirInputDeviceId mir_input_event_get_device_id(MirInputEvent const* ev)
3776 {
3777- auto old_ev = old_ev_from_new(ev);
3778-
3779- if(mir_event_get_type(old_ev) != mir_event_type_input)
3780+ if(mir_event_get_type(ev) != mir_event_type_input)
3781 {
3782- mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
3783+ mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(ev->type()));
3784 abort();
3785 }
3786
3787- switch (old_ev->type)
3788+ switch (ev->type())
3789 {
3790 case mir_event_type_motion:
3791- return old_ev->motion.device_id;
3792+ return ev->to_motion()->device_id();
3793 case mir_event_type_key:
3794- return old_ev->key.device_id;
3795+ return ev->to_keyboard()->device_id();
3796 default:
3797 abort();
3798 }
3799@@ -164,19 +131,18 @@
3800
3801 int64_t mir_input_event_get_event_time(MirInputEvent const* ev)
3802 {
3803- auto old_ev = old_ev_from_new(ev);
3804- if(mir_event_get_type(old_ev) != mir_event_type_input)
3805+ if(mir_event_get_type(ev) != mir_event_type_input)
3806 {
3807- mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
3808+ mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(ev->type()));
3809 abort();
3810 }
3811
3812- switch (old_ev->type)
3813+ switch (ev->type())
3814 {
3815 case mir_event_type_motion:
3816- return old_ev->motion.event_time.count();
3817+ return ev->to_motion()->event_time().count();
3818 case mir_event_type_key:
3819- return old_ev->key.event_time.count();
3820+ return ev->to_keyboard()->event_time().count();
3821 default:
3822 abort();
3823 }
3824@@ -213,29 +179,28 @@
3825
3826 MirKeyboardAction mir_keyboard_event_action(MirKeyboardEvent const* kev)
3827 {
3828- return kev->action;
3829+ return kev->action();
3830 }
3831
3832 xkb_keysym_t mir_keyboard_event_key_code(MirKeyboardEvent const* kev)
3833 {
3834- return kev->key_code;
3835+ return kev->key_code();
3836 }
3837
3838 int mir_keyboard_event_scan_code(MirKeyboardEvent const* kev)
3839 {
3840- return kev->scan_code;
3841+ return kev->scan_code();
3842 }
3843
3844 MirInputEventModifiers mir_keyboard_event_modifiers(MirKeyboardEvent const* kev)
3845 {
3846- return kev->modifiers;
3847+ return kev->modifiers();
3848 }
3849 /* Touch event accessors */
3850
3851 MirInputEventModifiers mir_touch_event_modifiers(MirTouchEvent const* tev)
3852 {
3853- auto const& old_mev = old_mev_from_new(tev);
3854- return old_mev.modifiers;
3855+ return tev->to_motion()->modifiers();
3856 }
3857
3858 MirTouchEvent const* mir_input_event_get_touch_event(MirInputEvent const* ev)
3859@@ -252,76 +217,67 @@
3860
3861 unsigned int mir_touch_event_point_count(MirTouchEvent const* event)
3862 {
3863- auto const& old_mev = reinterpret_cast<MirEvent const*>(event)->motion;
3864- return old_mev.pointer_count;
3865+ return event->to_motion()->pointer_count();
3866 }
3867
3868 MirTouchId mir_touch_event_id(MirTouchEvent const* event, size_t touch_index)
3869 {
3870- auto const& old_mev = old_mev_from_new(event);
3871-
3872- if (touch_index >= old_mev.pointer_count)
3873+ if (touch_index >= event->to_motion()->pointer_count())
3874 {
3875 mir::log_critical("touch index is greater than pointer count");
3876 abort();
3877 }
3878
3879- return old_mev.pointer_coordinates[touch_index].id;
3880+ return event->to_motion()->id(touch_index);
3881 }
3882
3883 MirTouchAction mir_touch_event_action(MirTouchEvent const* event, size_t touch_index)
3884 {
3885- auto const& old_mev = old_mev_from_new(event);
3886-
3887- if(touch_index > old_mev.pointer_count)
3888+ if(touch_index > event->to_motion()->pointer_count())
3889 {
3890 mir::log_critical("touch index is greater than pointer count");
3891 abort();
3892 }
3893
3894- return static_cast<MirTouchAction>(old_mev.pointer_coordinates[touch_index].action);
3895+ return static_cast<MirTouchAction>(event->to_motion()->action(touch_index));
3896 }
3897
3898 MirTouchTooltype mir_touch_event_tooltype(MirTouchEvent const* event,
3899 size_t touch_index)
3900 {
3901- auto const& old_mev = old_mev_from_new(event);
3902-
3903- if(touch_index > old_mev.pointer_count)
3904+ if(touch_index > event->to_motion()->pointer_count())
3905 {
3906 mir::log_critical("touch index is greater than pointer count");
3907 abort();
3908 }
3909
3910- return old_mev.pointer_coordinates[touch_index].tool_type;
3911+ return event->to_motion()->tool_type(touch_index);
3912 }
3913
3914 float mir_touch_event_axis_value(MirTouchEvent const* event,
3915 size_t touch_index, MirTouchAxis axis)
3916 {
3917- auto const& old_mev = old_mev_from_new(event);
3918-
3919- if(touch_index > old_mev.pointer_count)
3920+ if(touch_index > event->to_motion()->pointer_count())
3921 {
3922 mir::log_critical("touch index is greater than pointer count");
3923 abort();
3924 }
3925
3926- auto const& old_pc = old_mev.pointer_coordinates[touch_index];
3927+ auto mev = event->to_motion();
3928 switch (axis)
3929 {
3930 case mir_touch_axis_x:
3931- return old_pc.x;
3932+ return mev->x(touch_index);
3933 case mir_touch_axis_y:
3934- return old_pc.y;
3935+ return mev->y(touch_index);
3936 case mir_touch_axis_pressure:
3937- return old_pc.pressure;
3938+ return mev->pressure(touch_index);
3939 case mir_touch_axis_touch_major:
3940- return old_pc.touch_major;
3941+ return mev->touch_major(touch_index);
3942 case mir_touch_axis_touch_minor:
3943- return old_pc.touch_minor;
3944+ return mev->touch_minor(touch_index);
3945 case mir_touch_axis_size:
3946- return old_pc.size;
3947+ return mev->size(touch_index);
3948 default:
3949 return -1;
3950 }
3951@@ -343,46 +299,42 @@
3952
3953 MirInputEventModifiers mir_pointer_event_modifiers(MirPointerEvent const* pev)
3954 {
3955- auto const& old_mev = old_mev_from_new(pev);
3956- return old_mev.modifiers;
3957+ return pev->to_motion()->modifiers();
3958 }
3959
3960 MirPointerAction mir_pointer_event_action(MirPointerEvent const* pev)
3961 {
3962- auto const& old_mev = old_mev_from_new(pev);
3963- return static_cast<MirPointerAction>(old_mev.pointer_coordinates[0].action);
3964+ return static_cast<MirPointerAction>(pev->to_motion()->action(0));
3965 }
3966
3967 bool mir_pointer_event_button_state(MirPointerEvent const* pev,
3968 MirPointerButton button)
3969 {
3970- auto const& old_mev = old_mev_from_new(pev);
3971- return old_mev.buttons & button;
3972+ return pev->to_motion()->buttons() & button;
3973 }
3974
3975 MirPointerButtons mir_pointer_event_buttons(MirPointerEvent const* pev)
3976 {
3977- auto const& old_mev = old_mev_from_new(pev);
3978- return old_mev.buttons;
3979+ return pev->to_motion()->buttons();
3980 }
3981
3982 float mir_pointer_event_axis_value(MirPointerEvent const* pev, MirPointerAxis axis)
3983 {
3984- auto const& old_mev = old_mev_from_new(pev);
3985+ auto mev = pev->to_motion();
3986 switch (axis)
3987 {
3988 case mir_pointer_axis_x:
3989- return old_mev.pointer_coordinates[0].x;
3990+ return mev->x(0);
3991 case mir_pointer_axis_y:
3992- return old_mev.pointer_coordinates[0].y;
3993+ return mev->y(0);
3994 case mir_pointer_axis_relative_x:
3995- return old_mev.pointer_coordinates[0].dx;
3996+ return mev->dx(0);
3997 case mir_pointer_axis_relative_y:
3998- return old_mev.pointer_coordinates[0].dy;
3999+ return mev->dy(0);
4000 case mir_pointer_axis_vscroll:
4001- return old_mev.pointer_coordinates[0].vscroll;
4002+ return mev->vscroll(0);
4003 case mir_pointer_axis_hscroll:
4004- return old_mev.pointer_coordinates[0].hscroll;
4005+ return mev->hscroll(0);
4006 default:
4007 mir::log_critical("Invalid axis enumeration " + std::to_string(axis));
4008 abort();
4009@@ -432,17 +384,15 @@
4010
4011 MirCookie const* mir_input_event_get_cookie(MirInputEvent const* iev) try
4012 {
4013- auto const ev = old_ev_from_new(iev);
4014-
4015- switch (ev->type)
4016+ switch (iev->type())
4017 {
4018 case mir_event_type_motion:
4019- return new MirCookie(ev->motion.cookie);
4020+ return new MirCookie(iev->to_motion()->cookie());
4021 case mir_event_type_key:
4022- return new MirCookie(ev->key.cookie);
4023+ return new MirCookie(iev->to_keyboard()->cookie());
4024 default:
4025 {
4026- mir::log_critical("expected a key or motion events, type was: " + mir::event_type_to_string(ev->type));
4027+ mir::log_critical("expected a key or motion events, type was: " + mir::event_type_to_string(iev->type()));
4028 abort();
4029 }
4030 }
4031
4032=== modified file 'src/client/input/xkb_mapper.cpp'
4033--- src/client/input/xkb_mapper.cpp 2016-01-29 08:18:22 +0000
4034+++ src/client/input/xkb_mapper.cpp 2016-04-27 09:08:17 +0000
4035@@ -103,23 +103,23 @@
4036 {
4037 std::lock_guard<std::mutex> lg(guard);
4038
4039- auto& key_ev = ev.key;
4040+ auto& key_ev = *ev.to_input()->to_keyboard();
4041
4042 xkb_key_direction direction = XKB_KEY_DOWN;
4043
4044 bool update_state = true;
4045- if (key_ev.action == mir_keyboard_action_up)
4046+ if (key_ev.action() == mir_keyboard_action_up)
4047 direction = XKB_KEY_UP;
4048- else if (key_ev.action == mir_keyboard_action_down)
4049+ else if (key_ev.action() == mir_keyboard_action_down)
4050 direction = XKB_KEY_DOWN;
4051- else if (key_ev.action == mir_keyboard_action_repeat)
4052+ else if (key_ev.action() == mir_keyboard_action_repeat)
4053 update_state = false;
4054
4055- uint32_t xkb_scan_code = to_xkb_scan_code(key_ev.scan_code);
4056+ uint32_t xkb_scan_code = to_xkb_scan_code(key_ev.scan_code());
4057 if (update_state)
4058 xkb_state_update_key(state.get(), xkb_scan_code, direction);
4059
4060- key_ev.key_code = keysym_for_scan_code(state.get(), xkb_scan_code);
4061+ key_ev.set_key_code(keysym_for_scan_code(state.get(), xkb_scan_code));
4062 }
4063
4064 // id should be used in the future to implement per device keymaps
4065
4066=== modified file 'src/client/mir_connection.cpp'
4067--- src/client/mir_connection.cpp 2016-03-17 17:47:42 +0000
4068+++ src/client/mir_connection.cpp 2016-04-27 09:08:17 +0000
4069@@ -44,6 +44,7 @@
4070
4071 #include "mir/events/event_builders.h"
4072 #include "mir/logging/logger.h"
4073+#include "mir_error.h"
4074
4075 #include <algorithm>
4076 #include <cstddef>
4077@@ -172,6 +173,22 @@
4078 }
4079 }
4080
4081+ if (spec.streams.is_set())
4082+ {
4083+ for(auto const& stream : spec.streams.value())
4084+ {
4085+ auto const new_stream = message.add_stream();
4086+ new_stream->set_displacement_x(stream.displacement.dx.as_int());
4087+ new_stream->set_displacement_y(stream.displacement.dy.as_int());
4088+ new_stream->mutable_id()->set_value(stream.stream_id);
4089+ if (stream.size.is_set())
4090+ {
4091+ new_stream->set_width(stream.size.value().width.as_int());
4092+ new_stream->set_height(stream.size.value().height.as_int());
4093+ }
4094+ }
4095+ }
4096+
4097 return message;
4098 }
4099
4100@@ -400,7 +417,7 @@
4101 this, server, &debug, stream, input_platform, spec, *surface_proto, request->wh);
4102
4103 surface_map->insert(mf::SurfaceId{surface_proto->id().value()}, surf);
4104- surface_map->insert(mf::BufferStreamId{surface_proto->id().value()}, stream);
4105+ surface_map->insert(mf::BufferStreamId{surface_proto->buffer_stream().id().value()}, stream);
4106 }
4107
4108 callback(surf.get(), context);
4109@@ -879,7 +896,7 @@
4110 }
4111
4112 std::shared_ptr<mir::client::ClientBufferStream> MirConnection::make_consumer_stream(
4113- mp::BufferStream const& protobuf_bs, mir::geometry::Size)
4114+ mp::BufferStream const& protobuf_bs)
4115 {
4116 return std::make_shared<mcl::ScreencastStream>(
4117 this, server, platform, protobuf_bs);
4118@@ -908,6 +925,11 @@
4119 ping_handler->set_callback(std::bind(callback, this, std::placeholders::_1, context));
4120 }
4121
4122+void MirConnection::register_error_callback(mir_error_callback callback, void* context)
4123+{
4124+ error_handler.set_callback(std::bind(callback, this, std::placeholders::_1, context));
4125+}
4126+
4127 void MirConnection::pong(int32_t serial)
4128 {
4129 mp::PingEvent pong;
4130@@ -991,6 +1013,58 @@
4131 return &set_base_display_configuration_wait_handle;
4132 }
4133
4134+namespace
4135+{
4136+struct HandleErrorVoid
4137+{
4138+ std::unique_ptr<mp::Void> result;
4139+ std::function<void(mp::Void const&)> on_error;
4140+};
4141+
4142+void handle_structured_error(HandleErrorVoid* handler)
4143+{
4144+ if (handler->result->has_structured_error())
4145+ {
4146+ handler->on_error(*handler->result);
4147+ }
4148+ delete handler;
4149+}
4150+}
4151+
4152+void MirConnection::preview_base_display_configuration(
4153+ mp::DisplayConfiguration const& configuration,
4154+ std::chrono::seconds timeout)
4155+{
4156+ mp::PreviewConfiguration request;
4157+
4158+ request.mutable_configuration()->CopyFrom(configuration);
4159+ request.set_timeout(timeout.count());
4160+
4161+ auto store_error_result = new HandleErrorVoid;
4162+ store_error_result->result = std::make_unique<mp::Void>();
4163+ store_error_result->on_error = [this](mp::Void const& message)
4164+ {
4165+ MirError const error{
4166+ static_cast<MirErrorDomain>(message.structured_error().domain()),
4167+ message.structured_error().code()};
4168+ error_handler(&error);
4169+ };
4170+
4171+ server.preview_base_display_configuration(
4172+ &request,
4173+ store_error_result->result.get(),
4174+ google::protobuf::NewCallback(&handle_structured_error, store_error_result));
4175+}
4176+
4177+void MirConnection::confirm_base_display_configuration(
4178+ mp::DisplayConfiguration const& configuration)
4179+{
4180+ server.confirm_base_display_configuration(
4181+ &configuration,
4182+ set_base_display_configuration_response.get(),
4183+ google::protobuf::NewCallback(google::protobuf::DoNothing));
4184+}
4185+
4186 void MirConnection::done_set_base_display_configuration()
4187 {
4188 std::lock_guard<decltype(mutex)> lock(mutex);
4189
4190=== modified file 'src/client/mir_connection.h'
4191--- src/client/mir_connection.h 2016-03-17 17:47:42 +0000
4192+++ src/client/mir_connection.h 2016-04-27 09:08:17 +0000
4193@@ -135,6 +135,8 @@
4194
4195 void register_display_change_callback(mir_display_config_callback callback, void* context);
4196
4197+ void register_error_callback(mir_error_callback callback, void* context);
4198+
4199 void populate(MirPlatformPackage& platform_package);
4200 void populate_graphics_module(MirModuleProperties& properties);
4201 MirDisplayConfiguration* create_copy_of_display_config();
4202@@ -143,7 +145,7 @@
4203 unsigned int formats_size, unsigned int& valid_formats);
4204
4205 std::shared_ptr<mir::client::ClientBufferStream> make_consumer_stream(
4206- mir::protobuf::BufferStream const& protobuf_bs, mir::geometry::Size);
4207+ mir::protobuf::BufferStream const& protobuf_bs);
4208
4209 MirWaitHandle* create_client_buffer_stream(
4210 int width, int height,
4211@@ -174,6 +176,11 @@
4212 void done_display_configure();
4213
4214 MirWaitHandle* set_base_display_configuration(MirDisplayConfiguration const* configuration);
4215+ void preview_base_display_configuration(
4216+ mir::protobuf::DisplayConfiguration const& configuration,
4217+ std::chrono::seconds timeout);
4218+ void confirm_base_display_configuration(
4219+ mir::protobuf::DisplayConfiguration const& configuration);
4220 void done_set_base_display_configuration();
4221
4222 std::shared_ptr<mir::client::rpc::MirBasicRpcChannel> rpc_channel() const
4223@@ -306,6 +313,8 @@
4224
4225 std::shared_ptr<mir::client::ClientBufferStreamFactory> buffer_stream_factory;
4226
4227+ mir::client::AtomicCallback<MirError const*> error_handler;
4228+
4229 struct SurfaceRelease;
4230 struct StreamRelease;
4231
4232
4233=== modified file 'src/client/mir_connection_api.cpp'
4234--- src/client/mir_connection_api.cpp 2016-03-14 10:13:49 +0000
4235+++ src/client/mir_connection_api.cpp 2016-04-27 09:08:17 +0000
4236@@ -314,10 +314,46 @@
4237
4238 void mir_input_config_destroy(MirInputConfig const* config)
4239 {
4240- auto device_vector = reinterpret_cast<std::vector<mir::input::DeviceData>const*>(config);
4241+ auto device_vector = reinterpret_cast<std::vector<mir::input::DeviceData> const*>(config);
4242 delete device_vector;
4243 }
4244
4245+void mir_connection_preview_base_display_configuration(
4246+ MirConnection* connection,
4247+ MirDisplayConfig const* config,
4248+ int timeout_seconds)
4249+{
4250+ mir::require(mir_connection_is_valid(connection));
4251+
4252+ try
4253+ {
4254+ connection->preview_base_display_configuration(
4255+ *reinterpret_cast<mp::DisplayConfiguration const*>(config),
4256+ std::chrono::seconds{timeout_seconds});
4257+ }
4258+ catch (std::exception const& ex)
4259+ {
4260+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
4261+ }
4262+}
4263+
4264+void mir_connection_confirm_base_display_configuration(
4265+ MirConnection* connection,
4266+ MirDisplayConfig const* config)
4267+{
4268+ mir::require(mir_connection_is_valid(connection));
4269+
4270+ try
4271+ {
4272+ connection->confirm_base_display_configuration(
4273+ *reinterpret_cast<mp::DisplayConfiguration const*>(config));
4274+ }
4275+ catch (std::exception const& ex)
4276+ {
4277+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
4278+ }
4279+}
4280+
4281 MirEGLNativeDisplayType mir_connection_get_egl_native_display(
4282 MirConnection* connection)
4283 {
4284@@ -355,3 +391,21 @@
4285 return nullptr;
4286 }
4287 }
4288+
4289+void mir_connection_set_error_callback(
4290+ MirConnection* connection,
4291+ mir_error_callback callback,
4292+ void* context)
4293+{
4294+ mir::require(mir_connection_is_valid(connection));
4295+
4296+ try
4297+ {
4298+ connection->register_error_callback(callback, context);
4299+ }
4300+ catch (std::exception const& ex)
4301+ {
4302+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
4303+ }
4304+}
4305+
4306
4307=== added file 'src/client/mir_error.cpp'
4308--- src/client/mir_error.cpp 1970-01-01 00:00:00 +0000
4309+++ src/client/mir_error.cpp 2016-04-27 09:08:17 +0000
4310@@ -0,0 +1,35 @@
4311+/*
4312+ * Copyright © 2016 Canonical Ltd.
4313+ *
4314+ * This program is free software: you can redistribute it and/or modify it
4315+ * under the terms of the GNU Lesser General Public License version 3,
4316+ * as published by the Free Software Foundation.
4317+ *
4318+ * This program is distributed in the hope that it will be useful,
4319+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4320+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4321+ * GNU Lesser General Public License for more details.
4322+ *
4323+ * You should have received a copy of the GNU Lesser General Public License
4324+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4325+ *
4326+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
4327+ */
4328+
4329+#include "mir_error.h"
4330+
4331+MirError::MirError(MirErrorDomain domain, uint32_t code)
4332+ : domain_{domain},
4333+ code_{code}
4334+{
4335+}
4336+
4337+MirErrorDomain MirError::domain() const noexcept
4338+{
4339+ return domain_;
4340+}
4341+
4342+uint32_t MirError::code() const noexcept
4343+{
4344+ return code_;
4345+}
4346
4347=== added file 'src/client/mir_error.h'
4348--- src/client/mir_error.h 1970-01-01 00:00:00 +0000
4349+++ src/client/mir_error.h 2016-04-27 09:08:17 +0000
4350@@ -0,0 +1,37 @@
4351+/*
4352+ * Copyright © 2016 Canonical Ltd.
4353+ *
4354+ * This program is free software: you can redistribute it and/or modify it
4355+ * under the terms of the GNU Lesser General Public License version 3,
4356+ * as published by the Free Software Foundation.
4357+ *
4358+ * This program is distributed in the hope that it will be useful,
4359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4361+ * GNU Lesser General Public License for more details.
4362+ *
4363+ * You should have received a copy of the GNU Lesser General Public License
4364+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4365+ *
4366+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
4367+ */
4368+
4369+#ifndef MIR_CLIENT_MIR_ERROR_H_
4370+#define MIR_CLIENT_MIR_ERROR_H_
4371+
4372+#include "mir_toolkit/client_types.h"
4373+
4374+struct MirError
4375+{
4376+public:
4377+ MirError(MirErrorDomain domain, uint32_t code);
4378+
4379+ MirErrorDomain domain() const noexcept;
4380+ uint32_t code() const noexcept;
4381+
4382+private:
4383+ MirErrorDomain const domain_;
4384+ uint32_t const code_;
4385+};
4386+
4387+#endif //MIR_CLIENT_MIR_ERROR_H_
4388
4389=== added file 'src/client/mir_error_api.cpp'
4390--- src/client/mir_error_api.cpp 1970-01-01 00:00:00 +0000
4391+++ src/client/mir_error_api.cpp 2016-04-27 09:08:17 +0000
4392@@ -0,0 +1,30 @@
4393+/*
4394+ * Copyright © 2016 Canonical Ltd.
4395+ *
4396+ * This program is free software: you can redistribute it and/or modify it
4397+ * under the terms of the GNU Lesser General Public License version 3,
4398+ * as published by the Free Software Foundation.
4399+ *
4400+ * This program is distributed in the hope that it will be useful,
4401+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4402+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4403+ * GNU Lesser General Public License for more details.
4404+ *
4405+ * You should have received a copy of the GNU Lesser General Public License
4406+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4407+ *
4408+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
4409+ */
4410+
4411+#include "mir_toolkit/mir_error.h"
4412+#include "mir_error.h"
4413+
4414+MirErrorDomain mir_error_get_domain(MirError const* error)
4415+{
4416+ return error->domain();
4417+}
4418+
4419+uint32_t mir_error_get_code(MirError const* error)
4420+{
4421+ return error->code();
4422+}
4423
4424=== modified file 'src/client/mir_screencast.cpp'
4425--- src/client/mir_screencast.cpp 2016-03-16 06:59:01 +0000
4426+++ src/client/mir_screencast.cpp 2016-04-27 09:08:17 +0000
4427@@ -30,42 +30,101 @@
4428 namespace mp = mir::protobuf;
4429 namespace geom = mir::geometry;
4430
4431+namespace
4432+{
4433+mir::protobuf::ScreencastParameters serialize_spec(MirScreencastSpec const& spec)
4434+{
4435+ mp::ScreencastParameters message;
4436+
4437+#define SERIALIZE_OPTION_IF_SET(option) \
4438+ if (spec.option.is_set()) \
4439+ message.set_##option(spec.option.value());
4440+
4441+ SERIALIZE_OPTION_IF_SET(width);
4442+ SERIALIZE_OPTION_IF_SET(height);
4443+ SERIALIZE_OPTION_IF_SET(pixel_format);
4444+ SERIALIZE_OPTION_IF_SET(mirror_mode);
4445+ SERIALIZE_OPTION_IF_SET(num_buffers);
4446+
4447+ if (spec.capture_region.is_set())
4448+ {
4449+ auto const region = spec.capture_region.value();
4450+ message.mutable_region()->set_left(region.left);
4451+ message.mutable_region()->set_top(region.top);
4452+ message.mutable_region()->set_width(region.width);
4453+ message.mutable_region()->set_height(region.height);
4454+ }
4455+
4456+ return message;
4457+}
4458+
4459+//TODO: it should be up to the server to decide if the parameters are acceptable
4460+void throw_if_invalid(MirScreencastSpec const& spec)
4461+{
4462+#define THROW_IF_UNSET(option) \
4463+ if (!spec.option.is_set()) \
4464+ BOOST_THROW_EXCEPTION(std::runtime_error("Unset "#option));
4465+
4466+#define THROW_IF_EQ(option, val) \
4467+ THROW_IF_UNSET(option); \
4468+ if (spec.option.is_set() && spec.option.value() == val) \
4469+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid "#option));
4470+
4471+#define THROW_IF_ZERO(option) THROW_IF_EQ(option, 0)
4472+
4473+ THROW_IF_ZERO(width);
4474+ THROW_IF_ZERO(height);
4475+ THROW_IF_EQ(pixel_format, mir_pixel_format_invalid);
4476+ THROW_IF_UNSET(capture_region);
4477+
4478+ if (spec.capture_region.is_set())
4479+ {
4480+ auto const region = spec.capture_region.value();
4481+ if (region.width == 0)
4482+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid capture region width"));
4483+ if (region.height == 0)
4484+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid capture region height"));
4485+ }
4486+}
4487+}
4488+
4489+MirScreencastSpec::MirScreencastSpec() = default;
4490+
4491+MirScreencastSpec::MirScreencastSpec(MirConnection* connection)
4492+ : connection{connection}
4493+{
4494+}
4495+
4496+MirScreencastSpec::MirScreencastSpec(MirConnection* connection, MirScreencastParameters const& params)
4497+ : connection{connection},
4498+ width{params.width},
4499+ height{params.height},
4500+ pixel_format{params.pixel_format},
4501+ capture_region{params.region}
4502+{
4503+}
4504+
4505+MirScreencast::MirScreencast(std::string const& error)
4506+ : protobuf_screencast{mcl::make_protobuf_object<mir::protobuf::Screencast>()}
4507+{
4508+ protobuf_screencast->set_error(error);
4509+}
4510+
4511 MirScreencast::MirScreencast(
4512- geom::Rectangle const& region,
4513- geom::Size const& size,
4514- MirPixelFormat pixel_format,
4515- mir::client::rpc::DisplayServer& server,
4516- MirConnection* connection,
4517+ MirScreencastSpec const& spec,
4518+ mir::client::rpc::DisplayServer& the_server,
4519 mir_screencast_callback callback, void* context)
4520- : server(server),
4521- connection{connection},
4522- output_size{size},
4523+ : server{&the_server},
4524+ connection{spec.connection},
4525 protobuf_screencast{mcl::make_protobuf_object<mir::protobuf::Screencast>()},
4526 protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}
4527 {
4528- if (output_size.width.as_int() == 0 ||
4529- output_size.height.as_int() == 0 ||
4530- region.size.width.as_int() == 0 ||
4531- region.size.height.as_int() == 0 ||
4532- pixel_format == mir_pixel_format_invalid)
4533- {
4534- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid parameters"));
4535- }
4536- protobuf_screencast->set_error("Not initialized");
4537-
4538- mp::ScreencastParameters parameters;
4539-
4540- parameters.mutable_region()->set_left(region.top_left.x.as_int());
4541- parameters.mutable_region()->set_top(region.top_left.y.as_int());
4542- parameters.mutable_region()->set_width(region.size.width.as_uint32_t());
4543- parameters.mutable_region()->set_height(region.size.height.as_uint32_t());
4544- parameters.set_width(output_size.width.as_uint32_t());
4545- parameters.set_height(output_size.height.as_uint32_t());
4546- parameters.set_pixel_format(pixel_format);
4547+ throw_if_invalid(spec);
4548+ auto const message = serialize_spec(spec);
4549
4550 create_screencast_wait_handle.expect_result();
4551- server.create_screencast(
4552- &parameters,
4553+ server->create_screencast(
4554+ &message,
4555 protobuf_screencast.get(),
4556 google::protobuf::NewCallback(
4557 this, &MirScreencast::screencast_created,
4558@@ -79,36 +138,53 @@
4559
4560 bool MirScreencast::valid()
4561 {
4562+ std::lock_guard<decltype(mutex)> lock(mutex);
4563 return !protobuf_screencast->has_error();
4564 }
4565
4566-MirWaitHandle* MirScreencast::release(
4567- mir_screencast_callback callback, void* context)
4568-{
4569- mp::ScreencastId screencast_id;
4570- screencast_id.set_value(protobuf_screencast->screencast_id().value());
4571-
4572+char const* MirScreencast::get_error_message()
4573+{
4574+ std::lock_guard<decltype(mutex)> lock(mutex);
4575+ if (protobuf_screencast->has_error())
4576+ {
4577+ return protobuf_screencast->error().c_str();
4578+ }
4579+ return empty_error_message.c_str();
4580+}
4581+
4582+MirWaitHandle* MirScreencast::release(mir_screencast_callback callback, void* context)
4583+{
4584 release_wait_handle.expect_result();
4585- server.release_screencast(
4586- &screencast_id,
4587- protobuf_void.get(),
4588- google::protobuf::NewCallback(
4589- this, &MirScreencast::released, callback, context));
4590+ if (valid() && server)
4591+ {
4592+ mp::ScreencastId screencast_id;
4593+ {
4594+ std::lock_guard<decltype(mutex)> lock(mutex);
4595+ screencast_id.set_value(protobuf_screencast->screencast_id().value());
4596+ }
4597+ server->release_screencast(
4598+ &screencast_id,
4599+ protobuf_void.get(),
4600+ google::protobuf::NewCallback(
4601+ this, &MirScreencast::released, callback, context));
4602+ }
4603+ else
4604+ {
4605+ callback(this, context);
4606+ release_wait_handle.result_received();
4607+ }
4608
4609 return &release_wait_handle;
4610 }
4611
4612-void MirScreencast::request_and_wait_for_configure(MirSurfaceAttrib, int)
4613-{
4614-}
4615-
4616 void MirScreencast::screencast_created(
4617 mir_screencast_callback callback, void* context)
4618 {
4619 if (!protobuf_screencast->has_error() && connection)
4620 {
4621+ std::lock_guard<decltype(mutex)> lock(mutex);
4622 buffer_stream = connection->make_consumer_stream(
4623- protobuf_screencast->buffer_stream(), output_size);
4624+ protobuf_screencast->buffer_stream());
4625 }
4626
4627 callback(this, context);
4628@@ -119,14 +195,18 @@
4629 mir_screencast_callback callback, void* context)
4630 {
4631 callback(this, context);
4632- if (connection)
4633- connection->release_consumer_stream(buffer_stream.get());
4634- buffer_stream.reset();
4635
4636+ {
4637+ std::lock_guard<decltype(mutex)> lock(mutex);
4638+ if (connection)
4639+ connection->release_consumer_stream(buffer_stream.get());
4640+ buffer_stream.reset();
4641+ }
4642 release_wait_handle.result_received();
4643 }
4644
4645 mir::client::ClientBufferStream* MirScreencast::get_buffer_stream()
4646 {
4647+ std::lock_guard<decltype(mutex)> lock(mutex);
4648 return buffer_stream.get();
4649 }
4650
4651=== modified file 'src/client/mir_screencast.h'
4652--- src/client/mir_screencast.h 2016-01-29 08:18:22 +0000
4653+++ src/client/mir_screencast.h 2016-04-27 09:08:17 +0000
4654@@ -21,6 +21,7 @@
4655
4656 #include "mir_wait_handle.h"
4657 #include "mir_toolkit/client_types.h"
4658+#include "mir/optional_value.h"
4659 #include "mir/geometry/size.h"
4660 #include "mir/geometry/rectangle.h"
4661
4662@@ -46,27 +47,43 @@
4663 }
4664 }
4665
4666+struct MirScreencastSpec
4667+{
4668+ MirScreencastSpec();
4669+ MirScreencastSpec(MirConnection* connection);
4670+ MirScreencastSpec(MirConnection* connection, MirScreencastParameters const& params);
4671+
4672+ // Required parameters
4673+ MirConnection* connection{nullptr};
4674+
4675+ // Optional parameters
4676+ mir::optional_value<unsigned int> width;
4677+ mir::optional_value<unsigned int> height;
4678+ mir::optional_value<MirPixelFormat> pixel_format;
4679+ mir::optional_value<MirRectangle> capture_region;
4680+
4681+ mir::optional_value<MirMirrorMode> mirror_mode;
4682+ mir::optional_value<unsigned int> num_buffers;
4683+};
4684+
4685 struct MirScreencast
4686 {
4687 public:
4688+ MirScreencast(std::string const& error);
4689 MirScreencast(
4690- mir::geometry::Rectangle const& region,
4691- mir::geometry::Size const& size,
4692- MirPixelFormat pixel_format,
4693+ MirScreencastSpec const& spec,
4694 mir::client::rpc::DisplayServer& server,
4695- MirConnection* connection,
4696 mir_screencast_callback callback, void* context);
4697
4698 MirWaitHandle* creation_wait_handle();
4699 bool valid();
4700+ char const* get_error_message();
4701
4702 MirWaitHandle* release(
4703 mir_screencast_callback callback, void* context);
4704
4705 EGLNativeWindowType egl_native_window();
4706
4707- void request_and_wait_for_configure(MirSurfaceAttrib a, int value);
4708-
4709 mir::client::ClientBufferStream* get_buffer_stream();
4710
4711 private:
4712@@ -75,16 +92,18 @@
4713 void released(
4714 mir_screencast_callback callback, void* context);
4715
4716- mir::client::rpc::DisplayServer& server;
4717- MirConnection* connection;
4718- mir::geometry::Size const output_size;
4719+ std::mutex mutable mutex;
4720+ mir::client::rpc::DisplayServer* const server{nullptr};
4721+ MirConnection* const connection{nullptr};
4722 std::shared_ptr<mir::client::ClientBufferStream> buffer_stream;
4723
4724- std::unique_ptr<mir::protobuf::Screencast> protobuf_screencast;
4725- std::unique_ptr<mir::protobuf::Void> protobuf_void;
4726+ std::unique_ptr<mir::protobuf::Screencast> const protobuf_screencast;
4727+ std::unique_ptr<mir::protobuf::Void> const protobuf_void;
4728
4729 MirWaitHandle create_screencast_wait_handle;
4730 MirWaitHandle release_wait_handle;
4731+
4732+ std::string const empty_error_message;
4733 };
4734
4735 #endif /* MIR_CLIENT_MIR_SCREENCAST_H_ */
4736
4737=== modified file 'src/client/mir_screencast_api.cpp'
4738--- src/client/mir_screencast_api.cpp 2015-06-18 02:46:16 +0000
4739+++ src/client/mir_screencast_api.cpp 2016-04-27 09:08:17 +0000
4740@@ -1,5 +1,5 @@
4741 /*
4742- * Copyright © 2014 Canonical Ltd.
4743+ * Copyright © 2014,2016 Canonical Ltd.
4744 *
4745 * This program is free software: you can redistribute it and/or modify it
4746 * under the terms of the GNU Lesser General Public License version 3,
4747@@ -22,7 +22,7 @@
4748 #include "mir_screencast.h"
4749 #include "mir_connection.h"
4750 #include "mir/raii.h"
4751-
4752+#include "mir/require.h"
4753 #include "mir/uncaught.h"
4754
4755 #include <stdexcept>
4756@@ -31,53 +31,88 @@
4757 namespace
4758 {
4759 void null_callback(MirScreencast*, void*) {}
4760-}
4761+MirScreencast* create_screencast(MirScreencastSpec* spec)
4762+{
4763+ auto& server = spec->connection->display_server();
4764+ auto screencast = std::make_unique<MirScreencast>(*spec, server, null_callback, nullptr);
4765+ screencast->creation_wait_handle()->wait_for_all();
4766+
4767+ auto raw_screencast = screencast.get();
4768+ screencast.release();
4769+ return raw_screencast;
4770+}
4771+}
4772+
4773+MirScreencastSpec* mir_create_screencast_spec(MirConnection* connection)
4774+{
4775+ mir::require(mir_connection_is_valid(connection));
4776+ return new MirScreencastSpec{connection};
4777+}
4778+
4779+void mir_screencast_spec_set_width(MirScreencastSpec* spec, unsigned int width)
4780+{
4781+ spec->width = width;
4782+}
4783+
4784+void mir_screencast_spec_set_height(MirScreencastSpec* spec, unsigned int height)
4785+{
4786+ spec->height = height;
4787+}
4788+
4789+void mir_screencast_spec_set_pixel_format(MirScreencastSpec* spec, MirPixelFormat format)
4790+{
4791+ spec->pixel_format = format;
4792+}
4793+
4794+void mir_screencast_spec_set_capture_region(MirScreencastSpec* spec, MirRectangle const* region)
4795+{
4796+ spec->capture_region = *region;
4797+}
4798+
4799+void mir_screencast_spec_set_mirror_mode(MirScreencastSpec* spec, MirMirrorMode mode)
4800+{
4801+ spec->mirror_mode = mode;
4802+}
4803+
4804+void mir_screencast_spec_set_number_of_buffers(MirScreencastSpec* spec, unsigned int nbuffers)
4805+{
4806+ spec->num_buffers = nbuffers;
4807+}
4808+
4809+void mir_screencast_spec_release(MirScreencastSpec* spec)
4810+{
4811+ delete spec;
4812+}
4813+
4814+MirScreencast* mir_screencast_create_sync(MirScreencastSpec* spec)
4815+try
4816+{
4817+ return create_screencast(spec);
4818+}
4819+catch (std::exception const& ex)
4820+{
4821+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
4822+ return new MirScreencast(ex.what());
4823+}
4824+
4825+bool mir_screencast_is_valid(MirScreencast *screencast)
4826+{
4827+ return screencast && screencast->valid();
4828+}
4829+
4830+char const *mir_screencast_get_error_message(MirScreencast *screencast)
4831+{
4832+ return screencast->get_error_message();
4833+}
4834+
4835
4836 MirScreencast* mir_connection_create_screencast_sync(
4837 MirConnection* connection,
4838 MirScreencastParameters* parameters)
4839 {
4840- if (!MirConnection::is_valid(connection))
4841- return nullptr;
4842-
4843- MirScreencast* screencast = nullptr;
4844-
4845- try
4846- {
4847- auto const config = mir::raii::deleter_for(
4848- mir_connection_create_display_config(connection),
4849- &mir_display_config_destroy);
4850-
4851- mir::geometry::Rectangle const region{
4852- {parameters->region.left, parameters->region.top},
4853- {parameters->region.width, parameters->region.height}
4854- };
4855- mir::geometry::Size const size{parameters->width, parameters->height};
4856-
4857- std::unique_ptr<MirScreencast> screencast_uptr{
4858- new MirScreencast{
4859- region,
4860- size,
4861- parameters->pixel_format,
4862- connection->display_server(),
4863- connection,
4864- null_callback, nullptr}};
4865-
4866- screencast_uptr->creation_wait_handle()->wait_for_all();
4867-
4868- if (screencast_uptr->valid())
4869- {
4870- screencast = screencast_uptr.get();
4871- screencast_uptr.release();
4872- }
4873- }
4874- catch (std::exception const& ex)
4875- {
4876- MIR_LOG_UNCAUGHT_EXCEPTION(ex);
4877- return nullptr;
4878- }
4879-
4880- return screencast;
4881+ mir::require(mir_connection_is_valid(connection));
4882+ MirScreencastSpec spec{connection, *parameters};
4883+ return mir_screencast_create_sync(&spec);
4884 }
4885
4886 void mir_screencast_release_sync(MirScreencast* screencast)
4887
4888=== modified file 'src/client/presentation_chain.cpp'
4889--- src/client/presentation_chain.cpp 2016-03-16 13:45:00 +0000
4890+++ src/client/presentation_chain.cpp 2016-04-27 09:08:17 +0000
4891@@ -127,10 +127,12 @@
4892 if (buffer_it != buffers.end())
4893 {
4894 (*buffer_it)->received(*package);
4895- return;
4896- }
4897-
4898- buffers.emplace_back(mir_buffer_factory->generate_buffer(buffer));
4899+ }
4900+ else
4901+ {
4902+ buffers.emplace_back(mir_buffer_factory->generate_buffer(buffer));
4903+ buffers.back()->received();
4904+ }
4905 }
4906
4907 void mcl::PresentationChain::buffer_unavailable()
4908
4909=== modified file 'src/client/rpc/mir_display_server.cpp'
4910--- src/client/rpc/mir_display_server.cpp 2016-01-29 08:18:22 +0000
4911+++ src/client/rpc/mir_display_server.cpp 2016-04-27 09:08:17 +0000
4912@@ -56,13 +56,6 @@
4913 {
4914 channel->call_method(std::string(__func__), request, response, done);
4915 }
4916-void mclr::DisplayServer::next_buffer(
4917- mir::protobuf::SurfaceId const* request,
4918- mir::protobuf::Buffer* response,
4919- google::protobuf::Closure* done)
4920-{
4921- channel->call_method(std::string(__func__), request, response, done);
4922-}
4923 void mclr::DisplayServer::release_surface(
4924 mir::protobuf::SurfaceId const* request,
4925 mir::protobuf::Void* response,
4926@@ -98,6 +91,20 @@
4927 {
4928 channel->call_method(std::string(__func__), request, response, done);
4929 }
4930+void mclr::DisplayServer::preview_base_display_configuration(
4931+ mir::protobuf::PreviewConfiguration const* request,
4932+ mir::protobuf::Void* response,
4933+ google::protobuf::Closure* done)
4934+{
4935+ channel->call_method(std::string(__func__), request, response, done);
4936+}
4937+void mclr::DisplayServer::confirm_base_display_configuration(
4938+ mir::protobuf::DisplayConfiguration const* request,
4939+ mir::protobuf::Void* response,
4940+ google::protobuf::Closure* done)
4941+{
4942+ channel->call_method(std::string(__func__), request, response, done);
4943+}
4944 void mclr::DisplayServer::create_screencast(
4945 mir::protobuf::ScreencastParameters const* request,
4946 mir::protobuf::Screencast* response,
4947
4948=== modified file 'src/client/rpc/mir_display_server.h'
4949--- src/client/rpc/mir_display_server.h 2016-01-29 08:18:22 +0000
4950+++ src/client/rpc/mir_display_server.h 2016-04-27 09:08:17 +0000
4951@@ -51,10 +51,6 @@
4952 mir::protobuf::SurfaceModifications const* request,
4953 mir::protobuf::Void* response,
4954 google::protobuf::Closure* done) override;
4955- void next_buffer(
4956- mir::protobuf::SurfaceId const* request,
4957- mir::protobuf::Buffer* response,
4958- google::protobuf::Closure* done) override;
4959 void release_surface(
4960 mir::protobuf::SurfaceId const* request,
4961 mir::protobuf::Void* response,
4962@@ -75,6 +71,14 @@
4963 mir::protobuf::DisplayConfiguration const* request,
4964 mir::protobuf::Void* response,
4965 google::protobuf::Closure* done) override;
4966+ void preview_base_display_configuration(
4967+ mir::protobuf::PreviewConfiguration const* request,
4968+ mir::protobuf::Void* response,
4969+ google::protobuf::Closure* done) override;
4970+ void confirm_base_display_configuration(
4971+ mir::protobuf::DisplayConfiguration const* request,
4972+ mir::protobuf::Void* response,
4973+ google::protobuf::Closure* done) override;
4974 void create_screencast(
4975 mir::protobuf::ScreencastParameters const* request,
4976 mir::protobuf::Screencast* response,
4977
4978=== modified file 'src/client/rpc/mir_protobuf_rpc_channel.cpp'
4979--- src/client/rpc/mir_protobuf_rpc_channel.cpp 2016-03-17 17:47:42 +0000
4980+++ src/client/rpc/mir_protobuf_rpc_channel.cpp 2016-04-27 09:08:17 +0000
4981@@ -342,34 +342,34 @@
4982 auto const send_e = [&e](MirSurface* surface)
4983 { surface->handle_event(*e); };
4984
4985- switch (e->type)
4986+ switch (e->type())
4987 {
4988 case mir_event_type_surface:
4989 if (auto map = surface_map.lock())
4990- map->with_surface_do(mf::SurfaceId(e->surface.id), send_e);
4991+ map->with_surface_do(mf::SurfaceId(e->to_surface()->id()), send_e);
4992 break;
4993
4994 case mir_event_type_resize:
4995 if (auto map = surface_map.lock())
4996- map->with_surface_do(mf::SurfaceId(e->resize.surface_id), send_e);
4997+ map->with_surface_do(mf::SurfaceId(e->to_resize()->surface_id()), send_e);
4998 break;
4999
5000 case mir_event_type_orientation:
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: