From 56518b49dfdf603aa38804490af95e8ca320bacc Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Mon, 15 Jan 2024 09:26:03 -0300 Subject: [PATCH 1/4] Change placement of new floating windows --- src/miral/basic_window_manager.cpp | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/src/miral/basic_window_manager.cpp b/src/miral/basic_window_manager.cpp index 3575231a47d..f5718fa1f4a 100644 --- a/src/miral/basic_window_manager.cpp +++ b/src/miral/basic_window_manager.cpp @@ -29,6 +29,8 @@ #include #include +#include +#include using namespace mir; using namespace mir::geometry; @@ -2016,6 +2018,90 @@ auto miral::BasicWindowManager::place_new_surface(WindowSpecification parameters if (parameters.top_left().value().y < display_area.top_left.y) parameters.top_left() = Point{parameters.top_left().value().x, display_area.top_left.y}; + + if (parameters.state() == mir_window_state_restored) + { + Displacement const cascading_offset{48, 48}; + Displacement const position_tolerance{12, 12}; + + auto unique_window_positions{[&]() + { + struct PointHash + { + std::size_t operator() (Point const& point) const + { + std::size_t seed{}; + boost::hash_combine(seed, point.x.as_value()); + boost::hash_combine(seed, point.y.as_value()); + return seed; + } + }; + std::unordered_set unique_positions; + for_each_application([&](ApplicationInfo& info) + { + for (auto const& window : info.windows()) + { + unique_positions.insert(window.top_left()); + } + }); + return unique_positions; + }()}; + + auto const find_near_window_position{[&](Point const& point, Displacement const& tolerance) + { + return std::find_if( + unique_window_positions.begin(), + unique_window_positions.end(), + [&](auto const& it) + { + return std::abs(it.x.as_value() - point.x.as_value()) <= tolerance.dx.as_value() && + std::abs(it.y.as_value() - point.y.as_value()) <= tolerance.dy.as_value(); + }); + }}; + + auto new_position{parameters.top_left().value()}; + + auto near_window_position{find_near_window_position(new_position, position_tolerance)}; + while (near_window_position != unique_window_positions.end()) + { + unique_window_positions.erase(near_window_position); + new_position += cascading_offset; + near_window_position = find_near_window_position(new_position, position_tolerance); + } + + if (!display_area.contains(new_position + as_displacement(parameters.size().value()))) + { + Rectangle const placement_region{ + display_area.top_left, + as_size(display_area.bottom_right() - + as_displacement(parameters.size().value()) - + as_displacement(display_area.top_left) + Displacement{1, 1})}; + if (placement_region.size.width.as_value() > 0 && placement_region.size.height.as_value() > 0) + { + std::random_device rd; + std::default_random_engine gen(rd()); + std::uniform_int_distribution dist_x(0, placement_region.size.width.as_value() - 1); + std::uniform_int_distribution dist_y(0, placement_region.size.height.as_value() - 1); + new_position = placement_region.top_left + as_displacement(Point{dist_x(gen), dist_y(gen)}); + } + else + { + if(placement_region.size.width.as_value() <= 0) + { + new_position = Point{display_area.left(), new_position.y}; + parameters.size().value().width = display_area.size.width; + } + if(placement_region.size.height.as_value() <= 0) + { + new_position = Point{new_position.x, display_area.top()}; + parameters.size().value().height = display_area.size.height; + } + } + + } + + parameters.top_left() = new_position; + } } return parameters; From 874ce46a0f3f4b50f246b31d57f87b852b26b5c6 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Mon, 15 Jan 2024 18:16:13 -0300 Subject: [PATCH 2/4] New placement following feedback from code review --- src/miral/basic_window_manager.cpp | 98 +++++++----------------------- 1 file changed, 21 insertions(+), 77 deletions(-) diff --git a/src/miral/basic_window_manager.cpp b/src/miral/basic_window_manager.cpp index f5718fa1f4a..0b416d3fc81 100644 --- a/src/miral/basic_window_manager.cpp +++ b/src/miral/basic_window_manager.cpp @@ -29,8 +29,6 @@ #include #include -#include -#include using namespace mir; using namespace mir::geometry; @@ -2021,87 +2019,33 @@ auto miral::BasicWindowManager::place_new_surface(WindowSpecification parameters if (parameters.state() == mir_window_state_restored) { - Displacement const cascading_offset{48, 48}; - Displacement const position_tolerance{12, 12}; + auto const offset{48}; + std::array const positions { + parameters.top_left().value(), + parameters.top_left().value() + Displacement( offset, offset), + parameters.top_left().value() + Displacement(-offset, offset), + parameters.top_left().value() + Displacement( offset, -offset), + parameters.top_left().value() + Displacement(-offset, -offset)}; - auto unique_window_positions{[&]() + for (auto const& position : positions) { - struct PointHash + auto const window{window_at(position)}; + auto const window_type{info_for(window).type()}; + auto const window_state{info_for(window).state()}; + + if (!window || + window_state != mir_window_state_restored || + (window_type != mir_window_type_normal && + window_type != mir_window_type_decoration && + window_type != mir_window_type_freestyle) || + window.top_left() != position) { - std::size_t operator() (Point const& point) const - { - std::size_t seed{}; - boost::hash_combine(seed, point.x.as_value()); - boost::hash_combine(seed, point.y.as_value()); - return seed; - } - }; - std::unordered_set unique_positions; - for_each_application([&](ApplicationInfo& info) - { - for (auto const& window : info.windows()) - { - unique_positions.insert(window.top_left()); - } - }); - return unique_positions; - }()}; - - auto const find_near_window_position{[&](Point const& point, Displacement const& tolerance) - { - return std::find_if( - unique_window_positions.begin(), - unique_window_positions.end(), - [&](auto const& it) - { - return std::abs(it.x.as_value() - point.x.as_value()) <= tolerance.dx.as_value() && - std::abs(it.y.as_value() - point.y.as_value()) <= tolerance.dy.as_value(); - }); - }}; - - auto new_position{parameters.top_left().value()}; - - auto near_window_position{find_near_window_position(new_position, position_tolerance)}; - while (near_window_position != unique_window_positions.end()) - { - unique_window_positions.erase(near_window_position); - new_position += cascading_offset; - near_window_position = find_near_window_position(new_position, position_tolerance); - } - - if (!display_area.contains(new_position + as_displacement(parameters.size().value()))) - { - Rectangle const placement_region{ - display_area.top_left, - as_size(display_area.bottom_right() - - as_displacement(parameters.size().value()) - - as_displacement(display_area.top_left) + Displacement{1, 1})}; - if (placement_region.size.width.as_value() > 0 && placement_region.size.height.as_value() > 0) - { - std::random_device rd; - std::default_random_engine gen(rd()); - std::uniform_int_distribution dist_x(0, placement_region.size.width.as_value() - 1); - std::uniform_int_distribution dist_y(0, placement_region.size.height.as_value() - 1); - new_position = placement_region.top_left + as_displacement(Point{dist_x(gen), dist_y(gen)}); - } - else - { - if(placement_region.size.width.as_value() <= 0) - { - new_position = Point{display_area.left(), new_position.y}; - parameters.size().value().width = display_area.size.width; - } - if(placement_region.size.height.as_value() <= 0) - { - new_position = Point{new_position.x, display_area.top()}; - parameters.size().value().height = display_area.size.height; - } + parameters.top_left().value() = position; + break; } - } - - parameters.top_left() = new_position; } + } return parameters; From a458dcadec1902dbc112145ed3cf0992c94d3da4 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Tue, 16 Jan 2024 10:03:23 -0300 Subject: [PATCH 3/4] Fix case for invalid windows --- src/miral/basic_window_manager.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/miral/basic_window_manager.cpp b/src/miral/basic_window_manager.cpp index 0b416d3fc81..4c91c4bc2b4 100644 --- a/src/miral/basic_window_manager.cpp +++ b/src/miral/basic_window_manager.cpp @@ -2029,23 +2029,19 @@ auto miral::BasicWindowManager::place_new_surface(WindowSpecification parameters for (auto const& position : positions) { - auto const window{window_at(position)}; - auto const window_type{info_for(window).type()}; - auto const window_state{info_for(window).state()}; - - if (!window || - window_state != mir_window_state_restored || - (window_type != mir_window_type_normal && - window_type != mir_window_type_decoration && - window_type != mir_window_type_freestyle) || - window.top_left() != position) + if (auto const window{window_at(position)}; + !window || + info_for(window).state() != mir_window_state_restored || + (info_for(window).type() != mir_window_type_normal && + info_for(window).type() != mir_window_type_decoration && + info_for(window).type() != mir_window_type_freestyle) || + window.top_left() != position) { parameters.top_left().value() = position; break; } } } - } return parameters; From f4b238a99e77be7cb821441e6ba43e3b1474d409 Mon Sep 17 00:00:00 2001 From: Harlen Batagelo Date: Tue, 16 Jan 2024 15:01:46 -0300 Subject: [PATCH 4/4] Improve readability Co-authored-by: Alan Griffiths --- src/miral/basic_window_manager.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/miral/basic_window_manager.cpp b/src/miral/basic_window_manager.cpp index 4c91c4bc2b4..387ae48a924 100644 --- a/src/miral/basic_window_manager.cpp +++ b/src/miral/basic_window_manager.cpp @@ -2029,13 +2029,23 @@ auto miral::BasicWindowManager::place_new_surface(WindowSpecification parameters for (auto const& position : positions) { - if (auto const window{window_at(position)}; - !window || - info_for(window).state() != mir_window_state_restored || - (info_for(window).type() != mir_window_type_normal && - info_for(window).type() != mir_window_type_decoration && - info_for(window).type() != mir_window_type_freestyle) || - window.top_left() != position) + auto const window{window_at(position)}; + + static auto const ignored_state_or_type = [](WindowInfo const& info) + { + switch (info.type()) + { + case mir_window_type_normal: + case mir_window_type_decoration: + case mir_window_type_freestyle: + return info.state() != mir_window_state_restored; + + default: + return true; + } + }; + + if (!window || ignored_state_or_type(info_for(window)) || window.top_left() != position) { parameters.top_left().value() = position; break;