From c6d8e20b655ac1baffee3042d859526f4f2d9072 Mon Sep 17 00:00:00 2001 From: Alan Griffiths Date: Fri, 20 Dec 2024 10:47:59 +0000 Subject: [PATCH] Plumb the decoration strategy through msd::BasicManager so that the strategy always supplies StaticGeometry --- src/include/server/mir/shell/decoration.h | 28 -------- src/server/shell/abstract_shell.cpp | 5 +- .../shell/decoration/basic_decoration.cpp | 17 ----- src/server/shell/decoration/basic_manager.cpp | 30 +++++++- src/server/shell/decoration/basic_manager.h | 6 ++ .../shell/decoration/decoration_strategy.cpp | 61 ++++++++++++++++- .../shell/decoration/decoration_strategy.h | 3 +- src/server/shell/decoration/manager.h | 7 ++ src/server/shell/decoration/null_manager.h | 2 + src/server/shell/decoration/window.cpp | 68 ------------------- src/server/shell/default_configuration.cpp | 4 +- .../shell/test_decoration_basic_manager.cpp | 3 + 12 files changed, 113 insertions(+), 121 deletions(-) delete mode 100644 src/include/server/mir/shell/decoration.h diff --git a/src/include/server/mir/shell/decoration.h b/src/include/server/mir/shell/decoration.h deleted file mode 100644 index 85f6c05e312..00000000000 --- a/src/include/server/mir/shell/decoration.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 MIR_SHELL_DECORATION_H_ -#define MIR_SHELL_DECORATION_H_ - -#include "mir/geometry/forward.h" -#include "mir_toolkit/common.h" - -namespace mir::shell::decoration -{ - auto compute_size_with_decorations(geometry::Size content_size, MirWindowType type, MirWindowState state) -> geometry::Size; -} - -#endif diff --git a/src/server/shell/abstract_shell.cpp b/src/server/shell/abstract_shell.cpp index a868d8fbcee..f6972e454b7 100644 --- a/src/server/shell/abstract_shell.cpp +++ b/src/server/shell/abstract_shell.cpp @@ -16,7 +16,6 @@ #include "mir/shell/abstract_shell.h" -#include "mir/shell/decoration.h" #include "mir/shell/input_targeter.h" #include "mir/shell/shell_report.h" #include "mir/shell/surface_specification.h" @@ -233,7 +232,7 @@ auto msh::AbstractShell::create_surface( if (wm_visible_spec.server_side_decorated.value_or(false) && wm_visible_spec.width.is_set() && wm_visible_spec.height.is_set()) { geom::Size const content_size{wm_visible_spec.width.value(), wm_visible_spec.height.value()}; - auto const size = decoration::compute_size_with_decorations( + auto const size = decoration_manager->compute_size_with_decorations( content_size, wm_visible_spec.type.value(), wm_visible_spec.state.value()); @@ -302,7 +301,7 @@ void msh::AbstractShell::modify_surface(std::shared_ptr const& s wm_relevant_mods.height = content_size.height; // When adding decorations we need to resize the window for WM - window_size = decoration::compute_size_with_decorations( + window_size = decoration_manager->compute_size_with_decorations( content_size, modifications.type.value_or(surface->type()), modifications.state.value_or(surface->state())); diff --git a/src/server/shell/decoration/basic_decoration.cpp b/src/server/shell/decoration/basic_decoration.cpp index 6137e2d7dee..bf4d74a7e37 100644 --- a/src/server/shell/decoration/basic_decoration.cpp +++ b/src/server/shell/decoration/basic_decoration.cpp @@ -42,23 +42,6 @@ namespace geom = mir::geometry; namespace msh = mir::shell; namespace msd = mir::shell::decoration; -namespace mir::shell::decoration -{ -// See src/server/shell/decoration/window.h for a full description of each property -StaticGeometry const default_geometry { - geom::Height{24}, // titlebar_height - geom::Width{6}, // side_border_width - geom::Height{6}, // bottom_border_height - geom::Size{16, 16}, // resize_corner_input_size - geom::Width{24}, // button_width - geom::Width{6}, // padding_between_buttons - geom::Height{14}, // title_font_height - geom::Point{8, 2}, // title_font_top_left - geom::Displacement{5, 5}, // icon_padding - geom::Width{1}, // detail_line_width -}; -} - namespace { template diff --git a/src/server/shell/decoration/basic_manager.cpp b/src/server/shell/decoration/basic_manager.cpp index 4056707df00..43ab25f0689 100644 --- a/src/server/shell/decoration/basic_manager.cpp +++ b/src/server/shell/decoration/basic_manager.cpp @@ -16,6 +16,7 @@ #include "basic_manager.h" #include "decoration.h" +#include "decoration_strategy.h" #include #include @@ -49,8 +50,10 @@ class msd::DisplayConfigurationListener : public mg::NullDisplayConfigurationOb }; msd::BasicManager::BasicManager( + std::shared_ptr const& decoration_strategy, ObserverRegistrar& display_configuration_observers, DecorationBuilder&& decoration_builder) : + decoration_strategy{decoration_strategy}, decoration_builder{std::move(decoration_builder)}, display_config_monitor{std::make_shared( [&](mg::DisplayConfiguration const& config) @@ -92,7 +95,7 @@ void msd::BasicManager::decorate(std::shared_ptr const& surface) { decorations[surface.get()] = nullptr; lock.unlock(); - auto decoration = decoration_builder(locked_shell, surface); + auto decoration = decoration_builder(decoration_strategy, locked_shell, surface); lock.lock(); decoration->set_scale(scale); decorations[surface.get()] = std::move(decoration); @@ -128,6 +131,29 @@ void msd::BasicManager::undecorate_all() to_destroy.clear(); } +using mir::geometry::Size; + +auto msd::BasicManager::compute_size_with_decorations(Size content_size, + MirWindowType type, MirWindowState state) -> Size +{ + auto const geometry = decoration_strategy->static_geometry(); + + switch (border_type_for(type, state)) + { + case msd::BorderType::Full: + content_size.width += geometry->side_border_width * 2; + content_size.height += geometry->titlebar_height + geometry->bottom_border_height; + break; + case msd::BorderType::Titlebar: + content_size.height += geometry->titlebar_height; + break; + case msd::BorderType::None: + break; + } + + return content_size; +} + void msd::BasicManager::set_scale(float new_scale) { std::lock_guard lock{mutex}; @@ -139,4 +165,4 @@ void msd::BasicManager::set_scale(float new_scale) it.second->set_scale(scale); } } -} \ No newline at end of file +} diff --git a/src/server/shell/decoration/basic_manager.h b/src/server/shell/decoration/basic_manager.h index be4f2413924..5ae39b36f98 100644 --- a/src/server/shell/decoration/basic_manager.h +++ b/src/server/shell/decoration/basic_manager.h @@ -40,6 +40,7 @@ class Shell; namespace decoration { class Decoration; +class DecorationStrategy; class DisplayConfigurationListener; /// Facilitates decorating windows with Mir's built-in server size decorations @@ -48,10 +49,12 @@ class BasicManager : { public: using DecorationBuilder = std::function( + std::shared_ptr const& decoration_strategy, std::shared_ptr const& shell, std::shared_ptr const& surface)>; BasicManager( + std::shared_ptr const& decoration_strategy, mir::ObserverRegistrar& display_configuration_observers, DecorationBuilder&& decoration_builder); ~BasicManager(); @@ -60,8 +63,11 @@ class BasicManager : void decorate(std::shared_ptr const& surface) override; void undecorate(std::shared_ptr const& surface) override; void undecorate_all() override; + auto compute_size_with_decorations(geometry::Size content_size, MirWindowType type, + MirWindowState state) -> geometry::Size override; private: + std::shared_ptr const decoration_strategy; DecorationBuilder const decoration_builder; std::shared_ptr const display_config_monitor; std::weak_ptr shell; diff --git a/src/server/shell/decoration/decoration_strategy.cpp b/src/server/shell/decoration/decoration_strategy.cpp index f906c776e40..5746e1a6844 100644 --- a/src/server/shell/decoration/decoration_strategy.cpp +++ b/src/server/shell/decoration/decoration_strategy.cpp @@ -18,6 +18,7 @@ #include "decoration_strategy.h" #include "window.h" +#include "mir/fatal.h" #include "mir/geometry/displacement.h" #include "mir/log.h" @@ -297,10 +298,68 @@ class DecorationStrategy : public msd::DecorationStrategy auto button_placement(unsigned n, const WindowState& ws) const -> mir::geometry::Rectangle override; private: - std::shared_ptr const static_geometry_{std::make_shared(msd::default_geometry)}; + static StaticGeometry const default_geometry; + std::shared_ptr const static_geometry_{std::make_shared(default_geometry)}; +}; + +StaticGeometry const DecorationStrategy::default_geometry { + geom::Height{24}, // titlebar_height + geom::Width{6}, // side_border_width + geom::Height{6}, // bottom_border_height + geom::Size{16, 16}, // resize_corner_input_size + geom::Width{24}, // button_width + geom::Width{6}, // padding_between_buttons + geom::Height{14}, // title_font_height + geom::Point{8, 2}, // title_font_top_left + geom::Displacement{5, 5}, // icon_padding + geom::Width{1}, // detail_line_width }; } +auto msd::border_type_for(MirWindowType type, MirWindowState state) -> msd::BorderType +{ + using BorderType = msd::BorderType; + + switch (type) + { + case mir_window_type_normal: + case mir_window_type_utility: + case mir_window_type_dialog: + case mir_window_type_freestyle: + case mir_window_type_satellite: + break; + + case mir_window_type_gloss: + case mir_window_type_menu: + case mir_window_type_inputmethod: + case mir_window_type_tip: + case mir_window_type_decoration: + case mir_window_types: + return BorderType::None; + } + + switch (state) + { + case mir_window_state_unknown: + case mir_window_state_restored: + return BorderType::Full; + + case mir_window_state_maximized: + case mir_window_state_vertmaximized: + case mir_window_state_horizmaximized: + return BorderType::Titlebar; + + case mir_window_state_minimized: + case mir_window_state_fullscreen: + case mir_window_state_hidden: + case mir_window_state_attached: + case mir_window_states: + return BorderType::None; + } + + mir::fatal_error("%s:%d: should be unreachable", __FILE__, __LINE__); + return {}; +} auto msd::DecorationStrategy::default_decoration_strategy() -> std::unique_ptr { diff --git a/src/server/shell/decoration/decoration_strategy.h b/src/server/shell/decoration/decoration_strategy.h index 687aec256cd..bfcccefeffc 100644 --- a/src/server/shell/decoration/decoration_strategy.h +++ b/src/server/shell/decoration/decoration_strategy.h @@ -51,7 +51,6 @@ struct StaticGeometry MirPixelFormat const buffer_format = mir_pixel_format_argb_8888; }; -extern StaticGeometry const default_geometry; enum class ButtonState { @@ -74,6 +73,8 @@ enum class BorderType None, ///< No decorations (for fullscreen windows or popups) }; +auto border_type_for(MirWindowType type, MirWindowState state) -> BorderType; + struct ButtonInfo { ButtonFunction function; diff --git a/src/server/shell/decoration/manager.h b/src/server/shell/decoration/manager.h index eae620b7f53..30870af674e 100644 --- a/src/server/shell/decoration/manager.h +++ b/src/server/shell/decoration/manager.h @@ -17,6 +17,9 @@ #ifndef MIR_SHELL_DECORATION_MANAGER_H_ #define MIR_SHELL_DECORATION_MANAGER_H_ +#include "mir/geometry/size.h" +#include "mir_toolkit/client_types.h" + #include namespace mir @@ -49,6 +52,10 @@ class Manager /// Removes decorations from all currently decorated windows virtual void undecorate_all() = 0; + /// Compute the corresponding size + virtual auto compute_size_with_decorations(geometry::Size content_size, MirWindowType type, MirWindowState state) + -> geometry::Size = 0; + private: Manager(Manager const&) = delete; Manager& operator=(Manager const&) = delete; diff --git a/src/server/shell/decoration/null_manager.h b/src/server/shell/decoration/null_manager.h index ea69e7b1b61..57159613034 100644 --- a/src/server/shell/decoration/null_manager.h +++ b/src/server/shell/decoration/null_manager.h @@ -33,6 +33,8 @@ class NullManager void decorate(std::shared_ptr const&) override {} void undecorate(std::shared_ptr const&) override {} void undecorate_all() override {} + auto compute_size_with_decorations(geometry::Size sz, MirWindowType, MirWindowState) -> geometry::Size override + { return sz; } }; } } diff --git a/src/server/shell/decoration/window.cpp b/src/server/shell/decoration/window.cpp index 2ce793671d3..a8e1c1499b3 100644 --- a/src/server/shell/decoration/window.cpp +++ b/src/server/shell/decoration/window.cpp @@ -21,60 +21,11 @@ #include "mir/scene/surface.h" #include "mir/scene/null_surface_observer.h" -#include "mir/shell/decoration.h" namespace ms = mir::scene; namespace geom = mir::geometry; namespace msd = mir::shell::decoration; -namespace -{ -auto border_type_for(MirWindowType type, MirWindowState state) -> msd::BorderType -{ - using BorderType = msd::BorderType; - - switch (type) - { - case mir_window_type_normal: - case mir_window_type_utility: - case mir_window_type_dialog: - case mir_window_type_freestyle: - case mir_window_type_satellite: - break; - - case mir_window_type_gloss: - case mir_window_type_menu: - case mir_window_type_inputmethod: - case mir_window_type_tip: - case mir_window_type_decoration: - case mir_window_types: - return BorderType::None; - } - - switch (state) - { - case mir_window_state_unknown: - case mir_window_state_restored: - return BorderType::Full; - - case mir_window_state_maximized: - case mir_window_state_vertmaximized: - case mir_window_state_horizmaximized: - return BorderType::Titlebar; - - case mir_window_state_minimized: - case mir_window_state_fullscreen: - case mir_window_state_hidden: - case mir_window_state_attached: - case mir_window_states: - return BorderType::None; - } - - mir::fatal_error("%s:%d: should be unreachable", __FILE__, __LINE__); - return {}; -} -} - msd::WindowState::WindowState( std::shared_ptr const& static_geometry, std::shared_ptr const& surface, @@ -286,22 +237,3 @@ msd::WindowSurfaceObserverManager::~WindowSurfaceObserverManager() { surface_->unregister_interest(*observer); } - -auto msd::compute_size_with_decorations(geometry::Size content_size, MirWindowType type, MirWindowState state) - -> geometry::Size -{ - switch (border_type_for(type, state)) - { - case msd::BorderType::Full: - content_size.width += msd::default_geometry.side_border_width * 2; - content_size.height += msd::default_geometry.titlebar_height + msd::default_geometry.bottom_border_height; - break; - case msd::BorderType::Titlebar: - content_size.height += msd::default_geometry.titlebar_height; - break; - case msd::BorderType::None: - break; - } - - return content_size; -} diff --git a/src/server/shell/default_configuration.cpp b/src/server/shell/default_configuration.cpp index 22a5e9dedac..6e7ccf6f729 100644 --- a/src/server/shell/default_configuration.cpp +++ b/src/server/shell/default_configuration.cpp @@ -70,10 +70,12 @@ auto mir::DefaultServerConfiguration::the_decoration_manager() -> std::shared_pt [this]()->std::shared_ptr { return std::make_shared( + msd::DecorationStrategy::default_decoration_strategy(), *the_display_configuration_observer_registrar(), [buffer_allocator = the_buffer_allocator(), executor = the_main_loop(), cursor_images = the_cursor_images()]( + std::shared_ptr const& decoration_strategy, std::shared_ptr const& shell, std::shared_ptr const& surface) -> std::unique_ptr { @@ -83,7 +85,7 @@ auto mir::DefaultServerConfiguration::the_decoration_manager() -> std::shared_pt executor, cursor_images, surface, - msd::DecorationStrategy::default_decoration_strategy()); + decoration_strategy); }); }); } diff --git a/tests/unit-tests/shell/test_decoration_basic_manager.cpp b/tests/unit-tests/shell/test_decoration_basic_manager.cpp index 5dcf7e6ba98..a5564d16e0d 100644 --- a/tests/unit-tests/shell/test_decoration_basic_manager.cpp +++ b/tests/unit-tests/shell/test_decoration_basic_manager.cpp @@ -22,6 +22,7 @@ #include #include +#include namespace ms = mir::scene; namespace msh = mir::shell; @@ -59,8 +60,10 @@ struct DecorationBasicManager registrar{std::make_shared>()}; msd::BasicManager manager{ + msd::DecorationStrategy::default_decoration_strategy(), *registrar, [this]( + std::shared_ptr const&, std::shared_ptr const&, std::shared_ptr const&) -> std::unique_ptr {