Merge lp:~alan-griffiths/mir/move-miral-to-mir-cleanup into lp:mir
- move-miral-to-mir-cleanup
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4238 |
Proposed branch: | lp:~alan-griffiths/mir/move-miral-to-mir-cleanup |
Merge into: | lp:mir |
Prerequisite: | lp:~alan-griffiths/mir/mive-miral-to-mir-regeneration |
Diff against target: |
4207 lines (+127/-3772) 22 files modified
examples/CMakeLists.txt (+5/-21) examples/cursor-theme-dump.cpp (+0/-127) examples/miral-shell/CMakeLists.txt (+11/-7) examples/server_example.cpp (+66/-83) examples/server_example_basic_window_manager.cpp (+0/-328) examples/server_example_basic_window_manager.h (+0/-264) examples/server_example_canonical_window_manager.cpp (+0/-1007) examples/server_example_canonical_window_manager.h (+0/-142) examples/server_example_cursor_images.cpp (+0/-57) examples/server_example_cursor_images.h (+0/-33) examples/server_example_test_client.cpp (+31/-18) examples/server_example_test_client.h (+12/-8) examples/server_example_window_management.cpp (+0/-154) examples/server_example_window_management.h (+0/-33) examples/xcursor.c (+0/-973) examples/xcursor.h (+0/-65) examples/xcursor_loader.cpp (+0/-228) examples/xcursor_loader.h (+0/-74) playground/CMakeLists.txt (+1/-0) src/miral/process_doxygen_xml.py (+1/-1) tests/unit-tests/input/CMakeLists.txt (+0/-1) tests/unit-tests/input/test_xcursor_loader.cpp (+0/-148) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/move-miral-to-mir-cleanup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Gerry Boland (community) | Approve | ||
Review via email: mp+329622@code.launchpad.net |
Commit message
rework mir_demo_server to use miral (and parts of miral-shell)
Description of the change
Incorporate miral project into mir source tree
This is a initial pass at removing code obsoleted by MirAL
There's no reworking of the generated docs to include miral (yet)
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4264
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4264
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 : | # |
- auto const client = options-
+ auto const client = options1-
Interesting, necessary?
Gerry Boland (gerboland) wrote : | # |
Rest looks fine, tests ok. I'm not too familar with the features of mir_demo_server, but those I recall this new refactoring does support.
Alan Griffiths (alan-griffiths) wrote : | # |
> - auto const client =
> options-
> + auto const client = options1-
> Interesting, necessary?
No. CLion "improving" code without me noticing.
Good catch!
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4265
https:/
Executed test runs:
FAILURE: https:/
FAILURE: 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:4266
https:/
Executed test runs:
FAILURE: https:/
FAILURE: 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:4267
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:/
Preview Diff
1 | === modified file 'examples/CMakeLists.txt' |
2 | --- examples/CMakeLists.txt 2017-08-21 15:58:34 +0000 |
3 | +++ examples/CMakeLists.txt 2017-08-31 08:02:08 +0000 |
4 | @@ -9,26 +9,17 @@ |
5 | ) |
6 | |
7 | add_library(exampleserverconfig STATIC |
8 | - server_example_basic_window_manager.cpp |
9 | - server_example_basic_window_manager.h |
10 | - server_example_canonical_window_manager.cpp |
11 | - server_example_display_configuration_policy.cpp |
12 | server_example_input_device_config.cpp |
13 | server_example_input_event_filter.cpp |
14 | server_example_log_options.cpp |
15 | server_example_input_filter.cpp |
16 | server_example_host_lifecycle_event.cpp |
17 | - server_example_window_management.cpp |
18 | server_example_custom_compositor.cpp |
19 | server_example_adorning_compositor.cpp |
20 | - server_example_cursor_images.cpp |
21 | - server_example_cursor_images.h |
22 | - xcursor_loader.cpp |
23 | - xcursor_loader.h |
24 | - xcursor.c |
25 | - xcursor.h |
26 | ) |
27 | |
28 | +target_link_libraries(exampleserverconfig mirserver) |
29 | + |
30 | target_link_libraries(eglapp |
31 | mirclient |
32 | ${EGL_LIBRARIES} |
33 | @@ -175,6 +166,7 @@ |
34 | add_library(mirdraw STATIC graphics_utils.cpp) |
35 | |
36 | include_directories( |
37 | + ${PROJECT_SOURCE_DIR}/include/miral |
38 | ${PROJECT_SOURCE_DIR}/include/server |
39 | ${PROJECT_SOURCE_DIR}/include/client |
40 | ${PROJECT_SOURCE_DIR}/include/platform |
41 | @@ -190,7 +182,8 @@ |
42 | ) |
43 | |
44 | target_link_libraries(mir_demo_server_loadable |
45 | - mirserver |
46 | + miral-shell-lib |
47 | + miral |
48 | exampleserverconfig |
49 | ${GLog_LIBRARY} |
50 | ${GFlags_LIBRARY} |
51 | @@ -248,15 +241,6 @@ |
52 | endif () |
53 | endif () |
54 | |
55 | -add_executable(mir_cursor_theme_dump |
56 | - cursor-theme-dump.cpp |
57 | -) |
58 | - |
59 | -target_link_libraries(mir_cursor_theme_dump |
60 | - exampleserverconfig |
61 | - mirserver |
62 | -) |
63 | - |
64 | mir_add_wrapped_executable(mir_demo_client_multistream |
65 | multi_stream.cpp |
66 | ) |
67 | |
68 | === removed file 'examples/cursor-theme-dump.cpp' |
69 | --- examples/cursor-theme-dump.cpp 2017-07-28 17:00:43 +0000 |
70 | +++ examples/cursor-theme-dump.cpp 1970-01-01 00:00:00 +0000 |
71 | @@ -1,127 +0,0 @@ |
72 | -/* |
73 | - * Copyright © 2015 Canonical Ltd. |
74 | - * |
75 | - * This program is free software: you can redistribute it and/or modify it |
76 | - * under the terms of the GNU General Public License version 2 or 3, |
77 | - * as published by the Free Software Foundation. |
78 | - * |
79 | - * This program is distributed in the hope that it will be useful, |
80 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
81 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
82 | - * GNU General Public License for more details. |
83 | - * |
84 | - * You should have received a copy of the GNU General Public License |
85 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
86 | - * |
87 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
88 | - */ |
89 | - |
90 | -#include "xcursor_loader.h" |
91 | - |
92 | -#include "mir/graphics/cursor_image.h" |
93 | -#include <mir_toolkit/cursors.h> |
94 | - |
95 | -#include <fstream> |
96 | - |
97 | -using namespace mir::examples; |
98 | -using namespace mir::geometry; |
99 | - |
100 | -namespace |
101 | -{ |
102 | -auto const cursor_names = { |
103 | - mir_arrow_cursor_name, |
104 | - mir_busy_cursor_name, |
105 | - mir_caret_cursor_name, |
106 | - mir_default_cursor_name, |
107 | - mir_pointing_hand_cursor_name, |
108 | - mir_open_hand_cursor_name, |
109 | - mir_closed_hand_cursor_name, |
110 | - mir_horizontal_resize_cursor_name, |
111 | - mir_vertical_resize_cursor_name, |
112 | - mir_diagonal_resize_bottom_to_top_cursor_name, |
113 | - mir_diagonal_resize_top_to_bottom_cursor_name, |
114 | - mir_omnidirectional_resize_cursor_name, |
115 | - mir_vsplit_resize_cursor_name, |
116 | - mir_hsplit_resize_cursor_name, |
117 | - mir_crosshair_cursor_name }; |
118 | -} |
119 | - |
120 | - |
121 | -int main(int argc, char const* argv[]) |
122 | -try |
123 | -{ |
124 | - if (argc != 2) |
125 | - { |
126 | - puts("Usage mir_cursor_theme_dump <cursor theme>\n"); |
127 | - exit(-1); |
128 | - } |
129 | - |
130 | - auto const theme = argv[1]; |
131 | - std::ofstream output(std::string{theme} + "-theme.h"); |
132 | - |
133 | - output << "#include <initializer_list>\n" |
134 | - "\n" |
135 | - "namespace\n" |
136 | - "{\n" |
137 | - "struct CursorData\n" |
138 | - "{\n" |
139 | - " CursorData(char const* name, unsigned int hotspot_x, unsigned int hotspot_y, char const* pixel_data) :\n" |
140 | - " name(name), hotspot_x(hotspot_x), hotspot_y(hotspot_y), pixel_data(reinterpret_cast<unsigned char const*>(pixel_data)) {}\n" |
141 | - "\n" |
142 | - " unsigned int const width{" << mir::input::default_cursor_size.width.as_int() << "};\n" |
143 | - " unsigned int const height{" << mir::input::default_cursor_size.height.as_int() << "};\n" |
144 | - " char const* const name;\n" |
145 | - " unsigned int const hotspot_x;\n" |
146 | - " unsigned int const hotspot_y;\n" |
147 | - " unsigned char const* const pixel_data;\n" |
148 | - "};\n" |
149 | - "auto const cursor_data = {\n"; |
150 | - |
151 | - auto const buffer_size = 4*mir::input::default_cursor_size.height.as_int()*mir::input::default_cursor_size.height.as_int(); |
152 | - |
153 | - auto const xcursor_loader = std::make_shared<XCursorLoader>(theme); |
154 | - |
155 | - for (auto cursor : cursor_names) |
156 | - { |
157 | - if (auto const image = xcursor_loader->image(cursor, mir::input::default_cursor_size)) |
158 | - { |
159 | - printf("Have image for %s:%s\n", theme, cursor); |
160 | - |
161 | - auto const hotspot = image->hotspot(); |
162 | - auto const argb_8888 = static_cast<uint8_t const*>(image->as_argb_8888()); |
163 | - |
164 | - output << "CursorData{\"" << cursor << "\", " << hotspot.dx.as_int() << ", " << hotspot.dy.as_int() << ",\n"; |
165 | - |
166 | - int chars = 0; |
167 | - |
168 | - output << std::oct << " \""; |
169 | - |
170 | - for (auto pbyte = argb_8888; pbyte != argb_8888 + buffer_size; ++pbyte) |
171 | - { |
172 | - auto step = (*pbyte < 010) ? 2 : (*pbyte < 0100) ? 3 : 4; |
173 | - |
174 | - if ((chars += step) > 80) |
175 | - { |
176 | - output << "\"\n \""; |
177 | - chars = step; |
178 | - } |
179 | - |
180 | - output << '\\' << static_cast<unsigned>(*pbyte); |
181 | - } |
182 | - |
183 | - output << "\"\n"; |
184 | - |
185 | - output << "},\n"; |
186 | - } |
187 | - else |
188 | - { |
189 | - printf("** WARNING ** No image for %s:%s\n", theme, cursor); |
190 | - } |
191 | - } |
192 | - output << "};\n"; |
193 | - output << "}\n"; |
194 | -} |
195 | -catch (std::exception const& error) |
196 | -{ |
197 | - printf("** ERROR **: %s", error.what()); |
198 | -} |
199 | \ No newline at end of file |
200 | |
201 | === modified file 'examples/miral-shell/CMakeLists.txt' |
202 | --- examples/miral-shell/CMakeLists.txt 2017-08-21 15:58:34 +0000 |
203 | +++ examples/miral-shell/CMakeLists.txt 2017-08-31 08:02:08 +0000 |
204 | @@ -46,20 +46,24 @@ |
205 | DESTINATION ${CMAKE_INSTALL_PREFIX}/bin |
206 | ) |
207 | |
208 | -mir_add_wrapped_executable(miral-shell |
209 | - shell_main.cpp |
210 | +add_library(miral-shell-lib STATIC |
211 | tiling_window_manager.cpp tiling_window_manager.h |
212 | - floating_window_manager.cpp floating_window_manager.h |
213 | + floating_window_manager.cpp floating_window_manager.h |
214 | decoration_provider.cpp decoration_provider.h |
215 | titlebar_config.cpp titlebar_config.h |
216 | ) |
217 | |
218 | pkg_check_modules(FREETYPE freetype2 REQUIRED) |
219 | -target_include_directories(miral-shell PRIVATE ${FREETYPE_INCLUDE_DIRS}) |
220 | -target_compile_definitions(miral-shell PRIVATE -DTYPO_SUPPORTS_FREETYPE) |
221 | +target_include_directories(miral-shell-lib PRIVATE ${FREETYPE_INCLUDE_DIRS}) |
222 | +target_compile_definitions(miral-shell-lib PRIVATE -DTYPO_SUPPORTS_FREETYPE) |
223 | +target_link_libraries(miral-shell-lib miral-spinner miral ${FREETYPE_LIBRARIES}) |
224 | + |
225 | +mir_add_wrapped_executable(miral-shell |
226 | + shell_main.cpp |
227 | +) |
228 | + |
229 | target_link_libraries(miral-shell |
230 | - miral-spinner |
231 | + miral-shell-lib |
232 | miral |
233 | - ${FREETYPE_LIBRARIES} |
234 | ) |
235 | |
236 | |
237 | === modified file 'examples/server_example.cpp' |
238 | --- examples/server_example.cpp 2017-07-28 17:00:43 +0000 |
239 | +++ examples/server_example.cpp 2017-08-31 08:02:08 +0000 |
240 | @@ -1,5 +1,5 @@ |
241 | /* |
242 | - * Copyright © 2012-2015 Canonical Ltd. |
243 | + * Copyright © 2012-2017 Canonical Ltd. |
244 | * |
245 | * This program is free software: you can redistribute it and/or modify |
246 | * it under the terms of the GNU General Public License version 2 or 3 as |
247 | @@ -19,19 +19,24 @@ |
248 | #include "server_example_log_options.h" |
249 | #include "server_example_input_event_filter.h" |
250 | #include "server_example_input_filter.h" |
251 | -#include "server_example_display_configuration_policy.h" |
252 | #include "server_example_host_lifecycle_event_listener.h" |
253 | -#include "server_example_window_management.h" |
254 | #include "server_example_custom_compositor.h" |
255 | #include "server_example_test_client.h" |
256 | -#include "server_example_cursor_images.h" |
257 | #include "server_example_input_device_config.h" |
258 | |
259 | +#include "miral-shell/tiling_window_manager.h" |
260 | +#include "miral-shell/floating_window_manager.h" |
261 | +#include "miral-shell/titlebar_config.h" |
262 | +#include "miral-shell/spinner/splash.h" |
263 | + |
264 | +#include <miral/cursor_theme.h> |
265 | +#include <miral/display_configuration_option.h> |
266 | +#include <miral/runner.h> |
267 | +#include <miral/window_management_options.h> |
268 | + |
269 | #include "mir/abnormal_exit.h" |
270 | #include "mir/server.h" |
271 | #include "mir/main_loop.h" |
272 | -#include "mir/fd.h" |
273 | - |
274 | #include "mir/report_exception.h" |
275 | #include "mir/options/option.h" |
276 | |
277 | @@ -40,6 +45,8 @@ |
278 | #include <chrono> |
279 | #include <cstdlib> |
280 | |
281 | +namespace mir { class AbnormalExit; } |
282 | + |
283 | namespace me = mir::examples; |
284 | |
285 | ///\example server_example.cpp |
286 | @@ -47,51 +54,6 @@ |
287 | |
288 | namespace |
289 | { |
290 | -auto connection(int fd) -> std::string |
291 | -{ |
292 | - char connect_string[64] = {0}; |
293 | - // We can't have both the server and the client owning the same fd, since |
294 | - // that will result in a double-close(). We give the client a duplicate which |
295 | - // the client can safely own (and should close when done). |
296 | - sprintf(connect_string, "fd://%d", dup(fd)); |
297 | - return connect_string; |
298 | -} |
299 | - |
300 | -void add_launcher_option_to(mir::Server& server) |
301 | -{ |
302 | - static const char* const launch_child_opt = "launch-client"; |
303 | - static const char* const launch_client_descr = "system() command to launch client"; |
304 | - |
305 | - server.add_configuration_option(launch_child_opt, launch_client_descr, mir::OptionType::string); |
306 | - server.add_init_callback([&] |
307 | - { |
308 | - const auto options = server.get_options(); |
309 | - if (options->is_set(launch_child_opt)) |
310 | - { |
311 | - unsetenv("DISPLAY"); // Discourage toolkits from using X11 |
312 | - setenv("GDK_BACKEND", "mir", true); // configure GTK to use Mir |
313 | - setenv("QT_QPA_PLATFORM", "ubuntumirclient", true); // configure Qt to use Mir |
314 | - unsetenv("QT_QPA_PLATFORMTHEME"); // Discourage Qt from unsupported theme |
315 | - setenv("SDL_VIDEODRIVER", "mir", true); // configure SDL to use Mir |
316 | - |
317 | - auto const value = options->get<std::string>(launch_child_opt); |
318 | - |
319 | - for (auto i = begin(value); i != end(value); ) |
320 | - { |
321 | - auto const j = find(i, end(value), '&'); |
322 | - |
323 | - auto const cmd ="MIR_SOCKET=" + connection(server.open_client_socket()) + " " + |
324 | - std::string{i, j} + "&"; |
325 | - |
326 | - auto ignore = std::system(cmd.c_str()); |
327 | - (void)(ignore); |
328 | - |
329 | - if ((i = j) != end(value)) ++i; |
330 | - } |
331 | - } |
332 | - }); |
333 | -} |
334 | - |
335 | void add_timeout_option_to(mir::Server& server) |
336 | { |
337 | static const char* const timeout_opt = "timeout"; |
338 | @@ -110,6 +72,23 @@ |
339 | }); |
340 | } |
341 | |
342 | + |
343 | +// Create some input filters (we need to keep them or they deactivate) |
344 | +struct InputFilters |
345 | +{ |
346 | + void operator()(mir::Server& server) |
347 | + { |
348 | + quit_filter = me::make_quit_filter_for(server); |
349 | + printing_filter = me::make_printing_input_filter_for(server); |
350 | + screen_rotation_filter = me::make_screen_rotation_filter_for(server); |
351 | + } |
352 | + |
353 | +private: |
354 | + std::shared_ptr<mir::input::EventFilter> quit_filter; |
355 | + std::shared_ptr<mir::input::EventFilter> printing_filter; |
356 | + std::shared_ptr<mir::input::EventFilter> screen_rotation_filter; |
357 | +}; |
358 | + |
359 | void exception_handler() |
360 | try |
361 | { |
362 | @@ -145,44 +124,48 @@ |
363 | int main(int argc, char const* argv[]) |
364 | try |
365 | { |
366 | - mir::Server server; |
367 | - |
368 | - // Use config options file in e.g. ~/.config/mir/mir_demo_server.config |
369 | - server.set_config_filename("mir/mir_demo_server.config"); |
370 | - |
371 | - // Add example options for display layout, logging, launching clients and timeout |
372 | - me::add_display_configuration_options_to(server); |
373 | - me::add_log_host_lifecycle_option_to(server); |
374 | - me::add_glog_options_to(server); |
375 | - me::add_window_manager_option_to(server); |
376 | - me::add_custom_compositor_option_to(server); |
377 | - me::add_input_device_configuration_options_to(server); |
378 | - add_launcher_option_to(server); |
379 | - add_timeout_option_to(server); |
380 | - me::add_x_cursor_images(server); |
381 | - |
382 | - server.set_exception_handler(exception_handler); |
383 | - |
384 | - me::ClientContext context; |
385 | - me::add_test_client_option_to(server, context); |
386 | - |
387 | - // Create some input filters (we need to keep them or they deactivate) |
388 | - auto const quit_filter = me::make_quit_filter_for(server); |
389 | - auto const printing_filter = me::make_printing_input_filter_for(server); |
390 | - auto const screen_rotation_filter = me::make_screen_rotation_filter_for(server); |
391 | - |
392 | - // Provide the command line and run the server |
393 | - server.set_command_line(argc, argv); |
394 | - server.apply_settings(); |
395 | - server.run(); |
396 | + miral::MirRunner runner{argc, argv, "mir/mir_demo_server.config"}; |
397 | + |
398 | + runner.set_exception_handler(exception_handler); |
399 | + |
400 | + std::function<void()> shutdown_hook{[]{}}; |
401 | + runner.add_stop_callback([&] { shutdown_hook(); }); |
402 | + |
403 | + SpinnerSplash spinner; |
404 | + miral::InternalClientLauncher launcher; |
405 | + miral::ActiveOutputsMonitor outputs_monitor; |
406 | + miral::WindowManagerOptions window_managers |
407 | + { |
408 | + miral::add_window_manager_policy<FloatingWindowManagerPolicy>("floating", spinner, launcher, shutdown_hook), |
409 | + miral::add_window_manager_policy<TilingWindowManagerPolicy>("tiling", spinner, launcher, outputs_monitor), |
410 | + }; |
411 | + |
412 | + InputFilters input_filters; |
413 | + me::TestClientRunner test_runner; |
414 | + |
415 | + bool const server_exited_normally = runner.run_with({ |
416 | + // example options for display layout, logging and timeout |
417 | + miral::display_configuration_options, |
418 | + me::add_log_host_lifecycle_option_to, |
419 | + me::add_glog_options_to, |
420 | + miral::StartupInternalClient{"Intro", spinner}, |
421 | + launcher, |
422 | + window_managers, |
423 | + me::add_custom_compositor_option_to, |
424 | + me::add_input_device_configuration_options_to, |
425 | + add_timeout_option_to, |
426 | + miral::CursorTheme{"default"}, |
427 | + input_filters, |
428 | + test_runner |
429 | + }); |
430 | |
431 | // Propagate any test failure |
432 | - if (context.test_failed) |
433 | + if (test_runner.test_failed()) |
434 | { |
435 | return EXIT_FAILURE; |
436 | } |
437 | |
438 | - return server.exited_normally() ? EXIT_SUCCESS : EXIT_FAILURE; |
439 | + return server_exited_normally ? EXIT_SUCCESS : EXIT_FAILURE; |
440 | } |
441 | catch (...) |
442 | { |
443 | |
444 | === removed file 'examples/server_example_basic_window_manager.cpp' |
445 | --- examples/server_example_basic_window_manager.cpp 2017-07-28 17:00:43 +0000 |
446 | +++ examples/server_example_basic_window_manager.cpp 1970-01-01 00:00:00 +0000 |
447 | @@ -1,328 +0,0 @@ |
448 | -/* |
449 | - * Copyright © 2015 Canonical Ltd. |
450 | - * |
451 | - * This program is free software: you can redistribute it and/or modify it |
452 | - * under the terms of the GNU General Public License version 2 or 3, |
453 | - * as published by the Free Software Foundation. |
454 | - * |
455 | - * This program is distributed in the hope that it will be useful, |
456 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
457 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
458 | - * GNU General Public License for more details. |
459 | - * |
460 | - * You should have received a copy of the GNU General Public License |
461 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
462 | - * |
463 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
464 | - */ |
465 | - |
466 | -#include "server_example_basic_window_manager.h" |
467 | - |
468 | -#include "mir/scene/session.h" |
469 | -#include "mir/scene/surface.h" |
470 | -#include "mir/scene/surface_creation_parameters.h" |
471 | - |
472 | -namespace me = mir::examples; |
473 | - |
474 | -me::BasicWindowManager::BasicWindowManager( |
475 | - shell::FocusController* focus_controller, |
476 | - std::unique_ptr<WindowManagementPolicy> policy) : |
477 | - focus_controller(focus_controller), |
478 | - policy(std::move(policy)) |
479 | -{ |
480 | -} |
481 | - |
482 | -void me::BasicWindowManager::add_session(std::shared_ptr<scene::Session> const& session) |
483 | -{ |
484 | - std::lock_guard<decltype(mutex)> lock(mutex); |
485 | - session_info[session] = SessionInfo(); |
486 | - policy->handle_session_info_updated(session_info, displays); |
487 | -} |
488 | - |
489 | -void me::BasicWindowManager::remove_session(std::shared_ptr<scene::Session> const& session) |
490 | -{ |
491 | - std::lock_guard<decltype(mutex)> lock(mutex); |
492 | - session_info.erase(session); |
493 | - policy->handle_session_info_updated(session_info, displays); |
494 | -} |
495 | - |
496 | -auto me::BasicWindowManager::add_surface( |
497 | - std::shared_ptr<scene::Session> const& session, |
498 | - scene::SurfaceCreationParameters const& params, |
499 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) |
500 | --> frontend::SurfaceId |
501 | -{ |
502 | - std::lock_guard<decltype(mutex)> lock(mutex); |
503 | - scene::SurfaceCreationParameters const placed_params = policy->handle_place_new_surface(session, params); |
504 | - auto const result = build(session, placed_params); |
505 | - auto const surface = session->surface(result); |
506 | - surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params}); |
507 | - policy->handle_new_surface(session, surface); |
508 | - policy->generate_decorations_for(session, surface, surface_info, build); |
509 | - return result; |
510 | -} |
511 | - |
512 | -void me::BasicWindowManager::modify_surface( |
513 | - std::shared_ptr<scene::Session> const& session, |
514 | - std::shared_ptr<scene::Surface> const& surface, |
515 | - shell::SurfaceSpecification const& modifications) |
516 | -{ |
517 | - std::lock_guard<decltype(mutex)> lock(mutex); |
518 | - policy->handle_modify_surface(session, surface, modifications); |
519 | -} |
520 | - |
521 | -void me::BasicWindowManager::remove_surface( |
522 | - std::shared_ptr<scene::Session> const& session, |
523 | - std::weak_ptr<scene::Surface> const& surface) |
524 | -{ |
525 | - std::lock_guard<decltype(mutex)> lock(mutex); |
526 | - policy->handle_delete_surface(session, surface); |
527 | - |
528 | - surface_info.erase(surface); |
529 | -} |
530 | - |
531 | -void me::BasicWindowManager::forget(std::weak_ptr<scene::Surface> const& surface) |
532 | -{ |
533 | - surface_info.erase(surface); |
534 | -} |
535 | - |
536 | -void me::BasicWindowManager::add_display(geometry::Rectangle const& area) |
537 | -{ |
538 | - std::lock_guard<decltype(mutex)> lock(mutex); |
539 | - displays.add(area); |
540 | - policy->handle_displays_updated(session_info, displays); |
541 | -} |
542 | - |
543 | -void me::BasicWindowManager::remove_display(geometry::Rectangle const& area) |
544 | -{ |
545 | - std::lock_guard<decltype(mutex)> lock(mutex); |
546 | - displays.remove(area); |
547 | - policy->handle_displays_updated(session_info, displays); |
548 | -} |
549 | - |
550 | -bool me::BasicWindowManager::handle_keyboard_event(MirKeyboardEvent const* event) |
551 | -{ |
552 | - std::lock_guard<decltype(mutex)> lock(mutex); |
553 | - update_event_timestamp(event); |
554 | - return policy->handle_keyboard_event(event); |
555 | -} |
556 | - |
557 | -bool me::BasicWindowManager::handle_touch_event(MirTouchEvent const* event) |
558 | -{ |
559 | - std::lock_guard<decltype(mutex)> lock(mutex); |
560 | - update_event_timestamp(event); |
561 | - return policy->handle_touch_event(event); |
562 | -} |
563 | - |
564 | -bool me::BasicWindowManager::handle_pointer_event(MirPointerEvent const* event) |
565 | -{ |
566 | - std::lock_guard<decltype(mutex)> lock(mutex); |
567 | - update_event_timestamp(event); |
568 | - |
569 | - cursor = { |
570 | - mir_pointer_event_axis_value(event, mir_pointer_axis_x), |
571 | - mir_pointer_event_axis_value(event, mir_pointer_axis_y)}; |
572 | - |
573 | - return policy->handle_pointer_event(event); |
574 | -} |
575 | - |
576 | -void me::BasicWindowManager::handle_raise_surface( |
577 | - std::shared_ptr<scene::Session> const& session, |
578 | - std::shared_ptr<scene::Surface> const& surface, |
579 | - uint64_t timestamp) |
580 | -{ |
581 | - std::lock_guard<decltype(mutex)> lock(mutex); |
582 | - if (timestamp >= last_input_event_timestamp) |
583 | - policy->handle_raise_surface(session, surface); |
584 | -} |
585 | - |
586 | -void me::BasicWindowManager::handle_request_drag_and_drop( |
587 | - std::shared_ptr<scene::Session> const& /*session*/, |
588 | - std::shared_ptr<scene::Surface> const& /*surface*/, |
589 | - uint64_t /*timestamp*/) |
590 | -{ |
591 | - // Not supported in example servers |
592 | -} |
593 | - |
594 | -void me::BasicWindowManager::handle_request_move( |
595 | - std::shared_ptr<scene::Session> const& /*session*/, |
596 | - std::shared_ptr<scene::Surface> const& /*surface*/, |
597 | - uint64_t /*timestamp*/) |
598 | -{ |
599 | - // Not supported in example servers |
600 | -} |
601 | - |
602 | -int me::BasicWindowManager::set_surface_attribute( |
603 | - std::shared_ptr<scene::Session> const& /*session*/, |
604 | - std::shared_ptr<scene::Surface> const& surface, |
605 | - MirWindowAttrib attrib, |
606 | - int value) |
607 | -{ |
608 | - std::lock_guard<decltype(mutex)> lock(mutex); |
609 | - switch (attrib) |
610 | - { |
611 | - case mir_window_attrib_state: |
612 | - { |
613 | - auto const state = policy->handle_set_state(surface, MirWindowState(value)); |
614 | - return surface->configure(attrib, state); |
615 | - } |
616 | - default: |
617 | - return surface->configure(attrib, value); |
618 | - } |
619 | -} |
620 | - |
621 | -auto me::BasicWindowManager::find_session(std::function<bool(SessionInfo const& info)> const& predicate) |
622 | --> std::shared_ptr<scene::Session> |
623 | - { |
624 | - for(auto& info : session_info) |
625 | - { |
626 | - if (predicate(info.second)) |
627 | - { |
628 | - return info.first.lock(); |
629 | - } |
630 | - } |
631 | - |
632 | - return std::shared_ptr<scene::Session>{}; |
633 | - } |
634 | - |
635 | -auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Session> const& session) const |
636 | --> SessionInfo& |
637 | -{ |
638 | - return const_cast<SessionInfo&>(session_info.at(session)); |
639 | -} |
640 | - |
641 | -auto me::BasicWindowManager::info_for(std::weak_ptr<scene::Surface> const& surface) const |
642 | --> SurfaceInfo& |
643 | -{ |
644 | - return const_cast<SurfaceInfo&>(surface_info.at(surface)); |
645 | -} |
646 | - |
647 | -auto me::BasicWindowManager::focused_session() const |
648 | --> std::shared_ptr<scene::Session> |
649 | -{ |
650 | - return focus_controller->focused_session(); |
651 | -} |
652 | - |
653 | -auto me::BasicWindowManager::focused_surface() const |
654 | -->std::shared_ptr<scene::Surface> |
655 | -{ |
656 | - return focus_controller->focused_surface(); |
657 | -} |
658 | - |
659 | -void me::BasicWindowManager::focus_next_session() |
660 | -{ |
661 | - focus_controller->focus_next_session(); |
662 | -} |
663 | - |
664 | -void me::BasicWindowManager::set_focus_to( |
665 | - std::shared_ptr<scene::Session> const& focus, |
666 | - std::shared_ptr<scene::Surface> const& surface) |
667 | -{ |
668 | - focus_controller->set_focus_to(focus, surface); |
669 | -} |
670 | - |
671 | -auto me::BasicWindowManager::surface_at(geometry::Point cursor) const |
672 | --> std::shared_ptr<scene::Surface> |
673 | -{ |
674 | - return focus_controller->surface_at(cursor); |
675 | -} |
676 | - |
677 | -auto me::BasicWindowManager::active_display() |
678 | --> geometry::Rectangle const |
679 | -{ |
680 | - geometry::Rectangle result; |
681 | - |
682 | - // 1. If a window has input focus, whichever display contains the largest |
683 | - // proportion of the area of that window. |
684 | - if (auto const surface = focused_surface()) |
685 | - { |
686 | - auto const surface_rect = surface->input_bounds(); |
687 | - int max_overlap_area = -1; |
688 | - |
689 | - for (auto const& display : displays) |
690 | - { |
691 | - auto const intersection = surface_rect.intersection_with(display).size; |
692 | - if (intersection.width.as_int()*intersection.height.as_int() > max_overlap_area) |
693 | - { |
694 | - max_overlap_area = intersection.width.as_int()*intersection.height.as_int(); |
695 | - result = display; |
696 | - } |
697 | - } |
698 | - return result; |
699 | - } |
700 | - |
701 | - // 2. Otherwise, if any window previously had input focus, for the window that had |
702 | - // it most recently, the display that contained the largest proportion of the |
703 | - // area of that window at the moment it closed, as long as that display is still |
704 | - // available. |
705 | - |
706 | - // 3. Otherwise, the display that contains the pointer, if there is one. |
707 | - for (auto const& display : displays) |
708 | - { |
709 | - if (display.contains(cursor)) |
710 | - { |
711 | - // Ignore the (unspecified) possiblity of overlapping displays |
712 | - return display; |
713 | - } |
714 | - } |
715 | - |
716 | - // 4. Otherwise, the primary display, if there is one (for example, the laptop display). |
717 | - |
718 | - // 5. Otherwise, the first display. |
719 | - if (displays.size()) |
720 | - result = *displays.begin(); |
721 | - |
722 | - return result; |
723 | -} |
724 | - |
725 | -void me::BasicWindowManager::raise_tree(std::shared_ptr<scene::Surface> const& root) |
726 | -{ |
727 | - SurfaceSet surfaces; |
728 | - std::function<void(std::weak_ptr<scene::Surface> const& surface)> const add_children = |
729 | - [&,this](std::weak_ptr<scene::Surface> const& surface) |
730 | - { |
731 | - auto const& info = info_for(surface); |
732 | - surfaces.insert(begin(info.children), end(info.children)); |
733 | - for (auto const& child : info.children) |
734 | - add_children(child); |
735 | - }; |
736 | - |
737 | - surfaces.insert(root); |
738 | - add_children(root); |
739 | - |
740 | - focus_controller->raise(surfaces); |
741 | -} |
742 | - |
743 | -void me::BasicWindowManager::update_event_timestamp(MirKeyboardEvent const* kev) |
744 | -{ |
745 | - auto iev = mir_keyboard_event_input_event(kev); |
746 | - last_input_event_timestamp = mir_input_event_get_event_time(iev); |
747 | -} |
748 | - |
749 | -void me::BasicWindowManager::update_event_timestamp(MirPointerEvent const* pev) |
750 | -{ |
751 | - auto iev = mir_pointer_event_input_event(pev); |
752 | - auto pointer_action = mir_pointer_event_action(pev); |
753 | - |
754 | - if (pointer_action == mir_pointer_action_button_up || |
755 | - pointer_action == mir_pointer_action_button_down) |
756 | - { |
757 | - last_input_event_timestamp = mir_input_event_get_event_time(iev); |
758 | - } |
759 | -} |
760 | - |
761 | -void me::BasicWindowManager::update_event_timestamp(MirTouchEvent const* tev) |
762 | -{ |
763 | - auto iev = mir_touch_event_input_event(tev); |
764 | - auto touch_count = mir_touch_event_point_count(tev); |
765 | - for (unsigned i = 0; i < touch_count; i++) |
766 | - { |
767 | - auto touch_action = mir_touch_event_action(tev, i); |
768 | - if (touch_action == mir_touch_action_up || |
769 | - touch_action == mir_touch_action_down) |
770 | - { |
771 | - last_input_event_timestamp = mir_input_event_get_event_time(iev); |
772 | - break; |
773 | - } |
774 | - } |
775 | -} |
776 | |
777 | === removed file 'examples/server_example_basic_window_manager.h' |
778 | --- examples/server_example_basic_window_manager.h 2017-07-28 17:00:43 +0000 |
779 | +++ examples/server_example_basic_window_manager.h 1970-01-01 00:00:00 +0000 |
780 | @@ -1,264 +0,0 @@ |
781 | -/* |
782 | - * Copyright © 2015 Canonical Ltd. |
783 | - * |
784 | - * This program is free software: you can redistribute it and/or modify it |
785 | - * under the terms of the GNU General Public License version 2 or 3, |
786 | - * as published by the Free Software Foundation. |
787 | - * |
788 | - * This program is distributed in the hope that it will be useful, |
789 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
790 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
791 | - * GNU General Public License for more details. |
792 | - * |
793 | - * You should have received a copy of the GNU General Public License |
794 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
795 | - * |
796 | - * Authored By: Alan Griffiths <alan@octopull.co.uk> |
797 | - */ |
798 | - |
799 | -#ifndef MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ |
800 | -#define MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ |
801 | - |
802 | -#include "mir/shell/window_management_info.h" |
803 | - |
804 | -#include "mir/geometry/rectangles.h" |
805 | -#include "mir/shell/abstract_shell.h" |
806 | -#include "mir/shell/window_manager.h" |
807 | - |
808 | -#include <map> |
809 | -#include <mutex> |
810 | - |
811 | -///\example server_example_basic_window_manager.h |
812 | -/// A generic policy-based window manager implementation |
813 | - |
814 | -namespace mir |
815 | -{ |
816 | -namespace examples |
817 | -{ |
818 | -using shell::SurfaceSet; |
819 | -using shell::SurfaceInfo; |
820 | -using shell::SessionInfo; |
821 | - |
822 | -/// The interface through which the policy instructs the controller. |
823 | -/// These functions assume that the BasicWindowManager data structures can be accessed freely. |
824 | -/// I.e. should only be invoked by the policy handle_... methods (where any necessary locks are held). |
825 | -class WindowManagerTools |
826 | -{ |
827 | -public: |
828 | - using SurfaceInfoMap = std::map<std::weak_ptr<scene::Surface>, SurfaceInfo, std::owner_less<std::weak_ptr<scene::Surface>>>; |
829 | - using SessionInfoMap = std::map<std::weak_ptr<scene::Session>, SessionInfo, std::owner_less<std::weak_ptr<scene::Session>>>; |
830 | - |
831 | - virtual auto find_session(std::function<bool(SessionInfo const& info)> const& predicate) |
832 | - -> std::shared_ptr<scene::Session> = 0; |
833 | - |
834 | - virtual auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& = 0; |
835 | - |
836 | - virtual auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& = 0; |
837 | - |
838 | - virtual std::shared_ptr<scene::Session> focused_session() const = 0; |
839 | - |
840 | - virtual std::shared_ptr<scene::Surface> focused_surface() const = 0; |
841 | - |
842 | - virtual void focus_next_session() = 0; |
843 | - |
844 | - virtual void set_focus_to( |
845 | - std::shared_ptr<scene::Session> const& focus, |
846 | - std::shared_ptr<scene::Surface> const& surface) = 0; |
847 | - |
848 | - virtual auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> = 0; |
849 | - |
850 | - virtual auto active_display() -> geometry::Rectangle const = 0; |
851 | - |
852 | - virtual void forget(std::weak_ptr<scene::Surface> const& surface) = 0; |
853 | - |
854 | - virtual void raise_tree(std::shared_ptr<scene::Surface> const& root) = 0; |
855 | - |
856 | - virtual ~WindowManagerTools() = default; |
857 | - WindowManagerTools() = default; |
858 | - WindowManagerTools(WindowManagerTools const&) = delete; |
859 | - WindowManagerTools& operator=(WindowManagerTools const&) = delete; |
860 | -}; |
861 | - |
862 | -class WindowManagementPolicy |
863 | -{ |
864 | -public: |
865 | - using SessionInfoMap = typename WindowManagerTools::SessionInfoMap; |
866 | - using SurfaceInfoMap = typename WindowManagerTools::SurfaceInfoMap; |
867 | - |
868 | - virtual void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0; |
869 | - |
870 | - virtual void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays) = 0; |
871 | - |
872 | - virtual auto handle_place_new_surface( |
873 | - std::shared_ptr<scene::Session> const& session, |
874 | - scene::SurfaceCreationParameters const& request_parameters) |
875 | - -> scene::SurfaceCreationParameters = 0; |
876 | - |
877 | - virtual void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface) = 0; |
878 | - |
879 | - virtual void handle_modify_surface( |
880 | - std::shared_ptr<scene::Session> const& session, |
881 | - std::shared_ptr<scene::Surface> const& surface, |
882 | - shell::SurfaceSpecification const& modifications) = 0; |
883 | - |
884 | - virtual void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface) = 0; |
885 | - |
886 | - virtual int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirWindowState value) = 0; |
887 | - |
888 | - virtual void generate_decorations_for( |
889 | - std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface, |
890 | - SurfaceInfoMap& surface_info, |
891 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const&, scene::SurfaceCreationParameters const&)> const& build) = 0; |
892 | - |
893 | - virtual bool handle_keyboard_event(MirKeyboardEvent const* event) = 0; |
894 | - |
895 | - virtual bool handle_touch_event(MirTouchEvent const* event) = 0; |
896 | - |
897 | - virtual bool handle_pointer_event(MirPointerEvent const* event) = 0; |
898 | - |
899 | - virtual void handle_raise_surface( |
900 | - std::shared_ptr<scene::Session> const& session, |
901 | - std::shared_ptr<scene::Surface> const& surface) = 0; |
902 | - |
903 | - virtual ~WindowManagementPolicy() = default; |
904 | - WindowManagementPolicy() = default; |
905 | - WindowManagementPolicy(WindowManagementPolicy const&) = delete; |
906 | - WindowManagementPolicy& operator=(WindowManagementPolicy const&) = delete; |
907 | -}; |
908 | - |
909 | -/// A policy based window manager. |
910 | -/// This takes care of the management of any meta implementation held for the sessions and surfaces. |
911 | -class BasicWindowManager : public virtual shell::WindowManager, |
912 | - protected WindowManagerTools |
913 | -{ |
914 | -protected: |
915 | - BasicWindowManager( |
916 | - shell::FocusController* focus_controller, |
917 | - std::unique_ptr<WindowManagementPolicy> policy); |
918 | - |
919 | -public: |
920 | - using typename WindowManagerTools::SurfaceInfoMap; |
921 | - using typename WindowManagerTools::SessionInfoMap; |
922 | - |
923 | - void add_session(std::shared_ptr<scene::Session> const& session) override; |
924 | - |
925 | - void remove_session(std::shared_ptr<scene::Session> const& session) override; |
926 | - |
927 | - auto add_surface( |
928 | - std::shared_ptr<scene::Session> const& session, |
929 | - scene::SurfaceCreationParameters const& params, |
930 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) |
931 | - -> frontend::SurfaceId override; |
932 | - |
933 | - void modify_surface( |
934 | - std::shared_ptr<scene::Session> const& session, |
935 | - std::shared_ptr<scene::Surface> const& surface, |
936 | - shell::SurfaceSpecification const& modifications) override; |
937 | - |
938 | - void remove_surface( |
939 | - std::shared_ptr<scene::Session> const& session, |
940 | - std::weak_ptr<scene::Surface> const& surface) override; |
941 | - |
942 | - void forget(std::weak_ptr<scene::Surface> const& surface) override; |
943 | - |
944 | - void add_display(geometry::Rectangle const& area) override; |
945 | - |
946 | - void remove_display(geometry::Rectangle const& area) override; |
947 | - |
948 | - bool handle_keyboard_event(MirKeyboardEvent const* event) override; |
949 | - |
950 | - bool handle_touch_event(MirTouchEvent const* event) override; |
951 | - |
952 | - bool handle_pointer_event(MirPointerEvent const* event) override; |
953 | - |
954 | - void handle_raise_surface( |
955 | - std::shared_ptr<scene::Session> const& session, |
956 | - std::shared_ptr<scene::Surface> const& surface, |
957 | - uint64_t timestamp) override; |
958 | - |
959 | - void handle_request_drag_and_drop( |
960 | - std::shared_ptr<scene::Session> const& session, |
961 | - std::shared_ptr<scene::Surface> const& surface, |
962 | - uint64_t timestamp) override; |
963 | - |
964 | - void handle_request_move( |
965 | - std::shared_ptr<scene::Session> const& session, |
966 | - std::shared_ptr<scene::Surface> const& surface, |
967 | - uint64_t timestamp) override; |
968 | - |
969 | - int set_surface_attribute( |
970 | - std::shared_ptr<scene::Session> const& /*session*/, |
971 | - std::shared_ptr<scene::Surface> const& surface, |
972 | - MirWindowAttrib attrib, |
973 | - int value) override; |
974 | - |
975 | - auto find_session(std::function<bool(SessionInfo const& info)> const& predicate) |
976 | - -> std::shared_ptr<scene::Session> override; |
977 | - |
978 | - auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& override; |
979 | - |
980 | - auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& override; |
981 | - |
982 | - std::shared_ptr<scene::Session> focused_session() const override; |
983 | - |
984 | - std::shared_ptr<scene::Surface> focused_surface() const override; |
985 | - |
986 | - void focus_next_session() override; |
987 | - |
988 | - void set_focus_to( |
989 | - std::shared_ptr<scene::Session> const& focus, |
990 | - std::shared_ptr<scene::Surface> const& surface) override; |
991 | - |
992 | - auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> override; |
993 | - |
994 | - auto active_display() -> geometry::Rectangle const override; |
995 | - |
996 | - void raise_tree(std::shared_ptr<scene::Surface> const& root) override; |
997 | - |
998 | -private: |
999 | - shell::FocusController* const focus_controller; |
1000 | - std::unique_ptr<WindowManagementPolicy> const policy; |
1001 | - |
1002 | - std::mutex mutex; |
1003 | - SessionInfoMap session_info; |
1004 | - SurfaceInfoMap surface_info; |
1005 | - geometry::Rectangles displays; |
1006 | - geometry::Point cursor; |
1007 | - uint64_t last_input_event_timestamp{0}; |
1008 | - |
1009 | - void update_event_timestamp(MirKeyboardEvent const* kev); |
1010 | - void update_event_timestamp(MirPointerEvent const* pev); |
1011 | - void update_event_timestamp(MirTouchEvent const* tev); |
1012 | -}; |
1013 | - |
1014 | -/// A policy based window manager. This exists to initialize BasicWindowManager and |
1015 | -/// the WMPolicy (in an awkward manner). |
1016 | -/// TODO revisit this initialization sequence. |
1017 | -template<typename WMPolicy> |
1018 | -class WindowManagerBuilder : public BasicWindowManager |
1019 | -{ |
1020 | -public: |
1021 | - |
1022 | - template <typename... PolicyArgs> |
1023 | - WindowManagerBuilder( |
1024 | - shell::FocusController* focus_controller, |
1025 | - PolicyArgs&&... policy_args) : |
1026 | - BasicWindowManager( |
1027 | - focus_controller, |
1028 | - build_policy(std::forward<PolicyArgs>(policy_args)...)) |
1029 | - { |
1030 | - } |
1031 | - |
1032 | -private: |
1033 | - template <typename... PolicyArgs> |
1034 | - auto build_policy(PolicyArgs&&... policy_args) |
1035 | - -> std::unique_ptr<WMPolicy> |
1036 | - { |
1037 | - return std::unique_ptr<WMPolicy>( |
1038 | - new WMPolicy(this, std::forward<PolicyArgs>(policy_args)...)); |
1039 | - } |
1040 | -}; |
1041 | -} |
1042 | -} |
1043 | - |
1044 | -#endif /* MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_ */ |
1045 | |
1046 | === removed file 'examples/server_example_canonical_window_manager.cpp' |
1047 | --- examples/server_example_canonical_window_manager.cpp 2017-07-28 17:00:43 +0000 |
1048 | +++ examples/server_example_canonical_window_manager.cpp 1970-01-01 00:00:00 +0000 |
1049 | @@ -1,1007 +0,0 @@ |
1050 | -/* |
1051 | - * Copyright © 2015 Canonical Ltd. |
1052 | - * |
1053 | - * This program is free software: you can redistribute it and/or modify it |
1054 | - * under the terms of the GNU General Public License version 2 or 3, |
1055 | - * as published by the Free Software Foundation. |
1056 | - * |
1057 | - * This program is distributed in the hope that it will be useful, |
1058 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1059 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1060 | - * GNU General Public License for more details. |
1061 | - * |
1062 | - * You should have received a copy of the GNU General Public License |
1063 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1064 | - * |
1065 | - * Authored By: Alan Griffiths <alan@octopull.co.uk> |
1066 | - */ |
1067 | - |
1068 | -#include "server_example_canonical_window_manager.h" |
1069 | - |
1070 | -#include "mir/scene/session.h" |
1071 | -#include "mir/scene/surface.h" |
1072 | -#include "mir/scene/surface_creation_parameters.h" |
1073 | -#include "mir/shell/surface_ready_observer.h" |
1074 | -#include "mir/shell/display_layout.h" |
1075 | - |
1076 | -#include <linux/input.h> |
1077 | -#include <csignal> |
1078 | -#include <algorithm> |
1079 | - |
1080 | -namespace me = mir::examples; |
1081 | -namespace ms = mir::scene; |
1082 | -using namespace mir::geometry; |
1083 | - |
1084 | -///\example server_example_canonical_window_manager.cpp |
1085 | -// Based on "Mir and Unity: Surfaces, input, and displays (v0.3)" |
1086 | - |
1087 | -namespace |
1088 | -{ |
1089 | -int const title_bar_height = 10; |
1090 | -Size titlebar_size_for_window(Size window_size) |
1091 | -{ |
1092 | - return {window_size.width, Height{title_bar_height}}; |
1093 | -} |
1094 | - |
1095 | -Point titlebar_position_for_window(Point window_position) |
1096 | -{ |
1097 | - return { |
1098 | - window_position.x, |
1099 | - window_position.y - DeltaY(title_bar_height) |
1100 | - }; |
1101 | -} |
1102 | -} |
1103 | - |
1104 | -me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy( |
1105 | - WindowManagerTools* const tools, |
1106 | - std::shared_ptr<shell::DisplayLayout> const& display_layout, |
1107 | - std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator) : |
1108 | - tools{tools}, |
1109 | - display_layout{display_layout}, |
1110 | - allocator{allocator} |
1111 | -{ |
1112 | -} |
1113 | - |
1114 | -void me::CanonicalWindowManagerPolicyCopy::click(Point cursor) |
1115 | -{ |
1116 | - if (auto const surface = tools->surface_at(cursor)) |
1117 | - select_active_surface(surface); |
1118 | -} |
1119 | - |
1120 | -void me::CanonicalWindowManagerPolicyCopy::handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) |
1121 | -{ |
1122 | -} |
1123 | - |
1124 | -void me::CanonicalWindowManagerPolicyCopy::handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& displays) |
1125 | -{ |
1126 | - display_area = displays.bounding_rectangle(); |
1127 | - |
1128 | - for (auto const weak_surface : fullscreen_surfaces) |
1129 | - { |
1130 | - if (auto const surface = weak_surface.lock()) |
1131 | - { |
1132 | - auto const& info = tools->info_for(weak_surface); |
1133 | - Rectangle rect{surface->top_left(), surface->size()}; |
1134 | - |
1135 | - display_layout->place_in_output(info.output_id.value(), rect); |
1136 | - surface->move_to(rect.top_left); |
1137 | - surface->resize(rect.size); |
1138 | - } |
1139 | - } |
1140 | -} |
1141 | - |
1142 | -void me::CanonicalWindowManagerPolicyCopy::resize(Point cursor) |
1143 | -{ |
1144 | - if (!resizing) select_active_surface(tools->surface_at(old_cursor)); |
1145 | - resize(active_surface(), cursor, old_cursor, display_area); |
1146 | -} |
1147 | - |
1148 | -auto me::CanonicalWindowManagerPolicyCopy::handle_place_new_surface( |
1149 | - std::shared_ptr<ms::Session> const& session, |
1150 | - ms::SurfaceCreationParameters const& request_parameters) |
1151 | --> ms::SurfaceCreationParameters |
1152 | -{ |
1153 | - auto parameters = request_parameters; |
1154 | - auto surf_type = parameters.type.is_set() ? parameters.type.value() : mir_window_type_normal; |
1155 | - bool const needs_titlebar = SurfaceInfo::needs_titlebar(surf_type); |
1156 | - |
1157 | - if (needs_titlebar) |
1158 | - parameters.size.height = parameters.size.height + DeltaY{title_bar_height}; |
1159 | - |
1160 | - if (!parameters.state.is_set()) |
1161 | - parameters.state = mir_window_state_restored; |
1162 | - |
1163 | - auto const active_display = tools->active_display(); |
1164 | - |
1165 | - auto const width = parameters.size.width.as_int(); |
1166 | - auto const height = parameters.size.height.as_int(); |
1167 | - |
1168 | - bool positioned = false; |
1169 | - |
1170 | - auto const parent = parameters.parent.lock(); |
1171 | - |
1172 | - if (parameters.output_id != mir::graphics::DisplayConfigurationOutputId{0}) |
1173 | - { |
1174 | - Rectangle rect{parameters.top_left, parameters.size}; |
1175 | - display_layout->place_in_output(parameters.output_id, rect); |
1176 | - parameters.top_left = rect.top_left; |
1177 | - parameters.size = rect.size; |
1178 | - parameters.state = mir_window_state_fullscreen; |
1179 | - positioned = true; |
1180 | - } |
1181 | - else if (!parent) // No parent => client can't suggest positioning |
1182 | - { |
1183 | - if (auto const default_surface = session->default_surface()) |
1184 | - { |
1185 | - static Displacement const offset{title_bar_height, title_bar_height}; |
1186 | - |
1187 | - parameters.top_left = default_surface->top_left() + offset; |
1188 | - |
1189 | - geometry::Rectangle display_for_app{default_surface->top_left(), default_surface->size()}; |
1190 | - |
1191 | - display_layout->size_to_output(display_for_app); |
1192 | - |
1193 | - positioned = display_for_app.overlaps(Rectangle{parameters.top_left, parameters.size}); |
1194 | - } |
1195 | - } |
1196 | - |
1197 | - if (parent && parameters.aux_rect.is_set() && parameters.edge_attachment.is_set()) |
1198 | - { |
1199 | - auto const edge_attachment = parameters.edge_attachment.value(); |
1200 | - auto const aux_rect = parameters.aux_rect.value(); |
1201 | - auto const parent_top_left = parent->top_left(); |
1202 | - auto const top_left = aux_rect.top_left -Point{} + parent_top_left; |
1203 | - auto const top_right= aux_rect.top_right() -Point{} + parent_top_left; |
1204 | - auto const bot_left = aux_rect.bottom_left()-Point{} + parent_top_left; |
1205 | - |
1206 | - if (edge_attachment & mir_edge_attachment_vertical) |
1207 | - { |
1208 | - if (active_display.contains(top_right + Displacement{width, height})) |
1209 | - { |
1210 | - parameters.top_left = top_right; |
1211 | - positioned = true; |
1212 | - } |
1213 | - else if (active_display.contains(top_left + Displacement{-width, height})) |
1214 | - { |
1215 | - parameters.top_left = top_left + Displacement{-width, 0}; |
1216 | - positioned = true; |
1217 | - } |
1218 | - } |
1219 | - |
1220 | - if (edge_attachment & mir_edge_attachment_horizontal) |
1221 | - { |
1222 | - if (active_display.contains(bot_left + Displacement{width, height})) |
1223 | - { |
1224 | - parameters.top_left = bot_left; |
1225 | - positioned = true; |
1226 | - } |
1227 | - else if (active_display.contains(top_left + Displacement{width, -height})) |
1228 | - { |
1229 | - parameters.top_left = top_left + Displacement{0, -height}; |
1230 | - positioned = true; |
1231 | - } |
1232 | - } |
1233 | - } |
1234 | - else if (parent) |
1235 | - { |
1236 | - // o Otherwise, if the dialog is not the same as any previous dialog for the |
1237 | - // same parent window, and/or it does not have user-customized position: |
1238 | - // o It should be optically centered relative to its parent, unless this |
1239 | - // would overlap or cover the title bar of the parent. |
1240 | - // o Otherwise, it should be cascaded vertically (but not horizontally) |
1241 | - // relative to its parent, unless, this would cause at least part of |
1242 | - // it to extend into shell space. |
1243 | - auto const parent_top_left = parent->top_left(); |
1244 | - auto const centred = parent_top_left |
1245 | - + 0.5*(as_displacement(parent->size()) - as_displacement(parameters.size)) |
1246 | - - DeltaY{(parent->size().height.as_int()-height)/6}; |
1247 | - |
1248 | - parameters.top_left = centred; |
1249 | - positioned = true; |
1250 | - } |
1251 | - |
1252 | - if (!positioned) |
1253 | - { |
1254 | - auto const centred = active_display.top_left |
1255 | - + 0.5*(as_displacement(active_display.size) - as_displacement(parameters.size)) |
1256 | - - DeltaY{(active_display.size.height.as_int()-height)/6}; |
1257 | - |
1258 | - switch (parameters.state.value()) |
1259 | - { |
1260 | - case mir_window_state_fullscreen: |
1261 | - case mir_window_state_maximized: |
1262 | - parameters.top_left = active_display.top_left; |
1263 | - parameters.size = active_display.size; |
1264 | - break; |
1265 | - |
1266 | - case mir_window_state_vertmaximized: |
1267 | - parameters.top_left = centred; |
1268 | - parameters.top_left.y = active_display.top_left.y; |
1269 | - parameters.size.height = active_display.size.height; |
1270 | - break; |
1271 | - |
1272 | - case mir_window_state_horizmaximized: |
1273 | - parameters.top_left = centred; |
1274 | - parameters.top_left.x = active_display.top_left.x; |
1275 | - parameters.size.width = active_display.size.width; |
1276 | - break; |
1277 | - |
1278 | - default: |
1279 | - parameters.top_left = centred; |
1280 | - } |
1281 | - |
1282 | - if (parameters.top_left.y < display_area.top_left.y) |
1283 | - parameters.top_left.y = display_area.top_left.y; |
1284 | - } |
1285 | - |
1286 | - if (parameters.state != mir_window_state_fullscreen && needs_titlebar) |
1287 | - { |
1288 | - parameters.top_left.y = parameters.top_left.y + DeltaY{title_bar_height}; |
1289 | - parameters.size.height = parameters.size.height - DeltaY{title_bar_height}; |
1290 | - } |
1291 | - |
1292 | - return parameters; |
1293 | -} |
1294 | - |
1295 | -void me::CanonicalWindowManagerPolicyCopy::generate_decorations_for( |
1296 | - std::shared_ptr<scene::Session> const& session, |
1297 | - std::shared_ptr<scene::Surface> const& surface, |
1298 | - SurfaceInfoMap& surface_map, |
1299 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build) |
1300 | -{ |
1301 | - if (!SurfaceInfo::needs_titlebar(surface->type())) |
1302 | - return; |
1303 | - |
1304 | - auto format = mir_pixel_format_xrgb_8888; |
1305 | - mir::graphics::BufferProperties properties(titlebar_size_for_window(surface->size()), |
1306 | - format, mir::graphics::BufferUsage::software); |
1307 | - auto stream_id = session->create_buffer_stream(properties); |
1308 | - auto params = ms::a_surface() |
1309 | - .of_size(titlebar_size_for_window(surface->size())) |
1310 | - .of_name("decoration") |
1311 | - .of_pixel_format(format) |
1312 | - .of_buffer_usage(mir::graphics::BufferUsage::software) |
1313 | - .of_position(titlebar_position_for_window(surface->top_left())) |
1314 | - .of_type(mir_window_type_gloss) |
1315 | - .with_buffer_stream(stream_id); |
1316 | - auto id = build(session, params); |
1317 | - auto titlebar = session->surface(id); |
1318 | - titlebar->set_alpha(0.9); |
1319 | - |
1320 | - auto& surface_info = tools->info_for(surface); |
1321 | - surface_info.titlebar = titlebar; |
1322 | - surface_info.titlebar_id = id; |
1323 | - surface_info.titlebar_stream_id = stream_id; |
1324 | - surface_info.children.push_back(titlebar); |
1325 | - |
1326 | - SurfaceInfo& titlebar_info = |
1327 | - surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second; |
1328 | - titlebar_info.is_titlebar = true; |
1329 | - titlebar_info.parent = surface; |
1330 | - titlebar_info.init_titlebar(*allocator, titlebar); |
1331 | -} |
1332 | - |
1333 | -void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface) |
1334 | -{ |
1335 | - auto& surface_info = tools->info_for(surface); |
1336 | - if (auto const parent = surface_info.parent.lock()) |
1337 | - { |
1338 | - tools->info_for(parent).children.push_back(surface); |
1339 | - } |
1340 | - |
1341 | - tools->info_for(session).surfaces.push_back(surface); |
1342 | - |
1343 | - if (surface_info.can_be_active()) |
1344 | - { |
1345 | - surface->add_observer(std::make_shared<shell::SurfaceReadyObserver>( |
1346 | - [this](std::shared_ptr<scene::Session> const& /*session*/, |
1347 | - std::shared_ptr<scene::Surface> const& surface) |
1348 | - { |
1349 | - select_active_surface(surface); |
1350 | - }, |
1351 | - session, |
1352 | - surface)); |
1353 | - } |
1354 | - |
1355 | - if (surface_info.state == mir_window_state_fullscreen) |
1356 | - fullscreen_surfaces.insert(surface); |
1357 | -} |
1358 | - |
1359 | -void me::CanonicalWindowManagerPolicyCopy::handle_modify_surface( |
1360 | - std::shared_ptr<scene::Session> const& session, |
1361 | - std::shared_ptr<scene::Surface> const& surface, |
1362 | - shell::SurfaceSpecification const& modifications) |
1363 | -{ |
1364 | - auto& surface_info_old = tools->info_for(surface); |
1365 | - |
1366 | - auto surface_info = surface_info_old; |
1367 | - |
1368 | - if (modifications.parent.is_set()) |
1369 | - surface_info.parent = modifications.parent.value(); |
1370 | - |
1371 | - if (modifications.type.is_set() && |
1372 | - surface_info.type != modifications.type.value()) |
1373 | - { |
1374 | - auto const new_type = modifications.type.value(); |
1375 | - |
1376 | - if (!surface_info.can_morph_to(new_type)) |
1377 | - { |
1378 | - throw std::runtime_error("Unsupported surface type change"); |
1379 | - } |
1380 | - |
1381 | - surface_info.type = new_type; |
1382 | - |
1383 | - if (surface_info.must_not_have_parent()) |
1384 | - { |
1385 | - if (modifications.parent.is_set()) |
1386 | - throw std::runtime_error("Target surface type does not support parent"); |
1387 | - |
1388 | - surface_info.parent.reset(); |
1389 | - } |
1390 | - else if (surface_info.must_have_parent()) |
1391 | - { |
1392 | - if (!surface_info.parent.lock()) |
1393 | - throw std::runtime_error("Target surface type requires parent"); |
1394 | - } |
1395 | - |
1396 | - surface->configure(mir_window_attrib_type, new_type); |
1397 | - } |
1398 | - |
1399 | - #define COPY_IF_SET(field)\ |
1400 | - if (modifications.field.is_set())\ |
1401 | - surface_info.field = modifications.field.value() |
1402 | - |
1403 | - COPY_IF_SET(min_width); |
1404 | - COPY_IF_SET(min_height); |
1405 | - COPY_IF_SET(max_width); |
1406 | - COPY_IF_SET(max_height); |
1407 | - COPY_IF_SET(min_width); |
1408 | - COPY_IF_SET(width_inc); |
1409 | - COPY_IF_SET(height_inc); |
1410 | - COPY_IF_SET(min_aspect); |
1411 | - COPY_IF_SET(max_aspect); |
1412 | - COPY_IF_SET(output_id); |
1413 | - |
1414 | - #undef COPY_IF_SET |
1415 | - |
1416 | - std::swap(surface_info, surface_info_old); |
1417 | - |
1418 | - if (modifications.name.is_set()) |
1419 | - surface->rename(modifications.name.value()); |
1420 | - |
1421 | - if (modifications.streams.is_set()) |
1422 | - { |
1423 | - auto v = modifications.streams.value(); |
1424 | - std::vector<shell::StreamSpecification> l (v.begin(), v.end()); |
1425 | - session->configure_streams(*surface, l); |
1426 | - } |
1427 | - |
1428 | - if (modifications.width.is_set() || modifications.height.is_set()) |
1429 | - { |
1430 | - auto new_size = surface->size(); |
1431 | - |
1432 | - if (modifications.width.is_set()) |
1433 | - new_size.width = modifications.width.value(); |
1434 | - |
1435 | - if (modifications.height.is_set()) |
1436 | - new_size.height = modifications.height.value(); |
1437 | - |
1438 | - auto top_left = surface->top_left(); |
1439 | - |
1440 | - surface_info.constrain_resize( |
1441 | - surface, |
1442 | - top_left, |
1443 | - new_size, |
1444 | - false, |
1445 | - false, |
1446 | - display_area); |
1447 | - |
1448 | - apply_resize(surface, surface_info.titlebar, top_left, new_size); |
1449 | - } |
1450 | - |
1451 | - if (modifications.input_shape.is_set()) |
1452 | - { |
1453 | - auto rectangles = modifications.input_shape.value(); |
1454 | - auto displacement = surface->top_left() - Point{0, 0}; |
1455 | - for(auto& rect : rectangles) |
1456 | - { |
1457 | - rect.top_left = rect.top_left + displacement; |
1458 | - rect = rect.intersection_with({surface->top_left(), surface->size()}); |
1459 | - rect.top_left = rect.top_left - displacement; |
1460 | - } |
1461 | - surface->set_input_region(rectangles); |
1462 | - } |
1463 | - |
1464 | - |
1465 | - if (modifications.state.is_set()) |
1466 | - { |
1467 | - auto const state = handle_set_state(surface, modifications.state.value()); |
1468 | - surface->configure(mir_window_attrib_state, state); |
1469 | - } |
1470 | - |
1471 | - if (modifications.confine_pointer.is_set()) |
1472 | - { |
1473 | - surface->set_confine_pointer_state(modifications.confine_pointer.value()); |
1474 | - } |
1475 | -} |
1476 | - |
1477 | -void me::CanonicalWindowManagerPolicyCopy::handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) |
1478 | -{ |
1479 | - fullscreen_surfaces.erase(surface); |
1480 | - bool const is_active_surface{surface.lock() == active_surface()}; |
1481 | - |
1482 | - auto& info = tools->info_for(surface); |
1483 | - |
1484 | - if (auto const parent = info.parent.lock()) |
1485 | - { |
1486 | - auto& siblings = tools->info_for(parent).children; |
1487 | - |
1488 | - for (auto i = begin(siblings); i != end(siblings); ++i) |
1489 | - { |
1490 | - if (surface.lock() == i->lock()) |
1491 | - { |
1492 | - siblings.erase(i); |
1493 | - break; |
1494 | - } |
1495 | - } |
1496 | - } |
1497 | - |
1498 | - session->destroy_surface(surface); |
1499 | - if (info.titlebar) |
1500 | - { |
1501 | - session->destroy_surface(info.titlebar_id); |
1502 | - session->destroy_buffer_stream(info.titlebar_stream_id); |
1503 | - tools->forget(info.titlebar); |
1504 | - } |
1505 | - |
1506 | - auto& surfaces = tools->info_for(session).surfaces; |
1507 | - |
1508 | - for (auto i = begin(surfaces); i != end(surfaces); ++i) |
1509 | - { |
1510 | - if (surface.lock() == i->lock()) |
1511 | - { |
1512 | - surfaces.erase(i); |
1513 | - break; |
1514 | - } |
1515 | - } |
1516 | - |
1517 | - if (is_active_surface) |
1518 | - { |
1519 | - active_surface_.reset(); |
1520 | - |
1521 | - if (surfaces.empty()) |
1522 | - { |
1523 | - tools->focus_next_session(); |
1524 | - select_active_surface(tools->focused_surface()); |
1525 | - } |
1526 | - else |
1527 | - { |
1528 | - select_active_surface(surfaces[0].lock()); |
1529 | - } |
1530 | - } |
1531 | -} |
1532 | - |
1533 | -int me::CanonicalWindowManagerPolicyCopy::handle_set_state(std::shared_ptr<ms::Surface> const& surface, MirWindowState value) |
1534 | -{ |
1535 | - auto& info = tools->info_for(surface); |
1536 | - |
1537 | - switch (value) |
1538 | - { |
1539 | - case mir_window_state_restored: |
1540 | - case mir_window_state_maximized: |
1541 | - case mir_window_state_vertmaximized: |
1542 | - case mir_window_state_horizmaximized: |
1543 | - case mir_window_state_fullscreen: |
1544 | - case mir_window_state_hidden: |
1545 | - case mir_window_state_minimized: |
1546 | - break; |
1547 | - |
1548 | - default: |
1549 | - return info.state; |
1550 | - } |
1551 | - |
1552 | - if (info.state == mir_window_state_restored) |
1553 | - { |
1554 | - info.restore_rect = {surface->top_left(), surface->size()}; |
1555 | - } |
1556 | - |
1557 | - if (info.state != mir_window_state_fullscreen) |
1558 | - { |
1559 | - info.output_id = decltype(info.output_id){}; |
1560 | - fullscreen_surfaces.erase(surface); |
1561 | - } |
1562 | - else |
1563 | - { |
1564 | - fullscreen_surfaces.insert(surface); |
1565 | - } |
1566 | - |
1567 | - if (info.state == value) |
1568 | - { |
1569 | - return info.state; |
1570 | - } |
1571 | - |
1572 | - auto const old_pos = surface->top_left(); |
1573 | - Displacement movement; |
1574 | - |
1575 | - switch (value) |
1576 | - { |
1577 | - case mir_window_state_restored: |
1578 | - movement = info.restore_rect.top_left - old_pos; |
1579 | - surface->resize(info.restore_rect.size); |
1580 | - if (info.titlebar) |
1581 | - { |
1582 | - info.titlebar->resize(titlebar_size_for_window(info.restore_rect.size)); |
1583 | - info.titlebar->show(); |
1584 | - } |
1585 | - break; |
1586 | - |
1587 | - case mir_window_state_maximized: |
1588 | - movement = display_area.top_left - old_pos; |
1589 | - surface->resize(display_area.size); |
1590 | - if (info.titlebar) |
1591 | - info.titlebar->hide(); |
1592 | - break; |
1593 | - |
1594 | - case mir_window_state_horizmaximized: |
1595 | - movement = Point{display_area.top_left.x, info.restore_rect.top_left.y} - old_pos; |
1596 | - surface->resize({display_area.size.width, info.restore_rect.size.height}); |
1597 | - if (info.titlebar) |
1598 | - { |
1599 | - info.titlebar->resize(titlebar_size_for_window({display_area.size.width, info.restore_rect.size.height})); |
1600 | - info.titlebar->show(); |
1601 | - } |
1602 | - break; |
1603 | - |
1604 | - case mir_window_state_vertmaximized: |
1605 | - movement = Point{info.restore_rect.top_left.x, display_area.top_left.y} - old_pos; |
1606 | - surface->resize({info.restore_rect.size.width, display_area.size.height}); |
1607 | - if (info.titlebar) |
1608 | - info.titlebar->hide(); |
1609 | - break; |
1610 | - |
1611 | - case mir_window_state_fullscreen: |
1612 | - { |
1613 | - Rectangle rect{old_pos, surface->size()}; |
1614 | - |
1615 | - if (info.output_id.is_set()) |
1616 | - { |
1617 | - display_layout->place_in_output(info.output_id.value(), rect); |
1618 | - } |
1619 | - else |
1620 | - { |
1621 | - display_layout->size_to_output(rect); |
1622 | - } |
1623 | - |
1624 | - movement = rect.top_left - old_pos; |
1625 | - surface->resize(rect.size); |
1626 | - break; |
1627 | - } |
1628 | - |
1629 | - case mir_window_state_hidden: |
1630 | - case mir_window_state_minimized: |
1631 | - if (info.titlebar) |
1632 | - info.titlebar->hide(); |
1633 | - surface->hide(); |
1634 | - return info.state = value; |
1635 | - |
1636 | - default: |
1637 | - break; |
1638 | - } |
1639 | - |
1640 | - // TODO It is rather simplistic to move a tree WRT the top_left of the root |
1641 | - // TODO when resizing. But for more sophistication we would need to encode |
1642 | - // TODO some sensible layout rules. |
1643 | - move_tree(surface, movement); |
1644 | - |
1645 | - info.state = value; |
1646 | - |
1647 | - if (info.is_visible()) |
1648 | - surface->show(); |
1649 | - |
1650 | - return info.state; |
1651 | -} |
1652 | - |
1653 | -void me::CanonicalWindowManagerPolicyCopy::drag(Point cursor) |
1654 | -{ |
1655 | - select_active_surface(tools->surface_at(old_cursor)); |
1656 | - drag(active_surface(), cursor, old_cursor, display_area); |
1657 | -} |
1658 | - |
1659 | -void me::CanonicalWindowManagerPolicyCopy::handle_raise_surface( |
1660 | - std::shared_ptr<ms::Session> const& /*session*/, |
1661 | - std::shared_ptr<ms::Surface> const& surface) |
1662 | -{ |
1663 | - select_active_surface(surface); |
1664 | -} |
1665 | - |
1666 | -bool me::CanonicalWindowManagerPolicyCopy::handle_keyboard_event(MirKeyboardEvent const* event) |
1667 | -{ |
1668 | - auto const action = mir_keyboard_event_action(event); |
1669 | - auto const scan_code = mir_keyboard_event_scan_code(event); |
1670 | - auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask; |
1671 | - |
1672 | - if (action == mir_keyboard_action_down && scan_code == KEY_F11) |
1673 | - { |
1674 | - switch (modifiers) |
1675 | - { |
1676 | - case mir_input_event_modifier_alt: |
1677 | - toggle(mir_window_state_maximized); |
1678 | - return true; |
1679 | - |
1680 | - case mir_input_event_modifier_shift: |
1681 | - toggle(mir_window_state_vertmaximized); |
1682 | - return true; |
1683 | - |
1684 | - case mir_input_event_modifier_ctrl: |
1685 | - toggle(mir_window_state_horizmaximized); |
1686 | - return true; |
1687 | - |
1688 | - default: |
1689 | - break; |
1690 | - } |
1691 | - } |
1692 | - else if (action == mir_keyboard_action_down && scan_code == KEY_F4) |
1693 | - { |
1694 | - if (auto const session = tools->focused_session()) |
1695 | - { |
1696 | - switch (modifiers) |
1697 | - { |
1698 | - case mir_input_event_modifier_alt: |
1699 | - kill(session->process_id(), SIGTERM); |
1700 | - return true; |
1701 | - |
1702 | - case mir_input_event_modifier_ctrl: |
1703 | - if (auto const surf = session->default_surface()) |
1704 | - { |
1705 | - surf->request_client_surface_close(); |
1706 | - return true; |
1707 | - } |
1708 | - |
1709 | - default: |
1710 | - break; |
1711 | - } |
1712 | - } |
1713 | - } |
1714 | - else if (action == mir_keyboard_action_down && |
1715 | - modifiers == mir_input_event_modifier_alt && |
1716 | - scan_code == KEY_TAB) |
1717 | - { |
1718 | - tools->focus_next_session(); |
1719 | - if (auto const surface = tools->focused_surface()) |
1720 | - select_active_surface(surface); |
1721 | - |
1722 | - return true; |
1723 | - } |
1724 | - else if (action == mir_keyboard_action_down && |
1725 | - modifiers == mir_input_event_modifier_alt && |
1726 | - scan_code == KEY_GRAVE) |
1727 | - { |
1728 | - if (auto const prev = tools->focused_surface()) |
1729 | - { |
1730 | - if (auto const app = tools->focused_session()) |
1731 | - select_active_surface(app->surface_after(prev)); |
1732 | - } |
1733 | - |
1734 | - return true; |
1735 | - } |
1736 | - |
1737 | - return false; |
1738 | -} |
1739 | - |
1740 | -bool me::CanonicalWindowManagerPolicyCopy::handle_touch_event(MirTouchEvent const* event) |
1741 | -{ |
1742 | - auto const count = mir_touch_event_point_count(event); |
1743 | - |
1744 | - long total_x = 0; |
1745 | - long total_y = 0; |
1746 | - |
1747 | - for (auto i = 0U; i != count; ++i) |
1748 | - { |
1749 | - total_x += mir_touch_event_axis_value(event, i, mir_touch_axis_x); |
1750 | - total_y += mir_touch_event_axis_value(event, i, mir_touch_axis_y); |
1751 | - } |
1752 | - |
1753 | - Point const cursor{total_x/count, total_y/count}; |
1754 | - |
1755 | - bool is_drag = true; |
1756 | - for (auto i = 0U; i != count; ++i) |
1757 | - { |
1758 | - switch (mir_touch_event_action(event, i)) |
1759 | - { |
1760 | - case mir_touch_action_up: |
1761 | - return false; |
1762 | - |
1763 | - case mir_touch_action_down: |
1764 | - is_drag = false; |
1765 | - // fallthrough |
1766 | - case mir_touch_action_change: |
1767 | - continue; |
1768 | - |
1769 | - case mir_touch_actions: |
1770 | - abort(); |
1771 | - break; |
1772 | - } |
1773 | - } |
1774 | - |
1775 | - bool consumes_event = false; |
1776 | - if (is_drag) |
1777 | - { |
1778 | - switch (count) |
1779 | - { |
1780 | - case 4: |
1781 | - resize(cursor); |
1782 | - consumes_event = true; |
1783 | - break; |
1784 | - |
1785 | - case 3: |
1786 | - drag(cursor); |
1787 | - consumes_event = true; |
1788 | - break; |
1789 | - } |
1790 | - } |
1791 | - |
1792 | - old_cursor = cursor; |
1793 | - return consumes_event; |
1794 | -} |
1795 | - |
1796 | -bool me::CanonicalWindowManagerPolicyCopy::handle_pointer_event(MirPointerEvent const* event) |
1797 | -{ |
1798 | - auto const action = mir_pointer_event_action(event); |
1799 | - auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask; |
1800 | - Point const cursor{ |
1801 | - mir_pointer_event_axis_value(event, mir_pointer_axis_x), |
1802 | - mir_pointer_event_axis_value(event, mir_pointer_axis_y)}; |
1803 | - |
1804 | - bool consumes_event = false; |
1805 | - bool resize_event = false; |
1806 | - |
1807 | - if (action == mir_pointer_action_button_down) |
1808 | - { |
1809 | - click(cursor); |
1810 | - } |
1811 | - else if (action == mir_pointer_action_motion && |
1812 | - modifiers == mir_input_event_modifier_alt) |
1813 | - { |
1814 | - if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) |
1815 | - { |
1816 | - drag(cursor); |
1817 | - consumes_event = true; |
1818 | - } |
1819 | - |
1820 | - if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary)) |
1821 | - { |
1822 | - resize(cursor); |
1823 | - resize_event = active_surface_.lock().get(); |
1824 | - consumes_event = true; |
1825 | - } |
1826 | - } |
1827 | - else if (action == mir_pointer_action_motion && !modifiers) |
1828 | - { |
1829 | - if (mir_pointer_event_button_state(event, mir_pointer_button_primary)) |
1830 | - { |
1831 | - if (auto const possible_titlebar = tools->surface_at(old_cursor)) |
1832 | - { |
1833 | - if (tools->info_for(possible_titlebar).is_titlebar) |
1834 | - { |
1835 | - drag(cursor); |
1836 | - consumes_event = true; |
1837 | - } |
1838 | - } |
1839 | - } |
1840 | - } |
1841 | - |
1842 | - resizing = resize_event; |
1843 | - old_cursor = cursor; |
1844 | - return consumes_event; |
1845 | -} |
1846 | - |
1847 | -void me::CanonicalWindowManagerPolicyCopy::toggle(MirWindowState state) |
1848 | -{ |
1849 | - if (auto const surface = active_surface()) |
1850 | - { |
1851 | - auto& info = tools->info_for(surface); |
1852 | - |
1853 | - if (info.state == state) |
1854 | - state = mir_window_state_restored; |
1855 | - |
1856 | - auto const value = handle_set_state(surface, MirWindowState(state)); |
1857 | - surface->configure(mir_window_attrib_state, value); |
1858 | - } |
1859 | -} |
1860 | - |
1861 | -void me::CanonicalWindowManagerPolicyCopy::select_active_surface(std::shared_ptr<ms::Surface> const& surface) |
1862 | -{ |
1863 | - if (surface == active_surface_.lock()) |
1864 | - return; |
1865 | - |
1866 | - if (!surface) |
1867 | - { |
1868 | - if (auto const active_surface = active_surface_.lock()) |
1869 | - { |
1870 | - if (auto const titlebar = tools->info_for(active_surface).titlebar) |
1871 | - { |
1872 | - tools->info_for(titlebar).paint_titlebar(0x3F); |
1873 | - } |
1874 | - } |
1875 | - |
1876 | - if (active_surface_.lock()) |
1877 | - tools->set_focus_to({}, {}); |
1878 | - |
1879 | - active_surface_.reset(); |
1880 | - return; |
1881 | - } |
1882 | - |
1883 | - auto const& info_for = tools->info_for(surface); |
1884 | - |
1885 | - if (info_for.can_be_active()) |
1886 | - { |
1887 | - if (auto const active_surface = active_surface_.lock()) |
1888 | - { |
1889 | - if (auto const titlebar = tools->info_for(active_surface).titlebar) |
1890 | - { |
1891 | - tools->info_for(titlebar).paint_titlebar(0x3F); |
1892 | - } |
1893 | - } |
1894 | - if (auto const titlebar = tools->info_for(surface).titlebar) |
1895 | - { |
1896 | - tools->info_for(titlebar).paint_titlebar(0xFF); |
1897 | - } |
1898 | - tools->set_focus_to(info_for.session.lock(), surface); |
1899 | - tools->raise_tree(surface); |
1900 | - active_surface_ = surface; |
1901 | - } |
1902 | - else |
1903 | - { |
1904 | - // Cannot have input focus - try the parent |
1905 | - if (auto const parent = info_for.parent.lock()) |
1906 | - select_active_surface(parent); |
1907 | - } |
1908 | -} |
1909 | - |
1910 | -auto me::CanonicalWindowManagerPolicyCopy::active_surface() const |
1911 | --> std::shared_ptr<ms::Surface> |
1912 | -{ |
1913 | - if (auto const surface = active_surface_.lock()) |
1914 | - return surface; |
1915 | - |
1916 | - if (auto const session = tools->focused_session()) |
1917 | - { |
1918 | - if (auto const surface = session->default_surface()) |
1919 | - return surface; |
1920 | - } |
1921 | - |
1922 | - return std::shared_ptr<ms::Surface>{}; |
1923 | -} |
1924 | - |
1925 | -bool me::CanonicalWindowManagerPolicyCopy::resize(std::shared_ptr<scene::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds) |
1926 | -{ |
1927 | - if (!surface) |
1928 | - return false; |
1929 | - |
1930 | - auto const& surface_info = tools->info_for(surface); |
1931 | - |
1932 | - auto const top_left = surface->top_left(); |
1933 | - Rectangle const old_pos{top_left, surface->size()}; |
1934 | - |
1935 | - if (!resizing) |
1936 | - { |
1937 | - auto anchor = old_pos.bottom_right(); |
1938 | - |
1939 | - for (auto const& corner : { |
1940 | - old_pos.top_right(), |
1941 | - old_pos.bottom_left(), |
1942 | - top_left}) |
1943 | - { |
1944 | - if ((old_cursor - anchor).length_squared() < |
1945 | - (old_cursor - corner).length_squared()) |
1946 | - { |
1947 | - anchor = corner; |
1948 | - } |
1949 | - } |
1950 | - |
1951 | - left_resize = anchor.x != top_left.x; |
1952 | - top_resize = anchor.y != top_left.y; |
1953 | - } |
1954 | - |
1955 | - int const x_sign = left_resize? -1 : 1; |
1956 | - int const y_sign = top_resize? -1 : 1; |
1957 | - |
1958 | - auto delta = cursor-old_cursor; |
1959 | - |
1960 | - auto new_width = old_pos.size.width + x_sign * delta.dx; |
1961 | - auto new_height = old_pos.size.height + y_sign * delta.dy; |
1962 | - |
1963 | - auto const min_width = std::max(surface_info.min_width, Width{5}); |
1964 | - auto const min_height = std::max(surface_info.min_height, Height{5}); |
1965 | - |
1966 | - if (new_width < min_width) |
1967 | - { |
1968 | - new_width = min_width; |
1969 | - if (delta.dx > DeltaX{0}) |
1970 | - delta.dx = DeltaX{0}; |
1971 | - } |
1972 | - |
1973 | - if (new_height < min_height) |
1974 | - { |
1975 | - new_height = min_height; |
1976 | - if (delta.dy > DeltaY{0}) |
1977 | - delta.dy = DeltaY{0}; |
1978 | - } |
1979 | - |
1980 | - Size new_size{new_width, new_height}; |
1981 | - Point new_pos = top_left + left_resize*delta.dx + top_resize*delta.dy; |
1982 | - |
1983 | - |
1984 | - surface_info.constrain_resize(surface, new_pos, new_size, left_resize, top_resize, bounds); |
1985 | - |
1986 | - apply_resize(surface, surface_info.titlebar, new_pos, new_size); |
1987 | - |
1988 | - return true; |
1989 | -} |
1990 | - |
1991 | -void me::CanonicalWindowManagerPolicyCopy::apply_resize( |
1992 | - std::shared_ptr<ms::Surface> const& surface, |
1993 | - std::shared_ptr<ms::Surface> const& titlebar, |
1994 | - Point const& new_pos, |
1995 | - Size const& new_size) const |
1996 | -{ |
1997 | - if (titlebar) |
1998 | - titlebar->resize({new_size.width, Height{title_bar_height}}); |
1999 | - |
2000 | - surface->resize(new_size); |
2001 | - |
2002 | - move_tree(surface, new_pos-surface->top_left()); |
2003 | -} |
2004 | - |
2005 | -bool me::CanonicalWindowManagerPolicyCopy::drag(std::shared_ptr<scene::Surface> surface, Point to, Point from, Rectangle /*bounds*/) |
2006 | -{ |
2007 | - if (!surface) |
2008 | - return false; |
2009 | - |
2010 | - if (!surface->input_area_contains(from) && !tools->info_for(surface).titlebar) |
2011 | - return false; |
2012 | - |
2013 | - auto movement = to - from; |
2014 | - |
2015 | - // placeholder - constrain onscreen |
2016 | - |
2017 | - switch (tools->info_for(surface).state) |
2018 | - { |
2019 | - case mir_window_state_restored: |
2020 | - break; |
2021 | - |
2022 | - // "A vertically maximised surface is anchored to the top and bottom of |
2023 | - // the available workspace and can have any width." |
2024 | - case mir_window_state_vertmaximized: |
2025 | - movement.dy = DeltaY(0); |
2026 | - break; |
2027 | - |
2028 | - // "A horizontally maximised surface is anchored to the left and right of |
2029 | - // the available workspace and can have any height" |
2030 | - case mir_window_state_horizmaximized: |
2031 | - movement.dx = DeltaX(0); |
2032 | - break; |
2033 | - |
2034 | - // "A maximised surface is anchored to the top, bottom, left and right of the |
2035 | - // available workspace. For example, if the launcher is always-visible then |
2036 | - // the left-edge of the surface is anchored to the right-edge of the launcher." |
2037 | - case mir_window_state_maximized: |
2038 | - case mir_window_state_fullscreen: |
2039 | - default: |
2040 | - return true; |
2041 | - } |
2042 | - |
2043 | - move_tree(surface, movement); |
2044 | - |
2045 | - return true; |
2046 | -} |
2047 | - |
2048 | -void me::CanonicalWindowManagerPolicyCopy::move_tree(std::shared_ptr<ms::Surface> const& root, Displacement movement) const |
2049 | -{ |
2050 | - root->move_to(root->top_left() + movement); |
2051 | - |
2052 | - for (auto const& child: tools->info_for(root).children) |
2053 | - { |
2054 | - move_tree(child.lock(), movement); |
2055 | - } |
2056 | -} |
2057 | |
2058 | === removed file 'examples/server_example_canonical_window_manager.h' |
2059 | --- examples/server_example_canonical_window_manager.h 2017-07-28 17:00:43 +0000 |
2060 | +++ examples/server_example_canonical_window_manager.h 1970-01-01 00:00:00 +0000 |
2061 | @@ -1,142 +0,0 @@ |
2062 | -/* |
2063 | - * Copyright © 2015 Canonical Ltd. |
2064 | - * |
2065 | - * This program is free software: you can redistribute it and/or modify it |
2066 | - * under the terms of the GNU General Public License version 2 or 3, |
2067 | - * as published by the Free Software Foundation. |
2068 | - * |
2069 | - * This program is distributed in the hope that it will be useful, |
2070 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2071 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2072 | - * GNU General Public License for more details. |
2073 | - * |
2074 | - * You should have received a copy of the GNU General Public License |
2075 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2076 | - * |
2077 | - * Authored By: Alan Griffiths <alan@octopull.co.uk> |
2078 | - */ |
2079 | - |
2080 | -#ifndef MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ |
2081 | -#define MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ |
2082 | - |
2083 | -#include "server_example_basic_window_manager.h" |
2084 | - |
2085 | -#include "mir/geometry/displacement.h" |
2086 | - |
2087 | -#include <atomic> |
2088 | -#include <set> |
2089 | - |
2090 | -///\example server_example_canonical_window_manager.h |
2091 | -// Based on "Mir and Unity: Surfaces, input, and displays (v0.3)" |
2092 | - |
2093 | -namespace mir |
2094 | -{ |
2095 | -namespace shell { class DisplayLayout; } |
2096 | -namespace graphics |
2097 | -{ |
2098 | -class GraphicBufferAllocator; |
2099 | -} |
2100 | -namespace examples |
2101 | -{ |
2102 | -// standard window management algorithm: |
2103 | -// o Switch apps: tap or click on the corresponding tile |
2104 | -// o Move window: Alt-leftmousebutton drag (three finger drag) |
2105 | -// o Resize window: Alt-middle_button drag (two finger drag) |
2106 | -// o Maximize/restore current window (to display size): Alt-F11 |
2107 | -// o Maximize/restore current window (to display height): Shift-F11 |
2108 | -// o Maximize/restore current window (to display width): Ctrl-F11 |
2109 | -// o client requests to maximize, vertically maximize & restore |
2110 | -class CanonicalWindowManagerPolicyCopy : public WindowManagementPolicy |
2111 | -{ |
2112 | -public: |
2113 | - |
2114 | - explicit CanonicalWindowManagerPolicyCopy( |
2115 | - WindowManagerTools* const tools, |
2116 | - std::shared_ptr<shell::DisplayLayout> const& display_layout, |
2117 | - std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator); |
2118 | - |
2119 | - void click(geometry::Point cursor); |
2120 | - |
2121 | - void handle_session_info_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); |
2122 | - |
2123 | - void handle_displays_updated(SessionInfoMap& session_info, geometry::Rectangles const& displays); |
2124 | - |
2125 | - void resize(geometry::Point cursor); |
2126 | - |
2127 | - auto handle_place_new_surface( |
2128 | - std::shared_ptr<scene::Session> const& session, |
2129 | - scene::SurfaceCreationParameters const& request_parameters) |
2130 | - -> scene::SurfaceCreationParameters; |
2131 | - |
2132 | - void handle_new_surface(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface); |
2133 | - |
2134 | - void handle_modify_surface( |
2135 | - std::shared_ptr<scene::Session> const& session, |
2136 | - std::shared_ptr<scene::Surface> const& surface, |
2137 | - shell::SurfaceSpecification const& modifications); |
2138 | - |
2139 | - void handle_delete_surface(std::shared_ptr<scene::Session> const& session, std::weak_ptr<scene::Surface> const& surface); |
2140 | - |
2141 | - int handle_set_state(std::shared_ptr<scene::Surface> const& surface, MirWindowState value); |
2142 | - |
2143 | - void drag(geometry::Point cursor); |
2144 | - |
2145 | - bool handle_keyboard_event(MirKeyboardEvent const* event); |
2146 | - |
2147 | - bool handle_touch_event(MirTouchEvent const* event); |
2148 | - |
2149 | - bool handle_pointer_event(MirPointerEvent const* event); |
2150 | - |
2151 | - void handle_raise_surface( |
2152 | - std::shared_ptr<scene::Session> const& session, |
2153 | - std::shared_ptr<scene::Surface> const& surface); |
2154 | - |
2155 | - void generate_decorations_for( |
2156 | - std::shared_ptr<scene::Session> const& session, |
2157 | - std::shared_ptr<scene::Surface> const& surface, |
2158 | - SurfaceInfoMap& surface_map, |
2159 | - std::function<frontend::SurfaceId(std::shared_ptr<scene::Session> const& session, scene::SurfaceCreationParameters const& params)> const& build); |
2160 | - |
2161 | -private: |
2162 | - static const int modifier_mask = |
2163 | - mir_input_event_modifier_alt | |
2164 | - mir_input_event_modifier_shift | |
2165 | - mir_input_event_modifier_sym | |
2166 | - mir_input_event_modifier_ctrl | |
2167 | - mir_input_event_modifier_meta; |
2168 | - |
2169 | - void toggle(MirWindowState state); |
2170 | - |
2171 | - // "Mir and Unity: Surfaces, input, and displays (v0.3)" talks about active |
2172 | - // *window*,but Mir really only understands surfaces |
2173 | - void select_active_surface(std::shared_ptr<scene::Surface> const& surface); |
2174 | - auto active_surface() const -> std::shared_ptr<scene::Surface>; |
2175 | - |
2176 | - bool resize(std::shared_ptr<scene::Surface> const& surface, geometry::Point cursor, geometry::Point old_cursor, geometry::Rectangle bounds); |
2177 | - bool drag(std::shared_ptr<scene::Surface> surface, geometry::Point to, geometry::Point from, geometry::Rectangle bounds); |
2178 | - void move_tree(std::shared_ptr<scene::Surface> const& root, geometry::Displacement movement) const; |
2179 | - void apply_resize( |
2180 | - std::shared_ptr<mir::scene::Surface> const& surface, |
2181 | - std::shared_ptr<mir::scene::Surface> const& titlebar, |
2182 | - geometry::Point const& new_pos, |
2183 | - geometry::Size const& new_size) const; |
2184 | - |
2185 | - WindowManagerTools* const tools; |
2186 | - std::shared_ptr<shell::DisplayLayout> const display_layout; |
2187 | - std::shared_ptr<graphics::GraphicBufferAllocator> const allocator; |
2188 | - |
2189 | - geometry::Rectangle display_area; |
2190 | - geometry::Point old_cursor{}; |
2191 | - std::weak_ptr<scene::Surface> active_surface_; |
2192 | - using FullscreenSurfaces = std::set<std::weak_ptr<scene::Surface>, std::owner_less<std::weak_ptr<scene::Surface>>>; |
2193 | - |
2194 | - FullscreenSurfaces fullscreen_surfaces; |
2195 | - |
2196 | - bool resizing = false; |
2197 | - bool left_resize = false; |
2198 | - bool top_resize = false; |
2199 | -}; |
2200 | -} |
2201 | -} |
2202 | - |
2203 | -#endif /* MIR_EXAMPLE_CANONICAL_WINDOW_MANAGER_H_ */ |
2204 | |
2205 | === removed file 'examples/server_example_cursor_images.cpp' |
2206 | --- examples/server_example_cursor_images.cpp 2017-07-28 17:00:43 +0000 |
2207 | +++ examples/server_example_cursor_images.cpp 1970-01-01 00:00:00 +0000 |
2208 | @@ -1,57 +0,0 @@ |
2209 | -/* |
2210 | - * Copyright © 2015 Canonical Ltd. |
2211 | - * |
2212 | - * This program is free software: you can redistribute it and/or modify it |
2213 | - * under the terms of the GNU General Public License version 2 or 3, |
2214 | - * as published by the Free Software Foundation. |
2215 | - * |
2216 | - * This program is distributed in the hope that it will be useful, |
2217 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2218 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2219 | - * GNU General Public License for more details. |
2220 | - * |
2221 | - * You should have received a copy of the GNU General Public License |
2222 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2223 | - * |
2224 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
2225 | - */ |
2226 | - |
2227 | -#include "server_example_cursor_images.h" |
2228 | -#include "xcursor_loader.h" |
2229 | - |
2230 | -#include "mir/server.h" |
2231 | -#include "mir/options/option.h" |
2232 | - |
2233 | -#include <mir_toolkit/cursors.h> |
2234 | - |
2235 | -namespace mi = mir::input; |
2236 | - |
2237 | -namespace |
2238 | -{ |
2239 | -char const* const xcursor_theme = "x-cursor-theme"; |
2240 | -char const* const xcursor_description = "X Cursor theme to load [default, DMZ-White, DMZ-Black, ...]"; |
2241 | - |
2242 | -bool has_default_cursor(mi::CursorImages& images) |
2243 | -{ |
2244 | - if (images.image(mir_default_cursor_name, mi::default_cursor_size)) |
2245 | - return true; |
2246 | - return false; |
2247 | -} |
2248 | -} |
2249 | - |
2250 | -void mir::examples::add_x_cursor_images(Server& server) |
2251 | -{ |
2252 | - server.add_configuration_option(xcursor_theme, xcursor_description, "default"); |
2253 | - |
2254 | - server.override_the_cursor_images([&] |
2255 | - { |
2256 | - auto const theme = server.get_options()->get<std::string>(xcursor_theme); |
2257 | - |
2258 | - std::shared_ptr<mi::CursorImages> const xcursor_loader{std::make_shared<XCursorLoader>(theme)}; |
2259 | - |
2260 | - if (has_default_cursor(*xcursor_loader)) |
2261 | - return xcursor_loader; |
2262 | - else |
2263 | - return std::shared_ptr<mi::CursorImages>{}; |
2264 | - }); |
2265 | -} |
2266 | |
2267 | === removed file 'examples/server_example_cursor_images.h' |
2268 | --- examples/server_example_cursor_images.h 2017-07-28 17:00:43 +0000 |
2269 | +++ examples/server_example_cursor_images.h 1970-01-01 00:00:00 +0000 |
2270 | @@ -1,33 +0,0 @@ |
2271 | -/* |
2272 | - * Copyright © 2015 Canonical Ltd. |
2273 | - * |
2274 | - * This program is free software: you can redistribute it and/or modify it |
2275 | - * under the terms of the GNU General Public License version 2 or 3, |
2276 | - * as published by the Free Software Foundation. |
2277 | - * |
2278 | - * This program is distributed in the hope that it will be useful, |
2279 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2280 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2281 | - * GNU General Public License for more details. |
2282 | - * |
2283 | - * You should have received a copy of the GNU General Public License |
2284 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2285 | - * |
2286 | - * Authored by: Alan Griffiths <alan@octopull.co.uk> |
2287 | - */ |
2288 | - |
2289 | -#ifndef MIR_EXAMPLE_CURSOR_IMAGES_H |
2290 | -#define MIR_EXAMPLE_CURSOR_IMAGES_H |
2291 | - |
2292 | -namespace mir |
2293 | -{ |
2294 | -class Server; |
2295 | - |
2296 | -namespace examples |
2297 | -{ |
2298 | -void add_x_cursor_images(Server& server); |
2299 | -} |
2300 | -} // namespace mir |
2301 | - |
2302 | - |
2303 | -#endif //MIR_EXAMPLE_CURSOR_IMAGES_H |
2304 | |
2305 | === modified file 'examples/server_example_test_client.cpp' |
2306 | --- examples/server_example_test_client.cpp 2017-07-28 17:00:43 +0000 |
2307 | +++ examples/server_example_test_client.cpp 2017-08-31 08:02:08 +0000 |
2308 | @@ -1,5 +1,5 @@ |
2309 | /* |
2310 | - * Copyright © 2014-2015 Canonical Ltd. |
2311 | + * Copyright © 2014-2017 Canonical Ltd. |
2312 | * |
2313 | * This program is free software: you can redistribute it and/or modify it |
2314 | * under the terms of the GNU General Public License version 2 or 3, |
2315 | @@ -24,11 +24,12 @@ |
2316 | #include "mir/log.h" |
2317 | #include "mir/options/option.h" |
2318 | |
2319 | +#include <chrono> |
2320 | +#include <future> |
2321 | + |
2322 | #include <csignal> |
2323 | #include <sys/wait.h> |
2324 | |
2325 | -#include <chrono> |
2326 | - |
2327 | namespace me = mir::examples; |
2328 | namespace ml = mir::logging; |
2329 | |
2330 | @@ -87,7 +88,16 @@ |
2331 | } |
2332 | } |
2333 | |
2334 | -void me::add_test_client_option_to(mir::Server& server, me::ClientContext& context) |
2335 | +struct me::TestClientRunner::Self |
2336 | +{ |
2337 | + std::unique_ptr<time::Alarm> client_kill_action; |
2338 | + std::unique_ptr<time::Alarm> server_stop_action; |
2339 | + std::atomic<bool> test_failed; |
2340 | +}; |
2341 | + |
2342 | +me::TestClientRunner::TestClientRunner() : self{std::make_shared<Self>()} {} |
2343 | + |
2344 | +void me::TestClientRunner::operator()(mir::Server& server) |
2345 | { |
2346 | static const char* const test_client_opt = "test-client"; |
2347 | static const char* const test_client_descr = "client executable"; |
2348 | @@ -95,16 +105,16 @@ |
2349 | static const char* const test_timeout_opt = "test-timeout"; |
2350 | static const char* const test_timeout_descr = "Seconds to run before sending SIGTERM to client"; |
2351 | |
2352 | - server.add_configuration_option(test_client_opt, test_client_descr, mir::OptionType::string); |
2353 | + server.add_configuration_option(test_client_opt, test_client_descr, OptionType::string); |
2354 | server.add_configuration_option(test_timeout_opt, test_timeout_descr, 10); |
2355 | |
2356 | - server.add_init_callback([&server, &context] |
2357 | + server.add_init_callback([&server, self = self] |
2358 | { |
2359 | - const auto options = server.get_options(); |
2360 | + const auto options1 = server.get_options(); |
2361 | |
2362 | - if (options->is_set(test_client_opt)) |
2363 | + if (options1->is_set(test_client_opt)) |
2364 | { |
2365 | - context.test_failed = true; |
2366 | + self->test_failed = true; |
2367 | |
2368 | auto const client_fd = server.open_client_socket(); |
2369 | |
2370 | @@ -120,29 +130,30 @@ |
2371 | |
2372 | setenv("MIR_SOCKET", connect_string, 1); |
2373 | |
2374 | - auto const client = options->get<std::string>(test_client_opt); |
2375 | + auto const client = options1->get<std::string>(test_client_opt); |
2376 | execlp(client.c_str(), client.c_str(), static_cast<char const*>(nullptr)); |
2377 | + // If execl() returns then something is badly wrong |
2378 | log(logging::Severity::critical, "mir::examples", |
2379 | "Failed to execute client (%s) error: %s", client.c_str(), strerror(errno)); |
2380 | - abort(); // If execl() returns then something is badly wrong |
2381 | + abort(); |
2382 | } |
2383 | else if (pid > 0) |
2384 | { |
2385 | - context.client_kill_action = server.the_main_loop()->create_alarm( |
2386 | + self->client_kill_action = server.the_main_loop()->create_alarm( |
2387 | [pid] |
2388 | { |
2389 | kill(pid, SIGTERM); |
2390 | }); |
2391 | |
2392 | - context.server_stop_action = server.the_main_loop()->create_alarm( |
2393 | - [pid, &server, &context]() |
2394 | + self->server_stop_action = server.the_main_loop()->create_alarm( |
2395 | + [pid, &server, self]() |
2396 | { |
2397 | - context.test_failed = !exit_success(pid); |
2398 | + self->test_failed = !exit_success(pid); |
2399 | server.stop(); |
2400 | }); |
2401 | |
2402 | - context.client_kill_action->reschedule_in(std::chrono::seconds(options->get<int>(test_timeout_opt))); |
2403 | - context.server_stop_action->reschedule_in(std::chrono::seconds(options->get<int>(test_timeout_opt)+1)); |
2404 | + self->client_kill_action->reschedule_in(std::chrono::seconds(options1->get<int>(test_timeout_opt))); |
2405 | + self->server_stop_action->reschedule_in(std::chrono::seconds(options1->get<int>(test_timeout_opt) + 1)); |
2406 | } |
2407 | else |
2408 | { |
2409 | @@ -151,7 +162,9 @@ |
2410 | } |
2411 | else |
2412 | { |
2413 | - context.test_failed = false; |
2414 | + self->test_failed = false; |
2415 | } |
2416 | }); |
2417 | } |
2418 | + |
2419 | +bool me::TestClientRunner::test_failed() const { return self->test_failed; } |
2420 | |
2421 | === modified file 'examples/server_example_test_client.h' |
2422 | --- examples/server_example_test_client.h 2017-07-28 17:00:43 +0000 |
2423 | +++ examples/server_example_test_client.h 2017-08-31 08:02:08 +0000 |
2424 | @@ -20,9 +20,6 @@ |
2425 | #define MIR_EXAMPLE_TEST_CLIENT_H_ |
2426 | |
2427 | #include <memory> |
2428 | -#include <future> |
2429 | - |
2430 | -#include "mir/main_loop.h" |
2431 | |
2432 | namespace mir |
2433 | { |
2434 | @@ -30,14 +27,21 @@ |
2435 | |
2436 | namespace examples |
2437 | { |
2438 | -struct ClientContext |
2439 | + |
2440 | +class TestClientRunner |
2441 | { |
2442 | - std::unique_ptr<mir::time::Alarm> client_kill_action; |
2443 | - std::unique_ptr<mir::time::Alarm> server_stop_action; |
2444 | - std::atomic<bool> test_failed; |
2445 | +public: |
2446 | + TestClientRunner(); |
2447 | + |
2448 | + void operator()(mir::Server& server); |
2449 | + |
2450 | + bool test_failed() const; |
2451 | + |
2452 | +private: |
2453 | + struct Self; |
2454 | + std::shared_ptr<Self> self; |
2455 | }; |
2456 | |
2457 | -void add_test_client_option_to(mir::Server& server, ClientContext& context); |
2458 | } |
2459 | } |
2460 | |
2461 | |
2462 | === removed file 'examples/server_example_window_management.cpp' |
2463 | --- examples/server_example_window_management.cpp 2017-07-28 17:00:43 +0000 |
2464 | +++ examples/server_example_window_management.cpp 1970-01-01 00:00:00 +0000 |
2465 | @@ -1,154 +0,0 @@ |
2466 | -/* |
2467 | - * Copyright © 2014 Canonical Ltd. |
2468 | - * |
2469 | - * This program is free software: you can redistribute it and/or modify it |
2470 | - * under the terms of the GNU General Public License version 2 or 3, |
2471 | - * as published by the Free Software Foundation. |
2472 | - * |
2473 | - * This program is distributed in the hope that it will be useful, |
2474 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2475 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2476 | - * GNU General Public License for more details. |
2477 | - * |
2478 | - * You should have received a copy of the GNU General Public License |
2479 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2480 | - * |
2481 | - * Authored By: Alan Griffiths <alan@octopull.co.uk> |
2482 | - */ |
2483 | - |
2484 | -#include "server_example_window_management.h" |
2485 | - |
2486 | -#include "server_example_canonical_window_manager.h" |
2487 | - |
2488 | -#include "mir/abnormal_exit.h" |
2489 | -#include "mir/server.h" |
2490 | -#include "mir/input/composite_event_filter.h" |
2491 | -#include "mir/options/option.h" |
2492 | -#include "mir/scene/session.h" |
2493 | -#include "mir/scene/surface_creation_parameters.h" |
2494 | -#include "mir/shell/display_layout.h" |
2495 | -#include "mir/shell/system_compositor_window_manager.h" |
2496 | -#include "mir/graphics/platform.h" |
2497 | -#include "mir/graphics/graphic_buffer_allocator.h" |
2498 | - |
2499 | -namespace me = mir::examples; |
2500 | -namespace mf = mir::frontend; |
2501 | -namespace mg = mir::graphics; |
2502 | -namespace mi = mir::input; |
2503 | -namespace ms = mir::scene; |
2504 | -namespace msh = mir::shell; |
2505 | -using namespace mir::geometry; |
2506 | - |
2507 | -///\example server_example_window_management.cpp |
2508 | -/// Demonstrate introducing a window management strategy |
2509 | - |
2510 | -namespace |
2511 | -{ |
2512 | -char const* const wm_option = "window-manager"; |
2513 | -char const* const wm_description = "window management strategy [{canonical|fullscreen|system-compositor}]"; |
2514 | - |
2515 | -char const* const wm_fullscreen = "fullscreen"; |
2516 | -char const* const wm_canonical = "canonical"; |
2517 | -char const* const wm_system_compositor = "system-compositor"; |
2518 | - |
2519 | -// Very simple - make every surface fullscreen |
2520 | -class FullscreenWindowManagerPolicy : public me::WindowManagementPolicy |
2521 | -{ |
2522 | -public: |
2523 | - FullscreenWindowManagerPolicy(me::WindowManagerTools* const /*tools*/, std::shared_ptr<msh::DisplayLayout> const& display_layout) : |
2524 | - display_layout{display_layout} {} |
2525 | - |
2526 | - void handle_session_info_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) override {} |
2527 | - |
2528 | - void handle_displays_updated(SessionInfoMap& /*session_info*/, Rectangles const& /*displays*/) override {} |
2529 | - |
2530 | - auto handle_place_new_surface( |
2531 | - std::shared_ptr<ms::Session> const& /*session*/, |
2532 | - ms::SurfaceCreationParameters const& request_parameters) |
2533 | - -> ms::SurfaceCreationParameters override |
2534 | - { |
2535 | - auto placed_parameters = request_parameters; |
2536 | - |
2537 | - Rectangle rect{request_parameters.top_left, request_parameters.size}; |
2538 | - display_layout->size_to_output(rect); |
2539 | - placed_parameters.size = rect.size; |
2540 | - |
2541 | - return placed_parameters; |
2542 | - } |
2543 | - void handle_modify_surface( |
2544 | - std::shared_ptr<ms::Session> const& /*session*/, |
2545 | - std::shared_ptr<ms::Surface> const& /*surface*/, |
2546 | - msh::SurfaceSpecification const& /*modifications*/) override |
2547 | - { |
2548 | - } |
2549 | - |
2550 | - void handle_new_surface(std::shared_ptr<ms::Session> const& /*session*/, std::shared_ptr<ms::Surface> const& /*surface*/) override |
2551 | - { |
2552 | - } |
2553 | - |
2554 | - void handle_delete_surface(std::shared_ptr<ms::Session> const& session, std::weak_ptr<ms::Surface> const& surface) override |
2555 | - { session->destroy_surface(surface); } |
2556 | - |
2557 | - int handle_set_state(std::shared_ptr<ms::Surface> const& /*surface*/, MirWindowState value) override |
2558 | - { return value; } |
2559 | - |
2560 | - bool handle_keyboard_event(MirKeyboardEvent const* /*event*/) override { return false; } |
2561 | - |
2562 | - bool handle_touch_event(MirTouchEvent const* /*event*/) override { return false; } |
2563 | - |
2564 | - bool handle_pointer_event(MirPointerEvent const* /*event*/) override { return false; } |
2565 | - |
2566 | - void handle_raise_surface( |
2567 | - std::shared_ptr<ms::Session> const& /*session*/, |
2568 | - std::shared_ptr<ms::Surface> const& /*surface*/) override |
2569 | - { |
2570 | - } |
2571 | - |
2572 | - void generate_decorations_for( |
2573 | - std::shared_ptr<ms::Session> const&, |
2574 | - std::shared_ptr<ms::Surface> const&, |
2575 | - SurfaceInfoMap&, |
2576 | - std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const&, ms::SurfaceCreationParameters const&)> const&) override |
2577 | - { |
2578 | - } |
2579 | -private: |
2580 | - std::shared_ptr<msh::DisplayLayout> const display_layout; |
2581 | -}; |
2582 | - |
2583 | -} |
2584 | - |
2585 | -using FullscreenWindowManager = me::WindowManagerBuilder<FullscreenWindowManagerPolicy>; |
2586 | -using CanonicalWindowManager = me::WindowManagerBuilder<me::CanonicalWindowManagerPolicyCopy>; |
2587 | - |
2588 | -void me::add_window_manager_option_to(Server& server) |
2589 | -{ |
2590 | - server.add_configuration_option(wm_option, wm_description, wm_canonical); |
2591 | - |
2592 | - server.override_the_window_manager_builder([&server](msh::FocusController* focus_controller) |
2593 | - -> std::shared_ptr<msh::WindowManager> |
2594 | - { |
2595 | - auto const options = server.get_options(); |
2596 | - auto const selection = options->get<std::string>(wm_option); |
2597 | - |
2598 | - if (selection == wm_fullscreen) |
2599 | - { |
2600 | - return std::make_shared<FullscreenWindowManager>(focus_controller, server.the_shell_display_layout()); |
2601 | - } |
2602 | - else if (selection == wm_canonical) |
2603 | - { |
2604 | - return std::make_shared<CanonicalWindowManager>( |
2605 | - focus_controller, |
2606 | - server.the_shell_display_layout(), |
2607 | - server.the_graphics_platform()->create_buffer_allocator()); |
2608 | - } |
2609 | - else if (selection == wm_system_compositor) |
2610 | - { |
2611 | - return std::make_shared<msh::SystemCompositorWindowManager>( |
2612 | - focus_controller, |
2613 | - server.the_shell_display_layout(), |
2614 | - server.the_session_coordinator()); |
2615 | - } |
2616 | - |
2617 | - throw mir::AbnormalExit("Unknown window manager: " + selection); |
2618 | - }); |
2619 | -} |
2620 | |
2621 | === removed file 'examples/server_example_window_management.h' |
2622 | --- examples/server_example_window_management.h 2017-07-28 17:00:43 +0000 |
2623 | +++ examples/server_example_window_management.h 1970-01-01 00:00:00 +0000 |
2624 | @@ -1,33 +0,0 @@ |
2625 | -/* |
2626 | - * Copyright © 2014 Canonical Ltd. |
2627 | - * |
2628 | - * This program is free software: you can redistribute it and/or modify it |
2629 | - * under the terms of the GNU General Public License version 2 or 3, |
2630 | - * as published by the Free Software Foundation. |
2631 | - * |
2632 | - * This program is distributed in the hope that it will be useful, |
2633 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2634 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2635 | - * GNU General Public License for more details. |
2636 | - * |
2637 | - * You should have received a copy of the GNU General Public License |
2638 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2639 | - * |
2640 | - * Authored By: Alan Griffiths <alan@octopull.co.uk> |
2641 | - */ |
2642 | - |
2643 | -#ifndef MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ |
2644 | -#define MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ |
2645 | - |
2646 | -namespace mir |
2647 | -{ |
2648 | -class Server; |
2649 | - |
2650 | -namespace examples |
2651 | -{ |
2652 | -void add_window_manager_option_to(Server& server); |
2653 | -} |
2654 | -} // namespace mir |
2655 | - |
2656 | - |
2657 | -#endif // MIR_EXAMPLES_WINDOW_MANAGEMENT_H_ |
2658 | |
2659 | === removed file 'examples/xcursor.c' |
2660 | --- examples/xcursor.c 2016-01-29 08:18:22 +0000 |
2661 | +++ examples/xcursor.c 1970-01-01 00:00:00 +0000 |
2662 | @@ -1,973 +0,0 @@ |
2663 | -/* |
2664 | - * Copyright © 2002 Keith Packard |
2665 | - * |
2666 | - * Permission to use, copy, modify, distribute, and sell this software and its |
2667 | - * documentation for any purpose is hereby granted without fee, provided that |
2668 | - * the above copyright notice appear in all copies and that both that |
2669 | - * copyright notice and this permission notice appear in supporting |
2670 | - * documentation, and that the name of Keith Packard not be used in |
2671 | - * advertising or publicity pertaining to distribution of the software without |
2672 | - * specific, written prior permission. Keith Packard makes no |
2673 | - * representations about the suitability of this software for any purpose. It |
2674 | - * is provided "as is" without express or implied warranty. |
2675 | - * |
2676 | - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
2677 | - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
2678 | - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
2679 | - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
2680 | - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
2681 | - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
2682 | - * PERFORMANCE OF THIS SOFTWARE. |
2683 | - */ |
2684 | - |
2685 | -#include "xcursor.h" |
2686 | -#include <stdio.h> |
2687 | -#include <stdlib.h> |
2688 | -#include <string.h> |
2689 | -#include <dirent.h> |
2690 | - |
2691 | -/* |
2692 | - * From libXcursor/include/X11/extensions/Xcursor.h |
2693 | - */ |
2694 | - |
2695 | -#define XcursorTrue 1 |
2696 | -#define XcursorFalse 0 |
2697 | - |
2698 | -/* |
2699 | - * Cursor files start with a header. The header |
2700 | - * contains a magic number, a version number and a |
2701 | - * table of contents which has type and offset information |
2702 | - * for the remaining tables in the file. |
2703 | - * |
2704 | - * File minor versions increment for compatible changes |
2705 | - * File major versions increment for incompatible changes (never, we hope) |
2706 | - * |
2707 | - * Chunks of the same type are always upward compatible. Incompatible |
2708 | - * changes are made with new chunk types; the old data can remain under |
2709 | - * the old type. Upward compatible changes can add header data as the |
2710 | - * header lengths are specified in the file. |
2711 | - * |
2712 | - * File: |
2713 | - * FileHeader |
2714 | - * LISTofChunk |
2715 | - * |
2716 | - * FileHeader: |
2717 | - * CARD32 magic magic number |
2718 | - * CARD32 header bytes in file header |
2719 | - * CARD32 version file version |
2720 | - * CARD32 ntoc number of toc entries |
2721 | - * LISTofFileToc toc table of contents |
2722 | - * |
2723 | - * FileToc: |
2724 | - * CARD32 type entry type |
2725 | - * CARD32 subtype entry subtype (size for images) |
2726 | - * CARD32 position absolute file position |
2727 | - */ |
2728 | - |
2729 | -#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ |
2730 | - |
2731 | -/* |
2732 | - * Current Xcursor version number. Will be substituted by configure |
2733 | - * from the version in the libXcursor configure.ac file. |
2734 | - */ |
2735 | - |
2736 | -#define XCURSOR_LIB_MAJOR 1 |
2737 | -#define XCURSOR_LIB_MINOR 1 |
2738 | -#define XCURSOR_LIB_REVISION 13 |
2739 | -#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \ |
2740 | - (XCURSOR_LIB_MINOR * 100) + \ |
2741 | - (XCURSOR_LIB_REVISION)) |
2742 | - |
2743 | -/* |
2744 | - * This version number is stored in cursor files; changes to the |
2745 | - * file format require updating this version number |
2746 | - */ |
2747 | -#define XCURSOR_FILE_MAJOR 1 |
2748 | -#define XCURSOR_FILE_MINOR 0 |
2749 | -#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) |
2750 | -#define XCURSOR_FILE_HEADER_LEN (4 * 4) |
2751 | -#define XCURSOR_FILE_TOC_LEN (3 * 4) |
2752 | - |
2753 | -typedef struct _XcursorFileToc { |
2754 | - XcursorUInt type; /* chunk type */ |
2755 | - XcursorUInt subtype; /* subtype (size for images) */ |
2756 | - XcursorUInt position; /* absolute position in file */ |
2757 | -} XcursorFileToc; |
2758 | - |
2759 | -typedef struct _XcursorFileHeader { |
2760 | - XcursorUInt magic; /* magic number */ |
2761 | - XcursorUInt header; /* byte length of header */ |
2762 | - XcursorUInt version; /* file version number */ |
2763 | - XcursorUInt ntoc; /* number of toc entries */ |
2764 | - XcursorFileToc *tocs; /* table of contents */ |
2765 | -} XcursorFileHeader; |
2766 | - |
2767 | -/* |
2768 | - * The rest of the file is a list of chunks, each tagged by type |
2769 | - * and version. |
2770 | - * |
2771 | - * Chunk: |
2772 | - * ChunkHeader |
2773 | - * <extra type-specific header fields> |
2774 | - * <type-specific data> |
2775 | - * |
2776 | - * ChunkHeader: |
2777 | - * CARD32 header bytes in chunk header + type header |
2778 | - * CARD32 type chunk type |
2779 | - * CARD32 subtype chunk subtype |
2780 | - * CARD32 version chunk type version |
2781 | - */ |
2782 | - |
2783 | -#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) |
2784 | - |
2785 | -typedef struct _XcursorChunkHeader { |
2786 | - XcursorUInt header; /* bytes in chunk header */ |
2787 | - XcursorUInt type; /* chunk type */ |
2788 | - XcursorUInt subtype; /* chunk subtype (size for images) */ |
2789 | - XcursorUInt version; /* version of this type */ |
2790 | -} XcursorChunkHeader; |
2791 | - |
2792 | -/* |
2793 | - * Here's a list of the known chunk types |
2794 | - */ |
2795 | - |
2796 | -/* |
2797 | - * Comments consist of a 4-byte length field followed by |
2798 | - * UTF-8 encoded text |
2799 | - * |
2800 | - * Comment: |
2801 | - * ChunkHeader header chunk header |
2802 | - * CARD32 length bytes in text |
2803 | - * LISTofCARD8 text UTF-8 encoded text |
2804 | - */ |
2805 | - |
2806 | -#define XCURSOR_COMMENT_TYPE 0xfffe0001 |
2807 | -#define XCURSOR_COMMENT_VERSION 1 |
2808 | -#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4)) |
2809 | -#define XCURSOR_COMMENT_COPYRIGHT 1 |
2810 | -#define XCURSOR_COMMENT_LICENSE 2 |
2811 | -#define XCURSOR_COMMENT_OTHER 3 |
2812 | -#define XCURSOR_COMMENT_MAX_LEN 0x100000 |
2813 | - |
2814 | -typedef struct _XcursorComment { |
2815 | - XcursorUInt version; |
2816 | - XcursorUInt comment_type; |
2817 | - char *comment; |
2818 | -} XcursorComment; |
2819 | - |
2820 | -/* |
2821 | - * Each cursor image occupies a separate image chunk. |
2822 | - * The length of the image header follows the chunk header |
2823 | - * so that future versions can extend the header without |
2824 | - * breaking older applications |
2825 | - * |
2826 | - * Image: |
2827 | - * ChunkHeader header chunk header |
2828 | - * CARD32 width actual width |
2829 | - * CARD32 height actual height |
2830 | - * CARD32 xhot hot spot x |
2831 | - * CARD32 yhot hot spot y |
2832 | - * CARD32 delay animation delay |
2833 | - * LISTofCARD32 pixels ARGB pixels |
2834 | - */ |
2835 | - |
2836 | -#define XCURSOR_IMAGE_TYPE 0xfffd0002 |
2837 | -#define XCURSOR_IMAGE_VERSION 1 |
2838 | -#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) |
2839 | -#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ |
2840 | - |
2841 | -typedef struct _XcursorFile XcursorFile; |
2842 | - |
2843 | -struct _XcursorFile { |
2844 | - void *closure; |
2845 | - int (*read) (XcursorFile *file, unsigned char *buf, int len); |
2846 | - int (*write) (XcursorFile *file, unsigned char *buf, int len); |
2847 | - int (*seek) (XcursorFile *file, long offset, int whence); |
2848 | -}; |
2849 | - |
2850 | -typedef struct _XcursorComments { |
2851 | - int ncomment; /* number of comments */ |
2852 | - XcursorComment **comments; /* array of XcursorComment pointers */ |
2853 | -} XcursorComments; |
2854 | - |
2855 | -/* |
2856 | - * From libXcursor/src/file.c |
2857 | - */ |
2858 | - |
2859 | -static XcursorImage * |
2860 | -XcursorImageCreate (int width, int height) |
2861 | -{ |
2862 | - XcursorImage *image; |
2863 | - |
2864 | - image = malloc (sizeof (XcursorImage) + |
2865 | - width * height * sizeof (XcursorPixel)); |
2866 | - if (!image) |
2867 | - return NULL; |
2868 | - image->version = XCURSOR_IMAGE_VERSION; |
2869 | - image->pixels = (XcursorPixel *) (image + 1); |
2870 | - image->size = width > height ? width : height; |
2871 | - image->width = width; |
2872 | - image->height = height; |
2873 | - image->delay = 0; |
2874 | - return image; |
2875 | -} |
2876 | - |
2877 | -static void |
2878 | -XcursorImageDestroy (XcursorImage *image) |
2879 | -{ |
2880 | - free (image); |
2881 | -} |
2882 | - |
2883 | -static XcursorImages * |
2884 | -XcursorImagesCreate (int size) |
2885 | -{ |
2886 | - XcursorImages *images; |
2887 | - |
2888 | - images = malloc (sizeof (XcursorImages) + |
2889 | - size * sizeof (XcursorImage *)); |
2890 | - if (!images) |
2891 | - return NULL; |
2892 | - images->nimage = 0; |
2893 | - images->images = (XcursorImage **) (images + 1); |
2894 | - images->name = NULL; |
2895 | - return images; |
2896 | -} |
2897 | - |
2898 | -void |
2899 | -XcursorImagesDestroy (XcursorImages *images) |
2900 | -{ |
2901 | - int n; |
2902 | - |
2903 | - if (!images) |
2904 | - return; |
2905 | - |
2906 | - for (n = 0; n < images->nimage; n++) |
2907 | - XcursorImageDestroy (images->images[n]); |
2908 | - if (images->name) |
2909 | - free (images->name); |
2910 | - free (images); |
2911 | -} |
2912 | - |
2913 | -static void |
2914 | -XcursorImagesSetName (XcursorImages *images, const char *name) |
2915 | -{ |
2916 | - char *new; |
2917 | - |
2918 | - if (!images || !name) |
2919 | - return; |
2920 | - |
2921 | - new = malloc (strlen (name) + 1); |
2922 | - |
2923 | - if (!new) |
2924 | - return; |
2925 | - |
2926 | - strcpy (new, name); |
2927 | - if (images->name) |
2928 | - free (images->name); |
2929 | - images->name = new; |
2930 | -} |
2931 | - |
2932 | -static XcursorBool |
2933 | -_XcursorReadUInt (XcursorFile *file, XcursorUInt *u) |
2934 | -{ |
2935 | - unsigned char bytes[4]; |
2936 | - |
2937 | - if (!file || !u) |
2938 | - return XcursorFalse; |
2939 | - |
2940 | - if ((*file->read) (file, bytes, 4) != 4) |
2941 | - return XcursorFalse; |
2942 | - *u = (((XcursorUInt)bytes[0] << 0) | |
2943 | - ((XcursorUInt)bytes[1] << 8) | |
2944 | - ((XcursorUInt)bytes[2] << 16) | |
2945 | - ((XcursorUInt)bytes[3] << 24)); |
2946 | - return XcursorTrue; |
2947 | -} |
2948 | - |
2949 | -static void |
2950 | -_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader) |
2951 | -{ |
2952 | - free (fileHeader); |
2953 | -} |
2954 | - |
2955 | -static XcursorFileHeader * |
2956 | -_XcursorFileHeaderCreate (int ntoc) |
2957 | -{ |
2958 | - XcursorFileHeader *fileHeader; |
2959 | - |
2960 | - if (ntoc > 0x10000) |
2961 | - return NULL; |
2962 | - fileHeader = malloc (sizeof (XcursorFileHeader) + |
2963 | - ntoc * sizeof (XcursorFileToc)); |
2964 | - if (!fileHeader) |
2965 | - return NULL; |
2966 | - fileHeader->magic = XCURSOR_MAGIC; |
2967 | - fileHeader->header = XCURSOR_FILE_HEADER_LEN; |
2968 | - fileHeader->version = XCURSOR_FILE_VERSION; |
2969 | - fileHeader->ntoc = ntoc; |
2970 | - fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); |
2971 | - return fileHeader; |
2972 | -} |
2973 | - |
2974 | -static XcursorFileHeader * |
2975 | -_XcursorReadFileHeader (XcursorFile *file) |
2976 | -{ |
2977 | - XcursorFileHeader head, *fileHeader; |
2978 | - XcursorUInt skip; |
2979 | - unsigned int n; |
2980 | - |
2981 | - if (!file) |
2982 | - return NULL; |
2983 | - |
2984 | - if (!_XcursorReadUInt (file, &head.magic)) |
2985 | - return NULL; |
2986 | - if (head.magic != XCURSOR_MAGIC) |
2987 | - return NULL; |
2988 | - if (!_XcursorReadUInt (file, &head.header)) |
2989 | - return NULL; |
2990 | - if (!_XcursorReadUInt (file, &head.version)) |
2991 | - return NULL; |
2992 | - if (!_XcursorReadUInt (file, &head.ntoc)) |
2993 | - return NULL; |
2994 | - skip = head.header - XCURSOR_FILE_HEADER_LEN; |
2995 | - if (skip) |
2996 | - if ((*file->seek) (file, skip, SEEK_CUR) == EOF) |
2997 | - return NULL; |
2998 | - fileHeader = _XcursorFileHeaderCreate (head.ntoc); |
2999 | - if (!fileHeader) |
3000 | - return NULL; |
3001 | - fileHeader->magic = head.magic; |
3002 | - fileHeader->header = head.header; |
3003 | - fileHeader->version = head.version; |
3004 | - fileHeader->ntoc = head.ntoc; |
3005 | - for (n = 0; n < fileHeader->ntoc; n++) |
3006 | - { |
3007 | - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) |
3008 | - break; |
3009 | - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) |
3010 | - break; |
3011 | - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) |
3012 | - break; |
3013 | - } |
3014 | - if (n != fileHeader->ntoc) |
3015 | - { |
3016 | - _XcursorFileHeaderDestroy (fileHeader); |
3017 | - return NULL; |
3018 | - } |
3019 | - return fileHeader; |
3020 | -} |
3021 | - |
3022 | -static XcursorBool |
3023 | -_XcursorSeekToToc (XcursorFile *file, |
3024 | - XcursorFileHeader *fileHeader, |
3025 | - int toc) |
3026 | -{ |
3027 | - if (!file || !fileHeader || \ |
3028 | - (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF) |
3029 | - return XcursorFalse; |
3030 | - return XcursorTrue; |
3031 | -} |
3032 | - |
3033 | -static XcursorBool |
3034 | -_XcursorFileReadChunkHeader (XcursorFile *file, |
3035 | - XcursorFileHeader *fileHeader, |
3036 | - int toc, |
3037 | - XcursorChunkHeader *chunkHeader) |
3038 | -{ |
3039 | - if (!file || !fileHeader || !chunkHeader) |
3040 | - return XcursorFalse; |
3041 | - if (!_XcursorSeekToToc (file, fileHeader, toc)) |
3042 | - return XcursorFalse; |
3043 | - if (!_XcursorReadUInt (file, &chunkHeader->header)) |
3044 | - return XcursorFalse; |
3045 | - if (!_XcursorReadUInt (file, &chunkHeader->type)) |
3046 | - return XcursorFalse; |
3047 | - if (!_XcursorReadUInt (file, &chunkHeader->subtype)) |
3048 | - return XcursorFalse; |
3049 | - if (!_XcursorReadUInt (file, &chunkHeader->version)) |
3050 | - return XcursorFalse; |
3051 | - /* sanity check */ |
3052 | - if (chunkHeader->type != fileHeader->tocs[toc].type || |
3053 | - chunkHeader->subtype != fileHeader->tocs[toc].subtype) |
3054 | - return XcursorFalse; |
3055 | - return XcursorTrue; |
3056 | -} |
3057 | - |
3058 | -#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a)) |
3059 | - |
3060 | -static XcursorDim |
3061 | -_XcursorFindBestSize (XcursorFileHeader *fileHeader, |
3062 | - XcursorDim size, |
3063 | - int *nsizesp) |
3064 | -{ |
3065 | - unsigned int n; |
3066 | - int nsizes = 0; |
3067 | - XcursorDim bestSize = 0; |
3068 | - XcursorDim thisSize; |
3069 | - |
3070 | - if (!fileHeader || !nsizesp) |
3071 | - return 0; |
3072 | - |
3073 | - for (n = 0; n < fileHeader->ntoc; n++) |
3074 | - { |
3075 | - if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE) |
3076 | - continue; |
3077 | - thisSize = fileHeader->tocs[n].subtype; |
3078 | - if (!bestSize || dist (thisSize, size) < dist (bestSize, size)) |
3079 | - { |
3080 | - bestSize = thisSize; |
3081 | - nsizes = 1; |
3082 | - } |
3083 | - else if (thisSize == bestSize) |
3084 | - nsizes++; |
3085 | - } |
3086 | - *nsizesp = nsizes; |
3087 | - return bestSize; |
3088 | -} |
3089 | - |
3090 | -static int |
3091 | -_XcursorFindImageToc (XcursorFileHeader *fileHeader, |
3092 | - XcursorDim size, |
3093 | - int count) |
3094 | -{ |
3095 | - unsigned int toc; |
3096 | - XcursorDim thisSize; |
3097 | - |
3098 | - if (!fileHeader) |
3099 | - return 0; |
3100 | - |
3101 | - for (toc = 0; toc < fileHeader->ntoc; toc++) |
3102 | - { |
3103 | - if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE) |
3104 | - continue; |
3105 | - thisSize = fileHeader->tocs[toc].subtype; |
3106 | - if (thisSize != size) |
3107 | - continue; |
3108 | - if (!count) |
3109 | - break; |
3110 | - count--; |
3111 | - } |
3112 | - if (toc == fileHeader->ntoc) |
3113 | - return -1; |
3114 | - return toc; |
3115 | -} |
3116 | - |
3117 | -static XcursorImage * |
3118 | -_XcursorReadImage (XcursorFile *file, |
3119 | - XcursorFileHeader *fileHeader, |
3120 | - int toc) |
3121 | -{ |
3122 | - XcursorChunkHeader chunkHeader; |
3123 | - XcursorImage head; |
3124 | - XcursorImage *image; |
3125 | - int n; |
3126 | - XcursorPixel *p; |
3127 | - |
3128 | - if (!file || !fileHeader) |
3129 | - return NULL; |
3130 | - |
3131 | - if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) |
3132 | - return NULL; |
3133 | - if (!_XcursorReadUInt (file, &head.width)) |
3134 | - return NULL; |
3135 | - if (!_XcursorReadUInt (file, &head.height)) |
3136 | - return NULL; |
3137 | - if (!_XcursorReadUInt (file, &head.xhot)) |
3138 | - return NULL; |
3139 | - if (!_XcursorReadUInt (file, &head.yhot)) |
3140 | - return NULL; |
3141 | - if (!_XcursorReadUInt (file, &head.delay)) |
3142 | - return NULL; |
3143 | - /* sanity check data */ |
3144 | - if (head.width >= 0x10000 || head.height > 0x10000) |
3145 | - return NULL; |
3146 | - if (head.width == 0 || head.height == 0) |
3147 | - return NULL; |
3148 | - if (head.xhot > head.width || head.yhot > head.height) |
3149 | - return NULL; |
3150 | - |
3151 | - /* Create the image and initialize it */ |
3152 | - image = XcursorImageCreate (head.width, head.height); |
3153 | - if (image == NULL) |
3154 | - return NULL; |
3155 | - if (chunkHeader.version < image->version) |
3156 | - image->version = chunkHeader.version; |
3157 | - image->size = chunkHeader.subtype; |
3158 | - image->xhot = head.xhot; |
3159 | - image->yhot = head.yhot; |
3160 | - image->delay = head.delay; |
3161 | - n = image->width * image->height; |
3162 | - p = image->pixels; |
3163 | - while (n--) |
3164 | - { |
3165 | - if (!_XcursorReadUInt (file, p)) |
3166 | - { |
3167 | - XcursorImageDestroy (image); |
3168 | - return NULL; |
3169 | - } |
3170 | - p++; |
3171 | - } |
3172 | - return image; |
3173 | -} |
3174 | - |
3175 | -static XcursorImages * |
3176 | -XcursorXcFileLoadImages (XcursorFile *file, int size) |
3177 | -{ |
3178 | - XcursorFileHeader *fileHeader; |
3179 | - XcursorDim bestSize; |
3180 | - int nsize; |
3181 | - XcursorImages *images; |
3182 | - int n; |
3183 | - int toc; |
3184 | - |
3185 | - if (!file || size < 0) |
3186 | - return NULL; |
3187 | - fileHeader = _XcursorReadFileHeader (file); |
3188 | - if (!fileHeader) |
3189 | - return NULL; |
3190 | - bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); |
3191 | - if (!bestSize) |
3192 | - { |
3193 | - _XcursorFileHeaderDestroy (fileHeader); |
3194 | - return NULL; |
3195 | - } |
3196 | - images = XcursorImagesCreate (nsize); |
3197 | - if (!images) |
3198 | - { |
3199 | - _XcursorFileHeaderDestroy (fileHeader); |
3200 | - return NULL; |
3201 | - } |
3202 | - for (n = 0; n < nsize; n++) |
3203 | - { |
3204 | - toc = _XcursorFindImageToc (fileHeader, bestSize, n); |
3205 | - if (toc < 0) |
3206 | - break; |
3207 | - images->images[images->nimage] = _XcursorReadImage (file, fileHeader, |
3208 | - toc); |
3209 | - if (!images->images[images->nimage]) |
3210 | - break; |
3211 | - images->nimage++; |
3212 | - } |
3213 | - _XcursorFileHeaderDestroy (fileHeader); |
3214 | - if (images->nimage != nsize) |
3215 | - { |
3216 | - XcursorImagesDestroy (images); |
3217 | - images = NULL; |
3218 | - } |
3219 | - return images; |
3220 | -} |
3221 | - |
3222 | -static int |
3223 | -_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) |
3224 | -{ |
3225 | - FILE *f = file->closure; |
3226 | - return fread (buf, 1, len, f); |
3227 | -} |
3228 | - |
3229 | -static int |
3230 | -_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len) |
3231 | -{ |
3232 | - FILE *f = file->closure; |
3233 | - return fwrite (buf, 1, len, f); |
3234 | -} |
3235 | - |
3236 | -static int |
3237 | -_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) |
3238 | -{ |
3239 | - FILE *f = file->closure; |
3240 | - return fseek (f, offset, whence); |
3241 | -} |
3242 | - |
3243 | -static void |
3244 | -_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) |
3245 | -{ |
3246 | - file->closure = stdfile; |
3247 | - file->read = _XcursorStdioFileRead; |
3248 | - file->write = _XcursorStdioFileWrite; |
3249 | - file->seek = _XcursorStdioFileSeek; |
3250 | -} |
3251 | - |
3252 | -static XcursorImages * |
3253 | -XcursorFileLoadImages (FILE *file, int size) |
3254 | -{ |
3255 | - XcursorFile f; |
3256 | - |
3257 | - if (!file) |
3258 | - return NULL; |
3259 | - |
3260 | - _XcursorStdioFileInitialize (file, &f); |
3261 | - return XcursorXcFileLoadImages (&f, size); |
3262 | -} |
3263 | - |
3264 | -/* |
3265 | - * From libXcursor/src/library.c |
3266 | - */ |
3267 | - |
3268 | -#ifndef ICONDIR |
3269 | -#define ICONDIR "/usr/X11R6/lib/X11/icons" |
3270 | -#endif |
3271 | - |
3272 | -#ifndef XCURSORPATH |
3273 | -#define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR |
3274 | -#endif |
3275 | - |
3276 | -static const char * |
3277 | -XcursorLibraryPath (void) |
3278 | -{ |
3279 | - static const char *path; |
3280 | - |
3281 | - if (!path) |
3282 | - { |
3283 | - path = getenv ("XCURSOR_PATH"); |
3284 | - if (!path) |
3285 | - path = XCURSORPATH; |
3286 | - } |
3287 | - return path; |
3288 | -} |
3289 | - |
3290 | -static void |
3291 | -_XcursorAddPathElt (char *path, const char *elt, int len) |
3292 | -{ |
3293 | - int pathlen = strlen (path); |
3294 | - |
3295 | - /* append / if the path doesn't currently have one */ |
3296 | - if (path[0] == '\0' || path[pathlen - 1] != '/') |
3297 | - { |
3298 | - strcat (path, "/"); |
3299 | - pathlen++; |
3300 | - } |
3301 | - if (len == -1) |
3302 | - len = strlen (elt); |
3303 | - /* strip leading slashes */ |
3304 | - while (len && elt[0] == '/') |
3305 | - { |
3306 | - elt++; |
3307 | - len--; |
3308 | - } |
3309 | - strncpy (path + pathlen, elt, len); |
3310 | - path[pathlen + len] = '\0'; |
3311 | -} |
3312 | - |
3313 | -static char * |
3314 | -_XcursorBuildThemeDir (const char *dir, const char *theme) |
3315 | -{ |
3316 | - const char *colon; |
3317 | - const char *tcolon; |
3318 | - char *full; |
3319 | - char *home; |
3320 | - int dirlen; |
3321 | - int homelen; |
3322 | - int themelen; |
3323 | - int len; |
3324 | - |
3325 | - if (!dir || !theme) |
3326 | - return NULL; |
3327 | - |
3328 | - colon = strchr (dir, ':'); |
3329 | - if (!colon) |
3330 | - colon = dir + strlen (dir); |
3331 | - |
3332 | - dirlen = colon - dir; |
3333 | - |
3334 | - tcolon = strchr (theme, ':'); |
3335 | - if (!tcolon) |
3336 | - tcolon = theme + strlen (theme); |
3337 | - |
3338 | - themelen = tcolon - theme; |
3339 | - |
3340 | - home = NULL; |
3341 | - homelen = 0; |
3342 | - if (*dir == '~') |
3343 | - { |
3344 | - home = getenv ("HOME"); |
3345 | - if (!home) |
3346 | - return NULL; |
3347 | - homelen = strlen (home); |
3348 | - dir++; |
3349 | - dirlen--; |
3350 | - } |
3351 | - |
3352 | - /* |
3353 | - * add space for any needed directory separators, one per component, |
3354 | - * and one for the trailing null |
3355 | - */ |
3356 | - len = 1 + homelen + 1 + dirlen + 1 + themelen + 1; |
3357 | - |
3358 | - full = malloc (len); |
3359 | - if (!full) |
3360 | - return NULL; |
3361 | - full[0] = '\0'; |
3362 | - |
3363 | - if (home) |
3364 | - _XcursorAddPathElt (full, home, -1); |
3365 | - _XcursorAddPathElt (full, dir, dirlen); |
3366 | - _XcursorAddPathElt (full, theme, themelen); |
3367 | - return full; |
3368 | -} |
3369 | - |
3370 | -static char * |
3371 | -_XcursorBuildFullname (const char *dir, const char *subdir, const char *file) |
3372 | -{ |
3373 | - char *full; |
3374 | - |
3375 | - if (!dir || !subdir || !file) |
3376 | - return NULL; |
3377 | - |
3378 | - /* |
3379 | - * Following the g++5 transition the strlen() in _XcursorAddPathElt() can |
3380 | - * trigger valgrind. We add some padding as a workaround. |
3381 | - */ |
3382 | - size_t padding = 4; |
3383 | - full = malloc (padding + strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1); |
3384 | - if (!full) |
3385 | - return NULL; |
3386 | - full[0] = '\0'; |
3387 | - _XcursorAddPathElt (full, dir, -1); |
3388 | - _XcursorAddPathElt (full, subdir, -1); |
3389 | - _XcursorAddPathElt (full, file, -1); |
3390 | - return full; |
3391 | -} |
3392 | - |
3393 | -static const char * |
3394 | -_XcursorNextPath (const char *path) |
3395 | -{ |
3396 | - char *colon = strchr (path, ':'); |
3397 | - |
3398 | - if (!colon) |
3399 | - return NULL; |
3400 | - return colon + 1; |
3401 | -} |
3402 | - |
3403 | -#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') |
3404 | -#define XcursorSep(c) ((c) == ';' || (c) == ',') |
3405 | - |
3406 | -static char * |
3407 | -_XcursorThemeInherits (const char *full) |
3408 | -{ |
3409 | - char line[8192]; |
3410 | - char *result = NULL; |
3411 | - FILE *f; |
3412 | - |
3413 | - if (!full) |
3414 | - return NULL; |
3415 | - |
3416 | - f = fopen (full, "r"); |
3417 | - if (f) |
3418 | - { |
3419 | - while (fgets (line, sizeof (line), f)) |
3420 | - { |
3421 | - if (!strncmp (line, "Inherits", 8)) |
3422 | - { |
3423 | - char *l = line + 8; |
3424 | - char *r; |
3425 | - while (*l == ' ') l++; |
3426 | - if (*l != '=') continue; |
3427 | - l++; |
3428 | - while (*l == ' ') l++; |
3429 | - result = malloc (strlen (l) + 1); |
3430 | - if (result) |
3431 | - { |
3432 | - r = result; |
3433 | - while (*l) |
3434 | - { |
3435 | - while (XcursorSep(*l) || XcursorWhite (*l)) l++; |
3436 | - if (!*l) |
3437 | - break; |
3438 | - if (r != result) |
3439 | - *r++ = ':'; |
3440 | - while (*l && !XcursorWhite(*l) && |
3441 | - !XcursorSep(*l)) |
3442 | - *r++ = *l++; |
3443 | - } |
3444 | - *r++ = '\0'; |
3445 | - } |
3446 | - break; |
3447 | - } |
3448 | - } |
3449 | - fclose (f); |
3450 | - } |
3451 | - return result; |
3452 | -} |
3453 | - |
3454 | -static FILE * |
3455 | -XcursorScanTheme (const char *theme, const char *name) |
3456 | -{ |
3457 | - FILE *f = NULL; |
3458 | - char *full; |
3459 | - char *dir; |
3460 | - const char *path; |
3461 | - char *inherits = NULL; |
3462 | - const char *i; |
3463 | - |
3464 | - if (!theme || !name) |
3465 | - return NULL; |
3466 | - |
3467 | - /* |
3468 | - * Scan this theme |
3469 | - */ |
3470 | - for (path = XcursorLibraryPath (); |
3471 | - path && f == NULL; |
3472 | - path = _XcursorNextPath (path)) |
3473 | - { |
3474 | - dir = _XcursorBuildThemeDir (path, theme); |
3475 | - if (dir) |
3476 | - { |
3477 | - full = _XcursorBuildFullname (dir, "cursors", name); |
3478 | - if (full) |
3479 | - { |
3480 | - f = fopen (full, "r"); |
3481 | - free (full); |
3482 | - } |
3483 | - if (!f && !inherits) |
3484 | - { |
3485 | - full = _XcursorBuildFullname (dir, "", "index.theme"); |
3486 | - if (full) |
3487 | - { |
3488 | - inherits = _XcursorThemeInherits (full); |
3489 | - free (full); |
3490 | - } |
3491 | - } |
3492 | - free (dir); |
3493 | - } |
3494 | - } |
3495 | - /* |
3496 | - * Recurse to scan inherited themes |
3497 | - */ |
3498 | - for (i = inherits; i && f == NULL; i = _XcursorNextPath (i)) |
3499 | - f = XcursorScanTheme (i, name); |
3500 | - if (inherits != NULL) |
3501 | - free (inherits); |
3502 | - return f; |
3503 | -} |
3504 | - |
3505 | -XcursorImages * |
3506 | -XcursorLibraryLoadImages (const char *file, const char *theme, int size) |
3507 | -{ |
3508 | - FILE *f = NULL; |
3509 | - XcursorImages *images = NULL; |
3510 | - |
3511 | - if (!file) |
3512 | - return NULL; |
3513 | - |
3514 | - if (theme) |
3515 | - f = XcursorScanTheme (theme, file); |
3516 | - if (!f) |
3517 | - f = XcursorScanTheme ("default", file); |
3518 | - if (f) |
3519 | - { |
3520 | - images = XcursorFileLoadImages (f, size); |
3521 | - if (images) |
3522 | - XcursorImagesSetName (images, file); |
3523 | - fclose (f); |
3524 | - } |
3525 | - return images; |
3526 | -} |
3527 | - |
3528 | -static void |
3529 | -load_all_cursors_from_dir(const char *path, int size, |
3530 | - void (*load_callback)(XcursorImages *, void *), |
3531 | - void *user_data) |
3532 | -{ |
3533 | - FILE *f; |
3534 | - DIR *dir = opendir(path); |
3535 | - struct dirent *ent; |
3536 | - char *full; |
3537 | - XcursorImages *images; |
3538 | - |
3539 | - if (!dir) |
3540 | - return; |
3541 | - |
3542 | - for(ent = readdir(dir); ent; ent = readdir(dir)) { |
3543 | -#ifdef _DIRENT_HAVE_D_TYPE |
3544 | - if (ent->d_type != DT_UNKNOWN && |
3545 | - (ent->d_type != DT_REG && ent->d_type != DT_LNK)) |
3546 | - continue; |
3547 | -#endif |
3548 | - |
3549 | - full = _XcursorBuildFullname(path, "", ent->d_name); |
3550 | - if (!full) |
3551 | - continue; |
3552 | - |
3553 | - f = fopen(full, "r"); |
3554 | - if (!f) { |
3555 | - free(full); |
3556 | - continue; |
3557 | - } |
3558 | - |
3559 | - images = XcursorFileLoadImages(f, size); |
3560 | - |
3561 | - if (images) { |
3562 | - XcursorImagesSetName(images, ent->d_name); |
3563 | - load_callback(images, user_data); |
3564 | - } |
3565 | - |
3566 | - fclose (f); |
3567 | - free(full); |
3568 | - } |
3569 | - |
3570 | - closedir(dir); |
3571 | -} |
3572 | - |
3573 | -/** Load all the cursor of a theme |
3574 | - * |
3575 | - * This function loads all the cursor images of a given theme and its |
3576 | - * inherited themes. Each cursor is loaded into an XcursorImages object |
3577 | - * which is passed to the caller's load callback. If a cursor appears |
3578 | - * more than once across all the inherited themes, the load callback |
3579 | - * will be called multiple times, with possibly different XcursorImages |
3580 | - * object which have the same name. The user is expected to destroy the |
3581 | - * XcursorImages objects passed to the callback with |
3582 | - * XcursorImagesDestroy(). |
3583 | - * |
3584 | - * \param theme The name of theme that should be loaded |
3585 | - * \param size The desired size of the cursor images |
3586 | - * \param load_callback A callback function that will be called |
3587 | - * for each cursor loaded. The first parameter is the XcursorImages |
3588 | - * object representing the loaded cursor and the second is a pointer |
3589 | - * to data provided by the user. |
3590 | - * \param user_data The data that should be passed to the load callback |
3591 | - */ |
3592 | -void |
3593 | -xcursor_load_theme(const char *theme, int size, |
3594 | - void (*load_callback)(XcursorImages *, void *), |
3595 | - void *user_data) |
3596 | -{ |
3597 | - char *full, *dir; |
3598 | - char *inherits = NULL; |
3599 | - const char *path, *i; |
3600 | - |
3601 | - if (!theme) |
3602 | - theme = "default"; |
3603 | - |
3604 | - for (path = XcursorLibraryPath(); |
3605 | - path; |
3606 | - path = _XcursorNextPath(path)) { |
3607 | - dir = _XcursorBuildThemeDir(path, theme); |
3608 | - if (!dir) |
3609 | - continue; |
3610 | - |
3611 | - full = _XcursorBuildFullname(dir, "cursors", ""); |
3612 | - |
3613 | - if (full) { |
3614 | - load_all_cursors_from_dir(full, size, load_callback, |
3615 | - user_data); |
3616 | - free(full); |
3617 | - } |
3618 | - |
3619 | - if (!inherits) { |
3620 | - full = _XcursorBuildFullname(dir, "", "index.theme"); |
3621 | - if (full) { |
3622 | - inherits = _XcursorThemeInherits(full); |
3623 | - free(full); |
3624 | - } |
3625 | - } |
3626 | - |
3627 | - free(dir); |
3628 | - } |
3629 | - |
3630 | - for (i = inherits; i; i = _XcursorNextPath(i)) |
3631 | - xcursor_load_theme(i, size, load_callback, user_data); |
3632 | - |
3633 | - if (inherits) |
3634 | - free(inherits); |
3635 | -} |
3636 | |
3637 | === removed file 'examples/xcursor.h' |
3638 | --- examples/xcursor.h 2016-01-29 08:18:22 +0000 |
3639 | +++ examples/xcursor.h 1970-01-01 00:00:00 +0000 |
3640 | @@ -1,65 +0,0 @@ |
3641 | -/* |
3642 | - * Copyright © 2002 Keith Packard |
3643 | - * |
3644 | - * Permission to use, copy, modify, distribute, and sell this software and its |
3645 | - * documentation for any purpose is hereby granted without fee, provided that |
3646 | - * the above copyright notice appear in all copies and that both that |
3647 | - * copyright notice and this permission notice appear in supporting |
3648 | - * documentation, and that the name of Keith Packard not be used in |
3649 | - * advertising or publicity pertaining to distribution of the software without |
3650 | - * specific, written prior permission. Keith Packard makes no |
3651 | - * representations about the suitability of this software for any purpose. It |
3652 | - * is provided "as is" without express or implied warranty. |
3653 | - * |
3654 | - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
3655 | - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
3656 | - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
3657 | - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
3658 | - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
3659 | - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
3660 | - * PERFORMANCE OF THIS SOFTWARE. |
3661 | - */ |
3662 | - |
3663 | -#ifndef XCURSOR_H |
3664 | -#define XCURSOR_H |
3665 | - |
3666 | -#include <stdint.h> |
3667 | - |
3668 | - |
3669 | -typedef int XcursorBool; |
3670 | -typedef uint32_t XcursorUInt; |
3671 | - |
3672 | -typedef XcursorUInt XcursorDim; |
3673 | -typedef XcursorUInt XcursorPixel; |
3674 | - |
3675 | -typedef struct _XcursorImage { |
3676 | - XcursorUInt version; /* version of the image data */ |
3677 | - XcursorDim size; /* nominal size for matching */ |
3678 | - XcursorDim width; /* actual width */ |
3679 | - XcursorDim height; /* actual height */ |
3680 | - XcursorDim xhot; /* hot spot x (must be inside image) */ |
3681 | - XcursorDim yhot; /* hot spot y (must be inside image) */ |
3682 | - XcursorUInt delay; /* animation delay to next frame (ms) */ |
3683 | - XcursorPixel *pixels; /* pointer to pixels */ |
3684 | -} XcursorImage; |
3685 | - |
3686 | -/* |
3687 | - * Other data structures exposed by the library API |
3688 | - */ |
3689 | -typedef struct _XcursorImages { |
3690 | - int nimage; /* number of images */ |
3691 | - XcursorImage **images; /* array of XcursorImage pointers */ |
3692 | - char *name; /* name used to load images */ |
3693 | -} XcursorImages; |
3694 | - |
3695 | -XcursorImages * |
3696 | -XcursorLibraryLoadImages (const char *file, const char *theme, int size); |
3697 | - |
3698 | -void |
3699 | -XcursorImagesDestroy (XcursorImages *images); |
3700 | - |
3701 | -void |
3702 | -xcursor_load_theme(const char *theme, int size, |
3703 | - void (*load_callback)(XcursorImages *, void *), |
3704 | - void *user_data); |
3705 | -#endif |
3706 | |
3707 | === removed file 'examples/xcursor_loader.cpp' |
3708 | --- examples/xcursor_loader.cpp 2017-07-28 17:00:43 +0000 |
3709 | +++ examples/xcursor_loader.cpp 1970-01-01 00:00:00 +0000 |
3710 | @@ -1,228 +0,0 @@ |
3711 | -/* |
3712 | - * Copyright © 2014 Canonical Ltd. |
3713 | - * |
3714 | - * This program is free software: you can redistribute it and/or modify it |
3715 | - * under the terms of the GNU General Public License version 2 or 3, |
3716 | - * as published by the Free Software Foundation. |
3717 | - * |
3718 | - * This program is distributed in the hope that it will be useful, |
3719 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3720 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3721 | - * GNU General Public License for more details. |
3722 | - * |
3723 | - * You should have received a copy of the GNU General Public License |
3724 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3725 | - * |
3726 | - * Authored by: Robert Carr <robert.carr@canonical.com> |
3727 | - */ |
3728 | - |
3729 | -#include "xcursor_loader.h" |
3730 | - |
3731 | -#include "mir/graphics/cursor_image.h" |
3732 | - |
3733 | -#include <boost/throw_exception.hpp> |
3734 | -#include <stdexcept> |
3735 | - |
3736 | -#include <string.h> |
3737 | - |
3738 | -#include <mir_toolkit/cursors.h> |
3739 | - |
3740 | -// Unfortunately this can not be compiled as C++...so we can not namespace |
3741 | -// these symbols. In order to differentiate from internal symbols |
3742 | -// we refer to them via their _ prefixed version, i.e. _XcursorImage |
3743 | -extern "C" |
3744 | -{ |
3745 | -#include "xcursor.h" |
3746 | -} |
3747 | - |
3748 | -namespace me = mir::examples; |
3749 | -namespace mg = mir::graphics; |
3750 | -namespace mi = mir::input; |
3751 | -namespace geom = mir::geometry; |
3752 | - |
3753 | -namespace |
3754 | -{ |
3755 | -class XCursorImage : public mg::CursorImage |
3756 | -{ |
3757 | -public: |
3758 | - XCursorImage(_XcursorImage *image, std::shared_ptr<_XcursorImages> const& save_resource) |
3759 | - : image(image), |
3760 | - save_resource(save_resource) |
3761 | - { |
3762 | - if (image->width != mi::default_cursor_size.width.as_uint32_t() || |
3763 | - image->height != mi::default_cursor_size.height.as_uint32_t()) |
3764 | - { |
3765 | - BOOST_THROW_EXCEPTION( |
3766 | - std::runtime_error("Somehow we got a cursor not of the default size (currently only 24x24 supported)")); |
3767 | - } |
3768 | - } |
3769 | - |
3770 | - ~XCursorImage() |
3771 | - { |
3772 | - } |
3773 | - |
3774 | - void const* as_argb_8888() const override |
3775 | - { |
3776 | - return image->pixels; |
3777 | - } |
3778 | - geom::Size size() const override |
3779 | - { |
3780 | - return mi::default_cursor_size; |
3781 | - } |
3782 | - geom::Displacement hotspot() const override |
3783 | - { |
3784 | - return {image->xhot, image->yhot}; |
3785 | - } |
3786 | - |
3787 | -private: |
3788 | - _XcursorImage *image; |
3789 | - std::shared_ptr<_XcursorImages> const save_resource; |
3790 | -}; |
3791 | - |
3792 | -std::string const |
3793 | -xcursor_name_for_mir_cursor(std::string const& mir_cursor_name) |
3794 | -{ |
3795 | - if (mir_cursor_name == mir_default_cursor_name) |
3796 | - { |
3797 | - return "arrow"; |
3798 | - } |
3799 | - else if (mir_cursor_name == mir_arrow_cursor_name) |
3800 | - { |
3801 | - return "arrow"; |
3802 | - } |
3803 | - else if (mir_cursor_name == mir_busy_cursor_name) |
3804 | - { |
3805 | - return "watch"; |
3806 | - } |
3807 | - else if (mir_cursor_name == mir_caret_cursor_name) |
3808 | - { |
3809 | - return "xterm"; // Yep |
3810 | - } |
3811 | - else if (mir_cursor_name == mir_pointing_hand_cursor_name) |
3812 | - { |
3813 | - return "hand2"; |
3814 | - } |
3815 | - else if (mir_cursor_name == mir_open_hand_cursor_name) |
3816 | - { |
3817 | - return "hand"; |
3818 | - } |
3819 | - else if (mir_cursor_name == mir_closed_hand_cursor_name) |
3820 | - { |
3821 | - return "grabbing"; |
3822 | - } |
3823 | - else if (mir_cursor_name == mir_horizontal_resize_cursor_name) |
3824 | - { |
3825 | - return "h_double_arrow"; |
3826 | - } |
3827 | - else if (mir_cursor_name == mir_vertical_resize_cursor_name) |
3828 | - { |
3829 | - return "v_double_arrow"; |
3830 | - } |
3831 | - else if (mir_cursor_name == mir_diagonal_resize_bottom_to_top_cursor_name) |
3832 | - { |
3833 | - return "top_right_corner"; |
3834 | - } |
3835 | - else if (mir_cursor_name == mir_diagonal_resize_top_to_bottom_cursor_name) |
3836 | - { |
3837 | - return "bottom_right_corner"; |
3838 | - } |
3839 | - else if (mir_cursor_name == mir_omnidirectional_resize_cursor_name) |
3840 | - { |
3841 | - return "fleur"; |
3842 | - } |
3843 | - else if (mir_cursor_name == mir_vsplit_resize_cursor_name) |
3844 | - { |
3845 | - return "v_double_arrow"; |
3846 | - } |
3847 | - else if (mir_cursor_name == mir_hsplit_resize_cursor_name) |
3848 | - { |
3849 | - return "h_double_arrow"; |
3850 | - } |
3851 | - else if (mir_cursor_name == mir_crosshair_cursor_name) |
3852 | - { |
3853 | - return "crosshair"; |
3854 | - } |
3855 | - else |
3856 | - { |
3857 | - return mir_cursor_name; |
3858 | - } |
3859 | -} |
3860 | -} |
3861 | - |
3862 | -me::XCursorLoader::XCursorLoader() |
3863 | -{ |
3864 | - load_cursor_theme("default"); |
3865 | -} |
3866 | - |
3867 | -me::XCursorLoader::XCursorLoader(std::string const& theme) |
3868 | -{ |
3869 | - load_cursor_theme(theme); |
3870 | -} |
3871 | - |
3872 | -// Each XcursorImages represents images for the different sizes of a given symbolic cursor. |
3873 | -void me::XCursorLoader::load_appropriately_sized_image(_XcursorImages *images) |
3874 | -{ |
3875 | - // We would rather take this lock in load_cursor_theme but the Xcursor lib style |
3876 | - // makes it difficult to use our standard 'pass the lg around to _locked members' pattern |
3877 | - std::lock_guard<std::mutex> lg(guard); |
3878 | - |
3879 | - // We have to save all the images as XCursor expects us to free them. |
3880 | - // This contains the actual image data though, so we need to ensure they stay alive |
3881 | - // with the lifetime of the mg::CursorImage instance which refers to them. |
3882 | - auto saved_xcursor_library_resource = std::shared_ptr<_XcursorImages>(images, [](_XcursorImages *images) |
3883 | - { |
3884 | - XcursorImagesDestroy(images); |
3885 | - }); |
3886 | - |
3887 | - _XcursorImage *image_of_correct_size = nullptr; |
3888 | - for (int i = 0; i < images->nimage; i++) |
3889 | - { |
3890 | - _XcursorImage *candidate = images->images[i]; |
3891 | - if (candidate->width == mi::default_cursor_size.width.as_uint32_t() && |
3892 | - candidate->height == mi::default_cursor_size.height.as_uint32_t()) |
3893 | - { |
3894 | - image_of_correct_size = candidate; |
3895 | - break; |
3896 | - } |
3897 | - } |
3898 | - if (!image_of_correct_size) |
3899 | - return; |
3900 | - loaded_images[std::string(images->name)] = std::make_shared<XCursorImage>(image_of_correct_size, saved_xcursor_library_resource); |
3901 | -} |
3902 | - |
3903 | -void me::XCursorLoader::load_cursor_theme(std::string const& theme_name) |
3904 | -{ |
3905 | - // Cursors are named by their square dimension...called the nominal size in XCursor terminology, so we just look up by width. |
3906 | - // Later we verify the actual size. |
3907 | - xcursor_load_theme(theme_name.c_str(), mi::default_cursor_size.width.as_uint32_t(), |
3908 | - [](XcursorImages* images, void *this_ptr) -> void |
3909 | - { |
3910 | - // Can't use lambda capture as this lambda is thunked to a C function ptr |
3911 | - auto p = static_cast<me::XCursorLoader*>(this_ptr); |
3912 | - p->load_appropriately_sized_image(images); |
3913 | - }, this); |
3914 | -} |
3915 | - |
3916 | -std::shared_ptr<mg::CursorImage> me::XCursorLoader::image( |
3917 | - std::string const& cursor_name, |
3918 | - geom::Size const& size) |
3919 | -{ |
3920 | - auto xcursor_name = xcursor_name_for_mir_cursor(cursor_name); |
3921 | - |
3922 | - if (size != mi::default_cursor_size) |
3923 | - BOOST_THROW_EXCEPTION( |
3924 | - std::logic_error("Only the default cursor size is currently supported (mi::default_cursor_size)")); |
3925 | - |
3926 | - std::lock_guard<std::mutex> lg(guard); |
3927 | - |
3928 | - auto it = loaded_images.find(xcursor_name); |
3929 | - if (it != loaded_images.end()) |
3930 | - return it->second; |
3931 | - |
3932 | - // Fall back |
3933 | - it = loaded_images.find("arrow"); |
3934 | - if (it != loaded_images.end()) |
3935 | - return it->second; |
3936 | - |
3937 | - return nullptr; |
3938 | -} |
3939 | |
3940 | === removed file 'examples/xcursor_loader.h' |
3941 | --- examples/xcursor_loader.h 2017-07-28 17:00:43 +0000 |
3942 | +++ examples/xcursor_loader.h 1970-01-01 00:00:00 +0000 |
3943 | @@ -1,74 +0,0 @@ |
3944 | -/* |
3945 | - * Copyright © 2014 Canonical Ltd. |
3946 | - * |
3947 | - * This program is free software: you can redistribute it and/or modify it |
3948 | - * under the terms of the GNU General Public License version 2 or 3, |
3949 | - * as published by the Free Software Foundation. |
3950 | - * |
3951 | - * This program is distributed in the hope that it will be useful, |
3952 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3953 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3954 | - * GNU General Public License for more details. |
3955 | - * |
3956 | - * You should have received a copy of the GNU General Public License |
3957 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3958 | - * |
3959 | - * Authored by: Robert Carr <robert.carr@canonical.com> |
3960 | - */ |
3961 | - |
3962 | - |
3963 | -#ifndef MIR_INPUT_XCURSOR_CURSOR_LOADER_H_ |
3964 | -#define MIR_INPUT_XCURSOR_CURSOR_LOADER_H_ |
3965 | - |
3966 | -#include "mir/input/cursor_images.h" |
3967 | - |
3968 | -#include <memory> |
3969 | -#include <string> |
3970 | -#include <map> |
3971 | -#include <mutex> |
3972 | -#include <functional> |
3973 | - |
3974 | -// Unfortunately this library does not compile as C++ so we can not namespace it. |
3975 | -extern "C" |
3976 | -{ |
3977 | -struct _XcursorImages; |
3978 | -} |
3979 | - |
3980 | -namespace mir |
3981 | -{ |
3982 | -namespace graphics |
3983 | -{ |
3984 | -class CursorImage; |
3985 | -} |
3986 | - |
3987 | -namespace examples |
3988 | -{ |
3989 | -class XCursorLoader : public input::CursorImages |
3990 | -{ |
3991 | -public: |
3992 | - XCursorLoader(); |
3993 | - |
3994 | - explicit XCursorLoader(std::string const& theme); |
3995 | - |
3996 | - virtual ~XCursorLoader() = default; |
3997 | - |
3998 | - std::shared_ptr<graphics::CursorImage> image(std::string const& cursor_name, |
3999 | - geometry::Size const& size); |
4000 | - |
4001 | -protected: |
4002 | - XCursorLoader(XCursorLoader const&) = delete; |
4003 | - XCursorLoader& operator=(XCursorLoader const&) = delete; |
4004 | - |
4005 | -private: |
4006 | - std::mutex guard; |
4007 | - |
4008 | - std::map<std::string, std::shared_ptr<graphics::CursorImage>> loaded_images; |
4009 | - |
4010 | - void load_cursor_theme(std::string const& theme_name); |
4011 | - void load_appropriately_sized_image(_XcursorImages *images); |
4012 | -}; |
4013 | -} |
4014 | -} |
4015 | - |
4016 | - |
4017 | -#endif /* MIR_INPUT_XCURSOR_CURSOR_LOADER_H_ */ |
4018 | |
4019 | === renamed file 'include/platform/mir/abnormal_exit.h' => 'include/core/mir/abnormal_exit.h' |
4020 | === modified file 'playground/CMakeLists.txt' |
4021 | --- playground/CMakeLists.txt 2017-06-01 13:04:37 +0000 |
4022 | +++ playground/CMakeLists.txt 2017-08-31 08:02:08 +0000 |
4023 | @@ -16,6 +16,7 @@ |
4024 | |
4025 | add_library(playgroundserverconfig STATIC |
4026 | server_configuration.cpp |
4027 | + server_example_display_configuration_policy.cpp |
4028 | ) |
4029 | |
4030 | add_subdirectory(demo-shell/) |
4031 | |
4032 | === renamed file 'examples/server_example_display_configuration_policy.cpp' => 'playground/server_example_display_configuration_policy.cpp' |
4033 | === renamed file 'examples/server_example_display_configuration_policy.h' => 'playground/server_example_display_configuration_policy.h' |
4034 | === modified file 'src/miral/process_doxygen_xml.py' |
4035 | --- src/miral/process_doxygen_xml.py 2017-08-31 08:02:07 +0000 |
4036 | +++ src/miral/process_doxygen_xml.py 2017-08-31 08:02:08 +0000 |
4037 | @@ -1,4 +1,4 @@ |
4038 | -#! /usr/bin/python |
4039 | +#! /usr/bin/python3 |
4040 | """This script processes the XML generated by "make doc" and produces summary information |
4041 | on symbols that libmiral intends to make public. |
4042 | |
4043 | |
4044 | === modified file 'tests/unit-tests/input/CMakeLists.txt' |
4045 | --- tests/unit-tests/input/CMakeLists.txt 2017-05-08 03:04:26 +0000 |
4046 | +++ tests/unit-tests/input/CMakeLists.txt 2017-08-31 08:02:08 +0000 |
4047 | @@ -3,7 +3,6 @@ |
4048 | list(APPEND UNIT_TEST_SOURCES |
4049 | ${CMAKE_CURRENT_SOURCE_DIR}/test_event_filter_chain_dispatcher.cpp |
4050 | ${CMAKE_CURRENT_SOURCE_DIR}/test_cursor_controller.cpp |
4051 | - ${CMAKE_CURRENT_SOURCE_DIR}/test_xcursor_loader.cpp |
4052 | ${CMAKE_CURRENT_SOURCE_DIR}/test_touchspot_controller.cpp |
4053 | ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp |
4054 | ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp |
4055 | |
4056 | === removed file 'tests/unit-tests/input/test_xcursor_loader.cpp' |
4057 | --- tests/unit-tests/input/test_xcursor_loader.cpp 2017-07-28 17:00:43 +0000 |
4058 | +++ tests/unit-tests/input/test_xcursor_loader.cpp 1970-01-01 00:00:00 +0000 |
4059 | @@ -1,148 +0,0 @@ |
4060 | -/* |
4061 | - * Copyright © 2014 Canonical Ltd. |
4062 | - * |
4063 | - * This program is free software: you can redistribute it and/or modify |
4064 | - * it under the terms of the GNU General Public License version 2 or 3 as |
4065 | - * published by the Free Software Foundation. |
4066 | - * |
4067 | - * This program is distributed in the hope that it will be useful, |
4068 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4069 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4070 | - * GNU General Public License for more details. |
4071 | - * |
4072 | - * You should have received a copy of the GNU General Public License |
4073 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4074 | - * |
4075 | - * Authored by: Robert Carr <robert.carr@canonical.com> |
4076 | - */ |
4077 | - |
4078 | -#include "examples/xcursor_loader.h" |
4079 | - |
4080 | -#include "mir/graphics/cursor_image.h" |
4081 | -#include "mir_test_framework/executable_path.h" |
4082 | -#include "mir_test_framework/temporary_environment_value.h" |
4083 | - |
4084 | -#include <mir_toolkit/common.h> |
4085 | -#include <mir_toolkit/cursors.h> |
4086 | - |
4087 | -#include <gtest/gtest.h> |
4088 | -#include <gmock/gmock.h> |
4089 | - |
4090 | -#include <stdexcept> |
4091 | - |
4092 | -#include <stdlib.h> |
4093 | -#include <string.h> |
4094 | - |
4095 | -namespace me = mir::examples; |
4096 | -namespace mi = mir::input; |
4097 | -namespace mg = mir::graphics; |
4098 | -namespace mtf = mir_test_framework; |
4099 | - |
4100 | -namespace |
4101 | -{ |
4102 | -std::string const test_cursor_path{mir_test_framework::test_data_path() + std::string("/testing-cursor-theme")}; |
4103 | -} |
4104 | - |
4105 | -// Warning, XCURSOR_PATH will only be checked ONCE by libxcursor due to static var |
4106 | -class XCursorLoaderTest : public ::testing::Test |
4107 | -{ |
4108 | -public: |
4109 | - XCursorLoaderTest() |
4110 | - : xcursor_path("XCURSOR_PATH", test_cursor_path.c_str()) |
4111 | - { |
4112 | - } |
4113 | - |
4114 | - mtf::TemporaryEnvironmentValue xcursor_path; |
4115 | - me::XCursorLoader loader; |
4116 | -}; |
4117 | - |
4118 | -namespace |
4119 | -{ |
4120 | -bool raw_argb_is_only_pixel(uint32_t const* raw_argb, size_t size, uint32_t pixel) |
4121 | -{ |
4122 | - for (unsigned int i = 0; i < size; i++) |
4123 | - { |
4124 | - if (raw_argb[i] != pixel) |
4125 | - { |
4126 | - printf("Pixel: %u\n", raw_argb[i]); |
4127 | - return false; |
4128 | - } |
4129 | - } |
4130 | - return true; |
4131 | -} |
4132 | -bool cursor_image_is_solid_color(std::shared_ptr<mg::CursorImage> const& image, uint32_t pixel) |
4133 | -{ |
4134 | - auto raw_argb = static_cast<uint32_t const*>(image->as_argb_8888()); |
4135 | - size_t size = image->size().width.as_uint32_t() * image->size().height.as_uint32_t(); |
4136 | - |
4137 | - return raw_argb_is_only_pixel(raw_argb, size, pixel); |
4138 | -} |
4139 | - |
4140 | -MATCHER(HasLoaded, "cursor image has loaded and is not nullptr."\ |
4141 | - " Test expects cursor images to be installed to the directory the test is ran from") |
4142 | -{ |
4143 | - return arg != nullptr; |
4144 | -} |
4145 | - |
4146 | -MATCHER(IsSolidRed, "") |
4147 | -{ |
4148 | - return cursor_image_is_solid_color(arg, 0xffff0000); |
4149 | -} |
4150 | - |
4151 | -MATCHER(IsSolidGreen, "") |
4152 | -{ |
4153 | - return cursor_image_is_solid_color(arg, 0xff00ff00); |
4154 | -} |
4155 | - |
4156 | -MATCHER(IsSolidBlue, "") |
4157 | -{ |
4158 | - return cursor_image_is_solid_color(arg, 0xff0000ff); |
4159 | -} |
4160 | - |
4161 | -MATCHER(IsSolidBlack, "") |
4162 | -{ |
4163 | - return cursor_image_is_solid_color(arg, 0xff000000); |
4164 | -} |
4165 | -} |
4166 | - |
4167 | -TEST_F(XCursorLoaderTest, loads_cursors_from_testing_theme) |
4168 | -{ |
4169 | - auto size = mi::default_cursor_size; |
4170 | - auto red_image = loader.image("red", size); |
4171 | - auto blue_image = loader.image("blue", size); |
4172 | - auto green_image = loader.image("green", size); |
4173 | - |
4174 | - ASSERT_THAT(red_image, HasLoaded()); |
4175 | - ASSERT_THAT(green_image, HasLoaded()); |
4176 | - ASSERT_THAT(blue_image, HasLoaded()); |
4177 | - EXPECT_THAT(red_image, IsSolidRed()); |
4178 | - EXPECT_THAT(green_image, IsSolidGreen()); |
4179 | - EXPECT_THAT(blue_image, IsSolidBlue()); |
4180 | -} |
4181 | - |
4182 | -TEST_F(XCursorLoaderTest, only_supports_the_default_size) |
4183 | -{ |
4184 | - EXPECT_THROW({ |
4185 | - loader.image("red", {100, 100}); |
4186 | - }, std::logic_error); |
4187 | -} |
4188 | - |
4189 | -TEST_F(XCursorLoaderTest, default_image_is_arrow_from_xcursor_theme) |
4190 | -{ |
4191 | - auto size = mi::default_cursor_size; |
4192 | - auto arrow_image = loader.image(mir_default_cursor_name, size); |
4193 | - |
4194 | - // The testing theme uses a solid black image for the "arrow" symbolic |
4195 | - // name. |
4196 | - ASSERT_THAT(arrow_image, HasLoaded()); |
4197 | - EXPECT_THAT(arrow_image, IsSolidBlack()); |
4198 | -} |
4199 | - |
4200 | -TEST_F(XCursorLoaderTest, symbolic_names_which_are_not_present_resolve_to_default) |
4201 | -{ |
4202 | - auto size = mi::default_cursor_size; |
4203 | - auto default_image = loader.image(mir_default_cursor_name, size); |
4204 | - auto image_with_made_up_name = loader.image("Artickrumbulis", size); |
4205 | - |
4206 | - EXPECT_EQ(default_image, image_with_made_up_name); |
4207 | -} |
FAILED: Continuous integration, rev:4263 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3586/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4909/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/5134 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= artful/ 5123 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 5123 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/5123 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= artful/ 4948/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4948/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= artful/ 4948/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 4948/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4948/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= artful/ 4948/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= zesty/4948/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 4948/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3586/rebuild
https:/