mirror of
https://github.com/miracle-wm-org/miracle-wm.git
synced 2024-12-02 08:48:07 +03:00
feature: opening a new horizontal lane works
This commit is contained in:
parent
dff8dc83d5
commit
7804c8cf21
@ -49,11 +49,17 @@ bool MiracleWindowManagementPolicy::handle_keyboard_event(MirKeyboardEvent const
|
||||
auto const scan_code = miral::toolkit::mir_keyboard_event_scan_code(event);
|
||||
auto const modifiers = miral::toolkit::mir_keyboard_event_modifiers(event) & MODIFIER_MASK;
|
||||
|
||||
if (action == MirKeyboardAction::mir_keyboard_action_down && (modifiers && mir_input_event_modifier_alt)) {
|
||||
if (scan_code == KEY_ENTER) {
|
||||
if (action == MirKeyboardAction::mir_keyboard_action_down && (modifiers && mir_input_event_modifier_alt))
|
||||
{
|
||||
if (scan_code == KEY_ENTER)
|
||||
{
|
||||
external_client_launcher.launch({TERMINAL});
|
||||
return true;
|
||||
}
|
||||
else if (scan_code == KEY_V)
|
||||
{
|
||||
tree.request_vertical();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -74,3 +80,13 @@ void MiracleWindowManagementPolicy::handle_window_ready(miral::WindowInfo &windo
|
||||
// in the tree. This comes _after_ place_new_window has been called.
|
||||
tree.confirm(window_info.window());
|
||||
}
|
||||
|
||||
void MiracleWindowManagementPolicy::advise_focus_gained(const miral::WindowInfo &window_info)
|
||||
{
|
||||
tree.advise_focus_gained(window_info.window());
|
||||
}
|
||||
|
||||
void MiracleWindowManagementPolicy::advise_focus_lost(const miral::WindowInfo &window_info)
|
||||
{
|
||||
tree.advise_focus_lost(window_info.window());
|
||||
}
|
@ -32,6 +32,8 @@ public:
|
||||
miral::WindowSpecification const& requested_specification) -> miral::WindowSpecification override;
|
||||
void handle_window_ready(
|
||||
miral::WindowInfo& window_info) override;
|
||||
void advise_focus_gained(miral::WindowInfo const& window_info) override;
|
||||
void advise_focus_lost(miral::WindowInfo const& window_info) override;
|
||||
|
||||
private:
|
||||
WindowTree tree; // TODO: Keep a list per output
|
||||
|
@ -721,7 +721,7 @@
|
||||
<entry name="activated" value="4" summary="the surface is now activated">
|
||||
<description summary="the surface is now activated">
|
||||
Client window decorations should be painted as if the window is
|
||||
active. Do not assume this means that the window actually has
|
||||
active_lane. Do not assume this means that the window actually has
|
||||
keyboard or pointer focus.
|
||||
</description>
|
||||
</entry>
|
||||
@ -1013,7 +1013,7 @@
|
||||
will follow the same dismissing order as required from the client.
|
||||
|
||||
The parent of a grabbing popup must either be another xdg_popup with an
|
||||
active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
|
||||
active_lane explicit grab, or an xdg_popup or xdg_toplevel, if there are no
|
||||
explicit grabs already taken.
|
||||
|
||||
If the topmost grabbing popup is destroyed, the grab will be returned to
|
||||
|
@ -15,35 +15,114 @@
|
||||
*/
|
||||
|
||||
#include "window_tree.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace miracle;
|
||||
|
||||
namespace miracle
|
||||
{
|
||||
|
||||
/// A window tree lane item _always_ begins its life as a single window.
|
||||
/// When another window is added to it, it becomes a WindowTreeLane.
|
||||
class WindowTreeLaneItem
|
||||
/// Node Content _always_ begins its life as a single window.
|
||||
/// When requested by the user, it turns itself into a new
|
||||
/// node in the tree.
|
||||
class NodeContent
|
||||
{
|
||||
public:
|
||||
explicit WindowTreeLaneItem(miral::Window& window)
|
||||
explicit NodeContent(miral::Window& window)
|
||||
: window{window}
|
||||
{
|
||||
}
|
||||
|
||||
geom::Rectangle get_rectangle()
|
||||
{
|
||||
return geom::Rectangle{window.top_left(), window.size()};
|
||||
if (is_window())
|
||||
{
|
||||
return geom::Rectangle{window.top_left(), window.size()};
|
||||
}
|
||||
else
|
||||
{
|
||||
geom::Rectangle rectangle;
|
||||
for (auto item : node->items)
|
||||
{
|
||||
auto item_rectangle = item->get_rectangle();
|
||||
rectangle.top_left.x = std::min(rectangle.top_left.x, item_rectangle.top_left.x);
|
||||
rectangle.top_left.y = std::min(rectangle.top_left.y, item_rectangle.top_left.y);
|
||||
|
||||
if (node->direction == Node::horizontal)
|
||||
{
|
||||
rectangle.size.width = geom::Width{rectangle.size.width.as_int() + item_rectangle.size.width.as_int()};
|
||||
rectangle.size.height = std::max(
|
||||
rectangle.size.height,
|
||||
geom::Height{item_rectangle.top_left.y.as_int() + item_rectangle.size.height.as_int()});
|
||||
}
|
||||
else if (node->direction == Node::vertical)
|
||||
{
|
||||
rectangle.size.width = std::max(
|
||||
rectangle.size.width,
|
||||
geom::Width{item_rectangle.top_left.x.as_int() + item_rectangle.size.width.as_int()});
|
||||
rectangle.size.height = geom::Height{rectangle.size.height.as_int() + item_rectangle.size.height.as_int()};
|
||||
}
|
||||
}
|
||||
return rectangle;
|
||||
}
|
||||
}
|
||||
|
||||
void set_rectangle(geom::Rectangle rect)
|
||||
{
|
||||
if (is_window())
|
||||
{
|
||||
window.move_to(rect.top_left);
|
||||
window.resize(rect.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This needs to divide the space equally among windows
|
||||
for (auto item : node->items)
|
||||
{
|
||||
item->set_rectangle(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_window()
|
||||
{
|
||||
return node == nullptr;
|
||||
}
|
||||
|
||||
bool is_node()
|
||||
{
|
||||
return node != nullptr;
|
||||
}
|
||||
|
||||
miral::Window& get_window() {
|
||||
return window;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> get_node() {
|
||||
return node;
|
||||
}
|
||||
|
||||
/// Transforms this lane item into a node.
|
||||
std::shared_ptr<Node> to_node()
|
||||
{
|
||||
if (node != nullptr)
|
||||
return node;
|
||||
|
||||
node = std::make_shared<Node>();
|
||||
node->items.push_back(std::make_shared<NodeContent>(window));
|
||||
return node;
|
||||
}
|
||||
|
||||
private:
|
||||
miral::Window window;
|
||||
std::shared_ptr<Node> node = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
WindowTree::WindowTree(geom::Size default_size)
|
||||
: root{std::make_shared<WindowTreeLane>()},
|
||||
active{root},
|
||||
: root_lane{std::make_shared<Node>()},
|
||||
active_lane{root_lane},
|
||||
size{default_size}
|
||||
{
|
||||
}
|
||||
@ -51,8 +130,8 @@ WindowTree::WindowTree(geom::Size default_size)
|
||||
miral::WindowSpecification WindowTree::allocate_position(const miral::WindowSpecification &requested_specification)
|
||||
{
|
||||
miral::WindowSpecification new_spec = requested_specification;
|
||||
pending_lane = active;
|
||||
if (root == active && root->items.empty())
|
||||
pending_lane = active_lane;
|
||||
if (root_lane == active_lane && root_lane->items.empty())
|
||||
{
|
||||
// Special case: take up the full size of the root node.
|
||||
new_spec.top_left() = geom::Point{0, 0};
|
||||
@ -74,8 +153,7 @@ miral::WindowSpecification WindowTree::allocate_position(const miral::WindowSpec
|
||||
rectangle.top_left.x.as_int() + width_per_item * index,
|
||||
rectangle.top_left.y
|
||||
};
|
||||
item->window.move_to(new_position);
|
||||
item->window.resize(new_size);
|
||||
item->set_rectangle(geom::Rectangle{new_position, new_size});
|
||||
}
|
||||
|
||||
auto new_position = geom::Point{
|
||||
@ -95,9 +173,10 @@ miral::Rectangle WindowTree::confirm(miral::Window &window)
|
||||
return miral::Rectangle{};
|
||||
}
|
||||
|
||||
auto item = std::make_shared<WindowTreeLaneItem>(window);
|
||||
auto item = std::make_shared<NodeContent>(window);
|
||||
pending_lane->items.push_back(item);
|
||||
pending_lane = nullptr;
|
||||
advise_focus_gained(window);
|
||||
return item->get_rectangle();
|
||||
}
|
||||
|
||||
@ -112,17 +191,26 @@ void WindowTree::resize(geom::Size new_size)
|
||||
// TODO: Resize all windows
|
||||
}
|
||||
|
||||
void WindowTreeLane::add(miral::Window &window)
|
||||
void WindowTree::request_vertical()
|
||||
{
|
||||
active_lane = active_lane->to_lane(active_window);
|
||||
active_lane->direction = Node::horizontal;
|
||||
|
||||
// This is when we add a new lane, which means that we need to know who is currently
|
||||
// selected.
|
||||
}
|
||||
|
||||
void WindowTreeLane::remove(miral::Window &window)
|
||||
void WindowTree::advise_focus_gained(miral::Window& window)
|
||||
{
|
||||
|
||||
active_lane = root_lane->find_lane(window);
|
||||
active_window = window;
|
||||
}
|
||||
|
||||
geom::Rectangle WindowTreeLane::get_rectangle()
|
||||
void WindowTree::advise_focus_lost(miral::Window& window)
|
||||
{
|
||||
}
|
||||
|
||||
geom::Rectangle Node::get_rectangle()
|
||||
{
|
||||
geom::Rectangle rectangle{geom::Point{INT_MAX, INT_MAX}, geom::Size{0, 0}};
|
||||
for (auto item : items)
|
||||
@ -132,10 +220,48 @@ geom::Rectangle WindowTreeLane::get_rectangle()
|
||||
rectangle.top_left.y = std::min(rectangle.top_left.y, item_rectangle.top_left.y);
|
||||
rectangle.size.width = std::max(
|
||||
rectangle.size.width,
|
||||
geom::Width{item_rectangle.top_left.x.as_int() + item_rectangle.size.width.as_int()});
|
||||
geom::Width{item_rectangle.size.width.as_int()});
|
||||
rectangle.size.height = std::max(
|
||||
rectangle.size.height,
|
||||
geom::Height{item_rectangle.top_left.y.as_int() + item_rectangle.size.height.as_int()});
|
||||
geom::Height{item_rectangle.size.height.as_int()});
|
||||
}
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Node::find_lane(miral::Window &window)
|
||||
{
|
||||
for (auto item : items)
|
||||
{
|
||||
if (item->is_window())
|
||||
{
|
||||
if (item->get_window() == window)
|
||||
return shared_from_this();
|
||||
}
|
||||
else
|
||||
{
|
||||
return item->get_node()->find_lane(window);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Error
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<miracle::Node> Node::to_lane(miral::Window &window)
|
||||
{
|
||||
for (auto item : items)
|
||||
{
|
||||
if (item->is_window())
|
||||
{
|
||||
if (item->get_window() == window)
|
||||
return item->to_node();
|
||||
}
|
||||
else
|
||||
{
|
||||
return item->get_node()->to_lane(window);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Error
|
||||
return nullptr;
|
||||
}
|
@ -29,27 +29,31 @@ namespace geom = mir::geometry;
|
||||
namespace miracle
|
||||
{
|
||||
|
||||
class WindowTreeLaneItem;
|
||||
class NodeContent;
|
||||
|
||||
/// Terrible name. This describes an horizontal or vertical lane
|
||||
/// This describes an horizontal or vertical lane
|
||||
/// along which windows and other lanes may be laid out.
|
||||
struct WindowTreeLane
|
||||
struct Node : public std::enable_shared_from_this<Node>
|
||||
{
|
||||
std::vector<std::shared_ptr<WindowTreeLaneItem>> items;
|
||||
std::vector<std::shared_ptr<NodeContent>> items;
|
||||
|
||||
enum {
|
||||
horizontal,
|
||||
vertical,
|
||||
length
|
||||
} direction;
|
||||
} direction = horizontal;
|
||||
|
||||
/// The rectangle defined by the lane can be retrieved dynamically
|
||||
/// by calculating the dimensions of all the windows involved in
|
||||
/// this lane and its sub-lanes;
|
||||
geom::Rectangle get_rectangle();
|
||||
|
||||
void add(miral::Window& window);
|
||||
void remove(miral::Window& window);
|
||||
/// Walk the tree to find the lane that contains this window.
|
||||
std::shared_ptr<Node> find_lane(miral::Window& window);
|
||||
|
||||
/// Transform the window found in the list to a lane. Returns the
|
||||
/// new window tree lane item if found, otherwise null.
|
||||
std::shared_ptr<Node> to_lane(miral::Window& window);
|
||||
};
|
||||
|
||||
/// Represents a tiling tree for an output.
|
||||
@ -68,10 +72,17 @@ public:
|
||||
void remove(miral::Window&);
|
||||
void resize(geom::Size new_size);
|
||||
|
||||
// Request a change to vertical window placement
|
||||
void request_vertical();
|
||||
|
||||
void advise_focus_gained(miral::Window&);
|
||||
void advise_focus_lost(miral::Window&);
|
||||
|
||||
private:
|
||||
std::shared_ptr<WindowTreeLane> root;
|
||||
std::shared_ptr<WindowTreeLane> active;
|
||||
std::shared_ptr<WindowTreeLane> pending_lane;
|
||||
std::shared_ptr<Node> root_lane;
|
||||
std::shared_ptr<Node> active_lane;
|
||||
std::shared_ptr<Node> pending_lane;
|
||||
miral::Window active_window;
|
||||
geom::Size size;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user