Merge lp:~alan-griffiths/mir/move-miral-to-mir into lp:mir
- move-miral-to-mir
- Merge into development-branch
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Needs Fixing | |
Mir development team | 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
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4236
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4237
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4238
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4239
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4242
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
ABORTED: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4244
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4246
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4247
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
Artful/armhf:
"18:00:14 sbuild-
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.
18:00:18 subprocess installed post-installation script returned error exit status 2
18:00:18 dpkg: dependency problems prevent configuration of python-
18:00:18 python-
18:00:18 Package python2.
18:00:18
18:00:18 dpkg: error processing package python-
18:00:18 dependency problems - leaving unconfigured
18:00:18 Errors were encountered while processing:
18:00:18 python2.
18:00:18 python-
Python 2.7!?
Oh...
$ apt depends python-pil
python-pil
Depends: python (<< 2.8)
...
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4248
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
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, ®ion); |
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' |
4334 | Binary 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' |
4336 | Binary 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 | + |
FAILED: Continuous integration, rev:4235 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3563/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4883/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/5098 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= artful/ 5087 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 5087 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/5087 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= artful/ 4920/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4920/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= artful/ 4920/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 4920/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4920/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= artful/ 4920/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= zesty/4920/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 4920/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3563/rebuild
https:/