From 0c750ea306d0ce92308926bb27d1e806febe0141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sawicz?= Date: Thu, 8 Aug 2024 10:59:58 +0200 Subject: [PATCH 01/11] debian: draft changelog --- debian/changelog | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/debian/changelog b/debian/changelog index abf75dbe71b..aad34c24739 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,53 @@ +mir (2.18.0) UNRELEASED; urgency=medium + + * New upstream release 2.18.0 + + - ABI summary: + . miral ABI unchanged at 7 + . mircommon ABI bumped to 10 + . mircore ABI unchanged at 2 + . miroil ABI unchanged at 5 + . mirplatform ABI bumped to 29 + . mirserver ABI unchanged at 60 + . mirwayland ABI unchanged at 5 + . mirplatformgraphics ABI unchanged at 22 + . mirinputplatform ABI unchanged at 9 + + Enhancements: + . Move to 24.04 as the development focus (#3374) + . Implement a more principled `GraphicBufferAllocator` selector (#3402) + . Add input configuration options (#3415) + . Provide a listener for dim/screen off notifications and wiring it through miral (#3405) + . Resolve snap desktop files using app armor as the primary source (#3426) + . Wayland server side decorations (#3425) + . Add Wayland decorations strategy (#3454) + . `wp_viewporter` support (#3445) + . Enable keyboard LEDs when the modifier state changes (#3441) + . x11-kiosk (#3460) + . ci: replace codecov with TICS (#3485) + . ci: enable AddressSanitizer (#3026) + . Add support for `wp_fractional_scale_v1` (#3509) + + Documentation: + . Add Mir's CI documentation (#3434) + . Explanation of how libraries depend on one another (#3469) + . Draft a new Mir tutorial (#3496) + . Add a threat model diagram for Ubuntu Frame (#3484) + + Bugs fixed: + . Alt key sometimes getting stuck after Alt+Tab (#3307) + . Alt+` is confusing Firefox (#3379) + . Fix cross-GPU imports (#3401) + . Alt+Tab restores minimized windows, even if they don't end up focused (#3323) + . Don't re-send wl_output.geometry if unchanged (#3414) + . Abrupt cursor transition between outputs. (#3449) + (thanks @ehopperdietzel!) + . mir_kiosk_x11 crashes when the host platform has no outputs (#3427) + . Screenshots no longer respect output scale (#3461) + . Mir should respect flags from DEB_BUILD_MAINT_OPTIONS (LP#2073451) + + -- Michał Sawicz Thu, 08 Aug 2024 10:35:09 +0200 + mir (2.17.0) UNRELEASED; urgency=medium [ Matthew Kosarek ] From 088229ae374013d63c6ee2d4a8dba15e4cc149a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sawicz?= Date: Thu, 29 Aug 2024 17:57:40 +0200 Subject: [PATCH 02/11] debian: update changelog --- debian/changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/changelog b/debian/changelog index aad34c24739..d613b45ba72 100644 --- a/debian/changelog +++ b/debian/changelog @@ -45,6 +45,9 @@ mir (2.18.0) UNRELEASED; urgency=medium . mir_kiosk_x11 crashes when the host platform has no outputs (#3427) . Screenshots no longer respect output scale (#3461) . Mir should respect flags from DEB_BUILD_MAINT_OPTIONS (LP#2073451) + . Fix x11 rendering when scaled fractional scaling (#3508, #3554) + . wbg constantly resizing after switching to 2.17.0 (#3450) + . Decorations Eat Into Application Area (#3572) -- Michał Sawicz Thu, 08 Aug 2024 10:35:09 +0200 From 762337a78d21311422dfcfd45f7177d9daee9950 Mon Sep 17 00:00:00 2001 From: Alan Griffiths Date: Tue, 3 Sep 2024 13:06:08 +0000 Subject: [PATCH 03/11] live-input-configuation (#3531) Allow servers to dynamically update input configuration. There's a very simple "mir_demo_server.input" addition to `mir_demo_server` to exercise part of this API, but that is not intended prototype. --- debian/libmiral7.symbols | 43 +++ examples/mir_demo_server/server_example.cpp | 42 ++- include/miral/miral/input_configuration.h | 125 +++++++ src/miral/CMakeLists.txt | 3 +- src/miral/input_configuration.cpp | 323 ++++++++++++++++++ src/miral/input_device_config.cpp | 155 +++++---- src/miral/input_device_config.h | 62 +++- .../input_device_configuration_options.h | 30 ++ src/miral/runner.cpp | 2 +- src/miral/symbols.map | 29 ++ 10 files changed, 740 insertions(+), 74 deletions(-) create mode 100644 include/miral/miral/input_configuration.h create mode 100644 src/miral/input_configuration.cpp create mode 100644 src/miral/input_device_configuration_options.h diff --git a/debian/libmiral7.symbols b/debian/libmiral7.symbols index 46560b2caba..3a69178bdda 100644 --- a/debian/libmiral7.symbols +++ b/debian/libmiral7.symbols @@ -447,4 +447,47 @@ libmiral.so.7 libmiral7 #MINVER# (c++)"miral::IdleListener::on_off(std::function const&)@MIRAL_5.1" 5.1.0 (c++)"miral::IdleListener::on_wake(std::function const&)@MIRAL_5.1" 5.1.0 (c++)"miral::IdleListener::operator()(mir::Server&) const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::InputConfiguration()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::Mouse()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::Mouse(miral::InputConfiguration::Mouse const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::acceleration() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::acceleration(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::acceleration_bias() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::acceleration_bias(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::handedness() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::handedness(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::hscroll_speed() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::hscroll_speed(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::operator=(miral::InputConfiguration::Mouse)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::vscroll_speed() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::vscroll_speed(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Mouse::~Mouse()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::Touchpad()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::Touchpad(miral::InputConfiguration::Touchpad const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::acceleration() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::acceleration(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::acceleration_bias() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::acceleration_bias(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::click_mode() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::click_mode(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::disable_while_typing() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::disable_while_typing(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::disable_with_external_mouse() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::disable_with_external_mouse(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::hscroll_speed() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::hscroll_speed(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::operator=(miral::InputConfiguration::Touchpad)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::scroll_mode() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::scroll_mode(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::tap_to_click() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::tap_to_click(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::vscroll_speed() const@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::vscroll_speed(std::optional const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::Touchpad::~Touchpad()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::mouse()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::mouse(miral::InputConfiguration::Mouse const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::operator()(mir::Server&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::touchpad()@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::touchpad(miral::InputConfiguration::Touchpad const&)@MIRAL_5.1" 5.1.0 + (c++)"miral::InputConfiguration::~InputConfiguration()@MIRAL_5.1" 5.1.0 (c++)"miral::WindowManagerTools::move_cursor_to(mir::geometry::generic::Point)@MIRAL_5.1" 5.1.0 diff --git a/examples/mir_demo_server/server_example.cpp b/examples/mir_demo_server/server_example.cpp index 4f71421794a..feaf1667566 100644 --- a/examples/mir_demo_server/server_example.cpp +++ b/examples/mir_demo_server/server_example.cpp @@ -20,22 +20,25 @@ #include #include +#include #include +#include #include #include #include #include #include "mir/abnormal_exit.h" -#include "mir/server.h" #include "mir/main_loop.h" -#include "mir/report_exception.h" #include "mir/options/option.h" +#include "mir/report_exception.h" +#include "mir/server.h" #include #include #include +#include namespace mir { class AbnormalExit; } @@ -116,6 +119,38 @@ try { miral::MirRunner runner{argc, argv, "mir/mir_demo_server.config"}; + miral::InputConfiguration input_configuration; + + miral::ConfigFile test{runner, "mir_demo_server.input", miral::ConfigFile::Mode::reload_on_change, + [&input_configuration](auto& in, auto path) + { + std::cout << "** Reloading: " << path << std::endl; + + auto mouse = input_configuration.mouse(); + auto touchpad = input_configuration.touchpad(); + + for (std::string line; std::getline(in, line);) + { + std::cout << line << std::endl; + + if (line == "mir_pointer_handedness_right") + mouse.handedness(mir_pointer_handedness_right); + if (line == "mir_pointer_handedness_left") + mouse.handedness(mir_pointer_handedness_left); + + if (line == "mir_touchpad_scroll_mode_none") + touchpad.scroll_mode(mir_touchpad_scroll_mode_none); + if (line == "mir_touchpad_scroll_mode_two_finger_scroll") + touchpad.scroll_mode(mir_touchpad_scroll_mode_two_finger_scroll); + if (line == "mir_touchpad_scroll_mode_edge_scroll") + touchpad.scroll_mode(mir_touchpad_scroll_mode_edge_scroll); + if (line == "mir_touchpad_scroll_mode_button_down_scroll") + touchpad.scroll_mode(mir_touchpad_scroll_mode_button_down_scroll); + } + input_configuration.mouse(mouse); + input_configuration.touchpad(touchpad); + }}; + runner.set_exception_handler(exception_handler); std::function shutdown_hook{[]{}}; @@ -138,7 +173,8 @@ try add_timeout_option_to, miral::CursorTheme{"default:DMZ-White"}, input_filters, - test_runner + test_runner, + input_configuration, }); // Propagate any test failure diff --git a/include/miral/miral/input_configuration.h b/include/miral/miral/input_configuration.h new file mode 100644 index 00000000000..960e71c24eb --- /dev/null +++ b/include/miral/miral/input_configuration.h @@ -0,0 +1,125 @@ +/* + * Copyright © Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MIRAL_INPUT_CONFIGURATION_H +#define MIRAL_INPUT_CONFIGURATION_H + +#include + +#include +#include + +namespace mir { class Server; } + + +namespace miral +{ +/** Input configuration. + * Allow servers to make input configuration changes at runtime + * \remark Since MirAL 5.1 + */ +class InputConfiguration +{ +public: + InputConfiguration(); + ~InputConfiguration(); + void operator()(mir::Server& server); + + class Mouse; + class Touchpad; + + auto mouse() -> Mouse; + void mouse(Mouse const& val); + auto touchpad() -> Touchpad; + void touchpad(Touchpad const& val); + +private: + class Self; + std::shared_ptr self; +}; + +/** Input configuration for mouse pointer devices + * \remark Since MirAL 5.1 + */ +class InputConfiguration::Mouse +{ +public: + Mouse(); + ~Mouse(); + + Mouse(Mouse const& that); + auto operator=(Mouse that) -> Mouse&; + + auto handedness() const -> std::optional; + auto acceleration() const -> std::optional; + auto acceleration_bias() const -> std::optional; + auto vscroll_speed() const -> std::optional; + auto hscroll_speed() const -> std::optional; + + void handedness(std::optionalconst& val); + void acceleration(std::optionalconst& val); + /// \note val will be clamped to the range [-1.0, 1.0] + void acceleration_bias(std::optionalconst& val); + void vscroll_speed(std::optionalconst& val); + void hscroll_speed(std::optionalconst& val); + +private: + friend class InputConfiguration::Self; + class Self; + std::unique_ptr self; +}; + +/** Input configuration for touchpad devices + * \remark Since MirAL 5.1 + */ +class InputConfiguration::Touchpad +{ +public: + Touchpad(); + ~Touchpad(); + + Touchpad(Touchpad const& that); + auto operator=(Touchpad that) -> Touchpad&; + + auto disable_while_typing() const -> std::optional; + auto disable_with_external_mouse() const -> std::optional; + auto acceleration() const -> std::optional; + auto acceleration_bias() const -> std::optional; + auto vscroll_speed() const -> std::optional; + auto hscroll_speed() const -> std::optional; + auto click_mode() const -> std::optional; + auto scroll_mode() const -> std::optional; + auto tap_to_click() const -> std::optional; + + void disable_while_typing(std::optionalconst& val); + void disable_with_external_mouse(std::optionalconst& val); + void acceleration(std::optionalconst& val); + /// \note val will be clamped to the range [-1.0, 1.0] + void acceleration_bias(std::optionalconst& val); + void vscroll_speed(std::optionalconst& val); + void hscroll_speed(std::optionalconst& val); + void click_mode(std::optionalconst& val); + void scroll_mode(std::optionalconst& val); + void tap_to_click(std::optionalconst& val); + +private: + friend class InputConfiguration::Self; + class Self; + std::shared_ptr self; +}; +} + +#endif //MIRAL_INPUT_CONFIGURATION_H diff --git a/src/miral/CMakeLists.txt b/src/miral/CMakeLists.txt index 84351a2e81c..71ec872656d 100644 --- a/src/miral/CMakeLists.txt +++ b/src/miral/CMakeLists.txt @@ -20,7 +20,7 @@ add_library(miral-internal STATIC system_compositor_window_manager.cpp system_compositor_window_manager.h display_configuration_listeners.cpp display_configuration_listeners.h fd_manager.cpp fd_manager.h - input_device_config.cpp input_device_config.h + input_device_config.cpp input_device_configuration_options.h input_device_config.h launch_app.cpp launch_app.h mru_window_list.cpp mru_window_list.h open_desktop_entry.cpp open_desktop_entry.h @@ -63,6 +63,7 @@ add_library(miral-external OBJECT display_configuration.cpp ${miral_include}/miral/display_configuration.h external_client.cpp ${miral_include}/miral/external_client.h idle_listener.cpp ${miral_include}/miral/idle_listener.h + input_configuration.cpp ${miral_include}/miral/input_configuration.h keymap.cpp ${miral_include}/miral/keymap.h minimal_window_manager.cpp ${miral_include}/miral/minimal_window_manager.h display_configuration_option.cpp ${miral_include}/miral/display_configuration_option.h diff --git a/src/miral/input_configuration.cpp b/src/miral/input_configuration.cpp new file mode 100644 index 00000000000..3afa5016542 --- /dev/null +++ b/src/miral/input_configuration.cpp @@ -0,0 +1,323 @@ +/* + * Copyright © Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "miral/input_configuration.h" + +#include "input_device_config.h" + +#include +#include + +#include + +class miral::InputConfiguration::Mouse::Self : public MouseInputConfiguration +{ + friend class miral::InputConfiguration::Self; + using MouseInputConfiguration::operator=; +}; + +class miral::InputConfiguration::Touchpad::Self : public TouchpadInputConfiguration +{ + friend class miral::InputConfiguration::Self; + using TouchpadInputConfiguration::operator=; +}; + +class miral::InputConfiguration::Self +{ +public: + std::shared_ptr input_device_hub{}; + std::shared_ptr input_device_config; + + auto mouse() -> Mouse; + void mouse(Mouse const& val); + auto touchpad() -> Touchpad; + void touchpad(Touchpad const& val); + + void apply(Mouse const& m) + { + if (input_device_hub) + { + input_device_hub->for_each_mutable_input_device([&m](auto& input_device) + { + m.self->apply_to(input_device); + }); + } + + mouse(m); + } + + void apply(Touchpad const& t) + { + if (input_device_hub) + { + input_device_hub->for_each_mutable_input_device([&t](auto& input_device) + { + t.self->apply_to(input_device); + }); + } + + touchpad(t); + } +}; + +auto miral::InputConfiguration::Self::mouse() -> Mouse +{ + Mouse result; + if (input_device_config) + { + *result.self = input_device_config->mouse(); + } + return result; +} + +void miral::InputConfiguration::Self::mouse(Mouse const& val) +{ + if (input_device_config) + { + input_device_config->mouse(*val.self); + } +} + +auto miral::InputConfiguration::Self::touchpad() -> Touchpad +{ + Touchpad result; + if (input_device_config) + { + *result.self = input_device_config->touchpad(); + } + return result; +} + +void miral::InputConfiguration::Self::touchpad(Touchpad const& val) +{ + if (input_device_config) + { + input_device_config->touchpad(*val.self); + } +} + +miral::InputConfiguration::InputConfiguration() : + self{std::make_shared()} +{ +} + +void miral::InputConfiguration::mouse(Mouse const& m) +{ + self->apply(m); +} + +miral::InputConfiguration::~InputConfiguration() = default; + +void miral::InputConfiguration::operator()(mir::Server& server) +{ + server.add_init_callback([self=self, &server] + { + self->input_device_hub = server.the_input_device_hub(); + self->input_device_config = InputDeviceConfig::the_input_configuration(server.get_options()); + }); +} + +auto miral::InputConfiguration::mouse() -> Mouse +{ + return self->mouse(); +} + +auto miral::InputConfiguration::touchpad() -> Touchpad +{ + return self->touchpad(); +} + +void miral::InputConfiguration::touchpad(Touchpad const& t) +{ + self->apply(t); +} + +miral::InputConfiguration::Mouse::Mouse() : + self{std::make_unique()} +{ +} + +miral::InputConfiguration::Mouse::Mouse(Mouse const& that) : + self{std::make_unique(*that.self)} +{ +} + +auto miral::InputConfiguration::Mouse::operator=(Mouse that) -> Mouse& +{ + std::swap(self, that.self); + return *this; +} + +miral::InputConfiguration::Mouse::~Mouse() = default; + +auto miral::InputConfiguration::Mouse::handedness() const -> std::optional +{ + return self->handedness; +} + +auto miral::InputConfiguration::Mouse::acceleration() const -> std::optional +{ + return self->acceleration; +} + +auto miral::InputConfiguration::Mouse::acceleration_bias() const -> std::optional +{ + return self->acceleration_bias; +} + +auto miral::InputConfiguration::Mouse::vscroll_speed() const -> std::optional +{ + return self->acceleration_bias; +} + +auto miral::InputConfiguration::Mouse::hscroll_speed() const -> std::optional +{ + return self->acceleration_bias; +} + +void miral::InputConfiguration::Mouse::handedness(std::optional const& val) +{ + self->handedness = val; +} + +void miral::InputConfiguration::Mouse::acceleration(std::optional const& val) +{ + self->acceleration = val; +} + +void miral::InputConfiguration::Mouse::acceleration_bias(std::optional const& val) +{ + self->acceleration_bias = val.transform([](auto v) { return std::clamp(v, -1.0, +1.0); }); +} + +void miral::InputConfiguration::Mouse::vscroll_speed(std::optional const& val) +{ + self->vscroll_speed = val; +} + +void miral::InputConfiguration::Mouse::hscroll_speed(std::optional const& val) +{ + self->hscroll_speed = val; +} + +miral::InputConfiguration::Touchpad::Touchpad() : + self{std::make_unique()} +{ +} + +miral::InputConfiguration::Touchpad::~Touchpad() = default; + +miral::InputConfiguration::Touchpad::Touchpad(Touchpad const& that) : + self{std::make_unique(*that.self)} +{ +} + +auto miral::InputConfiguration::Touchpad::operator=(Touchpad that) -> Touchpad& +{ + std::swap(self, that.self); + return *this; +} + +auto miral::InputConfiguration::Touchpad::disable_while_typing() const -> std::optional +{ + return self->disable_while_typing; +} + +auto miral::InputConfiguration::Touchpad::disable_with_external_mouse() const -> std::optional +{ + return self->disable_with_external_mouse; +} + +auto miral::InputConfiguration::Touchpad::acceleration() const -> std::optional +{ + return self->acceleration; +} + +auto miral::InputConfiguration::Touchpad::acceleration_bias() const -> std::optional +{ + return self->acceleration_bias; +} + +auto miral::InputConfiguration::Touchpad::vscroll_speed() const -> std::optional +{ + return self->vscroll_speed; +} + +auto miral::InputConfiguration::Touchpad::hscroll_speed() const -> std::optional +{ + return self->hscroll_speed; +} + +auto miral::InputConfiguration::Touchpad::click_mode() const -> std::optional +{ + return self->click_mode; +} + +auto miral::InputConfiguration::Touchpad::scroll_mode() const -> std::optional +{ + return self->scroll_mode; +} + +auto miral::InputConfiguration::Touchpad::tap_to_click() const -> std::optional +{ + return self->tap_to_click; +} + +void miral::InputConfiguration::Touchpad::disable_while_typing(std::optional const& val) +{ + self->disable_while_typing = val; +} + +void miral::InputConfiguration::Touchpad::disable_with_external_mouse(std::optional const& val) +{ + self->disable_with_external_mouse = val; +} + +void miral::InputConfiguration::Touchpad::acceleration(std::optional const& val) +{ + self->acceleration = val; +} + +void miral::InputConfiguration::Touchpad::acceleration_bias(std::optional const& val) +{ + self->acceleration_bias = val.transform([](auto v) { return std::clamp(v, -1.0, +1.0); }); +} + +void miral::InputConfiguration::Touchpad::vscroll_speed(std::optional const& val) +{ + self->vscroll_speed = val; +} + +void miral::InputConfiguration::Touchpad::hscroll_speed(std::optional const& val) +{ + self->hscroll_speed = val; +} + + +void miral::InputConfiguration::Touchpad::click_mode(std::optional const& val) +{ + self->click_mode = val; +} + +void miral::InputConfiguration::Touchpad::scroll_mode(std::optional const& val) +{ + self->scroll_mode = val; +} + +void miral::InputConfiguration::Touchpad::tap_to_click(std::optional const& val) +{ + self->tap_to_click = val; +} diff --git a/src/miral/input_device_config.cpp b/src/miral/input_device_config.cpp index 96b52ae6242..a7390ac7567 100644 --- a/src/miral/input_device_config.cpp +++ b/src/miral/input_device_config.cpp @@ -15,6 +15,7 @@ */ #include "input_device_config.h" +#include "input_device_configuration_options.h" #include "mir/abnormal_exit.h" #include "mir/input/device.h" @@ -81,31 +82,6 @@ char const* const touchpad_click_mode_area = "area"; char const* const touchpad_click_mode_clickfinger = "clickfinger"; char const* const touchpad_middle_mouse_button_emulation_opt= "touchpad-middle-mouse-button-emulation"; -class InputDeviceConfig : public mi::InputDeviceObserver -{ -public: - explicit InputDeviceConfig(std::shared_ptr const& options); - void device_added(std::shared_ptr const& device) override; - void device_changed(std::shared_ptr const&) override {} - void device_removed(std::shared_ptr const&) override {} - void changes_complete() override {} -private: - std::optional const disable_while_typing; - std::optional const disable_with_external_mouse; - std::optional const mouse_handedness; - std::optional const mouse_cursor_acceleration; - std::optional const mouse_cursor_acceleration_bias; - std::optional const mouse_vscroll_speed; - std::optional const mouse_hscroll_speed; - std::optional const touchpad_cursor_acceleration; - std::optional const touchpad_cursor_acceleration_bias; - std::optional const touchpad_vscroll_speed; - std::optional const touchpad_hscroll_speed; - std::optional const click_mode; - std::optional const scroll_mode; - std::optional const tap_to_click; - std::optional const middle_mouse_button_emulation; -}; template auto clamp(std::optional opt_val)-> std::optional @@ -286,70 +262,121 @@ void miral::add_input_device_configuration_options_to(mir::Server& server) server.add_init_callback([&]() { - auto const input_config = std::make_shared(server.get_options()); + auto const input_config = InputDeviceConfig::the_input_configuration(server.get_options()); server.the_input_device_hub()->add_observer(input_config); }); } -InputDeviceConfig::InputDeviceConfig(std::shared_ptr const& options) : - disable_while_typing{get_optional(options, disable_while_typing_opt)}, - disable_with_external_mouse{get_optional(options, disable_with_external_mouse_opt)}, - mouse_handedness{to_handedness(get_optional(options, mouse_handedness_opt))}, - mouse_cursor_acceleration{to_acceleration_profile(get_optional(options, mouse_cursor_acceleration_opt))}, - mouse_cursor_acceleration_bias{clamp<-1.0, 1.0>(get_optional(options, mouse_cursor_acceleration_bias_opt))}, - mouse_vscroll_speed{get_optional(options, mouse_vscroll_speed_override_opt, mouse_scroll_speed_opt)}, - mouse_hscroll_speed{get_optional(options, mouse_hscroll_speed_override_opt, mouse_scroll_speed_opt)}, - touchpad_cursor_acceleration{to_acceleration_profile(get_optional(options, touchpad_cursor_acceleration_opt))}, - touchpad_cursor_acceleration_bias{clamp<-1.0, 1.0>(get_optional(options, touchpad_cursor_acceleration_bias_opt))}, - touchpad_vscroll_speed{get_optional(options, touchpad_vscroll_speed_override_opt, touchpad_scroll_speed_opt)}, - touchpad_hscroll_speed{get_optional(options, touchpad_hscroll_speed_override_opt, touchpad_scroll_speed_opt)}, - click_mode{convert_to_click_mode(get_optional(options, touchpad_click_mode_opt))}, - scroll_mode{convert_to_scroll_mode(get_optional(options, touchpad_scroll_mode_opt))}, - tap_to_click{get_optional(options, touchpad_tap_to_click_opt)}, - middle_mouse_button_emulation{get_optional(options, touchpad_middle_mouse_button_emulation_opt)} +miral::InputDeviceConfig::InputDeviceConfig(std::shared_ptr const& options) : + mouse_config{ + to_handedness(get_optional(options, mouse_handedness_opt)), + to_acceleration_profile(get_optional(options, mouse_cursor_acceleration_opt)), + clamp<-1.0, 1.0>(get_optional(options, mouse_cursor_acceleration_bias_opt)), + get_optional(options, mouse_vscroll_speed_override_opt, mouse_scroll_speed_opt), + get_optional(options, mouse_hscroll_speed_override_opt, mouse_scroll_speed_opt) + }, + touchpad_config{ + get_optional(options, disable_while_typing_opt), + get_optional(options, disable_with_external_mouse_opt), + to_acceleration_profile(get_optional(options, touchpad_cursor_acceleration_opt)), + clamp<-1.0, 1.0>(get_optional(options, touchpad_cursor_acceleration_bias_opt)), + get_optional(options, touchpad_vscroll_speed_override_opt, touchpad_scroll_speed_opt), + get_optional(options, touchpad_hscroll_speed_override_opt, touchpad_scroll_speed_opt), + convert_to_click_mode(get_optional(options, touchpad_click_mode_opt)), + convert_to_scroll_mode(get_optional(options, touchpad_scroll_mode_opt)), + get_optional(options, touchpad_tap_to_click_opt), + get_optional(options, touchpad_middle_mouse_button_emulation_opt) + } { } -void InputDeviceConfig::device_added(std::shared_ptr const& device) +auto miral::InputDeviceConfig::the_input_configuration(std::shared_ptr const& options) +-> std::shared_ptr { - if (contains(device->capabilities(), mi::DeviceCapability::touchpad)) + // This should only be called in single-threaded phase of startup, so no need for synchronization + static std::weak_ptr instance; + + if (auto result = instance.lock()) { - mir::log_debug("Configuring touchpad: '%s'", device->name().c_str()); - if (auto const optional_pointer_config = device->pointer_configuration(); optional_pointer_config.is_set()) + return result; + } + + std::shared_ptr result{new InputDeviceConfig(options)}; + instance = result; + return result; +} + +void miral::InputDeviceConfig::device_added(std::shared_ptr const& device) +{ + touchpad_config.apply_to(*device); + mouse_config.apply_to(*device); +} + +auto miral::InputDeviceConfig::mouse() const -> MouseInputConfiguration +{ + return mouse_config; +} + +auto miral::InputDeviceConfig::touchpad() const -> TouchpadInputConfiguration +{ + return touchpad_config; +} + +void miral::InputDeviceConfig::mouse(MouseInputConfiguration const& val) +{ + mouse_config = val; +} + +void miral::InputDeviceConfig::touchpad(TouchpadInputConfiguration const& val) +{ + touchpad_config = val; +} + +void miral::TouchpadInputConfiguration::apply_to(mi::Device& device) const +{ + if (contains(device.capabilities(), mi::DeviceCapability::touchpad)) + { + mir::log_debug("Configuring touchpad: '%s'", device.name().c_str()); + if (auto const optional_pointer_config = device.pointer_configuration(); optional_pointer_config.is_set()) { MirPointerConfig pointer_config( optional_pointer_config.value() ); - if (touchpad_cursor_acceleration) pointer_config.acceleration(*touchpad_cursor_acceleration); - if (touchpad_cursor_acceleration_bias) pointer_config.cursor_acceleration_bias(*touchpad_cursor_acceleration_bias); - if (touchpad_vscroll_speed) pointer_config.vertical_scroll_scale(*touchpad_vscroll_speed); - if (touchpad_hscroll_speed) pointer_config.horizontal_scroll_scale(*touchpad_hscroll_speed); - device->apply_pointer_configuration(pointer_config); + if (acceleration) pointer_config.acceleration(*acceleration); + if (acceleration_bias) pointer_config.cursor_acceleration_bias(*acceleration_bias); + if (vscroll_speed) pointer_config.vertical_scroll_scale(*vscroll_speed); + if (hscroll_speed) pointer_config.horizontal_scroll_scale(*hscroll_speed); + device.apply_pointer_configuration(pointer_config); } - if (auto const optional_touchpad_config = device->touchpad_configuration(); optional_touchpad_config.is_set()) + if (auto const optional_touchpad_config = device.touchpad_configuration(); optional_touchpad_config.is_set()) { MirTouchpadConfig touch_config( optional_touchpad_config.value() ); if (disable_while_typing) touch_config.disable_while_typing(*disable_while_typing); if (disable_with_external_mouse) touch_config.disable_while_typing(*disable_with_external_mouse); - if (click_mode) touch_config.click_mode(*click_mode); + if (click_mode) touch_config.click_mode(*click_mode); if (scroll_mode) touch_config.scroll_mode(*scroll_mode); if (tap_to_click) touch_config.tap_to_click(*tap_to_click); - if (middle_mouse_button_emulation) touch_config.middle_mouse_button_emulation(*middle_mouse_button_emulation); + if (middle_button_emulation) touch_config.middle_mouse_button_emulation(*middle_button_emulation); - device->apply_touchpad_configuration(touch_config); + device.apply_touchpad_configuration(touch_config); } } - else if (contains(device->capabilities(), mi::DeviceCapability::pointer)) +} + +void miral::MouseInputConfiguration::apply_to(mi::Device& device) const +{ + if (contains(device.capabilities(), mi::DeviceCapability::pointer)) { - mir::log_debug("Configuring pointer: '%s'", device->name().c_str()); - if (auto optional_pointer_config = device->pointer_configuration(); optional_pointer_config.is_set()) + mir::log_debug("Configuring pointer: '%s'", device.name().c_str()); + if (auto optional_pointer_config = device.pointer_configuration(); optional_pointer_config.is_set()) { MirPointerConfig pointer_config( optional_pointer_config.value() ); - if (mouse_handedness) pointer_config.handedness(*mouse_handedness); - if (mouse_cursor_acceleration) pointer_config.acceleration(*mouse_cursor_acceleration); - if (mouse_cursor_acceleration_bias) pointer_config.cursor_acceleration_bias(*mouse_cursor_acceleration_bias); - if (mouse_vscroll_speed) pointer_config.vertical_scroll_scale(*mouse_vscroll_speed); - if (mouse_hscroll_speed) pointer_config.horizontal_scroll_scale(*mouse_hscroll_speed); - device->apply_pointer_configuration(pointer_config); + if (handedness) pointer_config.handedness(*handedness); + if (acceleration) pointer_config.acceleration(*acceleration); + if (acceleration_bias) pointer_config.cursor_acceleration_bias(*acceleration_bias); + if (vscroll_speed) pointer_config.vertical_scroll_scale(*vscroll_speed); + if (hscroll_speed) pointer_config.horizontal_scroll_scale(*hscroll_speed); + device.apply_pointer_configuration(pointer_config); } } } + diff --git a/src/miral/input_device_config.h b/src/miral/input_device_config.h index 60fcb7acb75..85280f8096e 100644 --- a/src/miral/input_device_config.h +++ b/src/miral/input_device_config.h @@ -17,14 +17,66 @@ #ifndef MIRAL_INPUT_DEVICE_CONFIG_H_ #define MIRAL_INPUT_DEVICE_CONFIG_H_ -namespace mir -{ -class Server; -} +#include +#include +#include + +#include +#include + +namespace mir::input { class Device; } namespace miral { -void add_input_device_configuration_options_to(mir::Server& server); +struct MouseInputConfiguration +{ + void apply_to(mir::input::Device& device) const; + std::optional handedness; + std::optional acceleration; + std::optional acceleration_bias; + std::optional vscroll_speed; + std::optional hscroll_speed; +}; + +class TouchpadInputConfiguration +{ +public: + void apply_to(mir::input::Device& device) const; + std::optional disable_while_typing; + std::optional disable_with_external_mouse; + std::optional acceleration; + std::optional acceleration_bias; + std::optional vscroll_speed; + std::optional hscroll_speed; + std::optional click_mode; + std::optional scroll_mode; + std::optional tap_to_click; + std::optional middle_button_emulation; +}; + +class InputDeviceConfig : public mir::input::InputDeviceObserver +{ +public: + auto static the_input_configuration(std::shared_ptr const& options) + -> std::shared_ptr; + + void device_added(std::shared_ptr const& device) override; + void device_changed(std::shared_ptr const&) override {} + void device_removed(std::shared_ptr const&) override {} + void changes_complete() override {} + + auto mouse() const -> MouseInputConfiguration; + auto touchpad() const -> TouchpadInputConfiguration; + + void mouse(MouseInputConfiguration const& val); + void touchpad(TouchpadInputConfiguration const& val); +private: + explicit InputDeviceConfig(std::shared_ptr const& options); + + MouseInputConfiguration mouse_config; + TouchpadInputConfiguration touchpad_config; +}; + } #endif diff --git a/src/miral/input_device_configuration_options.h b/src/miral/input_device_configuration_options.h new file mode 100644 index 00000000000..358c2eba102 --- /dev/null +++ b/src/miral/input_device_configuration_options.h @@ -0,0 +1,30 @@ +/* + * Copyright © Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MIRAL_INPUT_DEVICE_CONFIGURATION_OPTIONS_H_ +#define MIRAL_INPUT_DEVICE_CONFIGURATION_OPTIONS_H_ + +namespace mir +{ +class Server; +} + +namespace miral +{ +void add_input_device_configuration_options_to(mir::Server& server); +} + +#endif diff --git a/src/miral/runner.cpp b/src/miral/runner.cpp index 26d861dca55..5b04036e168 100644 --- a/src/miral/runner.cpp +++ b/src/miral/runner.cpp @@ -17,7 +17,7 @@ #include "miral/runner.h" #include "system_compositor_window_manager.h" #include "fd_manager.h" -#include "input_device_config.h" +#include "input_device_configuration_options.h" #include "join_client_threads.h" #include "launch_app.h" diff --git a/src/miral/symbols.map b/src/miral/symbols.map index a2d1fd49702..29624e30270 100644 --- a/src/miral/symbols.map +++ b/src/miral/symbols.map @@ -470,10 +470,39 @@ global: miral::IdleListener::on_off*; miral::IdleListener::on_wake*; miral::IdleListener::operator*; + miral::InputConfiguration::?InputConfiguration*; + miral::InputConfiguration::InputConfiguration*; + miral::InputConfiguration::Mouse::?Mouse*; + miral::InputConfiguration::Mouse::Mouse*; + miral::InputConfiguration::Mouse::acceleration*; + miral::InputConfiguration::Mouse::acceleration_bias*; + miral::InputConfiguration::Mouse::handedness*; + miral::InputConfiguration::Mouse::hscroll_speed*; + miral::InputConfiguration::Mouse::operator*; + miral::InputConfiguration::Mouse::vscroll_speed*; + miral::InputConfiguration::Touchpad::?Touchpad*; + miral::InputConfiguration::Touchpad::Touchpad*; + miral::InputConfiguration::Touchpad::acceleration*; + miral::InputConfiguration::Touchpad::acceleration_bias*; + miral::InputConfiguration::Touchpad::click_mode*; + miral::InputConfiguration::Touchpad::disable_while_typing*; + miral::InputConfiguration::Touchpad::disable_with_external_mouse*; + miral::InputConfiguration::Touchpad::hscroll_speed*; + miral::InputConfiguration::Touchpad::operator*; + miral::InputConfiguration::Touchpad::scroll_mode*; + miral::InputConfiguration::Touchpad::tap_to_click*; + miral::InputConfiguration::Touchpad::vscroll_speed*; + miral::InputConfiguration::mouse*; + miral::InputConfiguration::operator*; + miral::InputConfiguration::touchpad*; miral::WindowManagerTools::move_cursor_to*; typeinfo?for?miral::ConfigFile; typeinfo?for?miral::Decorations; typeinfo?for?miral::IdleListener; + typeinfo?for?miral::InputConfiguration::Mouse; + typeinfo?for?miral::InputConfiguration::Touchpad; + typeinfo?for?miral::InputConfiguration; + typeinfo?for?miral::IdleListener; }; } MIRAL_5.0; From 2d0249713b88dfffb6639173c2afaa8b7ea64088 Mon Sep 17 00:00:00 2001 From: tarek-y-ismail Date: Tue, 3 Sep 2024 14:11:46 +0000 Subject: [PATCH 04/11] Fix toplevel window resize pingpong (#3575) closes #3573. --- src/server/frontend_wayland/wayland_surface_observer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/frontend_wayland/wayland_surface_observer.h b/src/server/frontend_wayland/wayland_surface_observer.h index 3e9732e80f0..845336e93fc 100644 --- a/src/server/frontend_wayland/wayland_surface_observer.h +++ b/src/server/frontend_wayland/wayland_surface_observer.h @@ -63,6 +63,7 @@ class WaylandSurfaceObserver : public scene::NullSurfaceObserver void latest_client_size(geometry::Size window_size) { impl->window_size = window_size; + impl->requested_size = {}; } /// Should only be called from the Wayland thread From e80f4bf53d0a21904d1e05a12f7cbefb49ac21bf Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Wed, 4 Sep 2024 11:09:48 +0000 Subject: [PATCH 05/11] bugfix: disable window management tests on riscv (#3584) --- debian/rules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 64371b6f21f..7d0e2472924 100755 --- a/debian/rules +++ b/debian/rules @@ -49,9 +49,10 @@ ifeq ($(filter Ubuntu,$(DEB_VENDOR)),) COMMON_CONFIGURE_OPTIONS += -DMIR_RUN_WLCS_TESTS=OFF endif -# Disable miral tests on Launchpad riscv64 (canonical/mir#3443) +# Disable tests on Launchpad riscv64 (canonical/mir#3443, canonical/mir#3470) ifeq ($(USER) $(DEB_HOST_ARCH),buildd riscv64) COMMON_CONFIGURE_OPTIONS += -DMIR_RUN_MIRAL_TESTS=OFF + COMMON_CONFIGURE_OPTIONS += -DMIR_RUN_WINDOW_MANAGEMENT_TESTS=OFF endif # Disable pre-compiled headers on GCC>=12 From 13cc41e4c48fa4c23b2548c86c7e95dd1ee95740 Mon Sep 17 00:00:00 2001 From: tarek-y-ismail Date: Thu, 5 Sep 2024 08:37:20 +0000 Subject: [PATCH 06/11] Fix output tracking (outputs are not identified by scale) (#3582) Drive-by fix --- src/server/frontend_wayland/fractional_scale_v1.cpp | 2 +- src/server/frontend_wayland/fractional_scale_v1.h | 4 ++-- .../frontend_wayland/wayland_surface_observer.cpp | 12 ++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/server/frontend_wayland/fractional_scale_v1.cpp b/src/server/frontend_wayland/fractional_scale_v1.cpp index 75a7840acf1..3d55c2b48ad 100644 --- a/src/server/frontend_wayland/fractional_scale_v1.cpp +++ b/src/server/frontend_wayland/fractional_scale_v1.cpp @@ -98,7 +98,7 @@ void mf::FractionalScaleV1::output_entered(mir::graphics::DisplayConfigurationOu void mf::FractionalScaleV1::output_left(mir::graphics::DisplayConfigurationOutput const& config) { - surface_outputs.erase({config.id, config.scale}); + surface_outputs.erase(config.id); recompute_scale(); } diff --git a/src/server/frontend_wayland/fractional_scale_v1.h b/src/server/frontend_wayland/fractional_scale_v1.h index e5c4c2260f0..7eab897c941 100644 --- a/src/server/frontend_wayland/fractional_scale_v1.h +++ b/src/server/frontend_wayland/fractional_scale_v1.h @@ -19,7 +19,7 @@ #include "fractional-scale-v1_wrapper.h" #include "mir/graphics/display_configuration.h" -#include +#include #include namespace mir @@ -42,7 +42,7 @@ class FractionalScaleV1 : public wayland::FractionalScaleV1 private: // Houses a set of outputs the surface occupies using Id = mir::graphics::DisplayConfigurationOutputId; - std::set> surface_outputs; + std::unordered_map surface_outputs; void recompute_scale(); }; diff --git a/src/server/frontend_wayland/wayland_surface_observer.cpp b/src/server/frontend_wayland/wayland_surface_observer.cpp index 446224bd7fd..3d5b55038f1 100644 --- a/src/server/frontend_wayland/wayland_surface_observer.cpp +++ b/src/server/frontend_wayland/wayland_surface_observer.cpp @@ -118,12 +118,20 @@ void mf::WaylandSurfaceObserver::input_consumed(ms::Surface const*, std::shared_ void mf::WaylandSurfaceObserver::entered_output(ms::Surface const*, graphics::DisplayConfigurationOutputId const& id) { - impl->window.value().handle_enter_output(id); + run_on_wayland_thread_unless_window_destroyed( + [id](Impl* impl, WindowWlSurfaceRole*) + { + impl->window.value().handle_enter_output(id); + }); } void mf::WaylandSurfaceObserver::left_output(ms::Surface const*, graphics::DisplayConfigurationOutputId const& id) { - impl->window.value().handle_leave_output(id); + run_on_wayland_thread_unless_window_destroyed( + [id](Impl* impl, WindowWlSurfaceRole*) + { + impl->window.value().handle_leave_output(id); + }); } void mf::WaylandSurfaceObserver::run_on_wayland_thread_unless_window_destroyed( From 7e21a55133b42559a149202c2c7874475d88368a Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Thu, 5 Sep 2024 17:31:36 +0000 Subject: [PATCH 07/11] Do not allocate memory between `fork()` and `exec()` (#3588) Fixes: #3581 --- src/miral/launch_app.cpp | 14 ++++++++------ src/platforms/wayland/cursor.cpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/miral/launch_app.cpp b/src/miral/launch_app.cpp index bb028aff67a..0087b08e879 100644 --- a/src/miral/launch_app.cpp +++ b/src/miral/launch_app.cpp @@ -29,7 +29,7 @@ namespace { -void strip_mir_env_variables() +auto mir_env_variables() -> std::vector { static char const mir_prefix[] = "MIR_"; @@ -51,10 +51,7 @@ void strip_mir_env_variables() } } - for (auto const& var : vars_to_remove) - { - unsetenv(var.c_str()); - } + return vars_to_remove; } } // namespace @@ -64,6 +61,8 @@ auto miral::launch_app_env( mir::optional_value const& x11_display, miral::AppEnvironment const& app_env) -> pid_t { + static auto const vars_to_remove = mir_env_variables(); + pid_t pid = fork(); if (pid < 0) @@ -73,7 +72,10 @@ auto miral::launch_app_env( if (pid == 0) { - strip_mir_env_variables(); + for (auto const& var : vars_to_remove) + { + unsetenv(var.c_str()); + } if (x11_display) { diff --git a/src/platforms/wayland/cursor.cpp b/src/platforms/wayland/cursor.cpp index 1c0d589d1c5..e4eda7d8f0f 100644 --- a/src/platforms/wayland/cursor.cpp +++ b/src/platforms/wayland/cursor.cpp @@ -41,7 +41,7 @@ struct wl_shm_pool* make_shm_pool(struct wl_shm* shm, int size, void **data) static auto const template_filename = std::string{getenv("XDG_RUNTIME_DIR")} + "/wayland-cursor-shared-XXXXXX"; - auto const filename = strdup(template_filename.c_str()); + char* const filename = const_cast(template_filename.c_str()); mir::Fd const fd{mkostemp(filename, O_CLOEXEC)}; unlink(filename); free(filename); From 0901953886dce4cd05e9659de5053ea61bec79ad Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Thu, 5 Sep 2024 20:53:27 +0000 Subject: [PATCH 08/11] OutputManager: When listeners are registered, they need to be notified of existing globals (#3586) In particular, `WindowWlSurfaceRole::output_global_created()` uses the notification to register as an observer on the global. Without this, it cannot track configuration changes --- src/server/frontend_wayland/output_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/server/frontend_wayland/output_manager.cpp b/src/server/frontend_wayland/output_manager.cpp index d40d1a576ca..512e49f5d84 100644 --- a/src/server/frontend_wayland/output_manager.cpp +++ b/src/server/frontend_wayland/output_manager.cpp @@ -310,6 +310,11 @@ auto mf::OutputManager::output_for(graphics::DisplayConfigurationOutputId id) -> void mf::OutputManager::add_listener(OutputManagerListener* listener) { listeners.push_back(listener); + + for (auto const& [_, output_global] : outputs) + { + listener->output_global_created(output_global.get()); + } } void mf::OutputManager::remove_listener(OutputManagerListener* listener) From 910d3b814d02fc896c665bc7c4aad1db6317c666 Mon Sep 17 00:00:00 2001 From: Alan Griffiths Date: Fri, 6 Sep 2024 13:41:49 +0000 Subject: [PATCH 09/11] Fix missing `wl_surface.enter` events for outputs enabled at runtime. (#3585) In my [previous fix](https://github.com/canonical/mir/pull/3430) for #3414, I accidentally disabled sending `wl_surface.enter` events for surfaces on outputs enabled at runtime. This PR resolves that issue while still addressing #3414. --- src/server/frontend_wayland/output_manager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/frontend_wayland/output_manager.cpp b/src/server/frontend_wayland/output_manager.cpp index 512e49f5d84..26c2ddc9149 100644 --- a/src/server/frontend_wayland/output_manager.cpp +++ b/src/server/frontend_wayland/output_manager.cpp @@ -224,7 +224,10 @@ void mf::OutputGlobal::bind(wl_resource* resource) { auto const instance = new OutputInstance(resource, this); instances[instance->client].push_back(instance); - instance->output_config_changed(output_config); + for (auto const& listener : listeners) + { + listener->output_config_changed(output_config); + } instance->send_done(); } From 4e10bef71b5ac31a67ece8f84c7d37baa3d15330 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Fri, 6 Sep 2024 20:47:08 +0000 Subject: [PATCH 10/11] Live scale changes (#3583) Surfaces need to track scale changes on outputs they appear on Fixes: #3552 (Reviewers note: this depends on #3586) --- .../server/mir/scene/null_surface_observer.h | 1 + .../server/mir/scene/surface_observer.h | 1 + src/miroil/surface.cpp | 7 +++++ .../frontend_wayland/fractional_scale_v1.cpp | 6 ++++ .../frontend_wayland/fractional_scale_v1.h | 1 + .../wayland_surface_observer.cpp | 9 ++++++ .../wayland_surface_observer.h | 1 + .../window_wl_surface_role.cpp | 21 ++++++++++++-- .../frontend_wayland/window_wl_surface_role.h | 2 ++ src/server/scene/basic_surface.cpp | 29 +++++++++++++------ src/server/scene/basic_surface.h | 2 +- src/server/scene/null_surface_observer.cpp | 5 ++-- src/server/symbols.map | 2 ++ .../window_management_test_harness.cpp | 2 +- 14 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/include/server/mir/scene/null_surface_observer.h b/src/include/server/mir/scene/null_surface_observer.h index b40a6ba94f6..548fc61cfd2 100644 --- a/src/include/server/mir/scene/null_surface_observer.h +++ b/src/include/server/mir/scene/null_surface_observer.h @@ -49,6 +49,7 @@ class NullSurfaceObserver : public SurfaceObserver void application_id_set_to(Surface const* surf, std::string const& application_id) override; void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override; void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override; + void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override; protected: NullSurfaceObserver(NullSurfaceObserver const&) = delete; diff --git a/src/include/server/mir/scene/surface_observer.h b/src/include/server/mir/scene/surface_observer.h index 6d1c7085383..6d94220a5bc 100644 --- a/src/include/server/mir/scene/surface_observer.h +++ b/src/include/server/mir/scene/surface_observer.h @@ -64,6 +64,7 @@ class SurfaceObserver virtual void depth_layer_set_to(Surface const* surf, MirDepthLayer depth_layer) = 0; virtual void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0; virtual void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0; + virtual void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0; protected: SurfaceObserver() = default; diff --git a/src/miroil/surface.cpp b/src/miroil/surface.cpp index 89eecfa20a8..c24d77d8b46 100644 --- a/src/miroil/surface.cpp +++ b/src/miroil/surface.cpp @@ -59,6 +59,7 @@ class miroil::SurfaceObserverImpl : public mir::scene::SurfaceObserver mir::geometry::Size const &window_size) override; void entered_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override; void left_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override; + void rescale_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override; private: std::shared_ptr listener; @@ -171,6 +172,12 @@ void miroil::SurfaceObserverImpl::left_output( { } +void miroil::SurfaceObserverImpl::rescale_output( + mir::scene::Surface const* /*surf*/, + mir::graphics::DisplayConfigurationOutputId const& /*id*/) +{ +} + miroil::Surface::Surface(std::shared_ptr wrapped) : wrapped(wrapped) { diff --git a/src/server/frontend_wayland/fractional_scale_v1.cpp b/src/server/frontend_wayland/fractional_scale_v1.cpp index 3d55c2b48ad..ce29e542d4a 100644 --- a/src/server/frontend_wayland/fractional_scale_v1.cpp +++ b/src/server/frontend_wayland/fractional_scale_v1.cpp @@ -102,6 +102,12 @@ void mf::FractionalScaleV1::output_left(mir::graphics::DisplayConfigurationOutpu recompute_scale(); } +void mf::FractionalScaleV1::scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config) +{ + surface_outputs[config.id] = config.scale; + recompute_scale(); +} + void mf::FractionalScaleV1::recompute_scale() { auto max_element = std::max_element( diff --git a/src/server/frontend_wayland/fractional_scale_v1.h b/src/server/frontend_wayland/fractional_scale_v1.h index 7eab897c941..658c00dab9b 100644 --- a/src/server/frontend_wayland/fractional_scale_v1.h +++ b/src/server/frontend_wayland/fractional_scale_v1.h @@ -38,6 +38,7 @@ class FractionalScaleV1 : public wayland::FractionalScaleV1 void output_entered(mir::graphics::DisplayConfigurationOutput const& config); void output_left(mir::graphics::DisplayConfigurationOutput const& config); + void scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config); private: // Houses a set of outputs the surface occupies diff --git a/src/server/frontend_wayland/wayland_surface_observer.cpp b/src/server/frontend_wayland/wayland_surface_observer.cpp index 3d5b55038f1..22b4838299b 100644 --- a/src/server/frontend_wayland/wayland_surface_observer.cpp +++ b/src/server/frontend_wayland/wayland_surface_observer.cpp @@ -134,6 +134,15 @@ void mf::WaylandSurfaceObserver::left_output(ms::Surface const*, graphics::Displ }); } +void mf::WaylandSurfaceObserver::rescale_output(ms::Surface const*, graphics::DisplayConfigurationOutputId const& id) +{ + run_on_wayland_thread_unless_window_destroyed( + [id](Impl* impl, WindowWlSurfaceRole*) + { + impl->window.value().handle_scale_output(id); + }); +} + void mf::WaylandSurfaceObserver::run_on_wayland_thread_unless_window_destroyed( std::function&& work) { diff --git a/src/server/frontend_wayland/wayland_surface_observer.h b/src/server/frontend_wayland/wayland_surface_observer.h index 845336e93fc..05ecd80ec6f 100644 --- a/src/server/frontend_wayland/wayland_surface_observer.h +++ b/src/server/frontend_wayland/wayland_surface_observer.h @@ -57,6 +57,7 @@ class WaylandSurfaceObserver : public scene::NullSurfaceObserver void input_consumed(scene::Surface const*, std::shared_ptr const& event) override; void entered_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override; void left_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override; + void rescale_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override; ///@} /// Should only be called from the Wayland thread diff --git a/src/server/frontend_wayland/window_wl_surface_role.cpp b/src/server/frontend_wayland/window_wl_surface_role.cpp index cc11e2777eb..9d29390ca5c 100644 --- a/src/server/frontend_wayland/window_wl_surface_role.cpp +++ b/src/server/frontend_wayland/window_wl_surface_role.cpp @@ -461,11 +461,20 @@ auto mf::WindowWlSurfaceRole::output_config_changed(graphics::DisplayConfigurati client, [&](OutputInstance* instance) { + if (auto const fractional_scale = surface.value().get_fractional_scale()) + fractional_scale.value().output_entered(config); surface.value().send_enter_event(instance->resource); pending_enter_events.erase(id_it); }); } } + + if (auto id_it{std::ranges::find(pending_rescale_events, config.id)}; id_it != pending_rescale_events.end()) + { + if (auto const fractional_scale = surface.value().get_fractional_scale()) + fractional_scale.value().scale_change_on_output(config); + pending_rescale_events.erase(id_it); + } } return true; @@ -524,7 +533,7 @@ void mf::WindowWlSurfaceRole::handle_enter_output(graphics::DisplayConfiguration auto const& config{global->current_config()}; if (config.id == id) { - if (auto fractional_scale = surface.value().get_fractional_scale()) + if (auto const fractional_scale = surface.value().get_fractional_scale()) fractional_scale.value().output_entered(config); global->for_each_output_bound_by( @@ -552,7 +561,7 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration auto const& config{global->current_config()}; if (config.id == id) { - if(auto fractional_scale = surface.value().get_fractional_scale()) + if(auto const fractional_scale = surface.value().get_fractional_scale()) fractional_scale.value().output_left(config); global->for_each_output_bound_by( @@ -566,6 +575,14 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration } } +void mf::WindowWlSurfaceRole::handle_scale_output(graphics::DisplayConfigurationOutputId id) +{ + if (surface) + { + pending_rescale_events.push_back(id); + } +} + void mf::WindowWlSurfaceRole::apply_client_size(mir::shell::SurfaceSpecification& mods) { if ((!committed_width_set_explicitly || !committed_height_set_explicitly) && surface) diff --git a/src/server/frontend_wayland/window_wl_surface_role.h b/src/server/frontend_wayland/window_wl_surface_role.h index 9bbedee02f5..04fc3c4c777 100644 --- a/src/server/frontend_wayland/window_wl_surface_role.h +++ b/src/server/frontend_wayland/window_wl_surface_role.h @@ -102,6 +102,7 @@ class WindowWlSurfaceRole void handle_enter_output(graphics::DisplayConfigurationOutputId id); void handle_leave_output(graphics::DisplayConfigurationOutputId id) const; + void handle_scale_output(graphics::DisplayConfigurationOutputId id); /// Gets called after the surface has committed (so current_size() may return the committed buffer size) but before /// the Mir window is modified (so if a pending size is set or a spec is applied those changes will take effect) @@ -174,6 +175,7 @@ class WindowWlSurfaceRole void apply_client_size(mir::shell::SurfaceSpecification& mods); std::vector pending_enter_events; + std::vector pending_rescale_events; }; } diff --git a/src/server/scene/basic_surface.cpp b/src/server/scene/basic_surface.cpp index f4bfc52e9ab..3e82471bf0a 100644 --- a/src/server/scene/basic_surface.cpp +++ b/src/server/scene/basic_surface.cpp @@ -169,6 +169,11 @@ class ms::BasicSurface::Multiplexer : public ObserverMultiplexer geo void mir::scene::BasicSurface::track_outputs() { auto const state{synchronised_state.lock()}; - std::set tracked; + decltype(tracked_output_scales) tracked; display_config->for_each_output( [&](mg::DisplayConfigurationOutput const& output) { if (output.valid() && output.used && output.extents().overlaps(state->surface_rect)) { - if (!tracked_outputs.contains(output.id)) + if (!tracked_output_scales.contains(output.id)) { observers->entered_output(this, output.id); } - tracked.insert(output.id); + tracked.emplace(output.id, output.scale); } }); - // TODO: Once std::views::filter is properly supported across compilers, replace the - // creation of `untracked` with iteration over a filtered view of `tracked_outputs` - std::vector untracked; - std::ranges::set_difference(tracked_outputs, tracked, std::back_inserter(untracked)); - std::ranges::for_each(untracked, [&](auto const& id) { observers->left_output(this, id); }); + for (auto const& [id, scale] : tracked_output_scales) + { + if (auto new_entry = tracked.find(id); new_entry == tracked.end()) + { + observers->left_output(this, id); + } + else if (new_entry->second != scale) + { + observers->rescale_output(this, id); + } + } - tracked_outputs = std::move(tracked); + tracked_output_scales = std::move(tracked); } void mir::scene::BasicSurface::linearised_track_outputs() diff --git a/src/server/scene/basic_surface.h b/src/server/scene/basic_surface.h index ddd308046ff..55e928fa574 100644 --- a/src/server/scene/basic_surface.h +++ b/src/server/scene/basic_surface.h @@ -239,7 +239,7 @@ class BasicSurface : public Surface std::shared_ptr> display_config_registrar; std::shared_ptr const display_config_monitor; std::shared_ptr display_config; - std::set tracked_outputs; + std::unordered_map tracked_output_scales; }; } diff --git a/src/server/scene/null_surface_observer.cpp b/src/server/scene/null_surface_observer.cpp index f80fc840754..67ca480e423 100644 --- a/src/server/scene/null_surface_observer.cpp +++ b/src/server/scene/null_surface_observer.cpp @@ -37,5 +37,6 @@ void ms::NullSurfaceObserver::placed_relative(Surface const*, geometry::Rectangl void ms::NullSurfaceObserver::input_consumed(Surface const*, std::shared_ptr const&) {} void ms::NullSurfaceObserver::depth_layer_set_to(Surface const*, MirDepthLayer) {} void ms::NullSurfaceObserver::application_id_set_to(Surface const*, std::string const&) {} -void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}; -void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}; +void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {} +void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {} +void ms::NullSurfaceObserver::rescale_output(Surface const*, graphics::DisplayConfigurationOutputId const&){} diff --git a/src/server/symbols.map b/src/server/symbols.map index c84817e704b..bcdc5a9de6d 100644 --- a/src/server/symbols.map +++ b/src/server/symbols.map @@ -488,6 +488,7 @@ global: mir::scene::NullSurfaceObserver::placed_relative*; mir::scene::NullSurfaceObserver::reception_mode_set_to*; mir::scene::NullSurfaceObserver::renamed*; + mir::scene::NullSurfaceObserver::rescale_output*; mir::scene::NullSurfaceObserver::transformation_set_to*; mir::scene::NullSurfaceObserver::window_resized_to*; mir::scene::Observer::?Observer*; @@ -947,6 +948,7 @@ global: non-virtual?thunk?to?mir::scene::NullSurfaceObserver::placed_relative*; non-virtual?thunk?to?mir::scene::NullSurfaceObserver::reception_mode_set_to*; non-virtual?thunk?to?mir::scene::NullSurfaceObserver::renamed*; + non-virtual?thunk?to?mir::scene::NullSurfaceObserver::rescale_output*; non-virtual?thunk?to?mir::scene::NullSurfaceObserver::transformation_set_to*; non-virtual?thunk?to?mir::scene::NullSurfaceObserver::window_resized_to*; non-virtual?thunk?to?mir::scene::Observer::?Observer*; diff --git a/tests/mir_test_framework/window_management_test_harness.cpp b/tests/mir_test_framework/window_management_test_harness.cpp index 0eb445e2e59..2360d239f00 100644 --- a/tests/mir_test_framework/window_management_test_harness.cpp +++ b/tests/mir_test_framework/window_management_test_harness.cpp @@ -83,7 +83,7 @@ struct mir_test_framework::WindowManagementTestHarness::Self : public ms::Surfac void depth_layer_set_to(ms::Surface const*, MirDepthLayer) override {} void entered_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {} void left_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {} - + void rescale_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {} std::mutex mutable mutex; std::vector> streams; std::vector> known_surfaces; From 4728e9f80d3fdf9ca26b0db6524a5f1ad4672afd Mon Sep 17 00:00:00 2001 From: Alan Griffiths Date: Mon, 9 Sep 2024 16:09:59 +0100 Subject: [PATCH 11/11] Update changelog --- debian/changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/changelog b/debian/changelog index d613b45ba72..05ad35ecf2f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -27,6 +27,7 @@ mir (2.18.0) UNRELEASED; urgency=medium . ci: replace codecov with TICS (#3485) . ci: enable AddressSanitizer (#3026) . Add support for `wp_fractional_scale_v1` (#3509) + . Allow servers to dynamically update input configuration Documentation: . Add Mir's CI documentation (#3434) @@ -48,6 +49,7 @@ mir (2.18.0) UNRELEASED; urgency=medium . Fix x11 rendering when scaled fractional scaling (#3508, #3554) . wbg constantly resizing after switching to 2.17.0 (#3450) . Decorations Eat Into Application Area (#3572) + . Fix toplevel window resize pingpong. (Fixes #3573) -- Michał Sawicz Thu, 08 Aug 2024 10:35:09 +0200