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