diff --git a/src/miracle_window_management_policy.cpp b/src/miracle_window_management_policy.cpp index 217281a..6752fb9 100644 --- a/src/miracle_window_management_policy.cpp +++ b/src/miracle_window_management_policy.cpp @@ -135,9 +135,7 @@ auto MiracleWindowManagementPolicy::place_new_window( void MiracleWindowManagementPolicy::handle_window_ready(miral::WindowInfo &window_info) { - // The new placement has been confirmed. We can now add the window into the pending position - // in the tree. This comes _after_ place_new_window has been called. - tree.confirm(window_info.window()); + tree.confirm_new_window(window_info.window()); } void MiracleWindowManagementPolicy::advise_focus_gained(const miral::WindowInfo &window_info) diff --git a/src/protocols/xdg-shell-unstable-v6.xml b/src/protocols/xdg-shell-unstable-v6.xml index cf5ddc3..ea12f79 100644 --- a/src/protocols/xdg-shell-unstable-v6.xml +++ b/src/protocols/xdg-shell-unstable-v6.xml @@ -721,7 +721,7 @@ Client window decorations should be painted as if the window is - active_lane. Do not assume this means that the window actually has + get_active_lane. Do not assume this means that the window actually has keyboard or pointer focus. @@ -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_lane explicit grab, or an xdg_popup or xdg_toplevel, if there are no + get_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 diff --git a/src/window_tree.cpp b/src/window_tree.cpp index d29e7bf..36ee72d 100644 --- a/src/window_tree.cpp +++ b/src/window_tree.cpp @@ -32,17 +32,17 @@ WindowTree::WindowTree(geom::Size default_size, const miral::WindowManagerTools miral::WindowSpecification WindowTree::allocate_position(const miral::WindowSpecification &requested_specification) { miral::WindowSpecification new_spec = requested_specification; - auto rect = active_lane()->new_node_position(); + auto rect = get_active_lane()->new_node_position(); new_spec.size() = rect.size; new_spec.top_left() = rect.top_left; return new_spec; } -void WindowTree::confirm(miral::Window &window) +void WindowTree::confirm_new_window(miral::Window &window) { - active_lane()->add_node(std::make_shared( + get_active_lane()->add_node(std::make_shared( geom::Rectangle{window.top_left(), window.size()}, - active_lane(), + get_active_lane(), window)); tools.select_active_window(window); } @@ -67,76 +67,10 @@ bool WindowTree::try_resize_active_window(miracle::Direction direction) return false; // TODO: We have a hardcoded resize amount - resize_node_internal(active_window, direction, 50); + resize_node_in_direction(active_window, direction, 50); return true; } -void WindowTree::resize_node_internal( - std::shared_ptr node, - Direction direction, - int amount) -{ - auto parent = node->parent; - if (parent == nullptr) - { - // Can't resize, most likely the root - return; - } - - bool is_vertical = direction == Direction::up || direction == Direction::down; - bool is_main_axis_movement = (is_vertical && parent->get_direction() == NodeLayoutDirection::vertical) - || (!is_vertical && parent->get_direction() == NodeLayoutDirection::horizontal); - if (!is_main_axis_movement) - { - resize_node_internal(parent, direction, amount); - return; - } - - bool is_negative = direction == Direction::left || direction == Direction::up; - auto resize_amount = is_negative ? -amount : amount; - auto nodes = parent->get_sub_nodes(); - if (is_vertical) - { - int height_for_others = floor(-resize_amount / static_cast(nodes.size() - 1)); - for (size_t i = 0; i < nodes.size(); i++) - { - auto other_node = nodes[i]; - auto other_rect = other_node->get_rectangle(); - if (node == other_node) - other_rect.size.height = geom::Height{other_rect.size.height.as_int() + resize_amount}; - else - other_rect.size.height = geom::Height{other_rect.size.height.as_int() + height_for_others}; - - if (i != 0) - { - auto prev_rect = nodes[i - 1]->get_rectangle(); - other_rect.top_left.y = geom::Y{prev_rect.top_left.y.as_int() + prev_rect.size.height.as_int()}; - } - other_node->set_rectangle(other_rect); - } - } - else - { - int width_for_others = floor(-resize_amount / static_cast(nodes.size() - 1)); - for (size_t i = 0; i < nodes.size(); i++) - { - auto other_node = nodes[i]; - auto other_rect = other_node->get_rectangle(); - if (node == other_node) - other_rect.size.width = geom::Width {other_rect.size.width.as_int() + resize_amount}; - else - other_rect.size.width = geom::Width {other_rect.size.width.as_int() + width_for_others}; - - if (i != 0) - { - auto prev_rect = nodes[i - 1]->get_rectangle(); - other_rect.top_left.x = geom::X{prev_rect.top_left.x.as_int() + prev_rect.size.width.as_int()}; - } - other_node->set_rectangle(other_rect); - } - } -} - bool WindowTree::try_select_next(miracle::Direction direction) { if (!active_window) @@ -149,9 +83,10 @@ bool WindowTree::try_select_next(miracle::Direction direction) return true; } -void WindowTree::resize(geom::Size new_size) +void WindowTree::resize_display(geom::Size new_size) { size = new_size; + root_lane->redistribute_size(); // TODO: Resize all windows } @@ -198,7 +133,7 @@ void WindowTree::handle_direction_request(NodeLayoutDirection direction) if (active_window->parent->get_sub_nodes().size() != 1) active_window = active_window->to_lane(); - active_lane()->set_direction(direction); + get_active_lane()->set_direction(direction); } void WindowTree::advise_focus_gained(miral::Window& window) @@ -220,7 +155,7 @@ void WindowTree::advise_focus_lost(miral::Window&) void WindowTree::advise_delete_window(miral::Window& window) { // Resize the other nodes in the lane accordingly - auto parent = active_lane(); + auto parent = get_active_lane(); if (parent->get_sub_nodes().size() == 1) { @@ -333,10 +268,76 @@ grandparent_route: return nullptr; } -std::shared_ptr WindowTree::active_lane() +std::shared_ptr WindowTree::get_active_lane() { if (!active_window) return root_lane; return active_window->parent; +} + +void WindowTree::resize_node_in_direction( + std::shared_ptr node, + Direction direction, + int amount) +{ + auto parent = node->parent; + if (parent == nullptr) + { + // Can't resize, most likely the root + return; + } + + bool is_vertical = direction == Direction::up || direction == Direction::down; + bool is_main_axis_movement = (is_vertical && parent->get_direction() == NodeLayoutDirection::vertical) + || (!is_vertical && parent->get_direction() == NodeLayoutDirection::horizontal); + if (!is_main_axis_movement) + { + resize_node_in_direction(parent, direction, amount); + return; + } + + bool is_negative = direction == Direction::left || direction == Direction::up; + auto resize_amount = is_negative ? -amount : amount; + auto nodes = parent->get_sub_nodes(); + if (is_vertical) + { + int height_for_others = floor(-resize_amount / static_cast(nodes.size() - 1)); + for (size_t i = 0; i < nodes.size(); i++) + { + auto other_node = nodes[i]; + auto other_rect = other_node->get_rectangle(); + if (node == other_node) + other_rect.size.height = geom::Height{other_rect.size.height.as_int() + resize_amount}; + else + other_rect.size.height = geom::Height{other_rect.size.height.as_int() + height_for_others}; + + if (i != 0) + { + auto prev_rect = nodes[i - 1]->get_rectangle(); + other_rect.top_left.y = geom::Y{prev_rect.top_left.y.as_int() + prev_rect.size.height.as_int()}; + } + other_node->set_rectangle(other_rect); + } + } + else + { + int width_for_others = floor(-resize_amount / static_cast(nodes.size() - 1)); + for (size_t i = 0; i < nodes.size(); i++) + { + auto other_node = nodes[i]; + auto other_rect = other_node->get_rectangle(); + if (node == other_node) + other_rect.size.width = geom::Width {other_rect.size.width.as_int() + resize_amount}; + else + other_rect.size.width = geom::Width {other_rect.size.width.as_int() + width_for_others}; + + if (i != 0) + { + auto prev_rect = nodes[i - 1]->get_rectangle(); + other_rect.top_left.x = geom::X{prev_rect.top_left.x.as_int() + prev_rect.size.width.as_int()}; + } + other_node->set_rectangle(other_rect); + } + } } \ No newline at end of file diff --git a/src/window_tree.h b/src/window_tree.h index 7bdd55e..8e2228b 100644 --- a/src/window_tree.h +++ b/src/window_tree.h @@ -51,16 +51,18 @@ public: miral::WindowSpecification allocate_position(const miral::WindowSpecification &requested_specification); /// Confirms the position of this window in the previously allocated position. - void confirm(miral::Window&); + void confirm_new_window(miral::Window&); /// Places us into resize mode. Other operations are prohibited while we are in resize mode. void toggle_resize_mode(); /// Try to resize the current active window in the provided direction bool try_resize_active_window(Direction direction); - void resize(geom::Size new_size); + /// Move the active window in the provided direction bool try_move_active_window(Direction direction); + + /// Select the next window in the provided direction bool try_select_next(Direction direction); // Request a change to vertical window placement @@ -69,10 +71,18 @@ public: // Request a change to horizontal window placement void request_horizontal(); + /// Advises us to focus the provided window. void advise_focus_gained(miral::Window&); + + /// Advises us to lose focus on the provided window. void advise_focus_lost(miral::Window&); + + /// Called when the window was deleted. void advise_delete_window(miral::Window&); + /// Called when the physical display is resized. + void resize_display(geom::Size new_size); + private: miral::WindowManagerTools tools; std::shared_ptr root_lane; @@ -80,9 +90,9 @@ private: geom::Size size; bool is_resizing = false; - std::shared_ptr active_lane(); + std::shared_ptr get_active_lane(); void handle_direction_request(NodeLayoutDirection direction); - void resize_node_internal(std::shared_ptr node, Direction direction, int amount); + void resize_node_in_direction(std::shared_ptr node, Direction direction, int amount); /// From the provided node, find the next node in the provided direction. /// This method is guaranteed to return a Window node, not a Lane. std::shared_ptr traverse(std::shared_ptr from, Direction direction);