Mir

Merge lp:~alan-griffiths/mir/move-miral-to-mir into lp:mir

Proposed by Alan Griffiths on 2017-08-21
Status: Superseded
Proposed branch: lp:~alan-griffiths/mir/move-miral-to-mir
Merge into: lp:mir
Diff against target: 18084 lines (+17390/-2)
127 files modified
CMakeLists.txt (+0/-2)
cmake/FindPIL.cmake (+8/-0)
debian/changelog (+3/-0)
debian/control (+51/-0)
debian/libmiral-dev.install (+3/-0)
debian/libmiral2.install (+1/-0)
debian/libmiral2.symbols (+399/-0)
debian/libmirclientcpp-dev.install (+2/-0)
debian/miral-examples.install (+9/-0)
examples/CMakeLists.txt (+3/-0)
examples/miral-kiosk/CMakeLists.txt (+12/-0)
examples/miral-kiosk/kiosk_main.cpp (+94/-0)
examples/miral-kiosk/kiosk_window_manager.cpp (+148/-0)
examples/miral-kiosk/kiosk_window_manager.h (+52/-0)
examples/miral-kiosk/sw_splash.cpp (+173/-0)
examples/miral-kiosk/sw_splash.h (+44/-0)
examples/miral-shell/CMakeLists.txt (+65/-0)
examples/miral-shell/decoration_provider.cpp (+666/-0)
examples/miral-shell/decoration_provider.h (+119/-0)
examples/miral-shell/desktop/CMakeLists.txt (+12/-0)
examples/miral-shell/desktop/miral-shell.desktop.in (+18/-0)
examples/miral-shell/desktop/ubuntu-logo.svg (+27/-0)
examples/miral-shell/floating_window_manager.cpp (+801/-0)
examples/miral-shell/floating_window_manager.h (+146/-0)
examples/miral-shell/miral-app.sh (+51/-0)
examples/miral-shell/miral-desktop.sh (+45/-0)
examples/miral-shell/miral-run.sh (+17/-0)
examples/miral-shell/miral-screencast.sh (+48/-0)
examples/miral-shell/miral-xrun.sh (+45/-0)
examples/miral-shell/shell_main.cpp (+98/-0)
examples/miral-shell/spinner/CMakeLists.txt (+67/-0)
examples/miral-shell/spinner/eglapp.cpp (+83/-0)
examples/miral-shell/spinner/eglapp.h (+33/-0)
examples/miral-shell/spinner/eglspinner.cpp (+372/-0)
examples/miral-shell/spinner/miregl.cpp (+239/-0)
examples/miral-shell/spinner/miregl.h (+67/-0)
examples/miral-shell/spinner/png2header.py (+87/-0)
examples/miral-shell/spinner/splash.h (+45/-0)
examples/miral-shell/tiling_window_manager.cpp (+688/-0)
examples/miral-shell/tiling_window_manager.h (+140/-0)
examples/miral-shell/titlebar_config.cpp (+38/-0)
examples/miral-shell/titlebar_config.h (+30/-0)
include/miral/mir/client/blob.h (+50/-0)
include/miral/mir/client/connection.h (+54/-0)
include/miral/mir/client/cookie.h (+50/-0)
include/miral/mir/client/display_config.h (+78/-0)
include/miral/mir/client/surface.h (+50/-0)
include/miral/mir/client/window.h (+53/-0)
include/miral/mir/client/window_id.h (+48/-0)
include/miral/mir/client/window_spec.h (+253/-0)
include/miral/miral/active_outputs.h (+74/-0)
include/miral/miral/add_init_callback.h (+47/-0)
include/miral/miral/append_event_filter.h (+44/-0)
include/miral/miral/application.h (+42/-0)
include/miral/miral/application_authorizer.h (+103/-0)
include/miral/miral/application_info.h (+55/-0)
include/miral/miral/canonical_window_manager.h (+59/-0)
include/miral/miral/command_line_option.h (+109/-0)
include/miral/miral/cursor_theme.h (+44/-0)
include/miral/miral/debug_extension.h (+47/-0)
include/miral/miral/display_configuration_option.h (+30/-0)
include/miral/miral/internal_client.h (+88/-0)
include/miral/miral/keymap.h (+58/-0)
include/miral/miral/output.h (+113/-0)
include/miral/miral/runner.h (+74/-0)
include/miral/miral/set_command_line_handler.h (+50/-0)
include/miral/miral/set_terminator.h (+47/-0)
include/miral/miral/set_window_management_policy.h (+55/-0)
include/miral/miral/version.h (+67/-0)
include/miral/miral/window.h (+82/-0)
include/miral/miral/window_info.h (+130/-0)
include/miral/miral/window_management_options.h (+65/-0)
include/miral/miral/window_management_policy.h (+194/-0)
include/miral/miral/window_management_policy_addendum2.h (+70/-0)
include/miral/miral/window_management_policy_addendum3.h (+68/-0)
include/miral/miral/window_manager_tools.h (+254/-0)
include/miral/miral/window_specification.h (+134/-0)
include/miral/miral/workspace_policy.h (+88/-0)
src/CMakeLists.txt (+1/-0)
src/miral/CMakeLists.txt (+139/-0)
src/miral/active_outputs.cpp (+65/-0)
src/miral/add_init_callback.cpp (+33/-0)
src/miral/append_event_filter.cpp (+48/-0)
src/miral/application.cpp (+51/-0)
src/miral/application_authorizer.cpp (+129/-0)
src/miral/application_info.cpp (+99/-0)
src/miral/basic_window_manager.cpp (+2234/-0)
src/miral/basic_window_manager.h (+272/-0)
src/miral/both_versions.h (+33/-0)
src/miral/canonical_window_manager.cpp (+77/-0)
src/miral/command_line_option.cpp (+210/-0)
src/miral/coordinate_translator.cpp (+51/-0)
src/miral/coordinate_translator.h (+52/-0)
src/miral/cursor_theme.cpp (+62/-0)
src/miral/debug_extension.cpp (+51/-0)
src/miral/display_configuration_listeners.cpp (+120/-0)
src/miral/display_configuration_listeners.h (+67/-0)
src/miral/display_configuration_option.cpp (+115/-0)
src/miral/internal_client.cpp (+215/-0)
src/miral/join_client_threads.h (+24/-0)
src/miral/keymap.cpp (+173/-0)
src/miral/miral.pc.in (+9/-0)
src/miral/mirclientcpp.pc.in (+7/-0)
src/miral/mru_window_list.cpp (+65/-0)
src/miral/mru_window_list.h (+46/-0)
src/miral/output.cpp (+117/-0)
src/miral/runner.cpp (+278/-0)
src/miral/set_command_line_handler.cpp (+33/-0)
src/miral/set_terminator.cpp (+33/-0)
src/miral/set_window_management_policy.cpp (+91/-0)
src/miral/symbols.map (+438/-0)
src/miral/version.h.in (+67/-0)
src/miral/window.cpp (+127/-0)
src/miral/window_info.cpp (+594/-0)
src/miral/window_management_options.cpp (+99/-0)
src/miral/window_management_policy.cpp (+37/-0)
src/miral/window_management_trace.cpp (+798/-0)
src/miral/window_management_trace.h (+146/-0)
src/miral/window_manager_tools.cpp (+141/-0)
src/miral/window_manager_tools_implementation.h (+108/-0)
src/miral/window_specification.cpp (+587/-0)
src/miral/workspace_policy.cpp (+29/-0)
src/miral/xcursor.c (+899/-0)
src/miral/xcursor.h (+62/-0)
src/miral/xcursor_loader.cpp (+215/-0)
src/miral/xcursor_loader.h (+66/-0)
tools/update_package_abis.sh (+1/-0)
To merge this branch: bzr merge lp:~alan-griffiths/mir/move-miral-to-mir
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Needs Fixing on 2017-08-23
Mir development team 2017-08-21 Pending
Review via email: mp+329316@code.launchpad.net

Commit message

Incorporate miral project into mir source tree

Description of the change

Incorporate miral project into mir source tree

This is a first-cut:

1. It lacks the miral-test build (as that needs rework to fit)
2. There's no attempt to remove code obsoleted by MirAL

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

FAILED: Continuous integration, rev:4235
https://mir-jenkins.ubuntu.com/job/mir-ci/3563/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4883/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5098
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5087
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5087
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5087
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4920/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4920/console

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

review: Needs Fixing (continuous-integration)
4236. By Alan Griffiths on 2017-08-21

Add PIL

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4236
https://mir-jenkins.ubuntu.com/job/mir-ci/3564/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4884/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5099
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5088
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5088
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5088
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4921/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4921/console

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

review: Needs Fixing (continuous-integration)
4237. By Alan Griffiths on 2017-08-22

add debian/tmp/DEBIAN

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4237
https://mir-jenkins.ubuntu.com/job/mir-ci/3565/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4885/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5100
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5089
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5089
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5089
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4922/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4922/console

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

review: Needs Fixing (continuous-integration)
4238. By Alan Griffiths on 2017-08-22

Fix check-miral-symbols

4239. By Alan Griffiths on 2017-08-22

Update package-abis script

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4238
https://mir-jenkins.ubuntu.com/job/mir-ci/3566/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4886/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5101
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5090
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5090
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5090
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4923/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4923/console

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4239
https://mir-jenkins.ubuntu.com/job/mir-ci/3567/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4887/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5102
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5091
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5091
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5091
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4924/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4924/console

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

review: Needs Fixing (continuous-integration)
4240. By Alan Griffiths on 2017-08-22

Use override consistently to placate clang

4241. By Alan Griffiths on 2017-08-22

Don't check libmiral symbols for clang builds

4242. By Alan Griffiths on 2017-08-22

Fix miral headers source

4243. By Alan Griffiths on 2017-08-22

Fix MirAL install path

4244. By Alan Griffiths on 2017-08-22

Remove miral-docs

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4242
https://mir-jenkins.ubuntu.com/job/mir-ci/3568/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4888/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5103
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5092
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5092
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5092
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4925/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4925/console
    ABORTED: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4925/console

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

review: Needs Fixing (continuous-integration)
4245. By Alan Griffiths on 2017-08-22

Revert unnecessary change to debian/libmiral2.symbols

4246. By Alan Griffiths on 2017-08-22

Code to debug CI build

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4244
https://mir-jenkins.ubuntu.com/job/mir-ci/3569/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4889/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5104
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5093
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5093
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5093
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4926/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4926/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4926
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4926/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4926
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4926/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4926
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4926/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4926/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4926/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4926
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4926/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
4247. By Alan Griffiths on 2017-08-22

Use CMAKE_COMPILER_IS_GNUCXX instead of trying to matck clang

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4246
https://mir-jenkins.ubuntu.com/job/mir-ci/3570/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4890/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5105
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5094
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5094
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5094
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4927/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4927/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4927/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4927/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4927/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4927/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4927/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4927
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4927/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4247
https://mir-jenkins.ubuntu.com/job/mir-ci/3571/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4891/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5106
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5095
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5095
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5095
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4928/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4928/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4928
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4928/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4928
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4928/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4928
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4928/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4928/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4928/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4928
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4928/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

Artful/armhf:

"18:00:14 sbuild-build-depends-mir-dummy:armhf : Depends: python-pil:armhf but it is not going to be installed"

Why not? Artful appears to have it.

Zesty/armhf:

18:00:18 /usr/bin/python2.7: 1: /usr/bin/python2.7: Syntax error: word unexpected (expecting ")")
18:00:18 dpkg: error processing package python2.7-minimal:armhf (--configure):
18:00:18 subprocess installed post-installation script returned error exit status 2
18:00:18 dpkg: dependency problems prevent configuration of python-minimal:armhf:
18:00:18 python-minimal:armhf depends on python2.7-minimal (>= 2.7.13-1~); however:
18:00:18 Package python2.7-minimal:armhf is not configured yet.
18:00:18
18:00:18 dpkg: error processing package python-minimal:armhf (--configure):
18:00:18 dependency problems - leaving unconfigured
18:00:18 Errors were encountered while processing:
18:00:18 python2.7-minimal:armhf
18:00:18 python-minimal:armhf

Python 2.7!?

Oh...

$ apt depends python-pil
python-pil
  Depends: python (<< 2.8)
...

4248. By Alan Griffiths on 2017-08-23

Use python*3*-pil

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4248
https://mir-jenkins.ubuntu.com/job/mir-ci/3573/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4895/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5115
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5104
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5104
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5104
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4932/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4932/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4932/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4932/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4932/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4932/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4932/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4932
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4932/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
4249. By Alan Griffiths on 2017-08-29

Add an epoch so that miral packaged with 1.0 will install

4250. By Alan Griffiths on 2017-08-29

Fix miral and mirclientcpp package configs

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2017-08-10 10:25:55 +0000
3+++ CMakeLists.txt 2017-08-23 11:59:25 +0000
4@@ -81,8 +81,6 @@
5 endif()
6
7 # Link time optimization allows leaner, cleaner libraries
8-message(STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER})
9-
10 option(MIR_LINK_TIME_OPTIMIZATION "Enables the linker to optimize binaries." OFF)
11 if(MIR_LINK_TIME_OPTIMIZATION)
12 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto -ffat-lto-objects")
13
14=== added file 'cmake/FindPIL.cmake'
15--- cmake/FindPIL.cmake 1970-01-01 00:00:00 +0000
16+++ cmake/FindPIL.cmake 2017-08-23 11:59:25 +0000
17@@ -0,0 +1,8 @@
18+execute_process(
19+ COMMAND python3 -c "from PIL import Image"
20+ RESULT_VARIABLE HAVE_PIL
21+)
22+
23+if (NOT ${HAVE_PIL} EQUAL 0)
24+ message(FATAL_ERROR "Python Imaging Library (PIL) not found")
25+endif()
26
27=== modified file 'debian/changelog'
28--- debian/changelog 2017-08-16 13:52:52 +0000
29+++ debian/changelog 2017-08-23 11:59:25 +0000
30@@ -3,6 +3,7 @@
31 * New upstream release 1.0.0(https://launchpad.net/mir/+milestone/1.0.0)
32 - ABI summary:
33 . mirclient ABI unchanged at 9
34+ . miral ABI introduced at 2
35 . mirserver ABI bumped to 45
36 . mircommon ABI unchanged at 7
37 . mirplatform ABI unchanged at 61
38@@ -15,6 +16,8 @@
39 . Update licences to (L)GPL3 or (L)GPL2.
40 . [mir_demo_client_display_config] add orientation changing
41 . RPC: Don't require the server ACK client's buffer-release requests.
42+ . Added libmirclientcpp to Mir source package
43+ . Added libmiral to Mir source package
44 - Bugs fixed:
45 . Fix handling of invalid display configuration. (LP: #1643446)
46 . Move full responsibility for buffer IPC into frontend. (LP: #1395421)
47
48=== modified file 'debian/control'
49--- debian/control 2017-08-02 13:18:44 +0000
50+++ debian/control 2017-08-23 11:59:25 +0000
51@@ -45,6 +45,7 @@
52 libcapnp-dev,
53 capnproto,
54 libepoxy-dev,
55+ python3-pil:native,
56 Standards-Version: 3.9.4
57 Homepage: https://launchpad.net/mir
58 # If you aren't a member of ~mir-team but need to upload packaging changes,
59@@ -477,3 +478,53 @@
60 .
61 Contains header files that define the interfaces through which platforms and
62 renderers access the functionality needed to render with GL.
63+
64+Package: libmiral2
65+Section: libs
66+Architecture: linux-any
67+Multi-Arch: same
68+Pre-Depends: ${misc:Pre-Depends}
69+Depends: ${misc:Depends},
70+ ${shlibs:Depends},
71+Description: Display server for Ubuntu - ABI preserving abstraction layer
72+ MirAL provides an ABI-stable abstraction layer for Mir based shells,
73+ insulating them from mirserver ABI breaks.
74+ .
75+ Contains the shared library containing MirAL abstraction layer.
76+
77+Package: libmiral-dev
78+Section: libdevel
79+Architecture: linux-any
80+Multi-Arch: same
81+Pre-Depends: ${misc:Pre-Depends}
82+Depends: libmiral2 (= ${binary:Version}),
83+ libmirclientcpp-dev (= ${binary:Version}),
84+ ${misc:Depends},
85+Description: Developer files for the Mir ABI-stable abstraction layer
86+ MirAL provides an ABI-stable abstraction layer for Mir based shells,
87+ insulating them from mirserver ABI breaks.
88+ .
89+ Contains header files required for development using the MirAL abstraction
90+ layer.
91+
92+Package: libmirclientcpp-dev
93+Section: libdevel
94+Architecture: linux-any
95+Multi-Arch: same
96+Pre-Depends: ${misc:Pre-Depends}
97+Depends: libmirclient-dev,
98+Description: A C++ wrapper for libmirclient-dev
99+ Provides RAII (and other facilities) for Mir client library types.
100+ .
101+ Contains header files useful for C++ development against Mir.
102+
103+Package: miral-examples
104+Architecture: linux-any
105+Depends: ${misc:Depends},
106+ ${shlibs:Depends},
107+Recommends: dmz-cursor-theme,
108+Description: Display server for Ubuntu - demonstration programs
109+ MirAL provides an ABI-stable abstraction layer for Mir based shells,
110+ insulating them from mirserver ABI breaks.
111+ .
112+ Contains demo applications that use the MirAL abstraction layer
113
114=== added file 'debian/libmiral-dev.install'
115--- debian/libmiral-dev.install 1970-01-01 00:00:00 +0000
116+++ debian/libmiral-dev.install 2017-08-23 11:59:25 +0000
117@@ -0,0 +1,3 @@
118+usr/include/miral/miral/*
119+usr/lib/*/pkgconfig/miral.pc
120+usr/lib/*/libmiral.so
121
122=== added file 'debian/libmiral2.install'
123--- debian/libmiral2.install 1970-01-01 00:00:00 +0000
124+++ debian/libmiral2.install 2017-08-23 11:59:25 +0000
125@@ -0,0 +1,1 @@
126+usr/lib/*/libmiral.so.2
127
128=== added file 'debian/libmiral2.symbols'
129--- debian/libmiral2.symbols 1970-01-01 00:00:00 +0000
130+++ debian/libmiral2.symbols 2017-08-23 11:59:25 +0000
131@@ -0,0 +1,399 @@
132+libmiral.so.2 libmiral2 #MINVER#
133+ MIRAL_1.0@MIRAL_1.0 1.0.0
134+ (c++)"miral::WindowInfo::height_inc(mir::geometry::detail::IntWrapper<mir::geometry::DeltaYTag>)@MIRAL_1.0" 1.0.0
135+ (c++)"miral::WindowInfo::max_aspect(miral::WindowSpecification::AspectRatio)@MIRAL_1.0" 1.0.0
136+ (c++)"miral::WindowInfo::max_height(mir::geometry::detail::IntWrapper<mir::geometry::HeightTag>)@MIRAL_1.0" 1.0.0
137+ (c++)"miral::WindowInfo::min_aspect(miral::WindowSpecification::AspectRatio)@MIRAL_1.0" 1.0.0
138+ (c++)"miral::WindowInfo::min_height(mir::geometry::detail::IntWrapper<mir::geometry::HeightTag>)@MIRAL_1.0" 1.0.0
139+ (c++)"miral::WindowInfo::remove_child(miral::Window const&)@MIRAL_1.0" 1.0.0
140+ (c++)"miral::WindowInfo::restore_rect(mir::geometry::Rectangle const&)@MIRAL_1.0" 1.0.0
141+ (c++)"miral::WindowInfo::needs_titlebar(MirSurfaceType)@MIRAL_1.0" 1.0.0
142+ (c++)"miral::WindowInfo::confine_pointer(MirPointerConfinementState)@MIRAL_1.0" 1.0.0
143+ (c++)"miral::WindowInfo::preferred_orientation(MirOrientationMode)@MIRAL_1.0" 1.0.0
144+ (c++)"miral::WindowInfo::name(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
145+ (c++)"miral::WindowInfo::type(MirSurfaceType)@MIRAL_1.0" 1.0.0
146+ (c++)"miral::WindowInfo::state(MirSurfaceState)@MIRAL_1.0" 1.0.0
147+ (c++)"miral::WindowInfo::parent(miral::Window const&)@MIRAL_1.0" 1.0.0
148+ (c++)"miral::WindowInfo::userdata(std::shared_ptr<void>)@MIRAL_1.0" 1.0.0
149+ (c++)"miral::WindowInfo::add_child(miral::Window const&)@MIRAL_1.0" 1.0.0
150+ (c++)"miral::WindowInfo::max_width(mir::geometry::detail::IntWrapper<mir::geometry::WidthTag>)@MIRAL_1.0" 1.0.0
151+ (c++)"miral::WindowInfo::min_width(mir::geometry::detail::IntWrapper<mir::geometry::WidthTag>)@MIRAL_1.0" 1.0.0
152+ (c++)"miral::WindowInfo::output_id(mir::optional_value<int>)@MIRAL_1.0" 1.0.0
153+ (c++)"miral::WindowInfo::width_inc(mir::geometry::detail::IntWrapper<mir::geometry::DeltaXTag>)@MIRAL_1.0" 1.0.0
154+ (c++)"miral::WindowInfo::WindowInfo(miral::Window const&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
155+ (c++)"miral::WindowInfo::WindowInfo(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
156+ (c++)"miral::WindowInfo::WindowInfo()@MIRAL_1.0" 1.0.0
157+ (c++)"miral::WindowInfo::WindowInfo(miral::Window const&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
158+ (c++)"miral::WindowInfo::WindowInfo(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
159+ (c++)"miral::WindowInfo::WindowInfo()@MIRAL_1.0" 1.0.0
160+ (c++)"miral::WindowInfo::~WindowInfo()@MIRAL_1.0" 1.0.0
161+ (c++)"miral::WindowInfo::~WindowInfo()@MIRAL_1.0" 1.0.0
162+ (c++)"miral::WindowInfo::operator=(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
163+ (c++)"miral::CursorTheme::CursorTheme(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
164+ (c++)"miral::CursorTheme::CursorTheme(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
165+ (c++)"miral::CursorTheme::~CursorTheme()@MIRAL_1.0" 1.0.0
166+ (c++)"miral::CursorTheme::~CursorTheme()@MIRAL_1.0" 1.0.0
167+ (c++)"miral::SetTerminator::SetTerminator(std::function<void (int)> const&)@MIRAL_1.0" 1.0.0
168+ (c++)"miral::SetTerminator::SetTerminator(std::function<void (int)> const&)@MIRAL_1.0" 1.0.0
169+ (c++)"miral::SetTerminator::~SetTerminator()@MIRAL_1.0" 1.0.0
170+ (c++)"miral::SetTerminator::~SetTerminator()@MIRAL_1.0" 1.0.0
171+ (c++)"miral::DebugExtension::enable()@MIRAL_1.0" 1.0.0
172+ (c++)"miral::DebugExtension::disable()@MIRAL_1.0" 1.0.0
173+ (c++)"miral::DebugExtension::DebugExtension(miral::DebugExtension const&)@MIRAL_1.0" 1.0.0
174+ (c++)"miral::DebugExtension::DebugExtension()@MIRAL_1.0" 1.0.0
175+ (c++)"miral::DebugExtension::DebugExtension(miral::DebugExtension const&)@MIRAL_1.0" 1.0.0
176+ (c++)"miral::DebugExtension::DebugExtension()@MIRAL_1.0" 1.0.0
177+ (c++)"miral::DebugExtension::operator=(miral::DebugExtension const&)@MIRAL_1.0" 1.0.0
178+ (c++)"miral::AddInitCallback::AddInitCallback(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
179+ (c++)"miral::AddInitCallback::AddInitCallback(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
180+ (c++)"miral::AddInitCallback::~AddInitCallback()@MIRAL_1.0" 1.0.0
181+ (c++)"miral::AddInitCallback::~AddInitCallback()@MIRAL_1.0" 1.0.0
182+ (c++)"miral::ApplicationInfo::add_window(miral::Window const&)@MIRAL_1.0" 1.0.0
183+ (c++)"miral::ApplicationInfo::remove_window(miral::Window const&)@MIRAL_1.0" 1.0.0
184+ (c++)"miral::ApplicationInfo::userdata(std::shared_ptr<void>)@MIRAL_1.0" 1.0.0
185+ (c++)"miral::ApplicationInfo::ApplicationInfo(miral::ApplicationInfo const&)@MIRAL_1.0" 1.0.0
186+ (c++)"miral::ApplicationInfo::ApplicationInfo(std::shared_ptr<mir::scene::Session> const&)@MIRAL_1.0" 1.0.0
187+ (c++)"miral::ApplicationInfo::ApplicationInfo()@MIRAL_1.0" 1.0.0
188+ (c++)"miral::ApplicationInfo::ApplicationInfo(miral::ApplicationInfo const&)@MIRAL_1.0" 1.0.0
189+ (c++)"miral::ApplicationInfo::ApplicationInfo(std::shared_ptr<mir::scene::Session> const&)@MIRAL_1.0" 1.0.0
190+ (c++)"miral::ApplicationInfo::ApplicationInfo()@MIRAL_1.0" 1.0.0
191+ (c++)"miral::ApplicationInfo::~ApplicationInfo()@MIRAL_1.0" 1.0.0
192+ (c++)"miral::ApplicationInfo::~ApplicationInfo()@MIRAL_1.0" 1.0.0
193+ (c++)"miral::ApplicationInfo::operator=(miral::ApplicationInfo const&)@MIRAL_1.0" 1.0.0
194+ (c++)"miral::AppendEventFilter::AppendEventFilter(std::function<int (MirEvent const*)> const&)@MIRAL_1.0" 1.0.0
195+ (c++)"miral::AppendEventFilter::AppendEventFilter(std::function<int (MirEvent const*)> const&)@MIRAL_1.0" 1.0.0
196+ (c++)"miral::AppendEventFilter::operator()(mir::Server&)@MIRAL_1.0" 1.0.0
197+ (c++)"miral::CommandLineOption::CommandLineOption(miral::CommandLineOption const&)@MIRAL_1.0" 1.0.0
198+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
199+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<bool> const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
200+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<int> const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
201+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)@MIRAL_1.0" 1.0.0
202+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
203+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (bool)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
204+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (bool)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@MIRAL_1.0" 1.0.0
205+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (double)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double)@MIRAL_1.0" 1.0.0
206+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (int)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)@MIRAL_1.0" 1.0.0
207+ (c++)"miral::CommandLineOption::CommandLineOption(miral::CommandLineOption const&)@MIRAL_1.0" 1.0.0
208+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
209+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<bool> const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
210+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (mir::optional_value<int> const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
211+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)@MIRAL_1.0" 1.0.0
212+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
213+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (bool)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
214+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (bool)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@MIRAL_1.0" 1.0.0
215+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (double)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double)@MIRAL_1.0" 1.0.0
216+ (c++)"miral::CommandLineOption::CommandLineOption(std::function<void (int)>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)@MIRAL_1.0" 1.0.0
217+ (c++)"miral::CommandLineOption::~CommandLineOption()@MIRAL_1.0" 1.0.0
218+ (c++)"miral::CommandLineOption::~CommandLineOption()@MIRAL_1.0" 1.0.0
219+ (c++)"miral::CommandLineOption::operator=(miral::CommandLineOption const&)@MIRAL_1.0" 1.0.0
220+ (c++)"miral::WindowManagerTools::raise_tree(miral::Window const&)@MIRAL_1.0" 1.0.0
221+ (c++)"miral::WindowManagerTools::force_close(miral::Window const&)@MIRAL_1.0" 1.0.0
222+ (c++)"miral::WindowManagerTools::modify_window(miral::Window const&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
223+ (c++)"miral::WindowManagerTools::modify_window(miral::WindowInfo&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
224+ (c++)"miral::WindowManagerTools::active_display()@MIRAL_1.0" 1.0.0
225+ (c++)"miral::WindowManagerTools::find_application(std::function<bool (miral::ApplicationInfo const&)> const&)@MIRAL_1.0" 1.0.0
226+ (c++)"miral::WindowManagerTools::invoke_under_lock(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
227+ (c++)"miral::WindowManagerTools::drag_active_window(mir::geometry::Displacement)@MIRAL_1.0" 1.0.0
228+ (c++)"miral::WindowManagerTools::ask_client_to_close(miral::Window const&)@MIRAL_1.0" 1.0.0
229+ (c++)"miral::WindowManagerTools::for_each_application(std::function<void (miral::ApplicationInfo&)> const&)@MIRAL_1.0" 1.0.0
230+ (c++)"miral::WindowManagerTools::select_active_window(miral::Window const&)@MIRAL_1.0" 1.0.0
231+ (c++)"miral::WindowManagerTools::focus_next_application()@MIRAL_1.0" 1.0.0
232+ (c++)"miral::WindowManagerTools::focus_next_within_application()@MIRAL_1.0" 1.0.0
233+ (c++)"miral::WindowManagerTools::WindowManagerTools(miral::WindowManagerToolsImplementation*)@MIRAL_1.0" 1.0.0
234+ (c++)"miral::WindowManagerTools::WindowManagerTools(miral::WindowManagerTools const&)@MIRAL_1.0" 1.0.0
235+ (c++)"miral::WindowManagerTools::WindowManagerTools(miral::WindowManagerToolsImplementation*)@MIRAL_1.0" 1.0.0
236+ (c++)"miral::WindowManagerTools::WindowManagerTools(miral::WindowManagerTools const&)@MIRAL_1.0" 1.0.0
237+ (c++)"miral::WindowManagerTools::~WindowManagerTools()@MIRAL_1.0" 1.0.0
238+ (c++)"miral::WindowManagerTools::~WindowManagerTools()@MIRAL_1.0" 1.0.0
239+ (c++)"miral::WindowManagerTools::operator=(miral::WindowManagerTools const&)@MIRAL_1.0" 1.0.0
240+ (c++)"miral::WindowSpecification::height_inc()@MIRAL_1.0" 1.0.0
241+ (c++)"miral::WindowSpecification::input_mode()@MIRAL_1.0" 1.0.0
242+ (c++)"miral::WindowSpecification::max_aspect()@MIRAL_1.0" 1.0.0
243+ (c++)"miral::WindowSpecification::max_height()@MIRAL_1.0" 1.0.0
244+ (c++)"miral::WindowSpecification::min_aspect()@MIRAL_1.0" 1.0.0
245+ (c++)"miral::WindowSpecification::min_height()@MIRAL_1.0" 1.0.0
246+ (c++)"miral::WindowSpecification::input_shape()@MIRAL_1.0" 1.0.0
247+ (c++)"miral::WindowSpecification::shell_chrome()@MIRAL_1.0" 1.0.0
248+ (c++)"miral::WindowSpecification::confine_pointer()@MIRAL_1.0" 1.0.0
249+ (c++)"miral::WindowSpecification::placement_hints()@MIRAL_1.0" 1.0.0
250+ (c++)"miral::WindowSpecification::preferred_orientation()@MIRAL_1.0" 1.0.0
251+ (c++)"miral::WindowSpecification::window_placement_gravity()@MIRAL_1.0" 1.0.0
252+ (c++)"miral::WindowSpecification::aux_rect_placement_offset()@MIRAL_1.0" 1.0.0
253+ (c++)"miral::WindowSpecification::aux_rect_placement_gravity()@MIRAL_1.0" 1.0.0
254+ (c++)"miral::WindowSpecification::name[abi:cxx11]()@MIRAL_1.0" 1.0.0
255+ (c++)"miral::WindowSpecification::size()@MIRAL_1.0" 1.0.0
256+ (c++)"miral::WindowSpecification::type()@MIRAL_1.0" 1.0.0
257+ (c++)"miral::WindowSpecification::state()@MIRAL_1.0" 1.0.0
258+ (c++)"miral::WindowSpecification::parent()@MIRAL_1.0" 1.0.0
259+ (c++)"miral::WindowSpecification::aux_rect()@MIRAL_1.0" 1.0.0
260+ (c++)"miral::WindowSpecification::top_left()@MIRAL_1.0" 1.0.0
261+ (c++)"miral::WindowSpecification::userdata()@MIRAL_1.0" 1.0.0
262+ (c++)"miral::WindowSpecification::max_width()@MIRAL_1.0" 1.0.0
263+ (c++)"miral::WindowSpecification::min_width()@MIRAL_1.0" 1.0.0
264+ (c++)"miral::WindowSpecification::output_id()@MIRAL_1.0" 1.0.0
265+ (c++)"miral::WindowSpecification::width_inc()@MIRAL_1.0" 1.0.0
266+ (c++)"miral::WindowSpecification::WindowSpecification(mir::scene::SurfaceCreationParameters const&)@MIRAL_1.0" 1.0.0
267+ (c++)"miral::WindowSpecification::WindowSpecification(mir::shell::SurfaceSpecification const&)@MIRAL_1.0" 1.0.0
268+ (c++)"miral::WindowSpecification::WindowSpecification(miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
269+ (c++)"miral::WindowSpecification::WindowSpecification()@MIRAL_1.0" 1.0.0
270+ (c++)"miral::WindowSpecification::WindowSpecification(mir::scene::SurfaceCreationParameters const&)@MIRAL_1.0" 1.0.0
271+ (c++)"miral::WindowSpecification::WindowSpecification(mir::shell::SurfaceSpecification const&)@MIRAL_1.0" 1.0.0
272+ (c++)"miral::WindowSpecification::WindowSpecification(miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
273+ (c++)"miral::WindowSpecification::WindowSpecification()@MIRAL_1.0" 1.0.0
274+ (c++)"miral::WindowSpecification::~WindowSpecification()@MIRAL_1.0" 1.0.0
275+ (c++)"miral::WindowSpecification::~WindowSpecification()@MIRAL_1.0" 1.0.0
276+ (c++)"miral::WindowSpecification::operator=(miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
277+ (c++)"miral::ActiveOutputsMonitor::add_listener(miral::ActiveOutputsListener*)@MIRAL_1.0" 1.0.0
278+ (c++)"miral::ActiveOutputsMonitor::delete_listener(miral::ActiveOutputsListener*)@MIRAL_1.0" 1.0.0
279+ (c++)"miral::ActiveOutputsMonitor::ActiveOutputsMonitor(miral::ActiveOutputsMonitor const&)@MIRAL_1.0" 1.0.0
280+ (c++)"miral::ActiveOutputsMonitor::ActiveOutputsMonitor()@MIRAL_1.0" 1.0.0
281+ (c++)"miral::ActiveOutputsMonitor::ActiveOutputsMonitor(miral::ActiveOutputsMonitor const&)@MIRAL_1.0" 1.0.0
282+ (c++)"miral::ActiveOutputsMonitor::ActiveOutputsMonitor()@MIRAL_1.0" 1.0.0
283+ (c++)"miral::ActiveOutputsMonitor::~ActiveOutputsMonitor()@MIRAL_1.0" 1.0.0
284+ (c++)"miral::ActiveOutputsMonitor::~ActiveOutputsMonitor()@MIRAL_1.0" 1.0.0
285+ (c++)"miral::ActiveOutputsMonitor::operator=(miral::ActiveOutputsMonitor const&)@MIRAL_1.0" 1.0.0
286+ (c++)"miral::ActiveOutputsMonitor::operator()(mir::Server&)@MIRAL_1.0" 1.0.0
287+ (c++)"miral::ActiveOutputsListener::advise_output_end()@MIRAL_1.0" 1.0.0
288+ (c++)"miral::ActiveOutputsListener::advise_output_begin()@MIRAL_1.0" 1.0.0
289+ (c++)"miral::ActiveOutputsListener::advise_output_create(miral::Output const&)@MIRAL_1.0" 1.0.0
290+ (c++)"miral::ActiveOutputsListener::advise_output_delete(miral::Output const&)@MIRAL_1.0" 1.0.0
291+ (c++)"miral::ActiveOutputsListener::advise_output_update(miral::Output const&, miral::Output const&)@MIRAL_1.0" 1.0.0
292+ (c++)"miral::SetCommandLineHandler::SetCommandLineHandler(std::function<void (int, char const* const*)> const&)@MIRAL_1.0" 1.0.0
293+ (c++)"miral::SetCommandLineHandler::SetCommandLineHandler(std::function<void (int, char const* const*)> const&)@MIRAL_1.0" 1.0.0
294+ (c++)"miral::SetCommandLineHandler::~SetCommandLineHandler()@MIRAL_1.0" 1.0.0
295+ (c++)"miral::SetCommandLineHandler::~SetCommandLineHandler()@MIRAL_1.0" 1.0.0
296+ (c++)"miral::StartupInternalClient::StartupInternalClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void (miral::toolkit::Connection)>, std::function<void (std::weak_ptr<mir::scene::Session>)>)@MIRAL_1.0" 1.0.0
297+ (c++)"miral::StartupInternalClient::StartupInternalClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void (miral::toolkit::Connection)>, std::function<void (std::weak_ptr<mir::scene::Session>)>)@MIRAL_1.0" 1.0.0
298+ (c++)"miral::StartupInternalClient::~StartupInternalClient()@MIRAL_1.0" 1.0.0
299+ (c++)"miral::StartupInternalClient::~StartupInternalClient()@MIRAL_1.0" 1.0.0
300+ (c++)"miral::StartupInternalClient::operator()(mir::Server&)@MIRAL_1.0" 1.0.0
301+ (c++)"miral::ApplicationCredentials::ApplicationCredentials(mir::frontend::SessionCredentials const&)@MIRAL_1.0" 1.0.0
302+ (c++)"miral::ApplicationCredentials::ApplicationCredentials(mir::frontend::SessionCredentials const&)@MIRAL_1.0" 1.0.0
303+ (c++)"miral::InternalClientLauncher::InternalClientLauncher()@MIRAL_1.0" 1.0.0
304+ (c++)"miral::InternalClientLauncher::InternalClientLauncher()@MIRAL_1.0" 1.0.0
305+ (c++)"miral::InternalClientLauncher::~InternalClientLauncher()@MIRAL_1.0" 1.0.0
306+ (c++)"miral::InternalClientLauncher::~InternalClientLauncher()@MIRAL_1.0" 1.0.0
307+ (c++)"miral::InternalClientLauncher::operator()(mir::Server&)@MIRAL_1.0" 1.0.0
308+ (c++)"miral::WindowManagementPolicy::advise_end()@MIRAL_1.0" 1.0.0
309+ (c++)"miral::WindowManagementPolicy::advise_begin()@MIRAL_1.0" 1.0.0
310+ (c++)"miral::WindowManagementPolicy::advise_raise(std::vector<miral::Window, std::allocator<miral::Window> > const&)@MIRAL_1.0" 1.0.0
311+ (c++)"miral::WindowManagementPolicy::advise_resize(miral::WindowInfo const&, mir::geometry::Size const&)@MIRAL_1.0" 1.0.0
312+ (c++)"miral::WindowManagementPolicy::advise_move_to(miral::WindowInfo const&, mir::geometry::Point)@MIRAL_1.0" 1.0.0
313+ (c++)"miral::WindowManagementPolicy::advise_new_app(miral::ApplicationInfo&)@MIRAL_1.0" 1.0.0
314+ (c++)"miral::WindowManagementPolicy::advise_delete_app(miral::ApplicationInfo const&)@MIRAL_1.0" 1.0.0
315+ (c++)"miral::WindowManagementPolicy::advise_focus_lost(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
316+ (c++)"miral::WindowManagementPolicy::advise_new_window(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
317+ (c++)"miral::WindowManagementPolicy::advise_focus_gained(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
318+ (c++)"miral::WindowManagementPolicy::advise_state_change(miral::WindowInfo const&, MirSurfaceState)@MIRAL_1.0" 1.0.0
319+ (c++)"miral::WindowManagementPolicy::advise_delete_window(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
320+ (c++)"miral::equivalent_display_area(miral::Output const&, miral::Output const&)@MIRAL_1.0" 1.0.0
321+ (c++)"miral::SetWindowManagmentPolicy::SetWindowManagmentPolicy(std::function<std::unique_ptr<miral::WindowManagementPolicy, std::default_delete<miral::WindowManagementPolicy> > (miral::WindowManagerTools const&)> const&)@MIRAL_1.0" 1.0.0
322+ (c++)"miral::SetWindowManagmentPolicy::SetWindowManagmentPolicy(std::function<std::unique_ptr<miral::WindowManagementPolicy, std::default_delete<miral::WindowManagementPolicy> > (miral::WindowManagerTools const&)> const&)@MIRAL_1.0" 1.0.0
323+ (c++)"miral::SetWindowManagmentPolicy::~SetWindowManagmentPolicy()@MIRAL_1.0" 1.0.0
324+ (c++)"miral::SetWindowManagmentPolicy::~SetWindowManagmentPolicy()@MIRAL_1.0" 1.0.0
325+ (c++)"miral::apply_lifecycle_state_to(std::shared_ptr<mir::scene::Session> const&, MirLifecycleState)@MIRAL_1.0" 1.0.0
326+ (c++)"miral::CanonicalWindowManagerPolicy::place_new_surface(miral::ApplicationInfo const&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
327+ (c++)"miral::CanonicalWindowManagerPolicy::advise_focus_gained(miral::WindowInfo const&)@MIRAL_1.0" 1.0.0
328+ (c++)"miral::CanonicalWindowManagerPolicy::handle_raise_window(miral::WindowInfo&)@MIRAL_1.0" 1.0.0
329+ (c++)"miral::CanonicalWindowManagerPolicy::handle_window_ready(miral::WindowInfo&)@MIRAL_1.0" 1.0.0
330+ (c++)"miral::CanonicalWindowManagerPolicy::handle_modify_window(miral::WindowInfo&, miral::WindowSpecification const&)@MIRAL_1.0" 1.0.0
331+ (c++)"miral::CanonicalWindowManagerPolicy::confirm_inherited_move(miral::WindowInfo const&, mir::geometry::Displacement)@MIRAL_1.0" 1.0.0
332+ (c++)"miral::CanonicalWindowManagerPolicy::CanonicalWindowManagerPolicy(miral::WindowManagerTools const&)@MIRAL_1.0" 1.0.0
333+ (c++)"miral::CanonicalWindowManagerPolicy::CanonicalWindowManagerPolicy(miral::WindowManagerTools const&)@MIRAL_1.0" 1.0.0
334+ (c++)"miral::BasicSetApplicationAuthorizer::BasicSetApplicationAuthorizer(std::function<std::shared_ptr<miral::ApplicationAuthorizer> ()> const&)@MIRAL_1.0" 1.0.0
335+ (c++)"miral::BasicSetApplicationAuthorizer::BasicSetApplicationAuthorizer(std::function<std::shared_ptr<miral::ApplicationAuthorizer> ()> const&)@MIRAL_1.0" 1.0.0
336+ (c++)"miral::BasicSetApplicationAuthorizer::~BasicSetApplicationAuthorizer()@MIRAL_1.0" 1.0.0
337+ (c++)"miral::BasicSetApplicationAuthorizer::~BasicSetApplicationAuthorizer()@MIRAL_1.0" 1.0.0
338+ (c++)"miral::BasicSetApplicationAuthorizer::operator()(mir::Server&)@MIRAL_1.0" 1.0.0
339+ (c++)"miral::display_configuration_options(mir::Server&)@MIRAL_1.0" 1.0.0
340+ (c++)"miral::kill(std::shared_ptr<mir::scene::Session> const&, int)@MIRAL_1.0" 1.0.0
341+ (c++)"miral::Keymap::set_keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
342+ (c++)"miral::Keymap::Keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
343+ (c++)"miral::Keymap::Keymap(miral::Keymap const&)@MIRAL_1.0" 1.0.0
344+ (c++)"miral::Keymap::Keymap()@MIRAL_1.0" 1.0.0
345+ (c++)"miral::Keymap::Keymap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@MIRAL_1.0" 1.0.0
346+ (c++)"miral::Keymap::Keymap(miral::Keymap const&)@MIRAL_1.0" 1.0.0
347+ (c++)"miral::Keymap::Keymap()@MIRAL_1.0" 1.0.0
348+ (c++)"miral::Keymap::~Keymap()@MIRAL_1.0" 1.0.0
349+ (c++)"miral::Keymap::~Keymap()@MIRAL_1.0" 1.0.0
350+ (c++)"miral::Keymap::operator=(miral::Keymap const&)@MIRAL_1.0" 1.0.0
351+ (c++)"miral::Output::Output(mir::graphics::DisplayConfigurationOutput const&)@MIRAL_1.0" 1.0.0
352+ (c++)"miral::Output::Output(miral::Output const&)@MIRAL_1.0" 1.0.0
353+ (c++)"miral::Output::Output(mir::graphics::DisplayConfigurationOutput const&)@MIRAL_1.0" 1.0.0
354+ (c++)"miral::Output::Output(miral::Output const&)@MIRAL_1.0" 1.0.0
355+ (c++)"miral::Output::~Output()@MIRAL_1.0" 1.0.0
356+ (c++)"miral::Output::~Output()@MIRAL_1.0" 1.0.0
357+ (c++)"miral::Output::operator=(miral::Output const&)@MIRAL_1.0" 1.0.0
358+ (c++)"miral::Window::resize(mir::geometry::Size const&)@MIRAL_1.0" 1.0.0
359+ (c++)"miral::Window::move_to(mir::geometry::Point)@MIRAL_1.0" 1.0.0
360+ (c++)"miral::Window::Window(std::shared_ptr<mir::scene::Session> const&, std::shared_ptr<mir::scene::Surface> const&)@MIRAL_1.0" 1.0.0
361+ (c++)"miral::Window::Window()@MIRAL_1.0" 1.0.0
362+ (c++)"miral::Window::Window(std::shared_ptr<mir::scene::Session> const&, std::shared_ptr<mir::scene::Surface> const&)@MIRAL_1.0" 1.0.0
363+ (c++)"miral::Window::Window()@MIRAL_1.0" 1.0.0
364+ (c++)"miral::Window::~Window()@MIRAL_1.0" 1.0.0
365+ (c++)"miral::Window::~Window()@MIRAL_1.0" 1.0.0
366+ (c++)"miral::pid_of(std::shared_ptr<mir::scene::Session> const&)@MIRAL_1.0" 1.0.0
367+ (c++)"miral::name_of[abi:cxx11](std::shared_ptr<mir::scene::Session> const&)@MIRAL_1.0" 1.0.0
368+ (c++)"miral::MirRunner::add_stop_callback(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
369+ (c++)"miral::MirRunner::add_start_callback(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
370+ (c++)"miral::MirRunner::set_exception_handler(std::function<void ()> const&)@MIRAL_1.0" 1.0.0
371+ (c++)"miral::MirRunner::stop()@MIRAL_1.0" 1.0.0
372+ (c++)"miral::MirRunner::run_with(std::initializer_list<std::function<void (mir::Server&)> >)@MIRAL_1.0" 1.0.0
373+ (c++)"miral::MirRunner::MirRunner(int, char const**)@MIRAL_1.0" 1.0.0
374+ (c++)"miral::MirRunner::MirRunner(int, char const**, char const*)@MIRAL_1.0" 1.0.0
375+ (c++)"miral::MirRunner::MirRunner(int, char const**)@MIRAL_1.0" 1.0.0
376+ (c++)"miral::MirRunner::MirRunner(int, char const**, char const*)@MIRAL_1.0" 1.0.0
377+ (c++)"miral::MirRunner::~MirRunner()@MIRAL_1.0" 1.0.0
378+ (c++)"miral::MirRunner::~MirRunner()@MIRAL_1.0" 1.0.0
379+ (c++)"miral::operator==(miral::Output::PhysicalSizeMM const&, miral::Output::PhysicalSizeMM const&)@MIRAL_1.0" 1.0.0
380+ (c++)"miral::operator==(miral::Window const&, std::shared_ptr<mir::scene::Surface> const&)@MIRAL_1.0" 1.0.0
381+ (c++)"miral::operator==(miral::Window const&, miral::Window const&)@MIRAL_1.0" 1.0.0
382+ (c++)"miral::operator==(std::shared_ptr<mir::scene::Surface> const&, miral::Window const&)@MIRAL_1.0" 1.0.0
383+ (c++)"miral::WindowInfo::height_inc() const@MIRAL_1.0" 1.0.0
384+ (c++)"miral::WindowInfo::is_visible() const@MIRAL_1.0" 1.0.0
385+ (c++)"miral::WindowInfo::max_aspect() const@MIRAL_1.0" 1.0.0
386+ (c++)"miral::WindowInfo::max_height() const@MIRAL_1.0" 1.0.0
387+ (c++)"miral::WindowInfo::min_aspect() const@MIRAL_1.0" 1.0.0
388+ (c++)"miral::WindowInfo::min_height() const@MIRAL_1.0" 1.0.0
389+ (c++)"miral::WindowInfo::can_morph_to(MirSurfaceType) const@MIRAL_1.0" 1.0.0
390+ (c++)"miral::WindowInfo::restore_rect() const@MIRAL_1.0" 1.0.0
391+ (c++)"miral::WindowInfo::can_be_active() const@MIRAL_1.0" 1.0.0
392+ (c++)"miral::WindowInfo::has_output_id() const@MIRAL_1.0" 1.0.0
393+ (c++)"miral::WindowInfo::confine_pointer() const@MIRAL_1.0" 1.0.0
394+ (c++)"miral::WindowInfo::constrain_resize(mir::geometry::Point&, mir::geometry::Size&) const@MIRAL_1.0" 1.0.0
395+ (c++)"miral::WindowInfo::must_have_parent() const@MIRAL_1.0" 1.0.0
396+ (c++)"miral::WindowInfo::must_not_have_parent() const@MIRAL_1.0" 1.0.0
397+ (c++)"miral::WindowInfo::preferred_orientation() const@MIRAL_1.0" 1.0.0
398+ (c++)"miral::WindowInfo::name[abi:cxx11]() const@MIRAL_1.0" 1.0.0
399+ (c++)"miral::WindowInfo::type() const@MIRAL_1.0" 1.0.0
400+ (c++)"miral::WindowInfo::state() const@MIRAL_1.0" 1.0.0
401+ (c++)"miral::WindowInfo::parent() const@MIRAL_1.0" 1.0.0
402+ (c++)"miral::WindowInfo::window() const@MIRAL_1.0" 1.0.0
403+ (c++)"miral::WindowInfo::children() const@MIRAL_1.0" 1.0.0
404+ (c++)"miral::WindowInfo::userdata() const@MIRAL_1.0" 1.0.0
405+ (c++)"miral::WindowInfo::max_width() const@MIRAL_1.0" 1.0.0
406+ (c++)"miral::WindowInfo::min_width() const@MIRAL_1.0" 1.0.0
407+ (c++)"miral::WindowInfo::output_id() const@MIRAL_1.0" 1.0.0
408+ (c++)"miral::WindowInfo::width_inc() const@MIRAL_1.0" 1.0.0
409+ (c++)"miral::CursorTheme::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
410+ (c++)"miral::SetTerminator::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
411+ (c++)"miral::DebugExtension::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
412+ (c++)"miral::AddInitCallback::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
413+ (c++)"miral::ApplicationInfo::application() const@MIRAL_1.0" 1.0.0
414+ (c++)"miral::ApplicationInfo::name[abi:cxx11]() const@MIRAL_1.0" 1.0.0
415+ (c++)"miral::ApplicationInfo::windows() const@MIRAL_1.0" 1.0.0
416+ (c++)"miral::ApplicationInfo::userdata() const@MIRAL_1.0" 1.0.0
417+ (c++)"miral::CommandLineOption::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
418+ (c++)"miral::WindowManagerTools::active_window() const@MIRAL_1.0" 1.0.0
419+ (c++)"miral::WindowManagerTools::id_for_window[abi:cxx11](miral::Window const&) const@MIRAL_1.0" 1.0.0
420+ (c++)"miral::WindowManagerTools::count_applications() const@MIRAL_1.0" 1.0.0
421+ (c++)"miral::WindowManagerTools::info_for_window_id(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@MIRAL_1.0" 1.0.0
422+ (c++)"miral::WindowManagerTools::place_and_size_for_state(miral::WindowSpecification&, miral::WindowInfo const&) const@MIRAL_1.0" 1.0.0
423+ (c++)"miral::WindowManagerTools::info_for(miral::Window const&) const@MIRAL_1.0" 1.0.0
424+ (c++)"miral::WindowManagerTools::info_for(std::weak_ptr<mir::scene::Session> const&) const@MIRAL_1.0" 1.0.0
425+ (c++)"miral::WindowManagerTools::info_for(std::weak_ptr<mir::scene::Surface> const&) const@MIRAL_1.0" 1.0.0
426+ (c++)"miral::WindowManagerTools::window_at(mir::geometry::Point) const@MIRAL_1.0" 1.0.0
427+ (c++)"miral::WindowSpecification::height_inc() const@MIRAL_1.0" 1.0.0
428+ (c++)"miral::WindowSpecification::input_mode() const@MIRAL_1.0" 1.0.0
429+ (c++)"miral::WindowSpecification::max_aspect() const@MIRAL_1.0" 1.0.0
430+ (c++)"miral::WindowSpecification::max_height() const@MIRAL_1.0" 1.0.0
431+ (c++)"miral::WindowSpecification::min_aspect() const@MIRAL_1.0" 1.0.0
432+ (c++)"miral::WindowSpecification::min_height() const@MIRAL_1.0" 1.0.0
433+ (c++)"miral::WindowSpecification::input_shape() const@MIRAL_1.0" 1.0.0
434+ (c++)"miral::WindowSpecification::shell_chrome() const@MIRAL_1.0" 1.0.0
435+ (c++)"miral::WindowSpecification::confine_pointer() const@MIRAL_1.0" 1.0.0
436+ (c++)"miral::WindowSpecification::placement_hints() const@MIRAL_1.0" 1.0.0
437+ (c++)"miral::WindowSpecification::preferred_orientation() const@MIRAL_1.0" 1.0.0
438+ (c++)"miral::WindowSpecification::window_placement_gravity() const@MIRAL_1.0" 1.0.0
439+ (c++)"miral::WindowSpecification::aux_rect_placement_offset() const@MIRAL_1.0" 1.0.0
440+ (c++)"miral::WindowSpecification::aux_rect_placement_gravity() const@MIRAL_1.0" 1.0.0
441+ (c++)"miral::WindowSpecification::name[abi:cxx11]() const@MIRAL_1.0" 1.0.0
442+ (c++)"miral::WindowSpecification::size() const@MIRAL_1.0" 1.0.0
443+ (c++)"miral::WindowSpecification::type() const@MIRAL_1.0" 1.0.0
444+ (c++)"miral::WindowSpecification::state() const@MIRAL_1.0" 1.0.0
445+ (c++)"miral::WindowSpecification::parent() const@MIRAL_1.0" 1.0.0
446+ (c++)"miral::WindowSpecification::update(mir::scene::SurfaceCreationParameters&) const@MIRAL_1.0" 1.0.0
447+ (c++)"miral::WindowSpecification::aux_rect() const@MIRAL_1.0" 1.0.0
448+ (c++)"miral::WindowSpecification::top_left() const@MIRAL_1.0" 1.0.0
449+ (c++)"miral::WindowSpecification::userdata() const@MIRAL_1.0" 1.0.0
450+ (c++)"miral::WindowSpecification::max_width() const@MIRAL_1.0" 1.0.0
451+ (c++)"miral::WindowSpecification::min_width() const@MIRAL_1.0" 1.0.0
452+ (c++)"miral::WindowSpecification::output_id() const@MIRAL_1.0" 1.0.0
453+ (c++)"miral::WindowSpecification::width_inc() const@MIRAL_1.0" 1.0.0
454+ (c++)"miral::ActiveOutputsMonitor::process_outputs(std::function<void (std::vector<miral::Output, std::allocator<miral::Output> > const&)> const&) const@MIRAL_1.0" 1.0.0
455+ (c++)"miral::WindowManagerOptions::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
456+ (c++)"miral::SetCommandLineHandler::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
457+ (c++)"miral::ApplicationCredentials::gid() const@MIRAL_1.0" 1.0.0
458+ (c++)"miral::ApplicationCredentials::pid() const@MIRAL_1.0" 1.0.0
459+ (c++)"miral::ApplicationCredentials::uid() const@MIRAL_1.0" 1.0.0
460+ (c++)"miral::InternalClientLauncher::launch(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (miral::toolkit::Connection)> const&, std::function<void (std::weak_ptr<mir::scene::Session>)> const&) const@MIRAL_1.0" 1.0.0
461+ (c++)"miral::SetWindowManagmentPolicy::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
462+ (c++)"miral::BasicSetApplicationAuthorizer::the_application_authorizer() const@MIRAL_1.0" 1.0.0
463+ (c++)"miral::Keymap::operator()(mir::Server&) const@MIRAL_1.0" 1.0.0
464+ (c++)"miral::Output::power_mode() const@MIRAL_1.0" 1.0.0
465+ (c++)"miral::Output::form_factor() const@MIRAL_1.0" 1.0.0
466+ (c++)"miral::Output::orientation() const@MIRAL_1.0" 1.0.0
467+ (c++)"miral::Output::pixel_format() const@MIRAL_1.0" 1.0.0
468+ (c++)"miral::Output::refresh_rate() const@MIRAL_1.0" 1.0.0
469+ (c++)"miral::Output::is_same_output(miral::Output const&) const@MIRAL_1.0" 1.0.0
470+ (c++)"miral::Output::physical_size_mm() const@MIRAL_1.0" 1.0.0
471+ (c++)"miral::Output::type() const@MIRAL_1.0" 1.0.0
472+ (c++)"miral::Output::used() const@MIRAL_1.0" 1.0.0
473+ (c++)"miral::Output::scale() const@MIRAL_1.0" 1.0.0
474+ (c++)"miral::Output::valid() const@MIRAL_1.0" 1.0.0
475+ (c++)"miral::Output::extents() const@MIRAL_1.0" 1.0.0
476+ (c++)"miral::Output::connected() const@MIRAL_1.0" 1.0.0
477+ (c++)"miral::Window::application() const@MIRAL_1.0" 1.0.0
478+ (c++)"miral::Window::size() const@MIRAL_1.0" 1.0.0
479+ (c++)"miral::Window::top_left() const@MIRAL_1.0" 1.0.0
480+ (c++)"miral::Window::operator std::shared_ptr<mir::scene::Surface>() const@MIRAL_1.0" 1.0.0
481+ (c++)"miral::Window::operator std::weak_ptr<mir::scene::Surface>() const@MIRAL_1.0" 1.0.0
482+ (c++)"miral::Window::operator bool() const@MIRAL_1.0" 1.0.0
483+ (c++)"typeinfo for miral::ActiveOutputsListener@MIRAL_1.0" 1.0.0
484+ (c++)"typeinfo for miral::WindowManagementPolicy@MIRAL_1.0" 1.0.0
485+ (c++)"typeinfo for miral::CanonicalWindowManagerPolicy@MIRAL_1.0" 1.0.0
486+ (c++)"vtable for miral::ActiveOutputsListener@MIRAL_1.0" 1.0.0
487+ (c++)"vtable for miral::WindowManagementPolicy@MIRAL_1.0" 1.0.0
488+ (c++)"vtable for miral::CanonicalWindowManagerPolicy@MIRAL_1.0" 1.0.0
489+ MIRAL_1.1@MIRAL_1.1 1.0.0
490+ (c++)"miral::WindowInfo::needs_titlebar(MirWindowType)@MIRAL_1.1" 1.0.0
491+ (c++)"miral::WindowInfo::type(MirWindowType)@MIRAL_1.1" 1.0.0
492+ (c++)"miral::WindowInfo::state(MirWindowState)@MIRAL_1.1" 1.0.0
493+ (c++)"miral::WindowManagementPolicy::advise_state_change(miral::WindowInfo const&, MirWindowState)@MIRAL_1.1" 1.0.0
494+ (c++)"miral::WindowInfo::can_morph_to(MirWindowType) const@MIRAL_1.1" 1.0.0
495+ (c++)"miral::CanonicalWindowManagerPolicy::place_new_window(miral::ApplicationInfo const&, miral::WindowSpecification const&)@MIRAL_1.1" 1.0.0
496+ MIRAL_1.2@MIRAL_1.2 1.0.0
497+ (c++)"miral::StartupInternalClient::StartupInternalClient(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void (mir::client::Connection)>, std::function<void (std::weak_ptr<mir::scene::Session>)>)@MIRAL_1.2" 1.0.0
498+ (c++)"miral::InternalClientLauncher::launch(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (mir::client::Connection)> const&, std::function<void (std::weak_ptr<mir::scene::Session>)> const&) const@MIRAL_1.2" 1.0.0
499+ (c++)"miral::WindowInfo::shell_chrome(MirShellChrome)@MIRAL_1.2" 1.0.0
500+ (c++)"miral::WindowInfo::shell_chrome() const@MIRAL_1.2" 1.0.0
501+ (c++)"miral::WindowManagerTools::drag_window(miral::Window const&, mir::geometry::Displacement)@MIRAL_1.2" 1.0.0
502+ (c++)"typeinfo for miral::ApplicationAuthorizer@MIRAL_1.0" 1.0.0
503+ (c++)"typeinfo for miral::ApplicationAuthorizer1@MIRAL_1.2" 1.0.0
504+ MIRAL_1.3@MIRAL_1.3 1.0.0
505+ (c++)"miral::operator<(miral::Window const&, miral::Window const&)@MIRAL_1.0" 1.0.0
506+ (c++)"miral::WindowManagerTools::create_workspace()@MIRAL_1.3" 1.0.0
507+ (c++)"miral::WindowManagerTools::add_tree_to_workspace(miral::Window const&, std::shared_ptr<miral::Workspace> const&)@MIRAL_1.3" 1.0.0
508+ (c++)"miral::WindowManagerTools::focus_prev_within_application()@MIRAL_1.3" 1.0.0
509+ (c++)"miral::WindowManagerTools::remove_tree_from_workspace(miral::Window const&, std::shared_ptr<miral::Workspace> const&)@MIRAL_1.3" 1.0.0
510+ (c++)"miral::WindowManagerTools::move_workspace_content_to_workspace(std::shared_ptr<miral::Workspace> const&, std::shared_ptr<miral::Workspace> const&)@MIRAL_1.3" 1.0.0
511+ (c++)"miral::WorkspacePolicy::advise_adding_to_workspace(std::shared_ptr<miral::Workspace> const&, std::vector<miral::Window, std::allocator<miral::Window> > const&)@MIRAL_1.3" 1.0.0
512+ (c++)"miral::WorkspacePolicy::advise_removing_from_workspace(std::shared_ptr<miral::Workspace> const&, std::vector<miral::Window, std::allocator<miral::Window> > const&)@MIRAL_1.3" 1.0.0
513+ (c++)"miral::WindowManagerTools::for_each_window_in_workspace(std::shared_ptr<miral::Workspace> const&, std::function<void (miral::Window const&)> const&)@MIRAL_1.3" 1.0.0
514+ (c++)"miral::WindowManagerTools::for_each_workspace_containing(miral::Window const&, std::function<void (std::shared_ptr<miral::Workspace> const&)> const&)@MIRAL_1.3" 1.0.0
515+ (c++)"typeinfo for miral::WorkspacePolicy@MIRAL_1.3" 1.0.0
516+ (c++)"vtable for miral::WorkspacePolicy@MIRAL_1.3" 1.0.0
517+ MIRAL_1.3.1@MIRAL_1.3.1 1.0.0
518+ (c++)"miral::SetWindowManagementPolicy::SetWindowManagementPolicy(std::function<std::unique_ptr<miral::WindowManagementPolicy, std::default_delete<miral::WindowManagementPolicy> > (miral::WindowManagerTools const&)> const&)@MIRAL_1.3.1" 1.0.0
519+ (c++)"miral::SetWindowManagementPolicy::SetWindowManagementPolicy(std::function<std::unique_ptr<miral::WindowManagementPolicy, std::default_delete<miral::WindowManagementPolicy> > (miral::WindowManagerTools const&)> const&)@MIRAL_1.3.1" 1.0.0
520+ (c++)"miral::SetWindowManagementPolicy::~SetWindowManagementPolicy()@MIRAL_1.3.1" 1.0.0
521+ (c++)"miral::SetWindowManagementPolicy::~SetWindowManagementPolicy()@MIRAL_1.3.1" 1.0.0
522+ (c++)"miral::SetWindowManagementPolicy::operator()(mir::Server&) const@MIRAL_1.3.1" 1.0.0
523+ MIRAL_1.4.0@MIRAL_1.4.0 1.0.0
524+ (c++)"miral::WindowManagerTools::end_drag_and_drop()@MIRAL_1.4.0" 1.0.0
525+ (c++)"miral::WindowManagerTools::start_drag_and_drop(miral::WindowInfo&, std::vector<unsigned char, std::allocator<unsigned char> > const&)@MIRAL_1.4.0" 1.0.0
526+ (c++)"typeinfo for miral::WindowManagementPolicyAddendum2@MIRAL_1.4.0" 1.0.0
527+ MIRAL_1.5.0@MIRAL_1.5.0 1.0.0
528+ (c++)"miral::pre_init(miral::CommandLineOption const&)@MIRAL_1.5.0" 1.0.0
529+ (c++)"typeinfo for miral::WindowManagementPolicyAddendum3@MIRAL_1.5.0" 1.0.0
530+ (c++)"miral::WindowManagerTools::active_output()@MIRAL_1.5.0" 1.0.0
531\ No newline at end of file
532
533=== added file 'debian/libmirclientcpp-dev.install'
534--- debian/libmirclientcpp-dev.install 1970-01-01 00:00:00 +0000
535+++ debian/libmirclientcpp-dev.install 2017-08-23 11:59:25 +0000
536@@ -0,0 +1,2 @@
537+usr/include/miral/mir/*/*
538+usr/lib/*/pkgconfig/mirclientcpp.pc
539
540=== added file 'debian/miral-examples.install'
541--- debian/miral-examples.install 1970-01-01 00:00:00 +0000
542+++ debian/miral-examples.install 2017-08-23 11:59:25 +0000
543@@ -0,0 +1,9 @@
544+usr/bin/miral-shell
545+usr/bin/miral-run
546+usr/bin/miral-kiosk
547+usr/bin/miral-xrun
548+usr/bin/miral-screencast
549+usr/bin/miral-desktop
550+usr/bin/miral-app
551+usr/share/applications/miral-shell.desktop
552+usr/share/icons/hicolor/scalable/apps/ubuntu-logo.svg
553
554=== modified file 'examples/CMakeLists.txt'
555--- examples/CMakeLists.txt 2017-07-14 11:29:56 +0000
556+++ examples/CMakeLists.txt 2017-08-23 11:59:25 +0000
557@@ -1,3 +1,6 @@
558+add_subdirectory(miral-kiosk)
559+add_subdirectory(miral-shell)
560+
561 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -fno-strict-aliasing -Wextra")
562
563 add_library(eglapp STATIC
564
565=== added directory 'examples/miral-kiosk'
566=== added file 'examples/miral-kiosk/CMakeLists.txt'
567--- examples/miral-kiosk/CMakeLists.txt 1970-01-01 00:00:00 +0000
568+++ examples/miral-kiosk/CMakeLists.txt 2017-08-23 11:59:25 +0000
569@@ -0,0 +1,12 @@
570+include_directories(
571+ ${PROJECT_SOURCE_DIR}/include/miral
572+ ${PROJECT_SOURCE_DIR}/include/client
573+)
574+
575+mir_add_wrapped_executable(miral-kiosk
576+ kiosk_main.cpp
577+ kiosk_window_manager.cpp kiosk_window_manager.h
578+ sw_splash.cpp sw_splash.h
579+)
580+
581+target_link_libraries(miral-kiosk miral)
582
583=== added file 'examples/miral-kiosk/kiosk_main.cpp'
584--- examples/miral-kiosk/kiosk_main.cpp 1970-01-01 00:00:00 +0000
585+++ examples/miral-kiosk/kiosk_main.cpp 2017-08-23 11:59:25 +0000
586@@ -0,0 +1,94 @@
587+/*
588+ * Copyright © 2016 Canonical Ltd.
589+ *
590+ * This program is free software: you can redistribute it and/or modify
591+ * under the terms of the GNU General Public License version 2 or 3 as as
592+ * published by the Free Software Foundation.
593+ *
594+ * This program is distributed in the hope that it will be useful,
595+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
596+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
597+ * GNU General Public License for more details.
598+ *
599+ * You should have received a copy of the GNU General Public License
600+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
601+ *
602+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
603+ */
604+
605+#include "kiosk_window_manager.h"
606+
607+#include <miral/runner.h>
608+#include <miral/application_authorizer.h>
609+#include <miral/command_line_option.h>
610+#include <miral/keymap.h>
611+#include <miral/set_window_management_policy.h>
612+#include <miral/internal_client.h>
613+
614+#include <unistd.h>
615+#include <atomic>
616+
617+namespace
618+{
619+struct KioskAuthorizer : miral::ApplicationAuthorizer
620+{
621+ KioskAuthorizer(SwSplash const& splash) : splash{splash}{}
622+
623+ virtual bool connection_is_allowed(miral::ApplicationCredentials const& creds) override
624+ {
625+ // Allow internal applications and (optionally) only ones that start "immediately"
626+ // (For the sake of an example "immediately" means while the spash is running)
627+ return getpid() == creds.pid() || !startup_only || splash.session().lock();
628+ }
629+
630+ virtual bool configure_display_is_allowed(miral::ApplicationCredentials const& /*creds*/) override
631+ {
632+ return false;
633+ }
634+
635+ virtual bool set_base_display_configuration_is_allowed(miral::ApplicationCredentials const& /*creds*/) override
636+ {
637+ return false;
638+ }
639+
640+ virtual bool screencast_is_allowed(miral::ApplicationCredentials const& /*creds*/) override
641+ {
642+ return true;
643+ }
644+
645+ virtual bool prompt_session_is_allowed(miral::ApplicationCredentials const& /*creds*/) override
646+ {
647+ return false;
648+ }
649+
650+ static std::atomic<bool> startup_only;
651+
652+ SwSplash splash;
653+};
654+
655+std::atomic<bool> KioskAuthorizer::startup_only{false};
656+}
657+
658+int main(int argc, char const* argv[])
659+{
660+ using namespace miral;
661+
662+ SwSplash splash;
663+
664+ CommandLineOption startup_only{
665+ [&](bool startup_only) {KioskAuthorizer::startup_only = startup_only; },
666+ "kiosk-startup-apps-only",
667+ "Only allow applications to connect during startup",
668+ KioskAuthorizer::startup_only};
669+
670+ return MirRunner{argc, argv}.run_with(
671+ {
672+ CommandLineOption{[&](std::string const& ) { },
673+ "desktop_file_hint", "Ignored for Unity8 compatability", "miral-shell.desktop"},
674+ set_window_management_policy<KioskWindowManagerPolicy>(splash),
675+ SetApplicationAuthorizer<KioskAuthorizer>{splash},
676+ Keymap{},
677+ startup_only,
678+ StartupInternalClient{"Intro", splash}
679+ });
680+}
681
682=== added file 'examples/miral-kiosk/kiosk_window_manager.cpp'
683--- examples/miral-kiosk/kiosk_window_manager.cpp 1970-01-01 00:00:00 +0000
684+++ examples/miral-kiosk/kiosk_window_manager.cpp 2017-08-23 11:59:25 +0000
685@@ -0,0 +1,148 @@
686+/*
687+ * Copyright © 2016 Canonical Ltd.
688+ *
689+ * This program is free software: you can redistribute it and/or modify it
690+ * under the terms of the GNU General Public License version 2 or 3 as
691+ * published by the Free Software Foundation.
692+ *
693+ * This program is distributed in the hope that it will be useful,
694+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
695+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
696+ * GNU General Public License for more details.
697+ *
698+ * You should have received a copy of the GNU General Public License
699+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
700+ *
701+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
702+ */
703+
704+#include "kiosk_window_manager.h"
705+
706+#include <miral/application_info.h>
707+#include <miral/window_info.h>
708+#include <miral/window_manager_tools.h>
709+
710+#include <linux/input.h>
711+
712+namespace ms = mir::scene;
713+using namespace miral;
714+
715+KioskWindowManagerPolicy::KioskWindowManagerPolicy(WindowManagerTools const& tools, SwSplash const& splash) :
716+ CanonicalWindowManagerPolicy{tools},
717+ splash{splash}
718+{
719+}
720+
721+bool KioskWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event)
722+{
723+ auto const action = mir_keyboard_event_action(event);
724+ auto const scan_code = mir_keyboard_event_scan_code(event);
725+ auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
726+
727+ if (action == mir_keyboard_action_down &&
728+ modifiers == mir_input_event_modifier_alt &&
729+ scan_code == KEY_TAB)
730+ {
731+ tools.focus_next_application();
732+
733+ return true;
734+ }
735+ else if (action == mir_keyboard_action_down &&
736+ modifiers == mir_input_event_modifier_alt &&
737+ scan_code == KEY_GRAVE)
738+ {
739+ tools.focus_next_within_application();
740+
741+ return true;
742+ }
743+ else if (action == mir_keyboard_action_down &&
744+ modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_shift) &&
745+ scan_code == KEY_GRAVE)
746+ {
747+ tools.focus_prev_within_application();
748+
749+ return true;
750+ }
751+ else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
752+ {
753+ switch (modifiers & modifier_mask)
754+ {
755+ case mir_input_event_modifier_alt:
756+ tools.ask_client_to_close(tools.active_window());;
757+ return true;
758+
759+ default:
760+ break;
761+ }
762+ }
763+
764+ return false;
765+}
766+
767+bool KioskWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event)
768+{
769+ auto const count = mir_touch_event_point_count(event);
770+
771+ long total_x = 0;
772+ long total_y = 0;
773+
774+ for (auto i = 0U; i != count; ++i)
775+ {
776+ total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x);
777+ total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y);
778+ }
779+
780+ Point const cursor{total_x/count, total_y/count};
781+
782+ tools.select_active_window(tools.window_at(cursor));
783+
784+ return false;
785+}
786+
787+bool KioskWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event)
788+{
789+ auto const action = mir_pointer_event_action(event);
790+
791+ Point const cursor{
792+ mir_pointer_event_axis_value(event, mir_pointer_axis_x),
793+ mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
794+
795+ if (action == mir_pointer_action_button_down)
796+ {
797+ tools.select_active_window(tools.window_at(cursor));
798+ }
799+
800+ return false;
801+}
802+
803+void KioskWindowManagerPolicy::advise_focus_gained(WindowInfo const& info)
804+{
805+ CanonicalWindowManagerPolicy::advise_focus_gained(info);
806+
807+ if (auto session = splash.session().lock())
808+ {
809+ auto const& app_info = tools.info_for(session);
810+
811+ for (auto const& s : app_info.windows())
812+ tools.raise_tree(s);
813+ }
814+}
815+
816+void KioskWindowManagerPolicy::advise_new_window(WindowInfo const& window_info)
817+{
818+ // We do this here, not in place_new_window() so that clients get a resize event.
819+ // This shouldn't be necessary, but works better with the gtk-mir backend.
820+ if (window_info.type() == mir_window_type_normal &&
821+ !window_info.parent() &&
822+ window_info.state() == mir_window_state_restored)
823+ {
824+ WindowSpecification specification;
825+
826+ specification.state() = mir_window_state_maximized;
827+
828+ tools.place_and_size_for_state(specification, window_info);
829+ tools.modify_window(window_info.window(), specification);
830+ }
831+
832+ CanonicalWindowManagerPolicy::advise_new_window(window_info);
833+}
834
835=== added file 'examples/miral-kiosk/kiosk_window_manager.h'
836--- examples/miral-kiosk/kiosk_window_manager.h 1970-01-01 00:00:00 +0000
837+++ examples/miral-kiosk/kiosk_window_manager.h 2017-08-23 11:59:25 +0000
838@@ -0,0 +1,52 @@
839+/*
840+ * Copyright © 2016 Canonical Ltd.
841+ *
842+ * This program is free software: you can redistribute it and/or modify it
843+ * under the terms of the GNU General Public License version 2 or 3 as
844+ * published by the Free Software Foundation.
845+ *
846+ * This program is distributed in the hope that it will be useful,
847+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
848+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
849+ * GNU General Public License for more details.
850+ *
851+ * You should have received a copy of the GNU General Public License
852+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
853+ *
854+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
855+ */
856+
857+#ifndef MIRAL_KIOSK_WINDOW_MANAGER_H
858+#define MIRAL_KIOSK_WINDOW_MANAGER_H
859+
860+#include "sw_splash.h"
861+
862+#include <miral/canonical_window_manager.h>
863+
864+using namespace mir::geometry;
865+
866+class KioskWindowManagerPolicy : public miral::CanonicalWindowManagerPolicy
867+{
868+public:
869+ KioskWindowManagerPolicy(miral::WindowManagerTools const& tools, SwSplash const&);
870+
871+ void advise_focus_gained(miral::WindowInfo const& info) override;
872+
873+ virtual void advise_new_window(miral::WindowInfo const& window_info) override;
874+
875+ bool handle_keyboard_event(MirKeyboardEvent const* event) override;
876+ bool handle_touch_event(MirTouchEvent const* event) override;
877+ bool handle_pointer_event(MirPointerEvent const* event) override;
878+
879+private:
880+ static const int modifier_mask =
881+ mir_input_event_modifier_alt |
882+ mir_input_event_modifier_shift |
883+ mir_input_event_modifier_sym |
884+ mir_input_event_modifier_ctrl |
885+ mir_input_event_modifier_meta;
886+
887+ SwSplash const splash;
888+};
889+
890+#endif /* MIRAL_KIOSK_WINDOW_MANAGER_H */
891
892=== added file 'examples/miral-kiosk/sw_splash.cpp'
893--- examples/miral-kiosk/sw_splash.cpp 1970-01-01 00:00:00 +0000
894+++ examples/miral-kiosk/sw_splash.cpp 2017-08-23 11:59:25 +0000
895@@ -0,0 +1,173 @@
896+/*
897+ * Copyright © 2016 Canonical Ltd.
898+ *
899+ * This program is free software: you can redistribute it and/or modify it
900+ * under the terms of the GNU General Public License version 2 or 3 as
901+ * published by the Free Software Foundation.
902+ *
903+ * This program is distributed in the hope that it will be useful,
904+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
905+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
906+ * GNU General Public License for more details.
907+ *
908+ * You should have received a copy of the GNU General Public License
909+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
910+ *
911+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
912+ */
913+
914+#include "sw_splash.h"
915+
916+#include <mir/client/display_config.h>
917+#include <mir/client/surface.h>
918+#include <mir/client/window.h>
919+#include <mir/client/window_spec.h>
920+
921+#include <mir_toolkit/mir_buffer_stream.h>
922+
923+#include <chrono>
924+#include <cstring>
925+#include <thread>
926+#include <mutex>
927+
928+namespace
929+{
930+MirPixelFormat find_8888_format(MirConnection* connection)
931+{
932+ unsigned int const num_formats = 32;
933+ MirPixelFormat pixel_formats[num_formats];
934+ unsigned int valid_formats;
935+ mir_connection_get_available_surface_formats(connection, pixel_formats, num_formats, &valid_formats);
936+
937+ for (unsigned int i = 0; i < num_formats; ++i)
938+ {
939+ MirPixelFormat cur_pf = pixel_formats[i];
940+ if (cur_pf == mir_pixel_format_abgr_8888 ||
941+ cur_pf == mir_pixel_format_argb_8888)
942+ {
943+ return cur_pf;
944+ }
945+ }
946+
947+ for (unsigned int i = 0; i < num_formats; ++i)
948+ {
949+ MirPixelFormat cur_pf = pixel_formats[i];
950+ if (cur_pf == mir_pixel_format_xbgr_8888 ||
951+ cur_pf == mir_pixel_format_xrgb_8888)
952+ {
953+ return cur_pf;
954+ }
955+ }
956+
957+ return *pixel_formats;
958+}
959+
960+auto create_window(MirConnection* connection, mir::client::Surface const& surface) -> mir::client::Window
961+{
962+ int id = 0;
963+ int width = 0;
964+ int height = 0;
965+
966+ mir::client::DisplayConfig{connection}.for_each_output([&](MirOutput const* output)
967+ {
968+ if (mir_output_get_connection_state(output) == mir_output_connection_state_connected &&
969+ mir_output_is_enabled(output))
970+ {
971+ id = mir_output_get_id(output);
972+
973+ MirOutputMode const* mode = mir_output_get_current_mode(output);
974+ width = mir_output_mode_get_width(mode);
975+ height = mir_output_mode_get_height(mode);
976+ }
977+ });
978+
979+ return mir::client::WindowSpec::for_normal_window(connection, width, height)
980+ .set_name("splash")
981+ .set_fullscreen_on_output(id)
982+ .add_surface(surface, width, height, 0, 0)
983+ .create_window();
984+}
985+
986+void render_pattern(MirGraphicsRegion *region, uint8_t pattern[])
987+{
988+ char *row = region->vaddr;
989+
990+ for (int j = 0; j < region->height; j++)
991+ {
992+ uint32_t *pixel = (uint32_t*)row;
993+
994+ for (int i = 0; i < region->width; i++)
995+ memcpy(pixel+i, pattern, sizeof pixel[i]);
996+
997+ row += region->stride;
998+ }
999+}
1000+}
1001+
1002+struct SwSplash::Self
1003+{
1004+ std::mutex mutex;
1005+ std::weak_ptr<mir::scene::Session> session;
1006+};
1007+
1008+SwSplash::SwSplash() : self{std::make_shared<Self>()} {}
1009+
1010+SwSplash::~SwSplash() = default;
1011+
1012+void SwSplash::operator()(std::weak_ptr<mir::scene::Session> const& session)
1013+{
1014+ std::lock_guard<decltype(self->mutex)> lock{self->mutex};
1015+ self->session = session;
1016+}
1017+
1018+auto SwSplash::session() const -> std::weak_ptr<mir::scene::Session>
1019+{
1020+ std::lock_guard<decltype(self->mutex)> lock{self->mutex};
1021+ return self->session;
1022+}
1023+
1024+void SwSplash::operator()(MirConnection* connection)
1025+{
1026+ MirPixelFormat pixel_format = find_8888_format(connection);
1027+
1028+ uint8_t pattern[4] = { 0x14, 0x48, 0xDD, 0xFF };
1029+
1030+ switch(pixel_format)
1031+ {
1032+ case mir_pixel_format_abgr_8888:
1033+ case mir_pixel_format_xbgr_8888:
1034+ std::swap(pattern[2],pattern[0]);
1035+ break;
1036+
1037+ case mir_pixel_format_argb_8888:
1038+ case mir_pixel_format_xrgb_8888:
1039+ break;
1040+
1041+ default:
1042+ return;
1043+ };
1044+
1045+
1046+ mir::client::Surface surface{mir_connection_create_render_surface_sync(connection, 42, 42)};
1047+ MirBufferStream* buffer_stream = mir_render_surface_get_buffer_stream(surface, 42, 42, pixel_format);
1048+
1049+ auto const window = create_window(connection, surface);
1050+
1051+ MirGraphicsRegion graphics_region;
1052+
1053+ auto const time_limit = std::chrono::steady_clock::now() + std::chrono::seconds(2);
1054+
1055+ do
1056+ {
1057+ mir_buffer_stream_get_graphics_region(buffer_stream, &graphics_region);
1058+
1059+ render_pattern(&graphics_region, pattern);
1060+ mir_buffer_stream_swap_buffers_sync(buffer_stream);
1061+
1062+ for (auto& x : pattern)
1063+ x = 3*x/4;
1064+
1065+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
1066+ }
1067+ while (std::chrono::steady_clock::now() < time_limit);
1068+}
1069
1070=== added file 'examples/miral-kiosk/sw_splash.h'
1071--- examples/miral-kiosk/sw_splash.h 1970-01-01 00:00:00 +0000
1072+++ examples/miral-kiosk/sw_splash.h 2017-08-23 11:59:25 +0000
1073@@ -0,0 +1,44 @@
1074+/*
1075+ * Copyright © 2016 Canonical Ltd.
1076+ *
1077+ * This program is free software: you can redistribute it and/or modify it
1078+ * under the terms of the GNU General Public License version 2 or 3 as
1079+ * published by the Free Software Foundation.
1080+ *
1081+ * This program is distributed in the hope that it will be useful,
1082+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1083+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1084+ * GNU General Public License for more details.
1085+ *
1086+ * You should have received a copy of the GNU General Public License
1087+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1088+ *
1089+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
1090+ */
1091+
1092+#ifndef MIRAL_SHELL_SW_SPLASH_H
1093+#define MIRAL_SHELL_SW_SPLASH_H
1094+
1095+#include <mir_toolkit/client_types.h>
1096+
1097+#include <memory>
1098+
1099+namespace mir { class Server; namespace scene { class Session; }}
1100+
1101+// A very simple s/w rendered splash animation
1102+class SwSplash
1103+{
1104+public:
1105+ SwSplash();
1106+ ~SwSplash();
1107+
1108+ void operator()(MirConnection* connection);
1109+ void operator()(std::weak_ptr<mir::scene::Session> const& session);
1110+ auto session() const -> std::weak_ptr<mir::scene::Session>;
1111+
1112+private:
1113+ struct Self;
1114+ std::shared_ptr<Self> const self;
1115+};
1116+
1117+#endif //MIRAL_SHELL_SW_SPLASH_H
1118
1119=== added directory 'examples/miral-shell'
1120=== added file 'examples/miral-shell/CMakeLists.txt'
1121--- examples/miral-shell/CMakeLists.txt 1970-01-01 00:00:00 +0000
1122+++ examples/miral-shell/CMakeLists.txt 2017-08-23 11:59:25 +0000
1123@@ -0,0 +1,65 @@
1124+include_directories(
1125+ ${PROJECT_SOURCE_DIR}/include/miral
1126+ ${PROJECT_SOURCE_DIR}/include/client
1127+)
1128+
1129+add_subdirectory(spinner)
1130+add_subdirectory(desktop)
1131+
1132+add_custom_target(miral-run ALL
1133+ cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-run.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-run
1134+)
1135+
1136+install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-run
1137+ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
1138+)
1139+
1140+add_custom_target(miral-xrun ALL
1141+ cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-xrun.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-xrun
1142+)
1143+
1144+install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-xrun
1145+ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
1146+)
1147+
1148+add_custom_target(miral-screencast ALL
1149+ cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-screencast.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-screencast
1150+)
1151+
1152+install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-screencast
1153+ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
1154+)
1155+
1156+add_custom_target(miral-desktop ALL
1157+ cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-desktop.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-desktop
1158+)
1159+
1160+install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-desktop
1161+ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
1162+)
1163+
1164+add_custom_target(miral-app ALL
1165+ cp ${CMAKE_CURRENT_SOURCE_DIR}/miral-app.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-app
1166+)
1167+
1168+install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/miral-app
1169+ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
1170+)
1171+
1172+mir_add_wrapped_executable(miral-shell
1173+ shell_main.cpp
1174+ tiling_window_manager.cpp tiling_window_manager.h
1175+ floating_window_manager.cpp floating_window_manager.h
1176+ decoration_provider.cpp decoration_provider.h
1177+ titlebar_config.cpp titlebar_config.h
1178+)
1179+
1180+pkg_check_modules(FREETYPE freetype2 REQUIRED)
1181+target_include_directories(miral-shell PRIVATE ${FREETYPE_INCLUDE_DIRS})
1182+target_compile_definitions(miral-shell PRIVATE -DTYPO_SUPPORTS_FREETYPE)
1183+target_link_libraries(miral-shell
1184+ miral-spinner
1185+ miral
1186+ ${FREETYPE_LIBRARIES}
1187+)
1188+
1189
1190=== added file 'examples/miral-shell/decoration_provider.cpp'
1191--- examples/miral-shell/decoration_provider.cpp 1970-01-01 00:00:00 +0000
1192+++ examples/miral-shell/decoration_provider.cpp 2017-08-23 11:59:25 +0000
1193@@ -0,0 +1,666 @@
1194+/*
1195+ * Copyright © 2016-2017 Canonical Ltd.
1196+ *
1197+ * This program is free software: you can redistribute it and/or modify it
1198+ * under the terms of the GNU General Public License version 2 or 3 as
1199+ * published by the Free Software Foundation.
1200+ *
1201+ * This program is distributed in the hope that it will be useful,
1202+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1203+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1204+ * GNU General Public License for more details.
1205+ *
1206+ * You should have received a copy of the GNU General Public License
1207+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1208+ *
1209+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
1210+ */
1211+
1212+#include "decoration_provider.h"
1213+#include "titlebar_config.h"
1214+
1215+#include <mir/client/display_config.h>
1216+#include <mir/client/window_spec.h>
1217+
1218+#include <mir_toolkit/mir_buffer_stream.h>
1219+
1220+#include <ft2build.h>
1221+#include FT_FREETYPE_H
1222+
1223+#include <locale>
1224+#include <codecvt>
1225+#include <string>
1226+#include <cstring>
1227+#include <sstream>
1228+
1229+#include <iostream>
1230+
1231+namespace
1232+{
1233+int const title_bar_height = 12;
1234+char const* const wallpaper_name = "wallpaper";
1235+
1236+void null_window_callback(MirWindow*, void*) {}
1237+
1238+struct preferred_codecvt : std::codecvt_byname<wchar_t, char, std::mbstate_t>
1239+{
1240+ preferred_codecvt() : std::codecvt_byname<wchar_t, char, std::mbstate_t>("") {}
1241+ ~preferred_codecvt() = default;
1242+};
1243+
1244+struct Printer
1245+{
1246+ Printer();
1247+ ~Printer();
1248+ Printer(Printer const&) = delete;
1249+ Printer& operator=(Printer const&) = delete;
1250+
1251+ void print(MirGraphicsRegion const& region, std::string const& title, int const intensity);
1252+ void printhelp(MirGraphicsRegion const& region);
1253+
1254+private:
1255+ std::wstring_convert<preferred_codecvt> converter;
1256+
1257+ bool working = false;
1258+ FT_Library lib;
1259+ FT_Face face;
1260+};
1261+
1262+void paint_surface(MirBufferStream* buffer_stream, std::string const& title, int const intensity)
1263+{
1264+ // TODO sometimes buffer_stream is nullptr - find out why (and fix).
1265+ // (Only observed when creating a lot of clients at once)
1266+ if (!buffer_stream)
1267+ return;
1268+
1269+ MirGraphicsRegion region;
1270+ mir_buffer_stream_get_graphics_region(buffer_stream, &region);
1271+
1272+ char* row = region.vaddr;
1273+
1274+ for (int j = 0; j != region.height; ++j)
1275+ {
1276+ memset(row, intensity, 4*region.width);
1277+ row += region.stride;
1278+ }
1279+
1280+ static Printer printer;
1281+ printer.print(region, title, intensity);
1282+
1283+ mir_buffer_stream_swap_buffers_sync(buffer_stream);
1284+}
1285+
1286+Printer::Printer()
1287+{
1288+ if (FT_Init_FreeType(&lib))
1289+ return;
1290+
1291+ if (FT_New_Face(lib, titlebar::font_file().c_str(), 0, &face))
1292+ {
1293+ std::cerr << "WARNING: failed to load titlebar font: \"" << titlebar::font_file() << "\"\n";
1294+ FT_Done_FreeType(lib);
1295+ return;
1296+ }
1297+
1298+ FT_Set_Pixel_Sizes(face, 0, 10);
1299+ working = true;
1300+}
1301+
1302+Printer::~Printer()
1303+{
1304+ if (working)
1305+ {
1306+ FT_Done_Face(face);
1307+ FT_Done_FreeType(lib);
1308+ }
1309+}
1310+
1311+void Printer::print(MirGraphicsRegion const& region, std::string const& title_, int const intensity)
1312+try
1313+{
1314+ if (!working)
1315+ return;
1316+
1317+ auto title = converter.from_bytes(title_);
1318+
1319+ int base_x = 2;
1320+ int base_y = region.height-2;
1321+
1322+ for (auto const& ch : title)
1323+ {
1324+ FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT);
1325+ auto const glyph = face->glyph;
1326+ FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL);
1327+
1328+ auto const& bitmap = glyph->bitmap;
1329+ auto const x = base_x + glyph->bitmap_left;
1330+
1331+ if (static_cast<int>(x + bitmap.width) <= region.width)
1332+ {
1333+ unsigned char* src = bitmap.buffer;
1334+
1335+ auto const y = base_y - glyph->bitmap_top;
1336+ char* dest = region.vaddr + y*region.stride + 4*x;
1337+
1338+ for (auto row = 0u; row != std::min(bitmap.rows, glyph->bitmap_top+2u); ++row)
1339+ {
1340+ for (auto col = 0u; col != bitmap.width; ++col)
1341+ memset(dest+ 4*col, (intensity*(0xff^src[col]))/0xff, 4);
1342+
1343+ src += bitmap.pitch;
1344+ dest += region.stride;
1345+ }
1346+ }
1347+
1348+ base_x += glyph->advance.x >> 6;
1349+ base_y += glyph->advance.y >> 6;
1350+ }
1351+}
1352+catch (...)
1353+{
1354+ std::cerr << "WARNING: failed render title: \"" << title_ << "\"\n";
1355+}
1356+
1357+void Printer::printhelp(MirGraphicsRegion const& region)
1358+{
1359+ if (!working)
1360+ return;
1361+
1362+ static char const* const helptext[] =
1363+ {
1364+ "Welcome to miral-shell",
1365+ "",
1366+ "Keyboard shortcuts:",
1367+ "",
1368+ " o Switch apps: Alt-Tab, tap or click on the corresponding window",
1369+ " o Next (previous) app window: Alt-` (Alt-Shift-`)",
1370+ "",
1371+ " o Move window: Alt-leftmousebutton drag (three finger drag)",
1372+ " o Resize window: Alt-middle_button drag (three finger pinch)",
1373+ "",
1374+ " o Maximize/restore current window (to display size). : Alt-F11",
1375+ " o Maximize/restore current window (to display height): Shift-F11",
1376+ " o Maximize/restore current window (to display width) : Ctrl-F11",
1377+ "",
1378+ " o Switch workspace: Meta-Alt-[F1|F2|F3|F4]",
1379+ " o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]",
1380+ "",
1381+ " o To exit: Ctrl-Alt-BkSp",
1382+ };
1383+
1384+ int help_width = 0;
1385+ unsigned int help_height = 0;
1386+ unsigned int line_height = 0;
1387+
1388+ for (auto const* rawline : helptext)
1389+ {
1390+ int line_width = 0;
1391+
1392+ auto const line = converter.from_bytes(rawline);
1393+
1394+ auto const fwidth = std::min(region.width / 60, 20);
1395+
1396+ FT_Set_Pixel_Sizes(face, fwidth, 0);
1397+
1398+ for (auto const& ch : line)
1399+ {
1400+ FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT);
1401+ auto const glyph = face->glyph;
1402+ FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL);
1403+
1404+ line_width += glyph->advance.x >> 6;
1405+ line_height = std::max(line_height, glyph->bitmap.rows + glyph->bitmap.rows/2);
1406+ }
1407+
1408+ if (help_width < line_width) help_width = line_width;
1409+ help_height += line_height;
1410+ }
1411+
1412+ int base_y = (region.height - help_height)/2;
1413+
1414+ for (auto const* rawline : helptext)
1415+ {
1416+ int base_x = (region.width - help_width)/2;
1417+
1418+ auto const line = converter.from_bytes(rawline);
1419+
1420+ for (auto const& ch : line)
1421+ {
1422+ FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT);
1423+ auto const glyph = face->glyph;
1424+ FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL);
1425+
1426+ auto const& bitmap = glyph->bitmap;
1427+ auto const x = base_x + glyph->bitmap_left;
1428+
1429+ if (static_cast<int>(x + bitmap.width) <= region.width)
1430+ {
1431+ unsigned char* src = bitmap.buffer;
1432+
1433+ auto const y = base_y - glyph->bitmap_top;
1434+ char* dest = region.vaddr + y * region.stride + 4 * x;
1435+
1436+ for (auto row = 0u; row != bitmap.rows; ++row)
1437+ {
1438+ for (auto col = 0u; col != 4 * bitmap.width; ++col)
1439+ dest[col] |= src[col / 4]/2;
1440+
1441+ src += bitmap.pitch;
1442+ dest += region.stride;
1443+
1444+ if (dest > region.vaddr + region.height * region.stride)
1445+ break;
1446+ }
1447+ }
1448+
1449+ base_x += glyph->advance.x >> 6;
1450+ }
1451+ base_y += line_height;
1452+ }
1453+}
1454+
1455+void render_background(MirBufferStream* buffer_stream, MirGraphicsRegion& graphics_region)
1456+{
1457+ static uint8_t const pattern[4] = {0x00, 0x00, 0x00, 0x00 };
1458+
1459+ char* row = (&graphics_region)->vaddr;
1460+
1461+ for (int j = 0; j < (&graphics_region)->height; j++)
1462+ {
1463+ uint32_t* pixel = (uint32_t*)row;
1464+
1465+ for (int i = 0; i < (&graphics_region)->width; i++)
1466+ memcpy(pixel + i, pattern, sizeof pixel[i]);
1467+
1468+ row += (&graphics_region)->stride;
1469+ }
1470+
1471+ static Printer printer;
1472+ printer.printhelp(*&graphics_region);
1473+
1474+ mir_buffer_stream_swap_buffers_sync(buffer_stream);
1475+}
1476+}
1477+
1478+using namespace mir::client;
1479+using namespace mir::geometry;
1480+
1481+DecorationProvider::DecorationProvider(miral::WindowManagerTools const& tools) : tools{tools}
1482+{
1483+
1484+}
1485+
1486+DecorationProvider::~DecorationProvider()
1487+{
1488+}
1489+
1490+void DecorationProvider::stop()
1491+{
1492+ enqueue_work([this]
1493+ {
1494+ std::lock_guard<decltype(mutex)> lock{mutex};
1495+ window_to_titlebar.clear();
1496+ });
1497+
1498+ enqueue_work([this]
1499+ {
1500+ if (connection)
1501+ {
1502+ wallpaper.erase(begin(wallpaper), end(wallpaper));
1503+ }
1504+ connection.reset();
1505+ });
1506+ stop_work();
1507+}
1508+
1509+void DecorationProvider::operator()(Connection connection)
1510+{
1511+ this->connection = connection;
1512+
1513+ DisplayConfig const display_conf{this->connection};
1514+
1515+ display_conf.for_each_output([this](MirOutput const* output)
1516+ {
1517+ if (!mir_output_is_enabled(output))
1518+ return;
1519+
1520+ auto const mode = mir_output_get_current_mode(output);
1521+ auto const output_id = mir_output_get_id(output);
1522+ auto const width = mir_output_mode_get_width(mode);
1523+ auto const height = mir_output_mode_get_height(mode);
1524+
1525+ Surface surface{mir_connection_create_render_surface_sync(DecorationProvider::connection, width, height)};
1526+
1527+ auto const buffer_stream =
1528+ mir_render_surface_get_buffer_stream(surface, width, height, mir_pixel_format_xrgb_8888);
1529+
1530+ auto window = WindowSpec::for_gloss(DecorationProvider::connection, width, height)
1531+ .set_fullscreen_on_output(output_id)
1532+ .set_event_handler(&handle_event_for_background, this)
1533+ .add_surface(surface, width, height, 0, 0)
1534+ .set_name(wallpaper_name).create_window();
1535+
1536+ wallpaper.push_back(Wallpaper{surface, window, buffer_stream});
1537+
1538+ MirGraphicsRegion graphics_region;
1539+ mir_buffer_stream_get_graphics_region(buffer_stream, &graphics_region);
1540+ render_background(buffer_stream, graphics_region);
1541+ });
1542+
1543+ start_work();
1544+}
1545+
1546+void DecorationProvider::operator()(std::weak_ptr<mir::scene::Session> const& session)
1547+{
1548+ std::lock_guard<decltype(mutex)> lock{mutex};
1549+ this->weak_session = session;
1550+}
1551+
1552+auto DecorationProvider::session() const -> std::shared_ptr<mir::scene::Session>
1553+{
1554+ std::lock_guard<decltype(mutex)> lock{mutex};
1555+ return weak_session.lock();
1556+}
1557+
1558+void DecorationProvider::handle_event(MirWindow* window, MirEvent const* ev, void* context_)
1559+{
1560+ auto* const context = (Data*)context_;
1561+
1562+ switch (mir_event_get_type(ev))
1563+ {
1564+ case mir_event_type_resize:
1565+ {
1566+ MirResizeEvent const* resize = mir_event_get_resize_event(ev);
1567+ int const new_width = mir_resize_event_get_width(resize);
1568+ int const new_height = mir_resize_event_get_height(resize);
1569+ mir_render_surface_set_size(context->surface, new_width, new_height);
1570+ WindowSpec::for_changes(context->connection)
1571+ .add_surface(context->surface, new_width, new_height, 0, 0)
1572+ .apply_to(window);
1573+ break;
1574+ }
1575+
1576+ default:
1577+ break;
1578+ }
1579+}
1580+
1581+void DecorationProvider::create_titlebar_for(miral::Window const& window)
1582+{
1583+ if (is_decoration(window)) return;
1584+
1585+ enqueue_work([this, window]
1586+ {
1587+ auto const width = window.size().width.as_int();
1588+ std::ostringstream buffer;
1589+ buffer << std::shared_ptr<mir::scene::Surface>(window).get();
1590+
1591+ Surface surface{mir_connection_create_render_surface_sync(this->connection, width, title_bar_height)};
1592+
1593+ std::lock_guard<decltype(mutex)> lock{mutex};
1594+
1595+ auto const data = &window_to_titlebar[window];
1596+ data->connection = connection;
1597+ data->surface = surface;
1598+ data->stream = mir_render_surface_get_buffer_stream(surface, width, title_bar_height, mir_pixel_format_xrgb_8888);
1599+ windows_awaiting_titlebar[buffer.str()] = window;
1600+
1601+ WindowSpec::for_gloss(connection, width, title_bar_height)
1602+ .add_surface(surface, width, title_bar_height, 0, 0)
1603+ .set_name(buffer.str().c_str())
1604+ .set_event_handler(&handle_event, data)
1605+ .create_window(insert, data);
1606+ });
1607+}
1608+
1609+void DecorationProvider::paint_titlebar_for(miral::WindowInfo const& info, int intensity)
1610+{
1611+ if (auto data = find_titlebar_data(info.window()))
1612+ {
1613+ data->intensity = intensity;
1614+
1615+ auto const title = info.name();
1616+
1617+ enqueue_work([this, stream=data->stream, title, intensity]{ paint_surface(stream, title, intensity); });
1618+ }
1619+}
1620+
1621+void DecorationProvider::destroy_titlebar_for(miral::Window const& window)
1622+{
1623+ if (auto data = find_titlebar_data(window))
1624+ {
1625+ if (auto surface = data->titlebar.exchange(nullptr))
1626+ {
1627+ enqueue_work([surface]
1628+ {
1629+ mir_window_release(surface, &null_window_callback, nullptr);
1630+ });
1631+ }
1632+
1633+ if (data->titlebar.load())
1634+ {
1635+ enqueue_work([this, window]
1636+ {
1637+ std::lock_guard<decltype(mutex)> lock{mutex};
1638+ window_to_titlebar.erase(window);
1639+ });
1640+ }
1641+ else
1642+ {
1643+ data->on_create = [this, window](MirWindow*)
1644+ {
1645+ enqueue_work([this, window]
1646+ {
1647+ std::lock_guard<decltype(mutex)> lock{mutex};
1648+ window_to_titlebar.erase(window);
1649+ });
1650+ };
1651+ }
1652+ }
1653+}
1654+
1655+void DecorationProvider::resize_titlebar_for(miral::WindowInfo const& window_info, Size const& size)
1656+{
1657+ auto const window = window_info.window();
1658+
1659+ if (window.size().width == size.width)
1660+ return;
1661+
1662+ if (auto titlebar_window = find_titlebar_window(window))
1663+ {
1664+ titlebar_window.resize({size.width, title_bar_height});
1665+
1666+ repaint_titlebar_for(window_info);
1667+ }
1668+}
1669+
1670+void DecorationProvider::place_new_decoration(miral::WindowSpecification& window_spec)
1671+{
1672+ auto const name = window_spec.name().value();
1673+ if (name == wallpaper_name) return;
1674+
1675+ std::lock_guard<decltype(mutex)> lock{mutex};
1676+
1677+ auto const scene_surface = windows_awaiting_titlebar[name].lock();
1678+ windows_awaiting_titlebar.erase(name);
1679+
1680+ auto& parent_info = tools.info_for(scene_surface);
1681+ auto const parent_window = parent_info.window();
1682+
1683+ window_spec.parent() = scene_surface;
1684+ window_spec.size() = Size{parent_window.size().width, Height{title_bar_height}};
1685+ window_spec.top_left() = parent_window.top_left() - Displacement{0, title_bar_height};
1686+}
1687+
1688+void DecorationProvider::advise_new_titlebar(miral::WindowInfo const& window_info)
1689+{
1690+ if (window_info.name() == wallpaper_name) return;
1691+
1692+ {
1693+ std::lock_guard<decltype(mutex)> lock{mutex};
1694+
1695+ window_to_titlebar[window_info.parent()].window = window_info.window();
1696+ }
1697+
1698+ tools.raise_tree(window_info.parent());
1699+}
1700+
1701+void DecorationProvider::advise_state_change(miral::WindowInfo const& window_info, MirWindowState state)
1702+{
1703+ if (auto titlebar = find_titlebar_window(window_info.window()))
1704+ {
1705+ miral::WindowSpecification modifications;
1706+ switch (state)
1707+ {
1708+ case mir_window_state_hidden:
1709+ case mir_window_state_minimized:
1710+ case mir_window_state_fullscreen:
1711+ modifications.state() = mir_window_state_hidden;
1712+ break;
1713+
1714+ default:
1715+ modifications.state() = mir_window_state_restored;
1716+ break;
1717+ }
1718+
1719+ tools.modify_window(titlebar, modifications);
1720+ repaint_titlebar_for(window_info);
1721+ }
1722+}
1723+
1724+void DecorationProvider::repaint_titlebar_for(miral::WindowInfo const& window_info)
1725+{
1726+ if (auto data = find_titlebar_data(window_info.window()))
1727+ {
1728+ auto const title = window_info.name();
1729+
1730+ enqueue_work([this, stream=data->stream, title, intensity=data->intensity.load()]
1731+ { paint_surface(stream, title, intensity); });
1732+ }
1733+}
1734+
1735+DecorationProvider::Data::~Data()
1736+{
1737+ if (auto surface = titlebar.exchange(nullptr))
1738+ mir_window_release(surface, &null_window_callback, nullptr);
1739+}
1740+
1741+void DecorationProvider::insert(MirWindow* surface, Data* data)
1742+{
1743+ data->on_create(surface);
1744+ data->titlebar = surface;
1745+}
1746+
1747+DecorationProvider::Data* DecorationProvider::find_titlebar_data(miral::Window const& window)
1748+{
1749+ std::lock_guard<decltype(mutex)> lock{mutex};
1750+
1751+ auto const find = window_to_titlebar.find(window);
1752+
1753+ return (find != window_to_titlebar.end()) ? &find->second : nullptr;
1754+}
1755+
1756+miral::Window DecorationProvider::find_titlebar_window(miral::Window const& window) const
1757+{
1758+ std::lock_guard<decltype(mutex)> lock{mutex};
1759+
1760+ auto const find = window_to_titlebar.find(window);
1761+
1762+ return (find != window_to_titlebar.end()) ? find->second.window : miral::Window{};
1763+}
1764+
1765+bool DecorationProvider::is_decoration(miral::Window const& window) const
1766+{
1767+ return window.application() == session();
1768+}
1769+
1770+bool DecorationProvider::is_titlebar(miral::WindowInfo const& window_info) const
1771+{
1772+ return window_info.window().application() == session() && window_info.name() != wallpaper_name;
1773+}
1774+
1775+void DecorationProvider::handle_event_for_background(MirWindow* window, MirEvent const* event, void* context)
1776+{
1777+ static_cast<DecorationProvider*>(context)->handle_event_for_background(window, event);
1778+}
1779+
1780+void DecorationProvider::handle_event_for_background(MirWindow* window, MirEvent const* ev)
1781+{
1782+ switch (mir_event_get_type(ev))
1783+ {
1784+ case mir_event_type_resize:
1785+ {
1786+ MirResizeEvent const* resize = mir_event_get_resize_event(ev);
1787+ int const new_width = mir_resize_event_get_width(resize);
1788+ int const new_height = mir_resize_event_get_height(resize);
1789+
1790+ enqueue_work([window, new_width, new_height, this]()
1791+ {
1792+ auto found = find_if(begin(wallpaper), end(wallpaper), [&](Wallpaper const& w) { return w.window == window;});
1793+ if (found == end(wallpaper)) return;
1794+
1795+ mir_buffer_stream_set_size(found->stream, new_width, new_height);
1796+ mir_render_surface_set_size(found->surface, new_width, new_height);
1797+
1798+ WindowSpec::for_changes(connection)
1799+ .add_surface(found->surface, new_width, new_height, 0, 0)
1800+ .apply_to(window);
1801+
1802+ MirGraphicsRegion graphics_region;
1803+
1804+ // We expect a buffer of the right size so we shouldn't need to limit repaints
1805+ // but we also to avoid an infinite loop.
1806+ int repaint_limit = 3;
1807+
1808+ do
1809+ {
1810+ mir_buffer_stream_get_graphics_region(found->stream, &graphics_region);
1811+ render_background(found->stream, graphics_region);
1812+ }
1813+ while ((new_width != graphics_region.width || new_height != graphics_region.height)
1814+ && --repaint_limit != 0);
1815+ });
1816+ break;
1817+ }
1818+
1819+ default:
1820+ break;
1821+ }
1822+}
1823+
1824+Worker::~Worker()
1825+{
1826+}
1827+
1828+void Worker::do_work()
1829+{
1830+ while (!work_done)
1831+ {
1832+ WorkQueue::value_type work;
1833+ {
1834+ std::unique_lock<decltype(work_mutex)> lock{work_mutex};
1835+ work_cv.wait(lock, [this] { return !work_queue.empty(); });
1836+ work = work_queue.front();
1837+ work_queue.pop();
1838+ }
1839+
1840+ work();
1841+ }
1842+}
1843+
1844+void Worker::enqueue_work(std::function<void()> const& functor)
1845+{
1846+ std::lock_guard<decltype(work_mutex)> lock{work_mutex};
1847+ work_queue.push(functor);
1848+ work_cv.notify_one();
1849+}
1850+
1851+void Worker::start_work()
1852+{
1853+ do_work();
1854+}
1855+
1856+void Worker::stop_work()
1857+{
1858+ enqueue_work([this] { work_done = true; });
1859+}
1860
1861=== added file 'examples/miral-shell/decoration_provider.h'
1862--- examples/miral-shell/decoration_provider.h 1970-01-01 00:00:00 +0000
1863+++ examples/miral-shell/decoration_provider.h 2017-08-23 11:59:25 +0000
1864@@ -0,0 +1,119 @@
1865+/*
1866+ * Copyright © 2016-2017 Canonical Ltd.
1867+ *
1868+ * This program is free software: you can redistribute it and/or modify it
1869+ * under the terms of the GNU General Public License version 2 or 3 as
1870+ * published by the Free Software Foundation.
1871+ *
1872+ * This program is distributed in the hope that it will be useful,
1873+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1874+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1875+ * GNU General Public License for more details.
1876+ *
1877+ * You should have received a copy of the GNU General Public License
1878+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1879+ *
1880+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
1881+ */
1882+
1883+#ifndef MIRAL_SHELL_DECORATION_PROVIDER_H
1884+#define MIRAL_SHELL_DECORATION_PROVIDER_H
1885+
1886+
1887+#include <miral/window_manager_tools.h>
1888+
1889+#include <mir/client/connection.h>
1890+#include <mir/client/surface.h>
1891+#include <mir/client/window.h>
1892+
1893+#include <mir/geometry/rectangle.h>
1894+#include <mir_toolkit/client_types.h>
1895+
1896+#include <atomic>
1897+#include <map>
1898+#include <mutex>
1899+#include <condition_variable>
1900+#include <queue>
1901+
1902+class Worker
1903+{
1904+public:
1905+ ~Worker();
1906+
1907+ void start_work();
1908+ void enqueue_work(std::function<void()> const& functor);
1909+ void stop_work();
1910+
1911+private:
1912+ using WorkQueue = std::queue<std::function<void()>>;
1913+
1914+ std::mutex mutable work_mutex;
1915+ std::condition_variable work_cv;
1916+ WorkQueue work_queue;
1917+ bool work_done = false;
1918+
1919+ void do_work();
1920+};
1921+
1922+class DecorationProvider : Worker
1923+{
1924+public:
1925+ DecorationProvider(miral::WindowManagerTools const& tools);
1926+ ~DecorationProvider();
1927+
1928+ void operator()(mir::client::Connection connection);
1929+ void operator()(std::weak_ptr<mir::scene::Session> const& session);
1930+
1931+ auto session() const -> std::shared_ptr<mir::scene::Session>;
1932+
1933+ void create_titlebar_for(miral::Window const& window);
1934+ void place_new_decoration(miral::WindowSpecification& window_spec);
1935+ void paint_titlebar_for(miral::WindowInfo const& window, int intensity);
1936+ void destroy_titlebar_for(miral::Window const& window);
1937+ void resize_titlebar_for(miral::WindowInfo const& window_info, mir::geometry::Size const& size);
1938+ void advise_new_titlebar(miral::WindowInfo const& window_info);
1939+ void advise_state_change(miral::WindowInfo const& window_info, MirWindowState state);
1940+
1941+ void stop();
1942+
1943+ bool is_decoration(miral::Window const& window) const;
1944+ bool is_titlebar(miral::WindowInfo const& window_info) const;
1945+
1946+private:
1947+ struct Data
1948+ {
1949+ MirConnection* connection{nullptr};
1950+ mir::client::Surface surface;
1951+ MirBufferStream* stream{nullptr};
1952+ std::atomic<MirWindow*> titlebar{nullptr};
1953+ std::atomic<int> intensity{0xff};
1954+ std::function<void(MirWindow* surface)> on_create{[](MirWindow*){}};
1955+ miral::Window window;
1956+
1957+ ~Data();
1958+ };
1959+
1960+ using SurfaceMap = std::map<std::weak_ptr<mir::scene::Surface>, Data, std::owner_less<std::weak_ptr<mir::scene::Surface>>>;
1961+ using TitleMap = std::map<std::string, std::weak_ptr<mir::scene::Surface>>;
1962+
1963+ miral::WindowManagerTools tools;
1964+ std::mutex mutable mutex;
1965+ mir::client::Connection connection;
1966+ struct Wallpaper { mir::client::Surface surface; mir::client::Window window; MirBufferStream* stream; };
1967+ std::vector<Wallpaper> wallpaper;
1968+ std::weak_ptr<mir::scene::Session> weak_session;
1969+
1970+ SurfaceMap window_to_titlebar;
1971+ TitleMap windows_awaiting_titlebar;
1972+
1973+ static void insert(MirWindow* surface, Data* data);
1974+ Data* find_titlebar_data(miral::Window const& window);
1975+ miral::Window find_titlebar_window(miral::Window const& window) const;
1976+ void repaint_titlebar_for(miral::WindowInfo const& window_info);
1977+ static void handle_event(MirWindow* window, MirEvent const* ev, void* context_);
1978+ static void handle_event_for_background(MirWindow* window, MirEvent const* event, void* context_);
1979+ void handle_event_for_background(MirWindow* window, MirEvent const* ev);
1980+};
1981+
1982+
1983+#endif //MIRAL_SHELL_DECORATION_PROVIDER_H
1984
1985=== added directory 'examples/miral-shell/desktop'
1986=== added file 'examples/miral-shell/desktop/CMakeLists.txt'
1987--- examples/miral-shell/desktop/CMakeLists.txt 1970-01-01 00:00:00 +0000
1988+++ examples/miral-shell/desktop/CMakeLists.txt 2017-08-23 11:59:25 +0000
1989@@ -0,0 +1,12 @@
1990+set(ICON_NAME ubuntu-logo)
1991+set(PROGRAM_NAME miral-app)
1992+
1993+configure_file(miral-shell.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/miral-shell.desktop @ONLY)
1994+
1995+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/miral-shell.desktop
1996+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications
1997+)
1998+
1999+install(FILES ${ICON_NAME}.svg
2000+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps
2001+)
2002
2003=== added file 'examples/miral-shell/desktop/miral-shell.desktop.in'
2004--- examples/miral-shell/desktop/miral-shell.desktop.in 1970-01-01 00:00:00 +0000
2005+++ examples/miral-shell/desktop/miral-shell.desktop.in 2017-08-23 11:59:25 +0000
2006@@ -0,0 +1,18 @@
2007+[Desktop Entry]
2008+Version=1.0
2009+Name=Miral Shell
2010+GenericName=Mir Shell
2011+Comment=A Mir Shell
2012+Keywords=Mir;Server;Shell
2013+Type=Application
2014+Icon=@ICON_NAME@
2015+Exec=@PROGRAM_NAME@
2016+Terminal=false
2017+Categories=Utility
2018+#MimeType=
2019+X-Ubuntu-Touch=true
2020+X-Ubuntu-Gettext-Domain=miral-shell
2021+X-Ubuntu-Single-Instance=true
2022+X-Ubuntu-Default-Department-ID=miral-shell
2023+#X-Screenshot=
2024+X-Ubuntu-Splash-Color=#FFFFFF
2025
2026=== added file 'examples/miral-shell/desktop/ubuntu-logo.svg'
2027--- examples/miral-shell/desktop/ubuntu-logo.svg 1970-01-01 00:00:00 +0000
2028+++ examples/miral-shell/desktop/ubuntu-logo.svg 2017-08-23 11:59:25 +0000
2029@@ -0,0 +1,27 @@
2030+<?xml version="1.0" encoding="utf-8"?>
2031+<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In -->
2032+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
2033+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
2034+]>
2035+<svg version="1.1"
2036+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
2037+ x="0px" y="0px" width="285px" height="285px" viewBox="-0.866 -0.866 285 285" enable-background="new -0.866 -0.866 285 285"
2038+ xml:space="preserve">
2039+<defs>
2040+</defs>
2041+<path fill="#DD4814" d="M283.465,141.734c0,78.273-63.457,141.73-141.734,141.73S0,220.008,0,141.734C0,63.455,63.453,0,141.73,0
2042+ S283.465,63.455,283.465,141.734z"/>
2043+<path fill="#FFFFFF" d="M45.356,122.812c-10.453,0-18.923,8.47-18.923,18.923c0,10.449,8.47,18.92,18.923,18.92
2044+ c10.449,0,18.92-8.471,18.92-18.92C64.276,131.281,55.806,122.812,45.356,122.812z M180.463,208.814
2045+ c-9.051,5.225-12.149,16.793-6.926,25.84c5.226,9.051,16.793,12.151,25.844,6.926c9.048-5.224,12.148-16.792,6.923-25.842
2046+ C201.08,206.691,189.511,203.59,180.463,208.814z M86.458,141.732c0-18.701,9.293-35.219,23.504-45.221L96.128,73.338
2047+ c-16.56,11.064-28.878,27.978-33.995,47.788c5.977,4.872,9.796,12.291,9.796,20.608c0,8.315-3.819,15.734-9.797,20.605
2048+ c5.116,19.812,17.435,36.726,33.995,47.789l13.835-23.175C95.751,176.953,86.458,160.436,86.458,141.732z M141.733,86.457
2049+ c28.877,0,52.564,22.141,55.047,50.373l26.968-0.394c-1.327-20.844-10.432-39.562-24.425-53.319
2050+ c-7.194,2.718-15.505,2.306-22.688-1.842c-7.192-4.152-11.705-11.156-12.941-18.757c-6.992-1.935-14.351-2.99-21.96-2.99
2051+ c-13.086,0-25.449,3.072-36.431,8.512l13.146,23.56C125.526,88.307,133.412,86.457,141.733,86.457z M141.733,197.008
2052+ c-8.322,0-16.207-1.85-23.285-5.143L105.3,215.427c10.983,5.438,23.347,8.511,36.433,8.511c7.609,0,14.968-1.055,21.961-2.99
2053+ c1.236-7.601,5.75-14.605,12.943-18.76c7.183-4.146,15.494-4.558,22.688-1.839c13.992-13.758,23.097-32.476,24.422-53.32
2054+ l-26.968-0.394C194.298,174.871,170.61,197.008,141.733,197.008z M180.46,74.649c9.05,5.227,20.619,2.126,25.842-6.921
2055+ c5.226-9.051,2.128-20.619-6.923-25.845c-9.049-5.224-20.617-2.124-25.843,6.927C168.312,57.857,171.412,69.426,180.46,74.649z"/>
2056+</svg>
2057
2058=== added file 'examples/miral-shell/floating_window_manager.cpp'
2059--- examples/miral-shell/floating_window_manager.cpp 1970-01-01 00:00:00 +0000
2060+++ examples/miral-shell/floating_window_manager.cpp 2017-08-23 11:59:25 +0000
2061@@ -0,0 +1,801 @@
2062+/*
2063+ * Copyright © 2016-2017 Canonical Ltd.
2064+ *
2065+ * This program is free software: you can redistribute it and/or modify it
2066+ * under the terms of the GNU General Public License version 2 or 3 as
2067+ * published by the Free Software Foundation.
2068+ *
2069+ * This program is distributed in the hope that it will be useful,
2070+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2071+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2072+ * GNU General Public License for more details.
2073+ *
2074+ * You should have received a copy of the GNU General Public License
2075+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2076+ *
2077+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
2078+ */
2079+
2080+#include "floating_window_manager.h"
2081+#include "decoration_provider.h"
2082+
2083+#include <miral/application_info.h>
2084+#include <miral/internal_client.h>
2085+#include <miral/window_info.h>
2086+#include <miral/window_manager_tools.h>
2087+
2088+#include <linux/input.h>
2089+#include <csignal>
2090+
2091+using namespace miral;
2092+
2093+namespace
2094+{
2095+DeltaY const title_bar_height{12};
2096+
2097+struct PolicyData
2098+{
2099+ bool in_hidden_workspace{false};
2100+
2101+ MirWindowState old_state;
2102+};
2103+
2104+inline PolicyData& policy_data_for(WindowInfo const& info)
2105+{
2106+ return *std::static_pointer_cast<PolicyData>(info.userdata());
2107+}
2108+}
2109+
2110+FloatingWindowManagerPolicy::FloatingWindowManagerPolicy(
2111+ WindowManagerTools const& tools,
2112+ SpinnerSplash const& spinner,
2113+ miral::InternalClientLauncher const& launcher,
2114+ std::function<void()>& shutdown_hook) :
2115+ CanonicalWindowManagerPolicy(tools),
2116+ spinner{spinner},
2117+ decoration_provider{std::make_unique<DecorationProvider>(tools)}
2118+{
2119+ launcher.launch("decorations", *decoration_provider);
2120+ shutdown_hook = [this] { decoration_provider->stop(); };
2121+
2122+ for (auto key : {KEY_F1, KEY_F2, KEY_F3, KEY_F4})
2123+ key_to_workspace[key] = this->tools.create_workspace();
2124+
2125+ active_workspace = key_to_workspace[KEY_F1];
2126+}
2127+
2128+FloatingWindowManagerPolicy::~FloatingWindowManagerPolicy() = default;
2129+
2130+bool FloatingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event)
2131+{
2132+ auto const action = mir_pointer_event_action(event);
2133+ auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask;
2134+ Point const cursor{
2135+ mir_pointer_event_axis_value(event, mir_pointer_axis_x),
2136+ mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
2137+
2138+ bool consumes_event = false;
2139+ bool is_resize_event = false;
2140+
2141+ if (action == mir_pointer_action_button_down)
2142+ {
2143+ if (auto const window = tools.window_at(cursor))
2144+ tools.select_active_window(window);
2145+ }
2146+ else if (action == mir_pointer_action_motion &&
2147+ modifiers == mir_input_event_modifier_alt)
2148+ {
2149+ if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
2150+ {
2151+ if (auto const target = tools.window_at(old_cursor))
2152+ {
2153+ if (tools.select_active_window(target) == target)
2154+ tools.drag_active_window(cursor - old_cursor);
2155+ }
2156+ consumes_event = true;
2157+ }
2158+
2159+ if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary))
2160+ {
2161+ { // Workaround for lp:1627697
2162+ auto now = std::chrono::steady_clock::now();
2163+ if (resizing && now < last_resize+std::chrono::milliseconds(20))
2164+ return true;
2165+
2166+ last_resize = now;
2167+ }
2168+
2169+ if (!resizing)
2170+ tools.select_active_window(tools.window_at(old_cursor));
2171+ is_resize_event = resize(tools.active_window(), cursor, old_cursor);
2172+ consumes_event = true;
2173+ }
2174+ }
2175+
2176+ if (!consumes_event && action == mir_pointer_action_motion && !modifiers)
2177+ {
2178+ if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
2179+ {
2180+ if (auto const possible_titlebar = tools.window_at(old_cursor))
2181+ {
2182+ auto const& info = tools.info_for(possible_titlebar);
2183+ if (decoration_provider->is_titlebar(info))
2184+ {
2185+ if (tools.select_active_window(info.parent()) == info.parent())
2186+ tools.drag_active_window(cursor - old_cursor);
2187+ consumes_event = true;
2188+ }
2189+ }
2190+ }
2191+ }
2192+
2193+ if (resizing && !is_resize_event)
2194+ end_resize();
2195+
2196+ resizing = is_resize_event;
2197+ old_cursor = cursor;
2198+ return consumes_event;
2199+}
2200+
2201+void FloatingWindowManagerPolicy::end_resize()
2202+{
2203+ if (!resizing && !pinching)
2204+ return;
2205+
2206+ if (auto window = tools.active_window())
2207+ {
2208+ auto& window_info = tools.info_for(window);
2209+
2210+ auto new_size = window.size();
2211+ auto new_pos = window.top_left();
2212+ window_info.constrain_resize(new_pos, new_size);
2213+
2214+ WindowSpecification modifications;
2215+ modifications.top_left() = new_pos;
2216+ modifications.size() = new_size;
2217+ tools.modify_window(window_info, modifications);
2218+ }
2219+
2220+ resizing = false;
2221+ pinching = false;
2222+}
2223+
2224+bool FloatingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event)
2225+{
2226+ auto const count = mir_touch_event_point_count(event);
2227+
2228+ long total_x = 0;
2229+ long total_y = 0;
2230+
2231+ for (auto i = 0U; i != count; ++i)
2232+ {
2233+ total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x);
2234+ total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y);
2235+ }
2236+
2237+ Point cursor{total_x/count, total_y/count};
2238+
2239+ bool is_drag = true;
2240+ for (auto i = 0U; i != count; ++i)
2241+ {
2242+ switch (mir_touch_event_action(event, i))
2243+ {
2244+ case mir_touch_action_up:
2245+ return false;
2246+
2247+ case mir_touch_action_down:
2248+ is_drag = false;
2249+ continue;
2250+
2251+ default:
2252+ continue;
2253+ }
2254+ }
2255+
2256+ int touch_pinch_top = std::numeric_limits<int>::max();
2257+ int touch_pinch_left = std::numeric_limits<int>::max();
2258+ int touch_pinch_width = 0;
2259+ int touch_pinch_height = 0;
2260+
2261+ for (auto i = 0U; i != count; ++i)
2262+ {
2263+ for (auto j = 0U; j != i; ++j)
2264+ {
2265+ int dx = mir_touch_event_axis_value(event, i, mir_touch_axis_x) -
2266+ mir_touch_event_axis_value(event, j, mir_touch_axis_x);
2267+
2268+ int dy = mir_touch_event_axis_value(event, i, mir_touch_axis_y) -
2269+ mir_touch_event_axis_value(event, j, mir_touch_axis_y);
2270+
2271+ if (touch_pinch_width < dx)
2272+ touch_pinch_width = dx;
2273+
2274+ if (touch_pinch_height < dy)
2275+ touch_pinch_height = dy;
2276+ }
2277+
2278+ int const x = mir_touch_event_axis_value(event, i, mir_touch_axis_x);
2279+
2280+ int const y = mir_touch_event_axis_value(event, i, mir_touch_axis_y);
2281+
2282+ if (touch_pinch_top > y)
2283+ touch_pinch_top = y;
2284+
2285+ if (touch_pinch_left > x)
2286+ touch_pinch_left = x;
2287+ }
2288+
2289+ bool consumes_event = false;
2290+ if (is_drag)
2291+ {
2292+ if (count == 3)
2293+ {
2294+ if (auto window = tools.active_window())
2295+ {
2296+ auto const old_size = window.size();
2297+ auto const delta_width = DeltaX{touch_pinch_width - old_touch_pinch_width};
2298+ auto const delta_height = DeltaY{touch_pinch_height - old_touch_pinch_height};
2299+
2300+ auto new_width = std::max(old_size.width + delta_width, Width{5});
2301+ auto new_height = std::max(old_size.height + delta_height, Height{5});
2302+ Displacement movement{
2303+ DeltaX{touch_pinch_left - old_touch_pinch_left},
2304+ DeltaY{touch_pinch_top - old_touch_pinch_top}};
2305+
2306+ auto& window_info = tools.info_for(window);
2307+ keep_window_within_constraints(window_info, movement, new_width, new_height);
2308+
2309+ auto new_pos = window.top_left() + movement;
2310+ Size new_size{new_width, new_height};
2311+
2312+ { // Workaround for lp:1627697
2313+ auto now = std::chrono::steady_clock::now();
2314+ if (pinching && now < last_resize+std::chrono::milliseconds(20))
2315+ return true;
2316+
2317+ last_resize = now;
2318+ }
2319+
2320+ WindowSpecification modifications;
2321+ modifications.top_left() = new_pos;
2322+ modifications.size() = new_size;
2323+ tools.modify_window(window_info, modifications);
2324+ pinching = true;
2325+ }
2326+ consumes_event = true;
2327+ }
2328+ }
2329+ else
2330+ {
2331+ if (auto const& window = tools.window_at(cursor))
2332+ tools.select_active_window(window);
2333+ }
2334+
2335+ if (!consumes_event && pinching)
2336+ end_resize();
2337+
2338+ old_cursor = cursor;
2339+ old_touch_pinch_top = touch_pinch_top;
2340+ old_touch_pinch_left = touch_pinch_left;
2341+ old_touch_pinch_width = touch_pinch_width;
2342+ old_touch_pinch_height = touch_pinch_height;
2343+ return consumes_event;
2344+}
2345+
2346+void FloatingWindowManagerPolicy::advise_new_window(WindowInfo const& window_info)
2347+{
2348+ CanonicalWindowManagerPolicy::advise_new_window(window_info);
2349+
2350+ auto const parent = window_info.parent();
2351+
2352+ if (decoration_provider->is_titlebar(window_info))
2353+ {
2354+ decoration_provider->advise_new_titlebar(window_info);
2355+
2356+ if (tools.active_window() == parent)
2357+ decoration_provider->paint_titlebar_for(tools.info_for(parent), 0xFF);
2358+ else
2359+ decoration_provider->paint_titlebar_for(tools.info_for(parent), 0x3F);
2360+ }
2361+
2362+ if (!parent)
2363+ tools.add_tree_to_workspace(window_info.window(), active_workspace);
2364+ else
2365+ {
2366+ if (policy_data_for(tools.info_for(parent)).in_hidden_workspace)
2367+ apply_workspace_hidden_to(window_info.window());
2368+ }
2369+}
2370+
2371+void FloatingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
2372+{
2373+ if (window_info.window().application() != spinner.session() && window_info.needs_titlebar(window_info.type()))
2374+ decoration_provider->create_titlebar_for(window_info.window());
2375+
2376+ CanonicalWindowManagerPolicy::handle_window_ready(window_info);
2377+ keep_spinner_on_top();
2378+}
2379+
2380+void FloatingWindowManagerPolicy::advise_focus_lost(WindowInfo const& info)
2381+{
2382+ CanonicalWindowManagerPolicy::advise_focus_lost(info);
2383+
2384+ decoration_provider->paint_titlebar_for(info, 0x3F);
2385+}
2386+
2387+void FloatingWindowManagerPolicy::advise_focus_gained(WindowInfo const& info)
2388+{
2389+ CanonicalWindowManagerPolicy::advise_focus_gained(info);
2390+
2391+ decoration_provider->paint_titlebar_for(info, 0xFF);
2392+ keep_spinner_on_top();
2393+}
2394+
2395+void FloatingWindowManagerPolicy::keep_spinner_on_top()
2396+{
2397+ // Frig to force the spinner to the top
2398+ if (auto const spinner_session = spinner.session())
2399+ {
2400+ auto const& spinner_info = tools.info_for(spinner_session);
2401+
2402+ for (auto const& window : spinner_info.windows())
2403+ tools.raise_tree(window);
2404+ }
2405+}
2406+
2407+void FloatingWindowManagerPolicy::advise_state_change(WindowInfo const& window_info, MirWindowState state)
2408+{
2409+ CanonicalWindowManagerPolicy::advise_state_change(window_info, state);
2410+
2411+ decoration_provider->advise_state_change(window_info, state);
2412+}
2413+
2414+void FloatingWindowManagerPolicy::advise_resize(WindowInfo const& window_info, Size const& new_size)
2415+{
2416+ CanonicalWindowManagerPolicy::advise_resize(window_info, new_size);
2417+
2418+ decoration_provider->resize_titlebar_for(window_info, new_size);
2419+}
2420+
2421+void FloatingWindowManagerPolicy::advise_delete_window(WindowInfo const& window_info)
2422+{
2423+ CanonicalWindowManagerPolicy::advise_delete_window(window_info);
2424+
2425+ decoration_provider->destroy_titlebar_for(window_info.window());
2426+}
2427+
2428+bool FloatingWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event)
2429+{
2430+ auto const action = mir_keyboard_event_action(event);
2431+ auto const scan_code = mir_keyboard_event_scan_code(event);
2432+ auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
2433+
2434+ // Switch workspaces
2435+ if (action == mir_keyboard_action_down &&
2436+ modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_meta))
2437+ {
2438+ auto const found = key_to_workspace.find(scan_code);
2439+
2440+ if (found != key_to_workspace.end())
2441+ {
2442+ switch_workspace_to(found->second);
2443+ return true;
2444+ }
2445+ }
2446+
2447+ // Switch workspace taking the active window
2448+ if (action == mir_keyboard_action_down &&
2449+ modifiers == (mir_input_event_modifier_ctrl | mir_input_event_modifier_meta))
2450+ {
2451+ auto const found = key_to_workspace.find(scan_code);
2452+
2453+ if (found != key_to_workspace.end())
2454+ {
2455+ switch_workspace_to(found->second, tools.active_window());
2456+ return true;
2457+ }
2458+ }
2459+
2460+ if (action != mir_keyboard_action_repeat)
2461+ end_resize();
2462+
2463+ if (action == mir_keyboard_action_down && scan_code == KEY_F11)
2464+ {
2465+ switch (modifiers)
2466+ {
2467+ case mir_input_event_modifier_alt:
2468+ toggle(mir_window_state_maximized);
2469+ return true;
2470+
2471+ case mir_input_event_modifier_shift:
2472+ toggle(mir_window_state_vertmaximized);
2473+ return true;
2474+
2475+ case mir_input_event_modifier_ctrl:
2476+ toggle(mir_window_state_horizmaximized);
2477+ return true;
2478+
2479+ case mir_input_event_modifier_meta:
2480+ toggle(mir_window_state_fullscreen);
2481+ return true;
2482+
2483+ default:
2484+ break;
2485+ }
2486+ }
2487+ else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
2488+ {
2489+ switch (modifiers)
2490+ {
2491+ case mir_input_event_modifier_alt|mir_input_event_modifier_shift:
2492+ if (auto const& window = tools.active_window())
2493+ kill(window.application(), SIGTERM);
2494+ return true;
2495+
2496+ case mir_input_event_modifier_alt:
2497+ tools.ask_client_to_close(tools.active_window());;
2498+ return true;
2499+
2500+ default:
2501+ break;
2502+ }
2503+ }
2504+ else if (action == mir_keyboard_action_down &&
2505+ modifiers == mir_input_event_modifier_alt &&
2506+ scan_code == KEY_TAB)
2507+ {
2508+ tools.focus_next_application();
2509+
2510+ return true;
2511+ }
2512+ else if (action == mir_keyboard_action_down &&
2513+ modifiers == mir_input_event_modifier_alt &&
2514+ scan_code == KEY_GRAVE)
2515+ {
2516+ tools.focus_next_within_application();
2517+
2518+ return true;
2519+ }
2520+ else if (action == mir_keyboard_action_down &&
2521+ modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_shift) &&
2522+ scan_code == KEY_GRAVE)
2523+ {
2524+ tools.focus_prev_within_application();
2525+
2526+ return true;
2527+ }
2528+ else if (action == mir_keyboard_action_down &&
2529+ modifiers == (mir_input_event_modifier_ctrl|mir_input_event_modifier_meta))
2530+ {
2531+ if (auto active_window = tools.active_window())
2532+ {
2533+ auto active_output = tools.active_output();
2534+ auto& window_info = tools.info_for(active_window);
2535+ WindowSpecification modifications;
2536+
2537+ switch (scan_code)
2538+ {
2539+ case KEY_LEFT:
2540+ modifications.state() = mir_window_state_vertmaximized;
2541+ tools.place_and_size_for_state(modifications, window_info);
2542+ modifications.top_left() = active_output.top_left + title_bar_height;
2543+ break;
2544+
2545+ case KEY_RIGHT:
2546+ modifications.state() = mir_window_state_vertmaximized;
2547+ tools.place_and_size_for_state(modifications, window_info);
2548+ modifications.top_left() = active_output.top_right() -
2549+ as_displacement({active_window.size().width, 0}) + title_bar_height;
2550+ break;
2551+
2552+ case KEY_UP:
2553+ modifications.state() = mir_window_state_horizmaximized;
2554+ tools.place_and_size_for_state(modifications, window_info);
2555+
2556+ modifications.top_left() = active_output.top_left + title_bar_height;
2557+ break;
2558+
2559+ case KEY_DOWN:
2560+ modifications.state() = mir_window_state_horizmaximized;
2561+ tools.place_and_size_for_state(modifications, window_info);
2562+
2563+ modifications.top_left() = active_output.bottom_right() - as_displacement(
2564+ modifications.size().is_set() ? modifications.size().value() : active_window.size());
2565+ break;
2566+
2567+ default:
2568+ return false;
2569+ }
2570+
2571+ tools.modify_window(window_info, modifications);
2572+ return true;
2573+ }
2574+ }
2575+
2576+ return false;
2577+}
2578+
2579+void FloatingWindowManagerPolicy::toggle(MirWindowState state)
2580+{
2581+ if (auto const window = tools.active_window())
2582+ {
2583+ auto& info = tools.info_for(window);
2584+
2585+ WindowSpecification modifications;
2586+
2587+ modifications.state() = (info.state() == state) ? mir_window_state_restored : state;
2588+ tools.place_and_size_for_state(modifications, info);
2589+ tools.modify_window(info, modifications);
2590+ }
2591+}
2592+
2593+bool FloatingWindowManagerPolicy::resize(Window const& window, Point cursor, Point old_cursor)
2594+{
2595+ if (!window)
2596+ return false;
2597+
2598+ auto& window_info = tools.info_for(window);
2599+
2600+ auto const top_left = window.top_left();
2601+ Rectangle const old_pos{top_left, window.size()};
2602+
2603+ if (!resizing)
2604+ {
2605+ auto anchor = old_pos.bottom_right();
2606+
2607+ for (auto const& corner : {
2608+ old_pos.top_right(),
2609+ old_pos.bottom_left(),
2610+ top_left})
2611+ {
2612+ if ((old_cursor - anchor).length_squared() <
2613+ (old_cursor - corner).length_squared())
2614+ {
2615+ anchor = corner;
2616+ }
2617+ }
2618+
2619+ left_resize = anchor.x != top_left.x;
2620+ top_resize = anchor.y != top_left.y;
2621+ }
2622+
2623+ int const x_sign = left_resize? -1 : 1;
2624+ int const y_sign = top_resize? -1 : 1;
2625+
2626+ auto movement = cursor-old_cursor;
2627+
2628+ auto new_width = old_pos.size.width + x_sign * movement.dx;
2629+ auto new_height = old_pos.size.height + y_sign * movement.dy;
2630+
2631+ keep_window_within_constraints(window_info, movement, new_width, new_height);
2632+
2633+ Size new_size{new_width, new_height};
2634+ Point new_pos = top_left + left_resize*movement.dx + top_resize*movement.dy;
2635+
2636+ WindowSpecification modifications;
2637+ modifications.top_left() = new_pos;
2638+ modifications.size() = new_size;
2639+ tools.modify_window(window, modifications);
2640+
2641+ return true;
2642+}
2643+
2644+void FloatingWindowManagerPolicy::keep_window_within_constraints(
2645+ WindowInfo const& window_info, Displacement& movement, Width& new_width, Height& new_height) const
2646+{
2647+ switch (window_info.state())
2648+ {
2649+ case mir_window_state_maximized:
2650+ case mir_window_state_fullscreen:
2651+ new_width = window_info.window().size().width;
2652+ new_height = window_info.window().size().height;
2653+ movement = {0, 0};
2654+ break;
2655+
2656+ case mir_window_state_vertmaximized:
2657+ new_height = window_info.window().size().height;
2658+ movement.dy = DeltaY{0};
2659+ break;
2660+
2661+ case mir_window_state_horizmaximized:
2662+ new_width = window_info.window().size().width;
2663+ movement.dx - DeltaX{0};
2664+ break;
2665+
2666+ default:;
2667+ }
2668+
2669+ auto const min_width = std::max(window_info.min_width(), Width{5});
2670+ auto const min_height = std::max(window_info.min_height(), Height{5});
2671+
2672+ if (new_width < min_width)
2673+ {
2674+ new_width = min_width;
2675+ if (movement.dx > DeltaX{0})
2676+ movement.dx = DeltaX{0};
2677+ }
2678+
2679+ if (new_height < min_height)
2680+ {
2681+ new_height = min_height;
2682+ if (movement.dy > DeltaY{0})
2683+ movement.dy = DeltaY{0};
2684+ }
2685+
2686+ auto const max_width = window_info.max_width();
2687+ auto const max_height = window_info.max_height();
2688+
2689+ if (new_width > max_width)
2690+ {
2691+ new_width = max_width;
2692+ if (movement.dx < DeltaX{0})
2693+ movement.dx = DeltaX{0};
2694+ }
2695+
2696+ if (new_height > max_height)
2697+ {
2698+ new_height = max_height;
2699+ if (movement.dy < DeltaY{0})
2700+ movement.dy = DeltaY{0};
2701+ }
2702+}
2703+
2704+WindowSpecification FloatingWindowManagerPolicy::place_new_window(
2705+ ApplicationInfo const& app_info, WindowSpecification const& request_parameters)
2706+{
2707+ auto parameters = CanonicalWindowManagerPolicy::place_new_window(app_info, request_parameters);
2708+
2709+ bool const needs_titlebar = WindowInfo::needs_titlebar(parameters.type().value());
2710+
2711+ if (parameters.state().value() != mir_window_state_fullscreen && needs_titlebar)
2712+ parameters.top_left() = Point{parameters.top_left().value().x, parameters.top_left().value().y + title_bar_height};
2713+
2714+ if (app_info.application() == decoration_provider->session())
2715+ decoration_provider->place_new_decoration(parameters);
2716+
2717+ parameters.userdata() = std::make_shared<PolicyData>();
2718+ return parameters;
2719+}
2720+
2721+void FloatingWindowManagerPolicy::advise_adding_to_workspace(
2722+ std::shared_ptr<Workspace> const& workspace, std::vector<Window> const& windows)
2723+{
2724+ if (windows.empty())
2725+ return;
2726+
2727+ for (auto const& window : windows)
2728+ {
2729+ if (workspace == active_workspace)
2730+ {
2731+ apply_workspace_visible_to(window);
2732+ }
2733+ else
2734+ {
2735+ apply_workspace_hidden_to(window);
2736+ }
2737+ }
2738+}
2739+
2740+auto FloatingWindowManagerPolicy::confirm_placement_on_display(
2741+ miral::WindowInfo const& /*window_info*/, MirWindowState new_state, Rectangle const& new_placement) -> Rectangle
2742+{
2743+ switch (new_state)
2744+ {
2745+ default:
2746+ return new_placement;
2747+
2748+ case mir_window_state_maximized:
2749+ case mir_window_state_vertmaximized:
2750+ auto result = new_placement;
2751+
2752+ result.top_left.y = result.top_left.y + title_bar_height;
2753+ result.size.height = result.size.height - title_bar_height;
2754+ return result;
2755+ }
2756+}
2757+
2758+void FloatingWindowManagerPolicy::switch_workspace_to(
2759+ std::shared_ptr<Workspace> const& workspace,
2760+ Window const& window)
2761+{
2762+ if (workspace == active_workspace)
2763+ return;
2764+
2765+ auto const old_active = active_workspace;
2766+ active_workspace = workspace;
2767+
2768+ auto const old_active_window = tools.active_window();
2769+
2770+ if (!old_active_window)
2771+ {
2772+ // If there's no active window, the first shown grabs focus: get the right one
2773+ if (auto const ww = workspace_to_active[workspace])
2774+ {
2775+ tools.for_each_workspace_containing(ww, [&](std::shared_ptr<miral::Workspace> const& ws)
2776+ {
2777+ if (ws == workspace)
2778+ {
2779+ apply_workspace_visible_to(ww);
2780+ }
2781+ });
2782+ }
2783+ }
2784+
2785+ tools.remove_tree_from_workspace(window, old_active);
2786+ tools.add_tree_to_workspace(window, active_workspace);
2787+
2788+ tools.for_each_window_in_workspace(active_workspace, [&](Window const& window)
2789+ {
2790+ if (decoration_provider->is_decoration(window))
2791+ return; // decorations are taken care of automatically
2792+
2793+ apply_workspace_visible_to(window);
2794+ });
2795+
2796+ bool hide_old_active = false;
2797+ tools.for_each_window_in_workspace(old_active, [&](Window const& window)
2798+ {
2799+ if (decoration_provider->is_decoration(window))
2800+ return; // decorations are taken care of automatically
2801+
2802+ if (window == old_active_window)
2803+ {
2804+ // If we hide the active window focus will shift: do that last
2805+ hide_old_active = true;
2806+ return;
2807+ }
2808+
2809+ apply_workspace_hidden_to(window);
2810+ });
2811+
2812+ if (hide_old_active)
2813+ {
2814+ apply_workspace_hidden_to(old_active_window);
2815+
2816+ // Remember the old active_window when we switch away
2817+ workspace_to_active[old_active] = old_active_window;
2818+ }
2819+}
2820+
2821+void FloatingWindowManagerPolicy::apply_workspace_hidden_to(Window const& window)
2822+{
2823+ auto const& window_info = tools.info_for(window);
2824+ auto& pdata = policy_data_for(window_info);
2825+ if (!pdata.in_hidden_workspace)
2826+ {
2827+ pdata.in_hidden_workspace = true;
2828+ pdata.old_state = window_info.state();
2829+
2830+ WindowSpecification modifications;
2831+ modifications.state() = mir_window_state_hidden;
2832+ tools.place_and_size_for_state(modifications, window_info);
2833+ tools.modify_window(window_info.window(), modifications);
2834+ }
2835+}
2836+
2837+void FloatingWindowManagerPolicy::apply_workspace_visible_to(Window const& window)
2838+{
2839+ auto const& window_info = tools.info_for(window);
2840+ auto& pdata = policy_data_for(window_info);
2841+ if (pdata.in_hidden_workspace)
2842+ {
2843+ pdata.in_hidden_workspace = false;
2844+ WindowSpecification modifications;
2845+ modifications.state() = pdata.old_state;
2846+ tools.place_and_size_for_state(modifications, window_info);
2847+ tools.modify_window(window_info.window(), modifications);
2848+ }
2849+}
2850+
2851+void FloatingWindowManagerPolicy::handle_modify_window(WindowInfo& window_info, WindowSpecification const& modifications)
2852+{
2853+ auto mods = modifications;
2854+
2855+ auto& pdata = policy_data_for(window_info);
2856+
2857+ if (pdata.in_hidden_workspace && mods.state().is_set())
2858+ pdata.old_state = mods.state().consume();
2859+
2860+ CanonicalWindowManagerPolicy::handle_modify_window(window_info, mods);
2861+}
2862+
2863
2864=== added file 'examples/miral-shell/floating_window_manager.h'
2865--- examples/miral-shell/floating_window_manager.h 1970-01-01 00:00:00 +0000
2866+++ examples/miral-shell/floating_window_manager.h 2017-08-23 11:59:25 +0000
2867@@ -0,0 +1,146 @@
2868+/*
2869+ * Copyright © 2016-2017 Canonical Ltd.
2870+ *
2871+ * This program is free software: you can redistribute it and/or modify it
2872+ * under the terms of the GNU General Public License version 2 or 3 as
2873+ * published by the Free Software Foundation.
2874+ *
2875+ * This program is distributed in the hope that it will be useful,
2876+ * but WITHOUT ANY WARRANTY; without even the implied warranty ofb
2877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2878+ * GNU General Public License for more details.
2879+ *
2880+ * You should have received a copy of the GNU General Public License
2881+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2882+ *
2883+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
2884+ */
2885+
2886+#ifndef MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H
2887+#define MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H
2888+
2889+#include <miral/canonical_window_manager.h>
2890+#include <miral/window_management_policy_addendum3.h>
2891+#include <miral/workspace_policy.h>
2892+
2893+
2894+#include "spinner/splash.h"
2895+
2896+#include <chrono>
2897+#include <map>
2898+
2899+namespace miral { class InternalClientLauncher; }
2900+
2901+using namespace mir::geometry;
2902+
2903+class DecorationProvider;
2904+
2905+class FloatingWindowManagerPolicy : public miral::CanonicalWindowManagerPolicy,
2906+ public miral::WorkspacePolicy, public miral::WindowManagementPolicyAddendum3
2907+{
2908+public:
2909+ FloatingWindowManagerPolicy(
2910+ miral::WindowManagerTools const& tools,
2911+ SpinnerSplash const& spinner,
2912+ miral::InternalClientLauncher const& launcher,
2913+ std::function<void()>& shutdown_hook);
2914+ ~FloatingWindowManagerPolicy();
2915+
2916+ virtual miral::WindowSpecification place_new_window(
2917+ miral::ApplicationInfo const& app_info, miral::WindowSpecification const& request_parameters) override;
2918+
2919+ /** @name example event handling:
2920+ * o Switch apps: Alt+Tab, tap or click on the corresponding window
2921+ * o Switch window: Alt+`, tap or click on the corresponding window
2922+ * o Move window: Alt-leftmousebutton drag (three finger drag)
2923+ * o Resize window: Alt-middle_button drag (three finger pinch)
2924+ * o Maximize/restore current window (to display size): Alt-F11
2925+ * o Maximize/restore current window (to display height): Shift-F11
2926+ * o Maximize/restore current window (to display width): Ctrl-F11
2927+ * o Switch workspace . . . . . . . . . . : Meta-Alt-[F1|F2|F3|F4]
2928+ * o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]
2929+ * @{ */
2930+ bool handle_pointer_event(MirPointerEvent const* event) override;
2931+ bool handle_touch_event(MirTouchEvent const* event) override;
2932+ bool handle_keyboard_event(MirKeyboardEvent const* event) override;
2933+ /** @} */
2934+
2935+ /** @name track events that affect titlebar
2936+ * @{ */
2937+ void advise_new_window(miral::WindowInfo const& window_info) override;
2938+ void handle_window_ready(miral::WindowInfo& window_info) override;
2939+ void advise_focus_lost(miral::WindowInfo const& info) override;
2940+ void advise_focus_gained(miral::WindowInfo const& info) override;
2941+ void advise_state_change(miral::WindowInfo const& window_info, MirWindowState state) override;
2942+ void advise_resize(miral::WindowInfo const& window_info, Size const& new_size) override;
2943+ void advise_delete_window(miral::WindowInfo const& window_info) override;
2944+
2945+ void handle_modify_window(miral::WindowInfo& window_info, miral::WindowSpecification const& modifications) override;
2946+ /** @} */
2947+
2948+protected:
2949+ static const int modifier_mask =
2950+ mir_input_event_modifier_alt |
2951+ mir_input_event_modifier_shift |
2952+ mir_input_event_modifier_sym |
2953+ mir_input_event_modifier_ctrl |
2954+ mir_input_event_modifier_meta;
2955+
2956+private:
2957+ void toggle(MirWindowState state);
2958+
2959+ bool resize(miral::Window const& window, Point cursor, Point old_cursor);
2960+
2961+ Point old_cursor{};
2962+
2963+ bool resizing = false;
2964+ bool left_resize = false;
2965+ bool top_resize = false;
2966+
2967+ int old_touch_pinch_top = 0;
2968+ int old_touch_pinch_left = 0;
2969+ int old_touch_pinch_width = 0;
2970+ int old_touch_pinch_height = 0;
2971+ bool pinching = false;
2972+
2973+ SpinnerSplash const spinner;
2974+
2975+ std::unique_ptr<DecorationProvider> const decoration_provider;
2976+
2977+ void end_resize();
2978+
2979+ void keep_window_within_constraints(
2980+ miral::WindowInfo const& window_info,
2981+ Displacement& movement,
2982+ Width& new_width,
2983+ Height& new_height) const;
2984+
2985+ // Workaround for lp:1627697
2986+ std::chrono::steady_clock::time_point last_resize;
2987+
2988+ void advise_adding_to_workspace(
2989+ std::shared_ptr<miral::Workspace> const& workspace,
2990+ std::vector<miral::Window> const& windows) override;
2991+
2992+ auto confirm_placement_on_display(
2993+ miral::WindowInfo const& window_info,
2994+ MirWindowState new_state,
2995+ Rectangle const& new_placement) -> Rectangle override;
2996+
2997+ // Switch workspace, taking window (if not null)
2998+ void switch_workspace_to(
2999+ std::shared_ptr<miral::Workspace> const& workspace,
3000+ miral::Window const& window = miral::Window{});
3001+
3002+ std::shared_ptr<miral::Workspace> active_workspace;
3003+ std::map<int, std::shared_ptr<miral::Workspace>> key_to_workspace;
3004+ std::map<std::shared_ptr<miral::Workspace>, miral::Window> workspace_to_active;
3005+
3006+ void apply_workspace_visible_to(miral::Window const& window);
3007+
3008+ void apply_workspace_hidden_to(miral::Window const& window);
3009+
3010+ void keep_spinner_on_top();
3011+};
3012+
3013+#endif //MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H
3014
3015=== added file 'examples/miral-shell/miral-app.sh'
3016--- examples/miral-shell/miral-app.sh 1970-01-01 00:00:00 +0000
3017+++ examples/miral-shell/miral-app.sh 2017-08-23 11:59:25 +0000
3018@@ -0,0 +1,51 @@
3019+#! /bin/bash
3020+
3021+miral_server=miral-shell
3022+launcher='gnome-terminal --app-id com.canonical.miral.Terminal'
3023+hostsocket=
3024+bindir=$(dirname $0)
3025+
3026+if [ -n "${MIR_SOCKET}" ]
3027+then
3028+ if [ ! -e "${MIR_SOCKET}" ]
3029+ then
3030+ echo "Error: Host endpoint '${MIR_SOCKET}' does not exists"; exit 1
3031+ fi
3032+ hostsocket='--host-socket ${MIR_SOCKET}'
3033+fi
3034+
3035+socket=${XDG_RUNTIME_DIR}/miral_socket
3036+
3037+while [ $# -gt 0 ]
3038+do
3039+ if [ "$1" == "--help" -o "$1" == "-h" ]
3040+ then
3041+ echo "$(basename $0) - Handy launch script for a hosted miral \"desktop session\""
3042+ echo "Usage: $(basename $0) [options] [shell options]"
3043+ echo "Options are:"
3044+ echo " -kiosk use miral-kiosk instead of ${miral_server}"
3045+ echo " -launcher <launcher> use <launcher> instead of '${launcher}'"
3046+ echo " -socket <socket> set the mir socket [${socket}]"
3047+ echo " -bindir <bindir> path to the miral executable [${bindir}]"
3048+ exit 0
3049+ elif [ "$1" == "-kiosk" ]; then miral_server=miral-kiosk
3050+ elif [ "$1" == "-launcher" ]; then shift; launcher=$1
3051+ elif [ "$1" == "-socket" ]; then shift; socket=$1
3052+ elif [ "$1" == "-bindir" ]; then shift; bindir=$1
3053+ elif [ "${1:0:2}" == "--" ]; then break
3054+ fi
3055+ shift
3056+done
3057+
3058+if [ "${bindir}" != "" ]; then bindir="${bindir}/"; fi
3059+
3060+if [ -e "${socket}" ]; then echo "Error: session endpoint '${socket}' already exists"; exit 1 ;fi
3061+
3062+sh -c "${bindir}${miral_server} $* ${hostsocket} --file ${socket} --desktop_file_hint=miral-shell.desktop"&
3063+
3064+while [ ! -e "${socket}" ]; do echo "waiting for ${socket}"; sleep 1 ;done
3065+
3066+unset QT_QPA_PLATFORMTHEME
3067+MIR_SOCKET=${socket} XDG_SESSION_TYPE=mir GDK_BACKEND=mir QT_QPA_PLATFORM=ubuntumirclient SDL_VIDEODRIVER=mir dbus-run-session -- ${launcher}
3068+killall ${bindir}${miral_server}
3069+
3070
3071=== added file 'examples/miral-shell/miral-desktop.sh'
3072--- examples/miral-shell/miral-desktop.sh 1970-01-01 00:00:00 +0000
3073+++ examples/miral-shell/miral-desktop.sh 2017-08-23 11:59:25 +0000
3074@@ -0,0 +1,45 @@
3075+#! /bin/bash
3076+
3077+socket=${XDG_RUNTIME_DIR}/miral_socket
3078+miral_server=miral-shell
3079+launcher='gnome-terminal --app-id com.canonical.miral.Terminal'
3080+bindir=$(dirname $0)
3081+vt=4
3082+
3083+while [ $# -gt 0 ]
3084+do
3085+ if [ "$1" == "--help" -o "$1" == "-h" ]
3086+ then
3087+ echo "$(basename $0) - Handy launch script for a miral \"desktop session\""
3088+ echo "Usage: $(basename $0) [options] [shell options]"
3089+ echo "Options are:"
3090+ echo " -kiosk use miral-kiosk instead of ${miral_server}"
3091+ echo " -launcher <launcher> use <launcher> instead of '${launcher}'"
3092+ echo " -vt <termid> set the virtual terminal [${vt}]"
3093+ echo " -socket <socket> set the mir socket [${socket}]"
3094+ echo " -bindir <bindir> path to the miral executable [${bindir}]"
3095+ exit 0
3096+ elif [ "$1" == "-kiosk" ]; then miral_server=miral-kiosk
3097+ elif [ "$1" == "-launcher" ]; then shift; launcher=$1
3098+ elif [ "$1" == "-vt" ]; then shift; vt=$1
3099+ elif [ "$1" == "-socket" ]; then shift; socket=$1
3100+ elif [ "$1" == "-bindir" ]; then shift; bindir=$1/
3101+ elif [ "${1:0:2}" == "--" ]; then break
3102+ fi
3103+ shift
3104+done
3105+
3106+if [ "${bindir}" != "" ]; then bindir="${bindir}/"; fi
3107+
3108+if [ -e "${socket}" ]; then echo "Error: '${socket}' already exists"; exit 1 ;fi
3109+
3110+sudo ls >> /dev/null
3111+oldvt=$(sudo fgconsole)
3112+sudo sh -c "LD_LIBRARY_PATH=${LD_LIBRARY_PATH} ${bindir}${miral_server} --vt ${vt} --arw-file --file ${socket} $*; chvt ${oldvt}"&
3113+
3114+while [ ! -e "${socket}" ]; do echo "waiting for ${socket}"; sleep 1 ;done
3115+
3116+unset QT_QPA_PLATFORMTHEME
3117+MIR_SOCKET=${socket} XDG_SESSION_TYPE=mir GDK_BACKEND=mir QT_QPA_PLATFORM=ubuntumirclient SDL_VIDEODRIVER=mir dbus-run-session -- ${launcher}
3118+sudo killall ${bindir}${miral_server}
3119+
3120
3121=== added file 'examples/miral-shell/miral-run.sh'
3122--- examples/miral-shell/miral-run.sh 1970-01-01 00:00:00 +0000
3123+++ examples/miral-shell/miral-run.sh 2017-08-23 11:59:25 +0000
3124@@ -0,0 +1,17 @@
3125+#!/bin/sh
3126+
3127+if [ -e "${XDG_RUNTIME_DIR}/miral_socket" ];
3128+then
3129+ socket=${XDG_RUNTIME_DIR}/miral_socket
3130+elif [ -e "${XDG_RUNTIME_DIR}/mir_socket" ];
3131+then
3132+ socket=${XDG_RUNTIME_DIR}/mir_socket
3133+else
3134+ echo "Error: Cannot detect Mir endpoint"; exit 1
3135+fi
3136+
3137+if [ "$1" = "gnome-terminal" ]
3138+then extras='--app-id com.canonical.miral.Terminal'
3139+fi
3140+unset QT_QPA_PLATFORMTHEME
3141+MIR_SOCKET=${socket} XDG_SESSION_TYPE=mir GDK_BACKEND=mir QT_QPA_PLATFORM=ubuntumirclient SDL_VIDEODRIVER=mir "$@" ${extras}&
3142
3143=== added file 'examples/miral-shell/miral-screencast.sh'
3144--- examples/miral-shell/miral-screencast.sh 1970-01-01 00:00:00 +0000
3145+++ examples/miral-shell/miral-screencast.sh 2017-08-23 11:59:25 +0000
3146@@ -0,0 +1,48 @@
3147+#!/bin/bash
3148+width=1920
3149+height=1080
3150+output=screencast.mp4
3151+socket=${XDG_RUNTIME_DIR}/miral_socket
3152+if [ -v MIR_SERVER ]; then socket=${MIR_SERVER}; fi
3153+
3154+while [ $# -gt 0 ]
3155+do
3156+ if [ "$1" == "--help" -o "$1" == "-h" ]
3157+ then
3158+ echo "$(basename $0) - screencast capture script for use with Mir servers"
3159+ echo "Usage: $0 [options]"
3160+ echo "Options are:"
3161+ echo " --width set the capture width [${width}]"
3162+ echo " --height set the capture height [${height}]"
3163+ echo " --output set the output filename [${output}]"
3164+ echo " --socket set the mir socket [${socket}]"
3165+ echo " --tmpfile specify the temporary work file"
3166+ exit 0
3167+ elif [ "$1" == "--socket" ]; then shift; socket=$1
3168+ elif [ "$1" == "--output" ]; then shift; output=$1
3169+ elif [ "$1" == "--width" ]; then shift; width=$1
3170+ elif [ "$1" == "--height" ]; then shift; height=$1
3171+ elif [ "$1" == "--tmpfile" ]; then shift; tempfile=$1
3172+ fi
3173+ shift
3174+done
3175+
3176+echo width = ${width}
3177+echo height = ${height}
3178+echo output = ${output}
3179+echo socket = ${socket}
3180+
3181+if ! which mirscreencast >> /dev/null ; then echo "Need mirscreencast - run \"sudo apt install mir-utils\""; exit 1 ;fi
3182+if ! which mencoder >> /dev/null ; then echo "Need mencoder - run \"sudo apt install mencoder\""; exit 1 ;fi
3183+
3184+if [ -e ${output} ]; then echo "Output exists, moving to ${output}~"; mv ${output} ${output}~ ;fi
3185+while [ ! -e "${socket}" ]; do echo "waiting for ${socket}"; sleep 1 ;done
3186+
3187+if [ ! -v tempfile ]; then tempfile=$(mktemp); fi
3188+mirscreencast --size ${width} ${height} -m ${socket} -f ${tempfile}& mirscreencast_pid=$!
3189+trap 'kill ${mirscreencast_pid}; rm -f -- "${tempfile}"; exit 0' INT TERM HUP EXIT
3190+
3191+sleep 1; # don't lose the next message in the spew from mirscreencast
3192+read -rsp $'\n\nPress enter when recording complete...'
3193+
3194+mencoder -demuxer rawvideo -rawvideo fps=60:w=${width}:h=${height}:format=bgra -ovc x264 -o ${output} ${tempfile}
3195
3196=== added file 'examples/miral-shell/miral-xrun.sh'
3197--- examples/miral-shell/miral-xrun.sh 1970-01-01 00:00:00 +0000
3198+++ examples/miral-shell/miral-xrun.sh 2017-08-23 11:59:25 +0000
3199@@ -0,0 +1,45 @@
3200+#!/bin/bash
3201+port=0
3202+
3203+while [ -e "/tmp/.X11-unix/X${port}" ]; do
3204+ let port+=1
3205+done
3206+
3207+unset QT_QPA_PLATFORMTHEME
3208+unset GDK_BACKEND
3209+unset QT_QPA_PLATFORM
3210+unset SDL_VIDEODRIVER
3211+
3212+if [ -e "${XDG_RUNTIME_DIR}/miral_socket" ];
3213+then
3214+ socket=${XDG_RUNTIME_DIR}/miral_socket
3215+elif [ -e "${XDG_RUNTIME_DIR}/mir_socket" ];
3216+then
3217+ socket=${XDG_RUNTIME_DIR}/mir_socket
3218+else
3219+ echo "Error: Cannot detect Mir endpoint"; exit 1
3220+fi
3221+
3222+while [ $# -gt 0 ]
3223+do
3224+ if [ "$1" == "--help" -o "$1" == "-h" ]
3225+ then
3226+ echo "$(basename $0) - Handy launch script for providing an Xmir X11 server"
3227+ echo "Usage: $(basename $0) [options] command"
3228+ echo "Options are:"
3229+ echo " -force set toolkit environment variables to force X11 use"
3230+ exit 0
3231+ elif [ "$1" == "-force" ];
3232+ then
3233+ export XDG_SESSION_TYPE=x11
3234+ export GDK_BACKEND=x11
3235+ export QT_QPA_PLATFORM=xcb
3236+ export SDL_VIDEODRIVER=x11
3237+ else break
3238+ fi
3239+ shift
3240+done
3241+
3242+MIR_SOCKET=${socket} Xmir -rootless :${port} & pid=$!
3243+DISPLAY=:${port} "$@"
3244+kill ${pid}
3245
3246=== added file 'examples/miral-shell/shell_main.cpp'
3247--- examples/miral-shell/shell_main.cpp 1970-01-01 00:00:00 +0000
3248+++ examples/miral-shell/shell_main.cpp 2017-08-23 11:59:25 +0000
3249@@ -0,0 +1,98 @@
3250+/*
3251+ * Copyright © 2016-2017 Canonical Ltd.
3252+ *
3253+ * This program is free software: you can redistribute it and/or modify
3254+ * under the terms of the GNU General Public License version 2 or 3 as as
3255+ * published by the Free Software Foundation.
3256+ *
3257+ * This program is distributed in the hope that it will be useful,
3258+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3259+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3260+ * GNU General Public License for more details.
3261+ *
3262+ * You should have received a copy of the GNU General Public License
3263+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3264+ *
3265+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
3266+ */
3267+
3268+#include "tiling_window_manager.h"
3269+#include "floating_window_manager.h"
3270+#include "titlebar_config.h"
3271+#include "spinner/splash.h"
3272+
3273+#include <miral/display_configuration_option.h>
3274+#include <miral/runner.h>
3275+#include <miral/window_management_options.h>
3276+#include <miral/append_event_filter.h>
3277+#include <miral/debug_extension.h>
3278+#include <miral/internal_client.h>
3279+#include <miral/command_line_option.h>
3280+#include <miral/cursor_theme.h>
3281+#include <miral/keymap.h>
3282+
3283+#include <linux/input.h>
3284+
3285+int main(int argc, char const* argv[])
3286+{
3287+ using namespace miral;
3288+
3289+ std::function<void()> shutdown_hook{[]{}};
3290+
3291+ SpinnerSplash spinner;
3292+ InternalClientLauncher launcher;
3293+ ActiveOutputsMonitor outputs_monitor;
3294+ WindowManagerOptions window_managers
3295+ {
3296+ add_window_manager_policy<FloatingWindowManagerPolicy>("floating", spinner, launcher, shutdown_hook),
3297+ add_window_manager_policy<TilingWindowManagerPolicy>("tiling", spinner, launcher, outputs_monitor),
3298+ };
3299+
3300+ MirRunner runner{argc, argv};
3301+
3302+ runner.add_stop_callback([&] { shutdown_hook(); });
3303+
3304+ auto const quit_on_ctrl_alt_bksp = [&](MirEvent const* event)
3305+ {
3306+ if (mir_event_get_type(event) != mir_event_type_input)
3307+ return false;
3308+
3309+ MirInputEvent const* input_event = mir_event_get_input_event(event);
3310+ if (mir_input_event_get_type(input_event) != mir_input_event_type_key)
3311+ return false;
3312+
3313+ MirKeyboardEvent const* kev = mir_input_event_get_keyboard_event(input_event);
3314+ if (mir_keyboard_event_action(kev) != mir_keyboard_action_down)
3315+ return false;
3316+
3317+ MirInputEventModifiers mods = mir_keyboard_event_modifiers(kev);
3318+ if (!(mods & mir_input_event_modifier_alt) || !(mods & mir_input_event_modifier_ctrl))
3319+ return false;
3320+
3321+ if (mir_keyboard_event_scan_code(kev) != KEY_BACKSPACE)
3322+ return false;
3323+
3324+ runner.stop();
3325+ return true;
3326+ };
3327+
3328+ Keymap config_keymap;
3329+ DebugExtension debug_extensions;
3330+
3331+ return runner.run_with(
3332+ {
3333+ CommandLineOption{[&](std::string const& ) { },
3334+ "desktop_file_hint", "Ignored for Unity8 compatibility", "miral-shell.desktop"},
3335+ CursorTheme{"DMZ-White"},
3336+ window_managers,
3337+ display_configuration_options,
3338+ launcher,
3339+ outputs_monitor,
3340+ config_keymap,
3341+ debug_extensions,
3342+ AppendEventFilter{quit_on_ctrl_alt_bksp},
3343+ StartupInternalClient{"Intro", spinner},
3344+ pre_init(CommandLineOption{[&](std::string const& typeface) { ::titlebar::font_file(typeface); },
3345+ "shell-titlebar-font", "font file to use for titlebars", ::titlebar::font_file()})
3346+ });
3347+}
3348
3349=== added directory 'examples/miral-shell/spinner'
3350=== added file 'examples/miral-shell/spinner/CMakeLists.txt'
3351--- examples/miral-shell/spinner/CMakeLists.txt 1970-01-01 00:00:00 +0000
3352+++ examples/miral-shell/spinner/CMakeLists.txt 2017-08-23 11:59:25 +0000
3353@@ -0,0 +1,67 @@
3354+# -*- Mode: CMake; indent-tabs-mode: nil; tab-width: 2 -*-
3355+#
3356+# Copyright © 2014 Canonical Ltd.
3357+#
3358+# This program is free software: you can redistribute it and/or modify
3359+# it under the terms of the GNU General Public License version 3 as
3360+# published by the Free Software Foundation.
3361+#
3362+# This program is distributed in the hope that it will be useful,
3363+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3364+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3365+# GNU General Public License for more details.
3366+#
3367+# You should have received a copy of the GNU General Public License
3368+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3369+
3370+pkg_check_modules(GLIB REQUIRED glib-2.0)
3371+find_package(GLESv2 REQUIRED)
3372+find_package(PIL REQUIRED)
3373+
3374+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overlength-strings")
3375+
3376+
3377+function(png2header png header varname)
3378+ add_custom_command(
3379+ OUTPUT ${header}
3380+ COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/png2header.py ${png} ${varname} > ${header}
3381+ DEPENDS ${png} ${CMAKE_CURRENT_SOURCE_DIR}/png2header.py
3382+ )
3383+endfunction()
3384+
3385+png2header(
3386+ ${CMAKE_CURRENT_SOURCE_DIR}/spinner-glow.png
3387+ ${CMAKE_CURRENT_BINARY_DIR}/spinner_glow.h
3388+ spinner_glow
3389+)
3390+
3391+png2header(
3392+ ${CMAKE_CURRENT_SOURCE_DIR}/spinner-logo.png
3393+ ${CMAKE_CURRENT_BINARY_DIR}/spinner_logo.h
3394+ spinner_logo
3395+)
3396+
3397+include_directories(
3398+ ${GLIB_INCLUDE_DIRS}
3399+ ${GLESv2_INCLUDE_DIRS}
3400+ ${CMAKE_CURRENT_BINARY_DIR}
3401+)
3402+
3403+add_library(miral-spinner STATIC
3404+ eglapp.cpp
3405+ eglapp.h
3406+ eglspinner.cpp
3407+ miregl.h
3408+ miregl.cpp
3409+ splash.h
3410+ ${CMAKE_CURRENT_BINARY_DIR}/spinner_logo.h
3411+ ${CMAKE_CURRENT_BINARY_DIR}/spinner_glow.h
3412+)
3413+
3414+target_link_libraries(miral-spinner
3415+ mirclientcpp
3416+ EGL
3417+ ${GLIB_LDFLAGS}
3418+ ${GLESv2_LIBRARIES}
3419+ ${MIRCLIENT_LDFLAGS}
3420+)
3421
3422=== added file 'examples/miral-shell/spinner/eglapp.cpp'
3423--- examples/miral-shell/spinner/eglapp.cpp 1970-01-01 00:00:00 +0000
3424+++ examples/miral-shell/spinner/eglapp.cpp 2017-08-23 11:59:25 +0000
3425@@ -0,0 +1,83 @@
3426+/*
3427+ * Copyright © 2013, 2015 Canonical Ltd.
3428+ *
3429+ * This program is free software: you can redistribute it and/or modify
3430+ * under the terms of the GNU General Public License version 2 or 3 as as
3431+ * published by the Free Software Foundation.
3432+ *
3433+ * This program is distributed in the hope that it will be useful,
3434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3436+ * GNU General Public License for more details.
3437+ *
3438+ * You should have received a copy of the GNU General Public License
3439+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3440+ */
3441+
3442+#include "eglapp.h"
3443+
3444+#include <mir/client/display_config.h>
3445+
3446+#include "miregl.h"
3447+
3448+
3449+float mir_eglapp_background_opacity = 1.0f;
3450+
3451+
3452+namespace
3453+{
3454+MirPixelFormat select_pixel_format(MirConnection* connection)
3455+{
3456+ unsigned int format[mir_pixel_formats];
3457+ unsigned int nformats;
3458+
3459+ mir_connection_get_available_surface_formats(
3460+ connection,
3461+ (MirPixelFormat*) format,
3462+ mir_pixel_formats,
3463+ &nformats);
3464+
3465+ auto const pixel_format = (MirPixelFormat) format[0];
3466+
3467+ printf("Server supports %d of %d surface pixel formats. Using format: %d\n",
3468+ nformats, mir_pixel_formats, pixel_format);
3469+
3470+ return pixel_format;
3471+}
3472+}
3473+
3474+std::vector<std::shared_ptr<MirEglSurface>> mir_eglapp_init(MirConnection* const connection)
3475+{
3476+ char const * const name = "eglappsurface";
3477+
3478+ if (!mir_connection_is_valid(connection))
3479+ throw std::runtime_error("Can't get connection");
3480+
3481+ auto const pixel_format = select_pixel_format(connection);
3482+
3483+ auto const mir_egl_app = make_mir_eglapp(connection, pixel_format);
3484+
3485+ std::vector<std::shared_ptr<MirEglSurface>> result;
3486+
3487+ mir::client::DisplayConfig{connection}.for_each_output([&](MirOutput const* output)
3488+ {
3489+ if (mir_output_get_connection_state(output) == mir_output_connection_state_connected &&
3490+ mir_output_is_enabled(output))
3491+ {
3492+ auto const mode = mir_output_get_current_mode(output);
3493+ auto const output_id = mir_output_get_id(output);
3494+
3495+ printf("Active output [%u] at (%d, %d) is %dx%d\n",
3496+ output_id,
3497+ mir_output_get_position_x(output), mir_output_get_position_y(output),
3498+ mir_output_mode_get_width(mode), mir_output_mode_get_height(mode));
3499+
3500+ result.push_back(std::make_shared<MirEglSurface>(mir_egl_app, name, output));
3501+ }
3502+ });
3503+
3504+ if (result.empty())
3505+ throw std::runtime_error("No active outputs found.");
3506+
3507+ return result;
3508+}
3509
3510=== added file 'examples/miral-shell/spinner/eglapp.h'
3511--- examples/miral-shell/spinner/eglapp.h 1970-01-01 00:00:00 +0000
3512+++ examples/miral-shell/spinner/eglapp.h 2017-08-23 11:59:25 +0000
3513@@ -0,0 +1,33 @@
3514+/*
3515+ * Copyright © 2013 Canonical Ltd.
3516+ *
3517+ * This program is free software: you can redistribute it and/or modify
3518+ * under the terms of the GNU General Public License version 2 or 3 as as
3519+ * published by the Free Software Foundation.
3520+ *
3521+ * This program is distributed in the hope that it will be useful,
3522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3524+ * GNU General Public License for more details.
3525+ *
3526+ * You should have received a copy of the GNU General Public License
3527+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3528+ *
3529+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
3530+ */
3531+
3532+#ifndef __EGLAPP_H__
3533+#define __EGLAPP_H__
3534+
3535+#include <mir_toolkit/client_types.h>
3536+
3537+#include <memory>
3538+#include <vector>
3539+
3540+class MirEglSurface;
3541+
3542+extern float mir_eglapp_background_opacity;
3543+
3544+std::vector<std::shared_ptr<MirEglSurface>> mir_eglapp_init(MirConnection* const connection);
3545+
3546+#endif
3547
3548=== added file 'examples/miral-shell/spinner/eglspinner.cpp'
3549--- examples/miral-shell/spinner/eglspinner.cpp 1970-01-01 00:00:00 +0000
3550+++ examples/miral-shell/spinner/eglspinner.cpp 2017-08-23 11:59:25 +0000
3551@@ -0,0 +1,372 @@
3552+/*
3553+ * Copyright © 2013-2015 Canonical Ltd.
3554+ *
3555+ * This program is free software: you can redistribute it and/or modify
3556+ * under the terms of the GNU General Public License version 2 or 3 as as
3557+ * published by the Free Software Foundation.
3558+ *
3559+ * This program is distributed in the hope that it will be useful,
3560+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3561+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3562+ * GNU General Public License for more details.
3563+ *
3564+ * You should have received a copy of the GNU General Public License
3565+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3566+ *
3567+ * Authors: Daniel van Vugt <daniel.van.vugt@canonical.com>
3568+ * Mirco Müller <mirco.mueller@canonical.com>
3569+ * Alan Griffiths <alan@octopull.co.uk>
3570+ * Kevin DuBois <kevin.dubois@canonical.com>
3571+ */
3572+
3573+#include "splash.h"
3574+
3575+#include <chrono>
3576+
3577+#include "eglapp.h"
3578+#include "miregl.h"
3579+#include <assert.h>
3580+#include <glib.h>
3581+#include <string.h>
3582+#include <GLES2/gl2.h>
3583+#include <sys/stat.h>
3584+#include <signal.h>
3585+#include <atomic>
3586+#include <mutex>
3587+
3588+#include <mir_toolkit/mir_client_library.h>
3589+
3590+#include "spinner_glow.h"
3591+#include "spinner_logo.h"
3592+
3593+static GLuint load_shader(const char *src, GLenum type)
3594+{
3595+ GLuint shader = glCreateShader(type);
3596+ if (shader)
3597+ {
3598+ GLint compiled;
3599+ glShaderSource(shader, 1, &src, NULL);
3600+ glCompileShader(shader);
3601+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
3602+ if (!compiled)
3603+ {
3604+ GLchar log[1024];
3605+ glGetShaderInfoLog(shader, sizeof log - 1, NULL, log);
3606+ log[sizeof log - 1] = '\0';
3607+ printf("load_shader compile failed: %s\n", log);
3608+ glDeleteShader(shader);
3609+ shader = 0;
3610+ }
3611+ }
3612+ return shader;
3613+}
3614+
3615+// Colours from http://design.ubuntu.com/brand/colour-palette
3616+//#define MID_AUBERGINE 0.368627451f, 0.152941176f, 0.31372549f
3617+//#define ORANGE 0.866666667f, 0.282352941f, 0.141414141f
3618+//#define WARM_GREY 0.682352941f, 0.654901961f, 0.623529412f
3619+//#define COOL_GREY 0.2f, 0.2f, 0.2f
3620+#define LIGHT_AUBERGINE 0.466666667f, 0.297297297f, 0.435294118f
3621+//#define DARK_AUBERGINE 0.17254902f, 0.0f, 0.117647059f
3622+//#define BLACK 0.0f, 0.0f, 0.0f
3623+//#define WHITE 1.0f, 1.0f, 1.0f
3624+
3625+template <typename Image>
3626+void uploadTexture (GLuint id, Image& image)
3627+{
3628+ glBindTexture(GL_TEXTURE_2D, id);
3629+
3630+ glTexImage2D(GL_TEXTURE_2D,
3631+ 0,
3632+ GL_RGBA,
3633+ image.width,
3634+ image.height,
3635+ 0,
3636+ GL_RGBA,
3637+ GL_UNSIGNED_BYTE,
3638+ image.pixel_data);
3639+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3640+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3641+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3642+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3643+ glBindTexture(GL_TEXTURE_2D, 0);
3644+}
3645+
3646+GLuint createShaderProgram(const char* vertexShaderSrc, const char* fragmentShaderSrc)
3647+{
3648+ if (!vertexShaderSrc || !fragmentShaderSrc)
3649+ return 0;
3650+
3651+ GLuint vShaderId = 0;
3652+ vShaderId = load_shader(vertexShaderSrc, GL_VERTEX_SHADER);
3653+ assert(vShaderId);
3654+
3655+ GLuint fShaderId = 0;
3656+ fShaderId = load_shader(fragmentShaderSrc, GL_FRAGMENT_SHADER);
3657+ assert(fShaderId);
3658+
3659+ GLuint progId = 0;
3660+ progId = glCreateProgram();
3661+ assert(progId);
3662+ glAttachShader(progId, vShaderId);
3663+ glAttachShader(progId, fShaderId);
3664+ glLinkProgram(progId);
3665+
3666+ GLint linked = 0;
3667+ glGetProgramiv(progId, GL_LINK_STATUS, &linked);
3668+ if (!linked)
3669+ {
3670+ GLchar log[1024];
3671+ glGetProgramInfoLog(progId, sizeof log - 1, NULL, log);
3672+ log[sizeof log - 1] = '\0';
3673+ printf("Link failed: %s\n", log);
3674+ return 0;
3675+ }
3676+
3677+ return progId;
3678+}
3679+
3680+typedef struct _AnimationValues
3681+{
3682+ double lastTimeStamp;
3683+ GLfloat angle;
3684+ GLfloat fadeBackground;
3685+ GLfloat fadeLogo;
3686+ GLfloat fadeGlow;
3687+} AnimationValues;
3688+
3689+bool updateAnimation (GTimer* timer, AnimationValues* anim)
3690+{
3691+ if (!timer || !anim)
3692+ return false;
3693+
3694+ //1.) 0.0 - 0.6: logo fades in fully
3695+ //2.) 0.0 - 6.0: logo does one full spin 360°
3696+ //3.) 6.0 - 6.833: glow fades in fully, black-background fades out to 50%
3697+ //4.) 6.833 - 7.666: glow fades out fully, black-background fades out to 0%
3698+ //5.) 7.666 - 8.266: logo fades out fully
3699+ //8.266..: now spinner can be closed as all its elements are faded out
3700+
3701+ // Hacked to run three times as fast
3702+ double elapsed = 3*g_timer_elapsed (timer, NULL);
3703+ double dt = elapsed - anim->lastTimeStamp;
3704+ anim->lastTimeStamp = elapsed;
3705+
3706+ // step 1.)
3707+ if (elapsed < 0.6f)
3708+ anim->fadeLogo += 1.6f * dt;
3709+
3710+ // step 2.)
3711+ anim->angle -= (0.017453292519943f * 360.0f / 18.0f) * dt;
3712+
3713+ // step 3.) glow
3714+ if (elapsed > 6.0f && elapsed < 6.833f)
3715+ anim->fadeGlow += 1.2f * dt;
3716+
3717+ // step 3.) background
3718+ if (elapsed > 0.6f && elapsed < 6.833f)
3719+ { if (anim->fadeBackground > 0) anim->fadeBackground -= 0.15f * dt; else anim->fadeBackground = 0; }
3720+
3721+ // step 4.) glow
3722+ if (elapsed > 7.0f)
3723+ anim->fadeGlow -= 0.6f * dt;
3724+
3725+ // step 5.)
3726+ if (elapsed > 6.833f)
3727+ anim->fadeLogo -= 1.6f * dt;
3728+
3729+ return elapsed < 8.266f;
3730+}
3731+
3732+namespace
3733+{
3734+const char vShaderSrcSpinner[] =
3735+ "attribute vec4 vPosition; \n"
3736+ "attribute vec2 aTexCoords; \n"
3737+ "uniform float theta; \n"
3738+ "varying vec2 vTexCoords; \n"
3739+ "void main() \n"
3740+ "{ \n"
3741+ " float c = cos(theta); \n"
3742+ " float s = sin(theta); \n"
3743+ " mat2 m; \n"
3744+ " m[0] = vec2(c, s); \n"
3745+ " m[1] = vec2(-s, c); \n"
3746+ " vTexCoords = m * aTexCoords + vec2 (0.5, 0.5); \n"
3747+ " gl_Position = vec4(vPosition.xy, -1.0, 1.0); \n"
3748+ "} \n";
3749+
3750+const char fShaderSrcGlow[] =
3751+ "precision mediump float; \n"
3752+ "varying vec2 vTexCoords; \n"
3753+ "uniform sampler2D uSampler; \n"
3754+ "uniform float uFadeGlow; \n"
3755+ "void main() \n"
3756+ "{ \n"
3757+ " vec4 col = texture2D(uSampler, vTexCoords); \n"
3758+ " col = col * uFadeGlow; \n"
3759+ " gl_FragColor = col; \n"
3760+ "} \n";
3761+
3762+const char fShaderSrcLogo[] =
3763+ "precision mediump float; \n"
3764+ "varying vec2 vTexCoords; \n"
3765+ "uniform sampler2D uSampler; \n"
3766+ "uniform float uFadeLogo; \n"
3767+ "void main() \n"
3768+ "{ \n"
3769+ " vec4 col = texture2D(uSampler, vTexCoords); \n"
3770+ " col = col * uFadeLogo; \n"
3771+ " gl_FragColor = col; \n"
3772+ "} \n";
3773+
3774+std::atomic<bool> dying{false};
3775+void lifecycle_event_callback(MirConnection* /*connection*/, MirLifecycleState state, void* context)
3776+{
3777+ if (state == mir_lifecycle_connection_lost)
3778+ static_cast<decltype(dying)*>(context)->store(true);
3779+}
3780+}
3781+
3782+struct SpinnerSplash::Self
3783+{
3784+ std::mutex mutex;
3785+ std::weak_ptr<mir::scene::Session> session;
3786+};
3787+
3788+SpinnerSplash::SpinnerSplash() : self{std::make_shared<Self>()} {}
3789+
3790+SpinnerSplash::~SpinnerSplash() = default;
3791+
3792+void SpinnerSplash::operator()(std::weak_ptr<mir::scene::Session> const& session)
3793+{
3794+ std::lock_guard<decltype(self->mutex)> lock{self->mutex};
3795+ self->session = session;
3796+}
3797+
3798+auto SpinnerSplash::session() const
3799+-> std::shared_ptr<mir::scene::Session>
3800+{
3801+ std::lock_guard<decltype(self->mutex)> lock{self->mutex};
3802+ return self->session.lock();
3803+}
3804+
3805+void SpinnerSplash::operator()(MirConnection* const connection)
3806+try
3807+{
3808+ GLuint prog[2];
3809+ GLuint texture[2];
3810+ GLint vpos[2];
3811+ GLint theta;
3812+ GLint fadeGlow;
3813+ GLint fadeLogo;
3814+ GLint aTexCoords[2];
3815+ GLint sampler[2];
3816+
3817+ mir_connection_set_lifecycle_event_callback(connection, &lifecycle_event_callback, &dying);
3818+ auto const windows = mir_eglapp_init(connection);
3819+
3820+ if (!windows.size()) return;
3821+
3822+ double pixelSize = 10 * 11.18;
3823+ const GLfloat texCoordsSpinner[] =
3824+ {
3825+ -0.5f, 0.5f,
3826+ -0.5f, -0.5f,
3827+ 0.5f, 0.5f,
3828+ 0.5f, -0.5f,
3829+ };
3830+
3831+ prog[0] = createShaderProgram(vShaderSrcSpinner, fShaderSrcGlow);
3832+ prog[1] = createShaderProgram(vShaderSrcSpinner, fShaderSrcLogo);
3833+
3834+ // setup proper GL-blending
3835+ glEnable(GL_BLEND);
3836+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
3837+ glBlendEquation(GL_FUNC_ADD);
3838+
3839+ // get locations of shader-attributes/uniforms
3840+ vpos[0] = glGetAttribLocation(prog[0], "vPosition");
3841+ aTexCoords[0] = glGetAttribLocation(prog[0], "aTexCoords");
3842+ theta = glGetUniformLocation(prog[0], "theta");
3843+ sampler[0] = glGetUniformLocation(prog[0], "uSampler");
3844+ fadeGlow = glGetUniformLocation(prog[0], "uFadeGlow");
3845+ vpos[1] = glGetAttribLocation(prog[1], "vPosition");
3846+ aTexCoords[1] = glGetAttribLocation(prog[1], "aTexCoords");
3847+ sampler[1] = glGetUniformLocation(prog[1], "uSampler");
3848+ fadeLogo = glGetUniformLocation(prog[1], "uFadeLogo");
3849+
3850+ // create and upload spinner-artwork
3851+ // note that the embedded image data has pre-multiplied alpha
3852+ glGenTextures(2, texture);
3853+ uploadTexture(texture[0], spinner_glow);
3854+ uploadTexture(texture[1], spinner_logo);
3855+
3856+ // bunch of shader-attributes to enable
3857+ glVertexAttribPointer(aTexCoords[0], 2, GL_FLOAT, GL_FALSE, 0, texCoordsSpinner);
3858+ glVertexAttribPointer(aTexCoords[1], 2, GL_FLOAT, GL_FALSE, 0, texCoordsSpinner);
3859+ glEnableVertexAttribArray(vpos[0]);
3860+ glEnableVertexAttribArray(vpos[1]);
3861+ glEnableVertexAttribArray(aTexCoords[0]);
3862+ glEnableVertexAttribArray(aTexCoords[1]);
3863+ glActiveTexture(GL_TEXTURE0);
3864+
3865+ AnimationValues anim = {0.0, 0.0, 1.0, 0.0, 0.0};
3866+ GTimer* timer = g_timer_new();
3867+
3868+ do
3869+ {
3870+ for (auto const& surface : windows)
3871+ surface->paint([&](unsigned int width, unsigned int height)
3872+ {
3873+ GLfloat halfRealWidth = ((2.0 / width) * pixelSize) / 2.0;
3874+ GLfloat halfRealHeight = ((2.0 / height) * pixelSize) / 2.0;
3875+
3876+ const GLfloat vertices[] =
3877+ {
3878+ halfRealWidth, halfRealHeight,
3879+ halfRealWidth, -halfRealHeight,
3880+ -halfRealWidth, halfRealHeight,
3881+ -halfRealWidth,-halfRealHeight,
3882+ };
3883+
3884+ glVertexAttribPointer(vpos[0], 2, GL_FLOAT, GL_FALSE, 0, vertices);
3885+ glVertexAttribPointer(vpos[1], 2, GL_FLOAT, GL_FALSE, 0, vertices);
3886+
3887+ glViewport(0, 0, width, height);
3888+
3889+ GLfloat color[] = {LIGHT_AUBERGINE};
3890+ for (auto& c : color) { c*= anim.fadeBackground; }
3891+
3892+ glClearColor(color[0], color[1], color[2], anim.fadeBackground);
3893+ glClear(GL_COLOR_BUFFER_BIT);
3894+
3895+ // draw glow
3896+ glUseProgram(prog[0]);
3897+ glBindTexture(GL_TEXTURE_2D, texture[0]);
3898+ glUniform1i(sampler[0], 0);
3899+ glUniform1f(theta, anim.angle);
3900+ glUniform1f(fadeGlow, anim.fadeGlow);
3901+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3902+
3903+ // draw logo
3904+ glUseProgram(prog[1]);
3905+ glBindTexture(GL_TEXTURE_2D, texture[1]);
3906+ glUniform1i(sampler[1], 0);
3907+ glUniform1f(theta, anim.angle);
3908+ glUniform1f(fadeLogo, anim.fadeLogo);
3909+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3910+ });
3911+
3912+ if (dying.load())
3913+ throw std::runtime_error("Server disconnected");
3914+ }
3915+ while (updateAnimation(timer, &anim));
3916+
3917+ glDeleteTextures(2, texture);
3918+ g_timer_destroy (timer);
3919+}
3920+catch (std::exception const& x)
3921+{
3922+ printf("%s\n", x.what());
3923+}
3924
3925=== added file 'examples/miral-shell/spinner/miregl.cpp'
3926--- examples/miral-shell/spinner/miregl.cpp 1970-01-01 00:00:00 +0000
3927+++ examples/miral-shell/spinner/miregl.cpp 2017-08-23 11:59:25 +0000
3928@@ -0,0 +1,239 @@
3929+/*
3930+ * Copyright © 2015 Canonical Ltd.
3931+ *
3932+ * This program is free software: you can redistribute it and/or modify
3933+ * under the terms of the GNU General Public License version 2 or 3 as as
3934+ * published by the Free Software Foundation.
3935+ *
3936+ * This program is distributed in the hope that it will be useful,
3937+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3938+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3939+ * GNU General Public License for more details.
3940+ *
3941+ * You should have received a copy of the GNU General Public License
3942+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3943+ */
3944+
3945+#include "miregl.h"
3946+#include <miral/window_specification.h>
3947+#include <mir/client/window_spec.h>
3948+#include <mir_toolkit/mir_client_library.h>
3949+
3950+#include <cstring>
3951+
3952+#include <GLES2/gl2.h>
3953+
3954+using namespace mir::client;
3955+
3956+class MirEglApp
3957+{
3958+public:
3959+ MirEglApp(MirConnection* const connection, MirPixelFormat pixel_format);
3960+
3961+ EGLSurface create_surface(MirRenderSurface* surface);
3962+
3963+ void make_current(EGLSurface eglsurface) const;
3964+
3965+ void swap_buffers(EGLSurface eglsurface) const;
3966+
3967+ void destroy_surface(EGLSurface eglsurface) const;
3968+
3969+ void get_surface_size(EGLSurface eglsurface, int* width, int* height) const;
3970+
3971+ void set_swap_interval(EGLSurface eglsurface, int interval) const;
3972+
3973+ bool supports_surfaceless_context();
3974+
3975+ ~MirEglApp();
3976+
3977+ MirConnection* const connection;
3978+private:
3979+ EGLDisplay egldisplay;
3980+ EGLContext eglctx;
3981+ EGLConfig eglconfig;
3982+ EGLint neglconfigs;
3983+ EGLSurface dummy_surface;
3984+};
3985+
3986+std::shared_ptr<MirEglApp> make_mir_eglapp(
3987+ MirConnection* const connection, MirPixelFormat const& pixel_format)
3988+{
3989+ return std::make_shared<MirEglApp>(connection, pixel_format);
3990+}
3991+
3992+MirEglSurface::MirEglSurface(
3993+ std::shared_ptr<MirEglApp> const& mir_egl_app,
3994+ char const* name,
3995+ MirOutput const* output)
3996+:
3997+ mir_egl_app{mir_egl_app}
3998+{
3999+ auto const mode = mir_output_get_current_mode(output);
4000+ auto const output_id = mir_output_get_id(output);
4001+ auto const width = mir_output_mode_get_width(mode);
4002+ auto const height = mir_output_mode_get_height(mode);
4003+
4004+ surface = Surface{mir_connection_create_render_surface_sync(mir_egl_app->connection, width, height)};
4005+
4006+ eglsurface = mir_egl_app->create_surface(surface);
4007+
4008+ window = WindowSpec::for_normal_window(mir_egl_app->connection, width, height)
4009+ .add_surface(surface, width, height, 0, 0)
4010+ .set_name(name)
4011+ .set_fullscreen_on_output(output_id)
4012+ .create_window();
4013+
4014+ if (!mir_window_is_valid(window))
4015+ throw std::runtime_error(std::string("Can't create a window ") + mir_window_get_error_message(window));
4016+
4017+ mir_egl_app->set_swap_interval(eglsurface, -1);
4018+}
4019+
4020+MirEglSurface::~MirEglSurface()
4021+{
4022+ mir_egl_app->destroy_surface(eglsurface);
4023+}
4024+
4025+void MirEglSurface::egl_make_current()
4026+{
4027+ mir_egl_app->get_surface_size(eglsurface, &width_, &height_);
4028+ mir_egl_app->make_current(eglsurface);
4029+}
4030+
4031+void MirEglSurface::swap_buffers()
4032+{
4033+ mir_egl_app->swap_buffers(eglsurface);
4034+}
4035+
4036+unsigned int MirEglSurface::width() const
4037+{
4038+ return width_;
4039+}
4040+
4041+unsigned int MirEglSurface::height() const
4042+{
4043+ return height_;
4044+}
4045+
4046+MirEglApp::MirEglApp(MirConnection* const connection, MirPixelFormat pixel_format) :
4047+ connection{connection},
4048+ dummy_surface{EGL_NO_SURFACE}
4049+{
4050+ unsigned int bpp = 8*MIR_BYTES_PER_PIXEL(pixel_format);
4051+
4052+ EGLint attribs[] =
4053+ {
4054+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
4055+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
4056+ EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
4057+ EGL_BUFFER_SIZE, (EGLint) bpp,
4058+ EGL_NONE
4059+ };
4060+
4061+ egldisplay = eglGetDisplay((EGLNativeDisplayType)(connection));
4062+ if (egldisplay == EGL_NO_DISPLAY)
4063+ throw std::runtime_error("Can't eglGetDisplay");
4064+
4065+ EGLint major;
4066+ EGLint minor;
4067+ if (!eglInitialize(egldisplay, &major, &minor))
4068+ throw std::runtime_error("Can't eglInitialize");
4069+
4070+ if (major != 1 || minor != 4)
4071+ throw std::runtime_error("EGL version is not 1.4");
4072+
4073+ if (!eglChooseConfig(egldisplay, attribs, &eglconfig, 1, &neglconfigs))
4074+ throw std::runtime_error("Could not eglChooseConfig");
4075+
4076+ if (neglconfigs == 0)
4077+ throw std::runtime_error("No EGL config available");
4078+
4079+ EGLint ctxattribs[] =
4080+ {
4081+ EGL_CONTEXT_CLIENT_VERSION, 2,
4082+ EGL_NONE
4083+ };
4084+
4085+ eglctx = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT, ctxattribs);
4086+ if (eglctx == EGL_NO_CONTEXT)
4087+ throw std::runtime_error("eglCreateContext failed");
4088+
4089+ if (!supports_surfaceless_context())
4090+ {
4091+ static EGLint const dummy_pbuffer_attribs[] =
4092+ {
4093+ EGL_WIDTH, 1,
4094+ EGL_HEIGHT, 1,
4095+ EGL_NONE
4096+ };
4097+
4098+ dummy_surface = eglCreatePbufferSurface(egldisplay, eglconfig, dummy_pbuffer_attribs);
4099+ if (dummy_surface == EGL_NO_SURFACE)
4100+ throw std::runtime_error("eglCreatePbufferSurface failed");
4101+ }
4102+
4103+ make_current(dummy_surface);
4104+}
4105+
4106+EGLSurface MirEglApp::create_surface(MirRenderSurface* surface)
4107+{
4108+ auto const eglsurface = eglCreateWindowSurface(
4109+ egldisplay,
4110+ eglconfig,
4111+ (EGLNativeWindowType)surface, NULL);
4112+
4113+ if (eglsurface == EGL_NO_SURFACE)
4114+ throw std::runtime_error("eglCreateWindowSurface failed");
4115+
4116+ return eglsurface;
4117+}
4118+
4119+void MirEglApp::make_current(EGLSurface eglsurface) const
4120+{
4121+ if (!eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglctx))
4122+ throw std::runtime_error("Can't eglMakeCurrent");
4123+}
4124+
4125+void MirEglApp::swap_buffers(EGLSurface eglsurface) const
4126+{
4127+ eglSwapBuffers(egldisplay, eglsurface);
4128+}
4129+
4130+void MirEglApp::destroy_surface(EGLSurface eglsurface) const
4131+{
4132+ eglDestroySurface(egldisplay, eglsurface);
4133+}
4134+
4135+void MirEglApp::get_surface_size(EGLSurface eglsurface, int* width, int* height) const
4136+{
4137+ eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, width);
4138+ eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, height);
4139+}
4140+
4141+void MirEglApp::set_swap_interval(EGLSurface eglsurface, int interval) const
4142+{
4143+ auto const previous_surface = eglGetCurrentSurface(EGL_DRAW);
4144+
4145+ make_current(eglsurface);
4146+ eglSwapInterval(egldisplay, interval);
4147+
4148+ if (previous_surface != EGL_NO_SURFACE)
4149+ make_current(previous_surface);
4150+}
4151+
4152+bool MirEglApp::supports_surfaceless_context()
4153+{
4154+ auto const extensions = eglQueryString(egldisplay, EGL_EXTENSIONS);
4155+ if (!extensions)
4156+ return false;
4157+ return std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr;
4158+}
4159+
4160+MirEglApp::~MirEglApp()
4161+{
4162+ eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
4163+ if (dummy_surface != EGL_NO_SURFACE)
4164+ destroy_surface(dummy_surface);
4165+ eglDestroyContext(egldisplay, eglctx);
4166+ eglTerminate(egldisplay);
4167+}
4168
4169=== added file 'examples/miral-shell/spinner/miregl.h'
4170--- examples/miral-shell/spinner/miregl.h 1970-01-01 00:00:00 +0000
4171+++ examples/miral-shell/spinner/miregl.h 2017-08-23 11:59:25 +0000
4172@@ -0,0 +1,67 @@
4173+/*
4174+ * Copyright © 2015 Canonical Ltd.
4175+ *
4176+ * This program is free software: you can redistribute it and/or modify
4177+ * under the terms of the GNU General Public License version 2 or 3 as as
4178+ * published by the Free Software Foundation.
4179+ *
4180+ * This program is distributed in the hope that it will be useful,
4181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4183+ * GNU General Public License for more details.
4184+ *
4185+ * You should have received a copy of the GNU General Public License
4186+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4187+ */
4188+
4189+#ifndef UNITYSYSTEMCOMPOSITOR_MIREGL_H
4190+#define UNITYSYSTEMCOMPOSITOR_MIREGL_H
4191+
4192+#include <mir/client/surface.h>
4193+#include <mir/client/window.h>
4194+
4195+#include <EGL/egl.h>
4196+
4197+#include <memory>
4198+
4199+class MirEglApp;
4200+class MirEglSurface;
4201+
4202+std::shared_ptr<MirEglApp> make_mir_eglapp(
4203+ MirConnection* const connection,
4204+ MirPixelFormat const& pixel_format);
4205+
4206+class MirEglSurface
4207+{
4208+public:
4209+ MirEglSurface(
4210+ std::shared_ptr<MirEglApp> const& mir_egl_app,
4211+ char const* name,
4212+ MirOutput const* output);
4213+
4214+ ~MirEglSurface();
4215+
4216+ template<typename Painter>
4217+ void paint(Painter const& functor)
4218+ {
4219+ egl_make_current();
4220+ functor(width(), height());
4221+ swap_buffers();
4222+ }
4223+
4224+private:
4225+ void egl_make_current();
4226+
4227+ void swap_buffers();
4228+ unsigned int width() const;
4229+ unsigned int height() const;
4230+
4231+ std::shared_ptr<MirEglApp> const mir_egl_app;
4232+ mir::client::Surface surface;
4233+ mir::client::Window window;
4234+ EGLSurface eglsurface;
4235+ int width_;
4236+ int height_;
4237+};
4238+
4239+#endif //UNITYSYSTEMCOMPOSITOR_MIREGL_H
4240
4241=== added file 'examples/miral-shell/spinner/png2header.py'
4242--- examples/miral-shell/spinner/png2header.py 1970-01-01 00:00:00 +0000
4243+++ examples/miral-shell/spinner/png2header.py 2017-08-23 11:59:25 +0000
4244@@ -0,0 +1,87 @@
4245+#!/usr/bin/env python
4246+# coding: utf-8
4247+
4248+# Copyright © 2015 Canonical Ltd.
4249+#
4250+# This program is free software: you can redistribute it and/or modify
4251+# it under the terms of the GNU General Public License version 2 or 3
4252+# as published by the Free Software Foundation.
4253+#
4254+# This program is distributed in the hope that it will be useful,
4255+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4256+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4257+# GNU General Public License for more details.
4258+#
4259+# You should have received a copy of the GNU General Public License
4260+# along with this program. If not, see <http://www.gnu.org/licenses/>.
4261+#
4262+# Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
4263+
4264+import sys
4265+from PIL import Image
4266+
4267+def premultiply(image):
4268+ pixels = image.load()
4269+ for i in range(image.size[0]):
4270+ for j in range(image.size[1]):
4271+ orig = pixels[i,j]
4272+ m = orig[3] / 255.0
4273+ pixels[i,j] = (int(orig[0] * m) , int(orig[1] * m), int(orig[2] * m), orig[3])
4274+
4275+def tocstring(data):
4276+ result = ''
4277+ line_chars = 0
4278+ line_limit = 80
4279+
4280+ for c in data:
4281+ if line_chars == 0:
4282+ result += ' "'
4283+
4284+ s = '\\%o' % c
4285+ result += s
4286+ line_chars += len(s)
4287+
4288+ if line_chars >= line_limit:
4289+ result += '"\n'
4290+ line_chars = 0
4291+
4292+ if line_chars != 0:
4293+ result += '"'
4294+
4295+ return result
4296+
4297+def bytes_per_pixel(image):
4298+ if image.mode == 'RGBA':
4299+ return 4
4300+ elif image.mode == 'RGB':
4301+ return 3
4302+ else:
4303+ raise "Unsupported image mode %s" % image.mode
4304+
4305+def export(image, variable_name):
4306+ image_info = (image.size[0], image.size[1], bytes_per_pixel(image))
4307+ print("static const struct {")
4308+ print(" unsigned int width;")
4309+ print(" unsigned int height;")
4310+ print(" unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */")
4311+ print(" unsigned char pixel_data[%d * %d * %d + 1];" % image_info)
4312+ print("} %s = {" % variable_name)
4313+ print(" %d, %d, %d," % image_info)
4314+ print(tocstring(image.tobytes()))
4315+ print("};")
4316+
4317+def show_usage():
4318+ print("Usage: ./png2header.py PNGFILE VARNAME > HEADER_FILE", file=sys.stderr)
4319+ print("Convert a PNG image to an embeddable C/C++ header file", file=sys.stderr)
4320+
4321+if len(sys.argv) < 3:
4322+ show_usage()
4323+ sys.exit(1)
4324+
4325+image_filename = sys.argv[1]
4326+variable_name = sys.argv[2]
4327+
4328+image = Image.open(image_filename)
4329+if image.mode == 'RGBA':
4330+ premultiply(image)
4331+export(image, variable_name)
4332
4333=== added file 'examples/miral-shell/spinner/spinner-glow.png'
4334Binary files examples/miral-shell/spinner/spinner-glow.png 1970-01-01 00:00:00 +0000 and examples/miral-shell/spinner/spinner-glow.png 2017-08-23 11:59:25 +0000 differ
4335=== added file 'examples/miral-shell/spinner/spinner-logo.png'
4336Binary files examples/miral-shell/spinner/spinner-logo.png 1970-01-01 00:00:00 +0000 and examples/miral-shell/spinner/spinner-logo.png 2017-08-23 11:59:25 +0000 differ
4337=== added file 'examples/miral-shell/spinner/splash.h'
4338--- examples/miral-shell/spinner/splash.h 1970-01-01 00:00:00 +0000
4339+++ examples/miral-shell/spinner/splash.h 2017-08-23 11:59:25 +0000
4340@@ -0,0 +1,45 @@
4341+/*
4342+ * Copyright © 2016 Canonical Ltd.
4343+ *
4344+ * This program is free software: you can redistribute it and/or modify it
4345+ * under the terms of the GNU General Public License version 2 or 3 as
4346+ * published by the Free Software Foundation.
4347+ *
4348+ * This program is distributed in the hope that it will be useful,
4349+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4350+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4351+ * GNU General Public License for more details.
4352+ *
4353+ * You should have received a copy of the GNU General Public License
4354+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4355+ *
4356+ * Authored by: Alan Griffiths <alan@octopull.co.uk>
4357+ */
4358+
4359+#ifndef MIRAL_SHELL_SPINNER_SPLASH_H
4360+#define MIRAL_SHELL_SPINNER_SPLASH_H
4361+
4362+#include <mir_toolkit/client_types.h>
4363+
4364+#include <memory>
4365+
4366+namespace mir { namespace scene { class Session; }}
4367+
4368+namespace mir { class Server; namespace scene { class Session; }}
4369+
4370+class SpinnerSplash
4371+{
4372+public:
4373+ SpinnerSplash();
4374+ ~SpinnerSplash();
4375+
4376+ void operator()(MirConnection* connection);
4377+ void operator()(std::weak_ptr<mir::scene::Session> const& session);
4378+ auto session() const -> std::shared_ptr<mir::scene::Session>;
4379+
4380+private:
4381+ struct Self;
4382+ std::shared_ptr<Self> const self;
4383+};
4384+
4385+#endif //MIRAL_SHELL_SPINNER_SPLASH_H
4386
4387=== added file 'examples/miral-shell/tiling_window_manager.cpp'
4388--- examples/miral-shell/tiling_window_manager.cpp 1970-01-01 00:00:00 +0000
4389+++ examples/miral-shell/tiling_window_manager.cpp 2017-08-23 11:59:25 +0000
4390@@ -0,0 +1,688 @@
4391+/*
4392+ * Copyright © 2015-2016 Canonical Ltd.
4393+ *
4394+ * This program is free software: you can redistribute it and/or modify it
4395+ * under the terms of the GNU General Public License version 2 or 3 as
4396+ * published by the Free Software Foundation.
4397+ *
4398+ * This program is distributed in the hope that it will be useful,
4399+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4400+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4401+ * GNU General Public License for more details.
4402+ *
4403+ * You should have received a copy of the GNU General Public License
4404+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4405+ *
4406+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
4407+ */
4408+
4409+#include "tiling_window_manager.h"
4410+
4411+#include <miral/application_info.h>
4412+#include <miral/window_info.h>
4413+#include <miral/window_manager_tools.h>
4414+#include <miral/output.h>
4415+
4416+#include <linux/input.h>
4417+#include <algorithm>
4418+#include <csignal>
4419+
4420+namespace ms = mir::scene;
4421+using namespace miral;
4422+
4423+namespace
4424+{
4425+struct TilingWindowManagerPolicyData
4426+{
4427+ Rectangle tile;
4428+ Rectangle old_tile;
4429+};
4430+
4431+template<class Info>
4432+inline Rectangle& tile_for(Info& info)
4433+{
4434+ return std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata())->tile;
4435+}
4436+
4437+template<class Info>
4438+inline Rectangle const& tile_for(Info const& info)
4439+{
4440+ return std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata())->tile;
4441+}
4442+}
4443+
4444+void TilingWindowManagerPolicy::MRUTileList::push(std::shared_ptr<void> const& tile)
4445+{
4446+ tiles.erase(remove(begin(tiles), end(tiles), tile), end(tiles));
4447+ tiles.push_back(tile);
4448+}
4449+
4450+void TilingWindowManagerPolicy::MRUTileList::erase(std::shared_ptr<void> const& tile)
4451+{
4452+ tiles.erase(remove(begin(tiles), end(tiles), tile), end(tiles));
4453+}
4454+
4455+void TilingWindowManagerPolicy::MRUTileList::enumerate(Enumerator const& enumerator) const
4456+{
4457+ for (auto i = tiles.rbegin(); i != tiles.rend(); ++i)
4458+ enumerator(const_cast<std::shared_ptr<void> const&>(*i));
4459+}
4460+
4461+// Demonstrate implementing a simple tiling algorithm
4462+
4463+TilingWindowManagerPolicy::TilingWindowManagerPolicy(
4464+ WindowManagerTools const& tools,
4465+ SpinnerSplash const& spinner,
4466+ miral::InternalClientLauncher const& launcher,
4467+ miral::ActiveOutputsMonitor& outputs_monitor) :
4468+ tools{tools},
4469+ spinner{spinner},
4470+ launcher{launcher},
4471+ outputs_monitor{outputs_monitor}
4472+{
4473+ outputs_monitor.add_listener(this);
4474+}
4475+
4476+TilingWindowManagerPolicy::~TilingWindowManagerPolicy()
4477+{
4478+ outputs_monitor.delete_listener(this);
4479+}
4480+
4481+void TilingWindowManagerPolicy::click(Point cursor)
4482+{
4483+ auto const window = tools.window_at(cursor);
4484+ tools.select_active_window(window);
4485+}
4486+
4487+void TilingWindowManagerPolicy::resize(Point cursor)
4488+{
4489+ if (auto const application = application_under(cursor))
4490+ {
4491+ if (application == application_under(old_cursor))
4492+ {
4493+ if (auto const window = tools.select_active_window(tools.window_at(old_cursor)))
4494+ {
4495+ resize(window, cursor, old_cursor, tile_for(tools.info_for(application)));
4496+ }
4497+ }
4498+ }
4499+}
4500+
4501+auto TilingWindowManagerPolicy::place_new_window(
4502+ ApplicationInfo const& app_info,
4503+ WindowSpecification const& request_parameters)
4504+ -> WindowSpecification
4505+{
4506+ auto parameters = request_parameters;
4507+
4508+ parameters.userdata() = app_info.userdata();
4509+ parameters.state() = parameters.state().is_set() ?
4510+ transform_set_state(parameters.state().value()) : mir_window_state_restored;
4511+
4512+ if (app_info.application() != spinner.session())
4513+ {
4514+ Rectangle const& tile = tile_for(app_info);
4515+
4516+ if (!parameters.parent().is_set() || !parameters.parent().value().lock())
4517+ {
4518+ if (app_info.windows().empty())
4519+ {
4520+ parameters.top_left() = tile.top_left;
4521+ parameters.size() = tile.size;
4522+ }
4523+ else
4524+ {
4525+ auto top_level_windows = count_if(begin(app_info.windows()), end(app_info.windows()), [this]
4526+ (Window const& window){ return !tools.info_for(window).parent(); });
4527+
4528+ parameters.top_left() = tile.top_left + top_level_windows*Displacement{15, 15};
4529+ }
4530+ }
4531+
4532+ clip_to_tile(parameters, tile);
4533+ }
4534+
4535+ return parameters;
4536+}
4537+
4538+void TilingWindowManagerPolicy::advise_new_window(WindowInfo const& window_info)
4539+{
4540+ if (window_info.type() == mir_window_type_normal &&
4541+ !window_info.parent() &&
4542+ window_info.state() == mir_window_state_restored)
4543+ {
4544+ WindowSpecification specification;
4545+
4546+ specification.state() = mir_window_state_maximized;
4547+
4548+ tools.place_and_size_for_state(specification, window_info);
4549+ constrain_size_and_place(specification, window_info.window(), tile_for(window_info));
4550+ tools.modify_window(window_info.window(), specification);
4551+ }
4552+}
4553+
4554+void TilingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
4555+{
4556+ if (window_info.can_be_active())
4557+ tools.select_active_window(window_info.window());
4558+
4559+ if (spinner.session() != window_info.window().application())
4560+ {
4561+ tiles.push(window_info.userdata());
4562+ dirty_tiles = true;
4563+ }
4564+}
4565+
4566+namespace
4567+{
4568+template<typename ValueType>
4569+void reset(mir::optional_value<ValueType>& option)
4570+{
4571+ if (option.is_set()) option.consume();
4572+}
4573+}
4574+
4575+void TilingWindowManagerPolicy::handle_modify_window(
4576+ miral::WindowInfo& window_info,
4577+ miral::WindowSpecification const& modifications)
4578+{
4579+ auto const window = window_info.window();
4580+ auto const tile = tile_for(window_info);
4581+ auto mods = modifications;
4582+
4583+ constrain_size_and_place(mods, window, tile);
4584+
4585+ reset(mods.output_id());
4586+
4587+ tools.modify_window(window_info, mods);
4588+}
4589+
4590+void TilingWindowManagerPolicy::constrain_size_and_place(
4591+ WindowSpecification& mods, Window const& window, Rectangle const& tile) const
4592+{
4593+ if (mods.size().is_set())
4594+ {
4595+ auto width = std::min(tile.size.width, mods.size().value().width);
4596+ auto height = std::min(tile.size.height, mods.size().value().height);
4597+
4598+ mods.size() = Size{width, height};
4599+ }
4600+
4601+ if (mods.top_left().is_set())
4602+ {
4603+ auto x = std::max(tile.top_left.x, mods.top_left().value().x);
4604+ auto y = std::max(tile.top_left.y, mods.top_left().value().y);
4605+
4606+ mods.top_left() = Point{x, y};
4607+ }
4608+
4609+ auto top_left = mods.top_left().is_set() ? mods.top_left().value() : window.top_left();
4610+ auto bottom_right = top_left + as_displacement(mods.size().is_set() ? mods.size().value() : window.size());
4611+ auto overhang = bottom_right - tile.bottom_right();
4612+
4613+ if (overhang.dx > DeltaX{0}) top_left = top_left - overhang.dx;
4614+ if (overhang.dy > DeltaY{0}) top_left = top_left - overhang.dy;
4615+
4616+ if (top_left != window.top_left())
4617+ mods.top_left() = top_left;
4618+ else
4619+ reset(mods.top_left());
4620+}
4621+
4622+auto TilingWindowManagerPolicy::transform_set_state(MirWindowState value)
4623+-> MirWindowState
4624+{
4625+ switch (value)
4626+ {
4627+ default:
4628+ return mir_window_state_restored;
4629+
4630+ case mir_window_state_hidden:
4631+ case mir_window_state_minimized:
4632+ return mir_window_state_hidden;
4633+ }
4634+}
4635+
4636+void TilingWindowManagerPolicy::drag(Point cursor)
4637+{
4638+ if (auto const application = application_under(cursor))
4639+ {
4640+ if (application == application_under(old_cursor))
4641+ {
4642+ if (auto const window = tools.select_active_window(tools.window_at(old_cursor)))
4643+ {
4644+
4645+ auto const tile = tile_for(tools.info_for(application));
4646+ WindowSpecification mods;
4647+ mods.top_left() = window.top_left() + (cursor-old_cursor);
4648+ constrain_size_and_place(mods, window, tile);
4649+ tools.modify_window(window, mods);
4650+ }
4651+ }
4652+ }
4653+}
4654+
4655+void TilingWindowManagerPolicy::handle_raise_window(WindowInfo& window_info)
4656+{
4657+ tools.select_active_window(window_info.window());
4658+}
4659+
4660+bool TilingWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event)
4661+{
4662+ auto const action = mir_keyboard_event_action(event);
4663+ auto const scan_code = mir_keyboard_event_scan_code(event);
4664+ auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
4665+
4666+ if (action == mir_keyboard_action_down && scan_code == KEY_F12 &&
4667+ (modifiers & modifier_mask) == mir_input_event_modifier_alt)
4668+ {
4669+ launcher.launch("Spinner", spinner);
4670+ return true;
4671+ }
4672+
4673+ if (action == mir_keyboard_action_down && scan_code == KEY_F11)
4674+ {
4675+ switch (modifiers & modifier_mask)
4676+ {
4677+ case mir_input_event_modifier_alt:
4678+ toggle(mir_window_state_maximized);
4679+ return true;
4680+
4681+ case mir_input_event_modifier_shift:
4682+ toggle(mir_window_state_vertmaximized);
4683+ return true;
4684+
4685+ case mir_input_event_modifier_ctrl:
4686+ toggle(mir_window_state_horizmaximized);
4687+ return true;
4688+
4689+ default:
4690+ break;
4691+ }
4692+ }
4693+ else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
4694+ {
4695+ switch (modifiers & modifier_mask)
4696+ {
4697+ case mir_input_event_modifier_alt|mir_input_event_modifier_shift:
4698+ if (auto const& window = tools.active_window())
4699+ kill(window.application(), SIGTERM);
4700+ return true;
4701+
4702+ case mir_input_event_modifier_alt:
4703+ tools.ask_client_to_close(tools.active_window());;
4704+ return true;
4705+
4706+ default:
4707+ break;
4708+ }
4709+ }
4710+ else if (action == mir_keyboard_action_down &&
4711+ modifiers == mir_input_event_modifier_alt &&
4712+ scan_code == KEY_TAB)
4713+ {
4714+ tools.focus_next_application();
4715+
4716+ return true;
4717+ }
4718+ else if (action == mir_keyboard_action_down &&
4719+ modifiers == mir_input_event_modifier_alt &&
4720+ scan_code == KEY_GRAVE)
4721+ {
4722+ tools.focus_next_within_application();
4723+
4724+ return true;
4725+ }
4726+ else if (action == mir_keyboard_action_down &&
4727+ modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_shift) &&
4728+ scan_code == KEY_GRAVE)
4729+ {
4730+ tools.focus_prev_within_application();
4731+
4732+ return true;
4733+ }
4734+
4735+ return false;
4736+}
4737+
4738+bool TilingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event)
4739+{
4740+ auto const count = mir_touch_event_point_count(event);
4741+
4742+ long total_x = 0;
4743+ long total_y = 0;
4744+
4745+ for (auto i = 0U; i != count; ++i)
4746+ {
4747+ total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x);
4748+ total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y);
4749+ }
4750+
4751+ Point const cursor{total_x/count, total_y/count};
4752+
4753+ bool is_drag = true;
4754+ for (auto i = 0U; i != count; ++i)
4755+ {
4756+ switch (mir_touch_event_action(event, i))
4757+ {
4758+ case mir_touch_action_up:
4759+ return false;
4760+
4761+ case mir_touch_action_down:
4762+ is_drag = false;
4763+ continue;
4764+
4765+ default:
4766+ continue;
4767+ }
4768+ }
4769+
4770+ bool consumes_event = false;
4771+ if (is_drag)
4772+ {
4773+ switch (count)
4774+ {
4775+ case 4:
4776+ resize(cursor);
4777+ consumes_event = true;
4778+ break;
4779+
4780+ case 3:
4781+ drag(cursor);
4782+ consumes_event = true;
4783+ break;
4784+ }
4785+ }
4786+ else
4787+ {
4788+ if (auto const& window = tools.window_at(cursor))
4789+ tools.select_active_window(window);
4790+ }
4791+
4792+ old_cursor = cursor;
4793+ return consumes_event;
4794+}
4795+
4796+bool TilingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event)
4797+{
4798+ auto const action = mir_pointer_event_action(event);
4799+ auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask;
4800+ Point const cursor{
4801+ mir_pointer_event_axis_value(event, mir_pointer_axis_x),
4802+ mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
4803+
4804+ bool consumes_event = false;
4805+
4806+ if (action == mir_pointer_action_button_down)
4807+ {
4808+ click(cursor);
4809+ }
4810+ else if (action == mir_pointer_action_motion &&
4811+ modifiers == mir_input_event_modifier_alt)
4812+ {
4813+ if (mir_pointer_event_button_state(event, mir_pointer_button_primary))
4814+ {
4815+ drag(cursor);
4816+ consumes_event = true;
4817+ }
4818+ else if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary))
4819+ {
4820+ resize(cursor);
4821+ consumes_event = true;
4822+ }
4823+ }
4824+
4825+ old_cursor = cursor;
4826+ return consumes_event;
4827+}
4828+
4829+void TilingWindowManagerPolicy::toggle(MirWindowState state)
4830+{
4831+ if (auto window = tools.active_window())
4832+ {
4833+ auto& window_info = tools.info_for(window);
4834+
4835+ if (window_info.state() == state)
4836+ state = mir_window_state_restored;
4837+
4838+ WindowSpecification mods;
4839+ mods.state() = transform_set_state(state);
4840+ tools.modify_window(window_info, mods);
4841+ }
4842+}
4843+
4844+auto TilingWindowManagerPolicy::application_under(Point position)
4845+-> Application
4846+{
4847+ return tools.find_application([&, this](ApplicationInfo const& info)
4848+ { return spinner.session() != info.application() && tile_for(info).contains(position);});
4849+}
4850+
4851+void TilingWindowManagerPolicy::update_tiles(Rectangles const& outputs)
4852+{
4853+ auto const tile_count = tiles.count();
4854+
4855+ if (tile_count < 1 || outputs.size() < 1) return;
4856+
4857+ auto const bounding_rect = outputs.bounding_rectangle();
4858+
4859+ auto const total_width = bounding_rect.size.width.as_int();
4860+ auto const total_height = bounding_rect.size.height.as_int();
4861+
4862+ auto index = 0;
4863+
4864+ if (tile_count < 3)
4865+ {
4866+ tiles.enumerate([&](std::shared_ptr<void> const& userdata)
4867+ {
4868+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(userdata);
4869+ tile_data->old_tile = tile_data->tile;
4870+
4871+ auto const x = (total_width * index) / tile_count;
4872+ ++index;
4873+ auto const dx = (total_width * index) / tile_count - x;
4874+
4875+ tile_data->tile = Rectangle{{x, 0}, {dx, total_height}};
4876+ });
4877+ }
4878+ else
4879+ {
4880+ tiles.enumerate([&](std::shared_ptr<void> const& userdata)
4881+ {
4882+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(userdata);
4883+ tile_data->old_tile = tile_data->tile;
4884+
4885+ auto const dx = total_width/2;
4886+ if (!index)
4887+ {
4888+ tile_data->tile = Rectangle{{0, 0}, {dx, total_height}};
4889+ }
4890+ else
4891+ {
4892+ auto const x = dx;
4893+ auto const y = total_height*(index-1) / (tile_count-1);
4894+ auto const dy = total_height / (tile_count-1);
4895+ tile_data->tile = Rectangle{{x, y}, {dx, dy}};
4896+ }
4897+
4898+ ++index;
4899+ });
4900+ }
4901+
4902+ tools.for_each_application([&](ApplicationInfo& info)
4903+ {
4904+ if (spinner.session() == info.application())
4905+ return;
4906+
4907+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata());
4908+ update_surfaces(info, tile_data->old_tile, tile_data->tile);
4909+ });
4910+}
4911+
4912+void TilingWindowManagerPolicy::update_surfaces(ApplicationInfo& info, Rectangle const& old_tile, Rectangle const& new_tile)
4913+{
4914+ for (auto const& window : info.windows())
4915+ {
4916+ if (window)
4917+ {
4918+ auto& window_info = tools.info_for(window);
4919+
4920+ if (!window_info.parent())
4921+ {
4922+ auto const new_pos = window.top_left() + (new_tile.top_left - old_tile.top_left);
4923+ auto const offset = new_pos - new_tile.top_left;
4924+
4925+ // For now just scale if was filling width/height of tile
4926+ auto const old_size = window.size();
4927+ auto const scaled_width = old_size.width == old_tile.size.width ? new_tile.size.width : old_size.width;
4928+ auto const scaled_height = old_size.height == old_tile.size.height ? new_tile.size.height : old_size.height;
4929+
4930+ auto width = std::min(new_tile.size.width.as_int() - offset.dx.as_int(), scaled_width.as_int());
4931+ auto height = std::min(new_tile.size.height.as_int() - offset.dy.as_int(), scaled_height.as_int());
4932+
4933+ WindowSpecification modifications;
4934+ modifications.top_left() = new_pos;
4935+ modifications.size() = {width, height};
4936+ tools.modify_window(window_info, modifications);
4937+ }
4938+ }
4939+ }
4940+}
4941+
4942+void TilingWindowManagerPolicy::clip_to_tile(miral::WindowSpecification& parameters, Rectangle const& tile)
4943+{
4944+ auto const displacement = parameters.top_left().value() - tile.top_left;
4945+
4946+ auto width = std::min(tile.size.width.as_int()-displacement.dx.as_int(), parameters.size().value().width.as_int());
4947+ auto height = std::min(tile.size.height.as_int()-displacement.dy.as_int(), parameters.size().value().height.as_int());
4948+
4949+ parameters.size() = Size{width, height};
4950+}
4951+
4952+void TilingWindowManagerPolicy::resize(Window window, Point cursor, Point old_cursor, Rectangle bounds)
4953+{
4954+ auto const top_left = window.top_left();
4955+
4956+ auto const old_displacement = old_cursor - top_left;
4957+ auto const new_displacement = cursor - top_left;
4958+
4959+ auto const scale_x = float(new_displacement.dx.as_int())/std::max(1.0f, float(old_displacement.dx.as_int()));
4960+ auto const scale_y = float(new_displacement.dy.as_int())/std::max(1.0f, float(old_displacement.dy.as_int()));
4961+
4962+ if (scale_x <= 0.0f || scale_y <= 0.0f) return;
4963+
4964+ auto const old_size = window.size();
4965+ Size new_size{scale_x*old_size.width, scale_y*old_size.height};
4966+
4967+ auto const size_limits = as_size(bounds.bottom_right() - top_left);
4968+
4969+ if (new_size.width > size_limits.width)
4970+ new_size.width = size_limits.width;
4971+
4972+ if (new_size.height > size_limits.height)
4973+ new_size.height = size_limits.height;
4974+
4975+ window.resize(new_size);
4976+}
4977+
4978+void TilingWindowManagerPolicy::advise_focus_gained(WindowInfo const& info)
4979+{
4980+ tools.raise_tree(info.window());
4981+
4982+ if (auto const spinner_session = spinner.session())
4983+ {
4984+ auto const& spinner_info = tools.info_for(spinner_session);
4985+
4986+ if (spinner_info.windows().size() > 0)
4987+ tools.raise_tree(spinner_info.windows()[0]);
4988+ }
4989+ else
4990+ {
4991+ tiles.push(info.userdata());
4992+ dirty_tiles = true;
4993+ }
4994+}
4995+
4996+void TilingWindowManagerPolicy::advise_new_app(miral::ApplicationInfo& application)
4997+{
4998+ if (spinner.session() == application.application())
4999+ return;
5000+
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches