mirror of
https://github.com/miracle-wm-org/miracle-wm.git
synced 2024-11-23 12:15:59 +03:00
bugfix: exclusion areas now work across workspaces
This commit is contained in:
parent
0e9eea63e2
commit
c6dbc2c402
@ -233,7 +233,7 @@ bool MiracleWindowManagementPolicy::handle_pointer_event(MirPointerEvent const*
|
||||
|
||||
for (auto const& pair : output_list)
|
||||
{
|
||||
if (pair->screen->get_active_tree().point_is_in_output(static_cast<int>(x), static_cast<int>(y)))
|
||||
if (pair->screen->point_is_in_output(static_cast<int>(x), static_cast<int>(y)))
|
||||
{
|
||||
if (active_output != pair)
|
||||
{
|
||||
@ -485,8 +485,7 @@ void MiracleWindowManagementPolicy::advise_application_zone_create(miral::Zone c
|
||||
{
|
||||
for (auto const& output : output_list)
|
||||
{
|
||||
for (auto& workspace : output->screen->get_workspaces())
|
||||
workspace.tree.advise_application_zone_create(application_zone);
|
||||
output->screen->advise_application_zone_create(application_zone);
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,8 +493,7 @@ void MiracleWindowManagementPolicy::advise_application_zone_update(miral::Zone c
|
||||
{
|
||||
for (auto const& output : output_list)
|
||||
{
|
||||
for (auto& workspace : output->screen->get_workspaces())
|
||||
workspace.tree.advise_application_zone_update(updated, original);
|
||||
output->screen->advise_application_zone_update(updated, original);
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +501,6 @@ void MiracleWindowManagementPolicy::advise_application_zone_delete(miral::Zone c
|
||||
{
|
||||
for (auto const& output : output_list)
|
||||
{
|
||||
for (auto& workspace : output->screen->get_workspaces())
|
||||
workspace.tree.advise_application_zone_delete(application_zone);
|
||||
output->screen->advise_application_zone_delete(application_zone);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ void Screen::advise_new_workspace(char workspace)
|
||||
{
|
||||
workspaces.push_back({
|
||||
workspace,
|
||||
WindowTree(area, tools, options)
|
||||
WindowTree(this, tools, options)
|
||||
});
|
||||
make_workspace_active(workspace);
|
||||
}
|
||||
@ -73,3 +73,39 @@ void Screen::show(ScreenWorkspaceInfo& info)
|
||||
{
|
||||
info.tree.show();
|
||||
}
|
||||
|
||||
void Screen::advise_application_zone_create(miral::Zone const& application_zone)
|
||||
{
|
||||
if (application_zone.extents().contains(area))
|
||||
{
|
||||
application_zone_list.push_back(application_zone);
|
||||
for (auto& workspace : workspaces)
|
||||
workspace.tree._recalculate_root_node_area();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::advise_application_zone_update(miral::Zone const& updated, miral::Zone const& original)
|
||||
{
|
||||
for (auto& zone : application_zone_list)
|
||||
if (zone == original)
|
||||
{
|
||||
zone = updated;
|
||||
for (auto& workspace : workspaces)
|
||||
workspace.tree._recalculate_root_node_area();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::advise_application_zone_delete(miral::Zone const& application_zone)
|
||||
{
|
||||
if (std::remove(application_zone_list.begin(), application_zone_list.end(), application_zone) != application_zone_list.end())
|
||||
{
|
||||
for (auto& workspace : workspaces)
|
||||
workspace.tree._recalculate_root_node_area();
|
||||
}
|
||||
}
|
||||
|
||||
bool Screen::point_is_in_output(int x, int y)
|
||||
{
|
||||
return area.contains(geom::Point(x, y));
|
||||
}
|
18
src/screen.h
18
src/screen.h
@ -33,12 +33,19 @@ public:
|
||||
geom::Rectangle const& area,
|
||||
miral::WindowManagerTools const& tools,
|
||||
WindowTreeOptions const& options);
|
||||
~Screen() = default;
|
||||
~Screen() = default;
|
||||
|
||||
WindowTree& get_active_tree();
|
||||
void advise_new_workspace(char workspace);
|
||||
bool make_workspace_active(char workspace);
|
||||
std::vector<ScreenWorkspaceInfo>& get_workspaces() { return workspaces; }
|
||||
WindowTree& get_active_tree();
|
||||
void advise_new_workspace(char workspace);
|
||||
bool make_workspace_active(char workspace);
|
||||
std::vector<ScreenWorkspaceInfo>& get_workspaces() { return workspaces; }
|
||||
void advise_application_zone_create(miral::Zone const& application_zone);
|
||||
void advise_application_zone_update(miral::Zone const& updated, miral::Zone const& original);
|
||||
void advise_application_zone_delete(miral::Zone const& application_zone);
|
||||
bool point_is_in_output(int x, int y);
|
||||
|
||||
geom::Rectangle const& get_area() { return area; }
|
||||
std::vector<miral::Zone> const& get_app_zones() { return application_zone_list; }
|
||||
|
||||
private:
|
||||
WorkspaceManager& workspace_manager;
|
||||
@ -47,6 +54,7 @@ private:
|
||||
WindowTreeOptions options;
|
||||
char active_workspace;
|
||||
std::vector<ScreenWorkspaceInfo> workspaces;
|
||||
std::vector<miral::Zone> application_zone_list;
|
||||
|
||||
void hide(ScreenWorkspaceInfo&);
|
||||
void show(ScreenWorkspaceInfo&);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "window_tree.h"
|
||||
#include "window_helpers.h"
|
||||
#include "screen.h"
|
||||
#include <memory>
|
||||
#include <mir/log.h>
|
||||
#include <iostream>
|
||||
@ -9,27 +10,19 @@
|
||||
|
||||
using namespace miracle;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool point_in_rect(geom::Rectangle const& area, int x, int y)
|
||||
{
|
||||
return x >= area.top_left.x.as_int() && x < area.top_left.x.as_int() + area.size.width.as_int()
|
||||
&& y >= area.top_left.y.as_int() && y < area.top_left.y.as_int() + area.size.height.as_int();
|
||||
}
|
||||
}
|
||||
|
||||
WindowTree::WindowTree(
|
||||
geom::Rectangle const& default_area,
|
||||
Screen* screen,
|
||||
miral::WindowManagerTools const& tools,
|
||||
WindowTreeOptions const& options)
|
||||
: root_lane{std::make_shared<Node>(
|
||||
: screen{screen},
|
||||
root_lane{std::make_shared<Node>(
|
||||
tools,
|
||||
std::move(geom::Rectangle{default_area.top_left, default_area.size}),
|
||||
std::move(geom::Rectangle{screen->get_area().top_left, screen->get_area().size}),
|
||||
options.gap_x, options.gap_y)},
|
||||
tools{tools},
|
||||
area{default_area},
|
||||
options{options}
|
||||
{
|
||||
_recalculate_root_node_area();
|
||||
}
|
||||
|
||||
miral::WindowSpecification WindowTree::allocate_position(const miral::WindowSpecification &requested_specification)
|
||||
@ -154,6 +147,7 @@ bool WindowTree::try_toggle_active_fullscreen()
|
||||
|
||||
void WindowTree::set_output_area(geom::Rectangle const& new_area)
|
||||
{
|
||||
auto area = screen->get_area();
|
||||
double x_scale = static_cast<double>(new_area.size.width.as_int()) / static_cast<double>(area.size.width.as_int());
|
||||
double y_scale = static_cast<double>(new_area.size.height.as_int()) / static_cast<double>(area.size.height.as_int());
|
||||
|
||||
@ -168,11 +162,6 @@ void WindowTree::set_output_area(geom::Rectangle const& new_area)
|
||||
root_lane->translate_by(position_diff_x, position_diff_y);
|
||||
}
|
||||
|
||||
bool WindowTree::point_is_in_output(int x, int y)
|
||||
{
|
||||
return point_in_rect(area, x, y);
|
||||
}
|
||||
|
||||
bool WindowTree::select_window_from_point(int x, int y)
|
||||
{
|
||||
if (is_active_window_fullscreen)
|
||||
@ -183,7 +172,7 @@ bool WindowTree::select_window_from_point(int x, int y)
|
||||
|
||||
auto node = root_lane->find_where([&](std::shared_ptr<Node> const& node)
|
||||
{
|
||||
return node->is_window() && point_in_rect(node->get_logical_area(), x, y);
|
||||
return node->is_window() && node->get_logical_area().contains(geom::Point(x, y));
|
||||
});
|
||||
if (!node)
|
||||
return false;
|
||||
@ -368,7 +357,7 @@ std::shared_ptr<Node> get_closest_window_to_select_from_node(
|
||||
if (is_negative)
|
||||
{
|
||||
auto sub_nodes = node->get_sub_nodes();
|
||||
for (auto i = sub_nodes.size() - 1; i >= 0; i--)
|
||||
for (auto i = sub_nodes.size() - 1; i != 0; i--)
|
||||
{
|
||||
if (auto retval = get_closest_window_to_select_from_node(sub_nodes[i], direction))
|
||||
return retval;
|
||||
@ -376,7 +365,7 @@ std::shared_ptr<Node> get_closest_window_to_select_from_node(
|
||||
}
|
||||
}
|
||||
|
||||
for (auto sub_node : node->get_sub_nodes())
|
||||
for (auto const& sub_node : node->get_sub_nodes())
|
||||
{
|
||||
if (auto retval = get_closest_window_to_select_from_node(sub_node, direction))
|
||||
return retval;
|
||||
@ -552,7 +541,7 @@ void WindowTree::_handle_resize_request(
|
||||
}
|
||||
}
|
||||
|
||||
void WindowTree::_handle_node_remove(std::shared_ptr<Node> node)
|
||||
void WindowTree::_handle_node_remove(std::shared_ptr<Node> const& node)
|
||||
{
|
||||
auto parent = node->get_parent();
|
||||
if (parent == nullptr)
|
||||
@ -571,38 +560,9 @@ void WindowTree::_handle_node_remove(std::shared_ptr<Node> node)
|
||||
}
|
||||
}
|
||||
|
||||
void WindowTree::advise_application_zone_create(miral::Zone const& application_zone)
|
||||
{
|
||||
if (application_zone.extents().contains(area))
|
||||
{
|
||||
application_zone_list.push_back(application_zone);
|
||||
_recalculate_root_node_area();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowTree::advise_application_zone_update(miral::Zone const& updated, miral::Zone const& original)
|
||||
{
|
||||
for (auto& zone : application_zone_list)
|
||||
if (zone == original)
|
||||
{
|
||||
zone = updated;
|
||||
_recalculate_root_node_area();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowTree::advise_application_zone_delete(miral::Zone const& application_zone)
|
||||
{
|
||||
if (std::remove(application_zone_list.begin(), application_zone_list.end(), application_zone) != application_zone_list.end())
|
||||
{
|
||||
_recalculate_root_node_area();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowTree::_recalculate_root_node_area()
|
||||
{
|
||||
// TODO: We don't take care of multiple application zones, so maybe that has to do with multiple outputs?
|
||||
for (auto const& zone : application_zone_list)
|
||||
for (auto const& zone : screen->get_app_zones())
|
||||
{
|
||||
root_lane->set_logical_area(zone.extents());
|
||||
break;
|
||||
|
@ -16,6 +16,8 @@ namespace geom = mir::geometry;
|
||||
namespace miracle
|
||||
{
|
||||
|
||||
class Screen;
|
||||
|
||||
enum class Direction
|
||||
{
|
||||
up,
|
||||
@ -34,7 +36,7 @@ struct WindowTreeOptions
|
||||
class WindowTree
|
||||
{
|
||||
public:
|
||||
WindowTree(geom::Rectangle const& area, miral::WindowManagerTools const& tools, WindowTreeOptions const& options);
|
||||
WindowTree(Screen* parent, miral::WindowManagerTools const& tools, WindowTreeOptions const& options);
|
||||
~WindowTree() = default;
|
||||
|
||||
/// Makes space for the new window and returns its specified spot in the grid. Note that the returned
|
||||
@ -76,14 +78,8 @@ public:
|
||||
/// Called when the physical display is resized.
|
||||
void set_output_area(geom::Rectangle const& new_area);
|
||||
|
||||
bool point_is_in_output(int x, int y);
|
||||
|
||||
bool select_window_from_point(int x, int y);
|
||||
|
||||
void advise_application_zone_create(miral::Zone const& application_zone);
|
||||
void advise_application_zone_update(miral::Zone const& updated, miral::Zone const& original);
|
||||
void advise_application_zone_delete(miral::Zone const& application_zone);
|
||||
|
||||
bool advise_fullscreen_window(miral::WindowInfo const&);
|
||||
bool advise_restored_window(miral::WindowInfo const &window_info);
|
||||
bool handle_window_ready(miral::WindowInfo& window_info);
|
||||
@ -109,6 +105,7 @@ public:
|
||||
void show();
|
||||
|
||||
std::shared_ptr<Node> get_root_node();
|
||||
void _recalculate_root_node_area();
|
||||
|
||||
private:
|
||||
struct MoveResult
|
||||
@ -128,13 +125,12 @@ private:
|
||||
MirWindowState state;
|
||||
};
|
||||
|
||||
Screen* screen;
|
||||
miral::WindowManagerTools tools;
|
||||
WindowTreeOptions options;
|
||||
std::shared_ptr<Node> root_lane;
|
||||
std::shared_ptr<Node> active_window;
|
||||
geom::Rectangle area;
|
||||
bool is_resizing = false;
|
||||
std::vector<miral::Zone> application_zone_list;
|
||||
bool is_active_window_fullscreen = false;
|
||||
bool is_hidden = false;
|
||||
std::vector<NodeResurrection> nodes_to_resurrect;
|
||||
@ -142,12 +138,11 @@ private:
|
||||
std::shared_ptr<Node> _get_active_lane();
|
||||
void _handle_direction_request(NodeLayoutDirection direction);
|
||||
void _handle_resize_request(std::shared_ptr<Node> const& node, Direction direction, int amount);
|
||||
void _handle_node_remove(std::shared_ptr<Node> node);
|
||||
void _handle_node_remove(std::shared_ptr<Node> const& node);
|
||||
/// From the provided node, find the next node in the provided direction.
|
||||
/// This method is guaranteed to return a Window node, not a Lane.
|
||||
MoveResult _move(std::shared_ptr<Node> const& from, Direction direction);
|
||||
static std::shared_ptr<Node> _select(std::shared_ptr<Node> const& from, Direction direction);
|
||||
void _recalculate_root_node_area();
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user