WindowServer: Consolidate tiled and maximized window rects calculation

Calculating tiled and miximized window frame have a lot in common. In
fact, we can look at maximized window state as a special case of the
tile type. It simplifies the code since there is a lot of cases when
we take an action only if the window is maximized or tiled.
This commit is contained in:
Vitaly Dyachkov 2022-02-09 16:26:46 +01:00 committed by Andreas Kling
parent 06e33788ea
commit 53ff271c6f
Notes: sideshowbarker 2024-07-17 20:58:35 +09:00
5 changed files with 91 additions and 164 deletions

View file

@ -294,12 +294,12 @@ void Window::update_window_menu_items()
m_window_menu_minimize_item->set_text(m_minimized_state != WindowMinimizedState::None ? "&Unminimize" : "Mi&nimize"); m_window_menu_minimize_item->set_text(m_minimized_state != WindowMinimizedState::None ? "&Unminimize" : "Mi&nimize");
m_window_menu_minimize_item->set_enabled(m_minimizable); m_window_menu_minimize_item->set_enabled(m_minimizable);
m_window_menu_maximize_item->set_text(m_maximized ? "&Restore" : "Ma&ximize"); m_window_menu_maximize_item->set_text(is_maximized() ? "&Restore" : "Ma&ximize");
m_window_menu_maximize_item->set_enabled(m_resizable); m_window_menu_maximize_item->set_enabled(m_resizable);
m_window_menu_close_item->set_enabled(m_closeable); m_window_menu_close_item->set_enabled(m_closeable);
m_window_menu_move_item->set_enabled(m_minimized_state == WindowMinimizedState::None && !m_maximized && !m_fullscreen); m_window_menu_move_item->set_enabled(m_minimized_state == WindowMinimizedState::None && !is_maximized() && !m_fullscreen);
} }
void Window::set_minimized(bool minimized) void Window::set_minimized(bool minimized)
@ -476,16 +476,15 @@ void Window::set_occluded(bool occluded)
void Window::set_maximized(bool maximized, Optional<Gfx::IntPoint> fixed_point) void Window::set_maximized(bool maximized, Optional<Gfx::IntPoint> fixed_point)
{ {
if (m_maximized == maximized) if (is_maximized() == maximized)
return; return;
if (maximized && (!is_resizable() || resize_aspect_ratio().has_value())) if (maximized && (!is_resizable() || resize_aspect_ratio().has_value()))
return; return;
m_tile_type = WindowTileType::None; m_tile_type = maximized ? WindowTileType::Maximized : WindowTileType::None;
m_maximized = maximized;
update_window_menu_items(); update_window_menu_items();
if (maximized) { if (maximized) {
m_unmaximized_rect = m_floating_rect; m_unmaximized_rect = m_floating_rect;
set_rect(WindowManager::the().maximized_window_rect(*this)); set_rect(WindowManager::the().tiled_window_rect(*this));
} else { } else {
if (fixed_point.has_value()) { if (fixed_point.has_value()) {
auto new_rect = Gfx::IntRect(m_rect); auto new_rect = Gfx::IntRect(m_rect);
@ -837,7 +836,7 @@ void Window::handle_window_menu_action(WindowMenuAction action)
WindowManager::the().move_to_front_and_make_active(*this); WindowManager::the().move_to_front_and_make_active(*this);
break; break;
case WindowMenuAction::MaximizeOrRestore: case WindowMenuAction::MaximizeOrRestore:
WindowManager::the().maximize_windows(*this, !m_maximized); WindowManager::the().maximize_windows(*this, !is_maximized());
WindowManager::the().move_to_front_and_make_active(*this); WindowManager::the().move_to_front_and_make_active(*this);
break; break;
case WindowMenuAction::Move: case WindowMenuAction::Move:
@ -881,7 +880,7 @@ void Window::popup_window_menu(const Gfx::IntPoint& position, WindowMenuDefaultA
m_window_menu_minimize_item->set_default(default_action == WindowMenuDefaultAction::Minimize || default_action == WindowMenuDefaultAction::Unminimize); m_window_menu_minimize_item->set_default(default_action == WindowMenuDefaultAction::Minimize || default_action == WindowMenuDefaultAction::Unminimize);
m_window_menu_minimize_item->set_icon(m_minimized_state != WindowMinimizedState::None ? nullptr : &minimize_icon()); m_window_menu_minimize_item->set_icon(m_minimized_state != WindowMinimizedState::None ? nullptr : &minimize_icon());
m_window_menu_maximize_item->set_default(default_action == WindowMenuDefaultAction::Maximize || default_action == WindowMenuDefaultAction::Restore); m_window_menu_maximize_item->set_default(default_action == WindowMenuDefaultAction::Maximize || default_action == WindowMenuDefaultAction::Restore);
m_window_menu_maximize_item->set_icon(m_maximized ? &restore_icon() : &maximize_icon()); m_window_menu_maximize_item->set_icon(is_maximized() ? &restore_icon() : &maximize_icon());
m_window_menu_close_item->set_default(default_action == WindowMenuDefaultAction::Close); m_window_menu_close_item->set_default(default_action == WindowMenuDefaultAction::Close);
m_window_menu_menubar_visibility_item->set_enabled(m_menubar.has_menus()); m_window_menu_menubar_visibility_item->set_enabled(m_menubar.has_menus());
m_window_menu_menubar_visibility_item->set_checked(m_menubar.has_menus() && m_should_show_menubar); m_window_menu_menubar_visibility_item->set_checked(m_menubar.has_menus() && m_should_show_menubar);
@ -921,118 +920,6 @@ void Window::set_fullscreen(bool fullscreen)
set_rect(new_window_rect); set_rect(new_window_rect);
} }
Gfx::IntRect Window::tiled_rect(Screen* target_screen, WindowTileType tile_type) const
{
if (!target_screen) {
// If no explicit target screen was supplied,
// guess based on the current frame rectangle
target_screen = &Screen::closest_to_rect(frame().rect());
}
VERIFY(tile_type != WindowTileType::None);
int frame_width = (m_frame.rect().width() - m_rect.width()) / 2;
int titlebar_height = m_frame.titlebar_rect().height();
auto maximized_rect_relative_to_window_screen = WindowManager::the().maximized_window_rect(*this, true);
int menu_height = maximized_rect_relative_to_window_screen.y();
int max_height = maximized_rect_relative_to_window_screen.height();
auto& screen = *target_screen;
auto screen_location = screen.rect().location();
switch (tile_type) {
case WindowTileType::Left:
return Gfx::IntRect(0,
menu_height,
screen.width() / 2 - frame_width,
max_height)
.translated(screen_location);
case WindowTileType::Right: {
Gfx::IntPoint location {
screen.width() / 2 + frame_width,
menu_height
};
return Gfx::IntRect(
location,
{ screen.width() - location.x(), max_height })
.translated(screen_location);
}
case WindowTileType::Top:
return Gfx::IntRect(0,
menu_height,
screen.width(),
(max_height - titlebar_height) / 2 - frame_width)
.translated(screen_location);
case WindowTileType::Bottom: {
Gfx::IntPoint location {
0,
menu_height + (titlebar_height + max_height) / 2 + frame_width
};
return Gfx::IntRect(
location,
{ screen.width(), screen.height() - location.y() })
.translated(screen_location);
}
case WindowTileType::TopLeft:
return Gfx::IntRect(0,
menu_height,
screen.width() / 2 - frame_width,
(max_height - titlebar_height) / 2 - frame_width)
.translated(screen_location);
case WindowTileType::TopRight: {
Gfx::IntPoint location {
screen.width() / 2 + frame_width,
menu_height
};
return Gfx::IntRect(
location,
{ screen.width() - location.x(), (max_height - titlebar_height) / 2 - frame_width })
.translated(screen_location);
}
case WindowTileType::BottomLeft: {
Gfx::IntPoint location {
0,
menu_height + (titlebar_height + max_height) / 2 + frame_width
};
return Gfx::IntRect(
location,
{ screen.width() / 2 - frame_width, screen.height() - location.y() })
.translated(screen_location);
}
case WindowTileType::BottomRight: {
Gfx::IntPoint location {
screen.width() / 2 + frame_width,
menu_height + (titlebar_height + max_height) / 2 + frame_width
};
return Gfx::IntRect(
location,
{ screen.width() - location.x(), screen.height() - location.y() })
.translated(screen_location);
}
case WindowTileType::VerticallyMaximized: {
Gfx::IntPoint location {
floating_rect().location().x(),
menu_height
};
return Gfx::IntRect(
location,
{ floating_rect().width(), max_height })
.translated(screen_location);
}
case WindowTileType::HorizontallyMaximized: {
Gfx::IntPoint location {
0,
floating_rect().location().y()
};
return Gfx::IntRect(
location,
{ screen.width(), floating_rect().height() })
.translated(screen_location);
}
default:
VERIFY_NOT_REACHED();
}
}
WindowTileType Window::tile_type_based_on_rect(Gfx::IntRect const& rect) const WindowTileType Window::tile_type_based_on_rect(Gfx::IntRect const& rect) const
{ {
auto& window_screen = Screen::closest_to_rect(this->rect()); // based on currently used rect auto& window_screen = Screen::closest_to_rect(this->rect()); // based on currently used rect
@ -1044,7 +931,7 @@ WindowTileType Window::tile_type_based_on_rect(Gfx::IntRect const& rect) const
bool tiling_to_left = current_tile_type == WindowTileType::Left || current_tile_type == WindowTileType::TopLeft || current_tile_type == WindowTileType::BottomLeft; bool tiling_to_left = current_tile_type == WindowTileType::Left || current_tile_type == WindowTileType::TopLeft || current_tile_type == WindowTileType::BottomLeft;
bool tiling_to_right = current_tile_type == WindowTileType::Right || current_tile_type == WindowTileType::TopRight || current_tile_type == WindowTileType::BottomRight; bool tiling_to_right = current_tile_type == WindowTileType::Right || current_tile_type == WindowTileType::TopRight || current_tile_type == WindowTileType::BottomRight;
auto ideal_tiled_rect = tiled_rect(&window_screen, current_tile_type); auto ideal_tiled_rect = WindowManager::the().tiled_window_rect(*this, current_tile_type);
bool same_top = ideal_tiled_rect.top() == rect.top(); bool same_top = ideal_tiled_rect.top() == rect.top();
bool same_left = ideal_tiled_rect.left() == rect.left(); bool same_left = ideal_tiled_rect.left() == rect.left();
bool same_right = ideal_tiled_rect.right() == rect.right(); bool same_right = ideal_tiled_rect.right() == rect.right();
@ -1056,9 +943,9 @@ WindowTileType Window::tile_type_based_on_rect(Gfx::IntRect const& rect) const
if (tiling_to_top && same_top && same_left && same_right) if (tiling_to_top && same_top && same_left && same_right)
return WindowTileType::Top; return WindowTileType::Top;
else if ((tiling_to_top || tiling_to_left) && same_top && same_left) else if ((tiling_to_top || tiling_to_left) && same_top && same_left)
return rect.bottom() == tiled_rect(&window_screen, WindowTileType::Bottom).bottom() ? WindowTileType::Left : WindowTileType::TopLeft; return rect.bottom() == WindowManager::the().tiled_window_rect(*this, WindowTileType::Bottom).bottom() ? WindowTileType::Left : WindowTileType::TopLeft;
else if ((tiling_to_top || tiling_to_right) && same_top && same_right) else if ((tiling_to_top || tiling_to_right) && same_top && same_right)
return rect.bottom() == tiled_rect(&window_screen, WindowTileType::Bottom).bottom() ? WindowTileType::Right : WindowTileType::TopRight; return rect.bottom() == WindowManager::the().tiled_window_rect(*this, WindowTileType::Bottom).bottom() ? WindowTileType::Right : WindowTileType::TopRight;
else if (tiling_to_left && same_left && same_top && same_bottom) else if (tiling_to_left && same_left && same_top && same_bottom)
return WindowTileType::Left; return WindowTileType::Left;
else if (tiling_to_right && same_right && same_top && same_bottom) else if (tiling_to_right && same_right && same_top && same_bottom)
@ -1066,9 +953,9 @@ WindowTileType Window::tile_type_based_on_rect(Gfx::IntRect const& rect) const
else if (tiling_to_bottom && same_bottom && same_left && same_right) else if (tiling_to_bottom && same_bottom && same_left && same_right)
return WindowTileType::Bottom; return WindowTileType::Bottom;
else if ((tiling_to_bottom || tiling_to_left) && same_bottom && same_left) else if ((tiling_to_bottom || tiling_to_left) && same_bottom && same_left)
return rect.top() == tiled_rect(&window_screen, WindowTileType::Left).top() ? WindowTileType::Left : WindowTileType::BottomLeft; return rect.top() == WindowManager::the().tiled_window_rect(*this, WindowTileType::Left).top() ? WindowTileType::Left : WindowTileType::BottomLeft;
else if ((tiling_to_bottom || tiling_to_right) && same_bottom && same_right) else if ((tiling_to_bottom || tiling_to_right) && same_bottom && same_right)
return rect.top() == tiled_rect(&window_screen, WindowTileType::Right).top() ? WindowTileType::Right : WindowTileType::BottomRight; return rect.top() == WindowManager::the().tiled_window_rect(*this, WindowTileType::Right).top() ? WindowTileType::Right : WindowTileType::BottomRight;
} }
return tile_type; return tile_type;
} }
@ -1111,7 +998,7 @@ bool Window::set_untiled(Optional<Gfx::IntPoint> fixed_point)
return true; return true;
} }
void Window::set_tiled(Screen* screen, WindowTileType tile_type) void Window::set_tiled(WindowTileType tile_type)
{ {
VERIFY(tile_type != WindowTileType::None); VERIFY(tile_type != WindowTileType::None);
@ -1126,7 +1013,7 @@ void Window::set_tiled(Screen* screen, WindowTileType tile_type)
m_tile_type = tile_type; m_tile_type = tile_type;
set_rect(tiled_rect(screen, tile_type)); set_rect(WindowManager::the().tiled_window_rect(*this, tile_type));
Core::EventLoop::current().post_event(*this, make<ResizeEvent>(m_rect)); Core::EventLoop::current().post_event(*this, make<ResizeEvent>(m_rect));
} }
@ -1142,9 +1029,7 @@ void Window::recalculate_rect()
bool send_event = true; bool send_event = true;
if (is_tiled()) { if (is_tiled()) {
set_rect(tiled_rect(nullptr, m_tile_type)); set_rect(WindowManager::the().tiled_window_rect(*this, m_tile_type));
} else if (is_maximized()) {
set_rect(WindowManager::the().maximized_window_rect(*this));
} else if (type() == WindowType::Desktop) { } else if (type() == WindowType::Desktop) {
set_rect(WindowManager::the().arena_rect_for_type(Screen::main(), WindowType::Desktop)); set_rect(WindowManager::the().arena_rect_for_type(Screen::main(), WindowType::Desktop));
} else { } else {

View file

@ -51,6 +51,7 @@ enum class WindowTileType {
BottomRight, BottomRight,
VerticallyMaximized, VerticallyMaximized,
HorizontallyMaximized, HorizontallyMaximized,
Maximized,
}; };
enum class WindowMenuAction { enum class WindowMenuAction {
@ -107,7 +108,7 @@ public:
bool is_resizable() const { return m_resizable && !m_fullscreen; } bool is_resizable() const { return m_resizable && !m_fullscreen; }
void set_resizable(bool); void set_resizable(bool);
bool is_maximized() const { return m_maximized; } bool is_maximized() const { return m_tile_type == WindowTileType::Maximized; }
void set_maximized(bool, Optional<Gfx::IntPoint> fixed_point = {}); void set_maximized(bool, Optional<Gfx::IntPoint> fixed_point = {});
bool is_always_on_top() const { return m_always_on_top; } bool is_always_on_top() const { return m_always_on_top; }
@ -118,7 +119,7 @@ public:
WindowTileType tile_type() const { return m_tile_type; } WindowTileType tile_type() const { return m_tile_type; }
bool is_tiled() const { return m_tile_type != WindowTileType::None; } bool is_tiled() const { return m_tile_type != WindowTileType::None; }
void set_tiled(Screen*, WindowTileType); void set_tiled(WindowTileType);
WindowTileType tile_type_based_on_rect(Gfx::IntRect const&) const; WindowTileType tile_type_based_on_rect(Gfx::IntRect const&) const;
void check_untile_due_to_resize(Gfx::IntRect const&); void check_untile_due_to_resize(Gfx::IntRect const&);
bool set_untiled(Optional<Gfx::IntPoint> fixed_point = {}); bool set_untiled(Optional<Gfx::IntPoint> fixed_point = {});
@ -291,7 +292,6 @@ public:
void start_launch_animation(Gfx::IntRect const&); void start_launch_animation(Gfx::IntRect const&);
Gfx::IntRect tiled_rect(Screen*, WindowTileType) const;
void recalculate_rect(); void recalculate_rect();
IntrusiveListNode<Window> m_list_node; IntrusiveListNode<Window> m_list_node;
@ -423,7 +423,6 @@ private:
bool m_resizable { false }; bool m_resizable { false };
Optional<Gfx::IntSize> m_resize_aspect_ratio {}; Optional<Gfx::IntSize> m_resize_aspect_ratio {};
WindowMinimizedState m_minimized_state { WindowMinimizedState::None }; WindowMinimizedState m_minimized_state { WindowMinimizedState::None };
bool m_maximized { false };
bool m_fullscreen { false }; bool m_fullscreen { false };
bool m_accessory { false }; bool m_accessory { false };
bool m_destroyed { false }; bool m_destroyed { false };

View file

@ -84,18 +84,16 @@ void WindowFrame::window_was_constructed(Badge<Window>)
m_window.handle_window_menu_action(WindowMenuAction::MaximizeOrRestore); m_window.handle_window_menu_action(WindowMenuAction::MaximizeOrRestore);
}); });
button->on_middle_click = [&](auto&) { button->on_middle_click = [&](auto&) {
auto& window_screen = Screen::closest_to_location(m_window.rect().location());
if (m_window.tile_type() == WindowTileType::VerticallyMaximized) if (m_window.tile_type() == WindowTileType::VerticallyMaximized)
m_window.set_untiled(); m_window.set_untiled();
else else
m_window.set_tiled(&window_screen, WindowTileType::VerticallyMaximized); m_window.set_tiled(WindowTileType::VerticallyMaximized);
}; };
button->on_secondary_click = [&](auto&) { button->on_secondary_click = [&](auto&) {
auto& window_screen = Screen::closest_to_location(m_window.rect().location());
if (m_window.tile_type() == WindowTileType::HorizontallyMaximized) if (m_window.tile_type() == WindowTileType::HorizontallyMaximized)
m_window.set_untiled(); m_window.set_untiled();
else else
m_window.set_tiled(&window_screen, WindowTileType::HorizontallyMaximized); m_window.set_tiled(WindowTileType::HorizontallyMaximized);
}; };
m_maximize_button = button.ptr(); m_maximize_button = button.ptr();
m_buttons.append(move(button)); m_buttons.append(move(button));
@ -543,7 +541,7 @@ Gfx::IntRect WindowFrame::rect() const
Gfx::IntRect WindowFrame::constrained_render_rect_to_screen(const Gfx::IntRect& render_rect) const Gfx::IntRect WindowFrame::constrained_render_rect_to_screen(const Gfx::IntRect& render_rect) const
{ {
if (m_window.is_maximized() || m_window.is_tiled()) if (m_window.is_tiled())
return render_rect.intersected(Screen::closest_to_rect(rect()).rect()); return render_rect.intersected(Screen::closest_to_rect(rect()).rect());
return render_rect; return render_rect;
} }

View file

@ -674,7 +674,7 @@ void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origi
m_move_window->set_default_positioned(false); m_move_window->set_default_positioned(false);
m_move_origin = origin; m_move_origin = origin;
m_move_window_origin = window.position(); m_move_window_origin = window.position();
m_move_window_cursor_position = window.is_tiled() || window.is_maximized() ? to_floating_cursor_position(m_mouse_down_origin) : m_mouse_down_origin; m_move_window_cursor_position = window.is_tiled() ? to_floating_cursor_position(m_mouse_down_origin) : m_mouse_down_origin;
m_geometry_overlay = Compositor::the().create_overlay<WindowGeometryOverlay>(window); m_geometry_overlay = Compositor::the().create_overlay<WindowGeometryOverlay>(window);
m_geometry_overlay->set_enabled(true); m_geometry_overlay->set_enabled(true);
window.invalidate(true, true); window.invalidate(true, true);
@ -741,7 +741,7 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
dbgln_if(MOVE_DEBUG, "[WM] Finish moving Window({})", m_move_window); dbgln_if(MOVE_DEBUG, "[WM] Finish moving Window({})", m_move_window);
if (!m_move_window->is_tiled() && !m_move_window->is_maximized()) if (!m_move_window->is_tiled())
m_move_window->set_floating_rect(m_move_window->rect()); m_move_window->set_floating_rect(m_move_window->rect());
m_move_window->invalidate(true, true); m_move_window->invalidate(true, true);
@ -787,22 +787,22 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
auto event_location_relative_to_screen = event.position().translated(-cursor_screen.rect().location()); auto event_location_relative_to_screen = event.position().translated(-cursor_screen.rect().location());
if (is_resizable && event_location_relative_to_screen.x() <= tiling_deadzone) { if (is_resizable && event_location_relative_to_screen.x() <= tiling_deadzone) {
if (event_location_relative_to_screen.y() <= tiling_deadzone + desktop_relative_to_screen.top()) if (event_location_relative_to_screen.y() <= tiling_deadzone + desktop_relative_to_screen.top())
m_move_window->set_tiled(&cursor_screen, WindowTileType::TopLeft); m_move_window->set_tiled(WindowTileType::TopLeft);
else if (event_location_relative_to_screen.y() >= desktop_relative_to_screen.height() - tiling_deadzone) else if (event_location_relative_to_screen.y() >= desktop_relative_to_screen.height() - tiling_deadzone)
m_move_window->set_tiled(&cursor_screen, WindowTileType::BottomLeft); m_move_window->set_tiled(WindowTileType::BottomLeft);
else else
m_move_window->set_tiled(&cursor_screen, WindowTileType::Left); m_move_window->set_tiled(WindowTileType::Left);
} else if (is_resizable && event_location_relative_to_screen.x() >= cursor_screen.width() - tiling_deadzone) { } else if (is_resizable && event_location_relative_to_screen.x() >= cursor_screen.width() - tiling_deadzone) {
if (event_location_relative_to_screen.y() <= tiling_deadzone + desktop.top()) if (event_location_relative_to_screen.y() <= tiling_deadzone + desktop.top())
m_move_window->set_tiled(&cursor_screen, WindowTileType::TopRight); m_move_window->set_tiled(WindowTileType::TopRight);
else if (event_location_relative_to_screen.y() >= desktop_relative_to_screen.height() - tiling_deadzone) else if (event_location_relative_to_screen.y() >= desktop_relative_to_screen.height() - tiling_deadzone)
m_move_window->set_tiled(&cursor_screen, WindowTileType::BottomRight); m_move_window->set_tiled(WindowTileType::BottomRight);
else else
m_move_window->set_tiled(&cursor_screen, WindowTileType::Right); m_move_window->set_tiled(WindowTileType::Right);
} else if (is_resizable && event_location_relative_to_screen.y() <= secondary_deadzone + desktop_relative_to_screen.top()) { } else if (is_resizable && event_location_relative_to_screen.y() <= secondary_deadzone + desktop_relative_to_screen.top()) {
m_move_window->set_tiled(&cursor_screen, WindowTileType::Top); m_move_window->set_tiled(WindowTileType::Top);
} else if (is_resizable && event_location_relative_to_screen.y() >= desktop_relative_to_screen.bottom() - secondary_deadzone) { } else if (is_resizable && event_location_relative_to_screen.y() >= desktop_relative_to_screen.bottom() - secondary_deadzone) {
m_move_window->set_tiled(&cursor_screen, WindowTileType::Bottom); m_move_window->set_tiled(WindowTileType::Bottom);
} else if (!m_move_window->is_tiled()) { } else if (!m_move_window->is_tiled()) {
Gfx::IntPoint pos = m_move_window_origin.translated(event.position() - m_move_origin); Gfx::IntPoint pos = m_move_window_origin.translated(event.position() - m_move_origin);
m_move_window->set_position_without_repaint(pos); m_move_window->set_position_without_repaint(pos);
@ -864,7 +864,7 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
auto desktop_rect = this->desktop_rect(cursor_screen); auto desktop_rect = this->desktop_rect(cursor_screen);
if (event.y() >= desktop_rect.bottom() - vertical_maximize_deadzone + 1 || event.y() <= desktop_rect.top() + vertical_maximize_deadzone - 1) { if (event.y() >= desktop_rect.bottom() - vertical_maximize_deadzone + 1 || event.y() <= desktop_rect.top() + vertical_maximize_deadzone - 1) {
dbgln_if(RESIZE_DEBUG, "Should tile as VerticallyMaximized"); dbgln_if(RESIZE_DEBUG, "Should tile as VerticallyMaximized");
m_resize_window->set_tiled(&cursor_screen, WindowTileType::VerticallyMaximized); m_resize_window->set_tiled(WindowTileType::VerticallyMaximized);
m_resize_window = nullptr; m_resize_window = nullptr;
m_geometry_overlay = nullptr; m_geometry_overlay = nullptr;
m_resizing_mouse_button = MouseButton::None; m_resizing_mouse_button = MouseButton::None;
@ -876,7 +876,7 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
if (event.type() == Event::MouseUp && event.button() == m_resizing_mouse_button) { if (event.type() == Event::MouseUp && event.button() == m_resizing_mouse_button) {
dbgln_if(RESIZE_DEBUG, "[WM] Finish resizing Window({})", m_resize_window); dbgln_if(RESIZE_DEBUG, "[WM] Finish resizing Window({})", m_resize_window);
if (!m_resize_window->is_tiled() && !m_resize_window->is_maximized()) if (!m_resize_window->is_tiled())
m_resize_window->set_floating_rect(m_resize_window->rect()); m_resize_window->set_floating_rect(m_resize_window->rect());
Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(m_resize_window->rect())); Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(m_resize_window->rect()));
@ -1692,7 +1692,7 @@ void WindowManager::process_key_event(KeyEvent& event)
} }
if (active_input_window->is_maximized()) if (active_input_window->is_maximized())
maximize_windows(*active_input_window, false); maximize_windows(*active_input_window, false);
active_input_window->set_tiled(nullptr, WindowTileType::Left); active_input_window->set_tiled(WindowTileType::Left);
return; return;
} }
if (event.key() == Key_Right) { if (event.key() == Key_Right) {
@ -1702,7 +1702,7 @@ void WindowManager::process_key_event(KeyEvent& event)
} }
if (active_input_window->is_maximized()) if (active_input_window->is_maximized())
maximize_windows(*active_input_window, false); maximize_windows(*active_input_window, false);
active_input_window->set_tiled(nullptr, WindowTileType::Right); active_input_window->set_tiled(WindowTileType::Right);
return; return;
} }
} }
@ -1717,7 +1717,7 @@ void WindowManager::process_key_event(KeyEvent& event)
} }
if (active_input_window->is_maximized()) if (active_input_window->is_maximized())
maximize_windows(*active_input_window, false); maximize_windows(*active_input_window, false);
active_input_window->set_tiled(nullptr, WindowTileType::HorizontallyMaximized); active_input_window->set_tiled(WindowTileType::HorizontallyMaximized);
return; return;
} }
if (event.key() == Key_Up || event.key() == Key_Down) { if (event.key() == Key_Up || event.key() == Key_Down) {
@ -1727,7 +1727,7 @@ void WindowManager::process_key_event(KeyEvent& event)
} }
if (active_input_window->is_maximized()) if (active_input_window->is_maximized())
maximize_windows(*active_input_window, false); maximize_windows(*active_input_window, false);
active_input_window->set_tiled(nullptr, WindowTileType::VerticallyMaximized); active_input_window->set_tiled(WindowTileType::VerticallyMaximized);
return; return;
} }
} }
@ -1960,15 +1960,13 @@ ResizeDirection WindowManager::resize_direction_of_window(Window const& window)
return m_resize_direction; return m_resize_direction;
} }
Gfx::IntRect WindowManager::maximized_window_rect(Window const& window, bool relative_to_window_screen) const Gfx::IntRect WindowManager::tiled_window_rect(Window const& window, WindowTileType tile_type, bool relative_to_window_screen) const
{ {
VERIFY(tile_type != WindowTileType::None);
auto& screen = Screen::closest_to_rect(window.frame().rect()); auto& screen = Screen::closest_to_rect(window.frame().rect());
Gfx::IntRect rect = screen.rect(); Gfx::IntRect rect = screen.rect();
// Subtract window title bar (leaving the border)
rect.set_y(rect.y() + window.frame().titlebar_rect().height() + window.frame().menubar_rect().height());
rect.set_height(rect.height() - window.frame().titlebar_rect().height() - window.frame().menubar_rect().height());
if (screen.is_main_screen()) { if (screen.is_main_screen()) {
// Subtract taskbar window height if present // Subtract taskbar window height if present
const_cast<WindowManager*>(this)->current_window_stack().for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, [&rect](Window& taskbar_window) { const_cast<WindowManager*>(this)->current_window_stack().for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, [&rect](Window& taskbar_window) {
@ -1977,9 +1975,56 @@ Gfx::IntRect WindowManager::maximized_window_rect(Window const& window, bool rel
}); });
} }
constexpr int tasteful_space_above_maximized_window = 1; if (tile_type == WindowTileType::Maximized) {
rect.set_y(rect.y() + tasteful_space_above_maximized_window); auto border_thickness = palette().window_border_thickness();
rect.set_height(rect.height() - tasteful_space_above_maximized_window); rect.inflate(border_thickness * 2, border_thickness * 2);
}
if (tile_type == WindowTileType::Left
|| tile_type == WindowTileType::TopLeft
|| tile_type == WindowTileType::BottomLeft) {
rect.set_width(rect.width() / 2);
}
if (tile_type == WindowTileType::Right
|| tile_type == WindowTileType::TopRight
|| tile_type == WindowTileType::BottomRight) {
rect.set_width(rect.width() / 2);
rect.set_x(rect.width());
}
if (tile_type == WindowTileType::Top
|| tile_type == WindowTileType::TopLeft
|| tile_type == WindowTileType::TopRight) {
rect.set_height(rect.height() / 2);
}
if (tile_type == WindowTileType::Bottom
|| tile_type == WindowTileType::BottomLeft
|| tile_type == WindowTileType::BottomRight) {
auto half_screen_reminder = rect.height() % 2;
rect.set_height(rect.height() / 2 + half_screen_reminder);
rect.set_y(rect.height() - half_screen_reminder);
}
Gfx::IntRect window_rect = window.rect();
Gfx::IntRect window_frame_rect = window.frame().rect();
if (tile_type == WindowTileType::VerticallyMaximized) {
rect.set_x(window_rect.x());
rect.set_width(window_rect.width());
} else {
rect.set_x(rect.x() + window_rect.x() - window_frame_rect.x());
rect.set_width(rect.width() - window_frame_rect.width() + window_rect.width());
}
if (tile_type == WindowTileType::HorizontallyMaximized) {
rect.set_y(window_rect.y());
rect.set_height(window_rect.height());
} else {
rect.set_y(rect.y() + window_rect.y() - window_frame_rect.y());
rect.set_height(rect.height() - window_frame_rect.height() + window_rect.height());
}
if (relative_to_window_screen) if (relative_to_window_screen)
rect.translate_by(-screen.rect().location()); rect.translate_by(-screen.rect().location());

View file

@ -88,7 +88,7 @@ public:
void notify_progress_changed(Window&); void notify_progress_changed(Window&);
void notify_modified_changed(Window&); void notify_modified_changed(Window&);
Gfx::IntRect maximized_window_rect(Window const&, bool relative_to_window_screen = false) const; Gfx::IntRect tiled_window_rect(Window const&, WindowTileType tile_type = WindowTileType::Maximized, bool relative_to_window_screen = false) const;
ClientConnection const* dnd_client() const { return m_dnd_client.ptr(); } ClientConnection const* dnd_client() const { return m_dnd_client.ptr(); }
Core::MimeData const& dnd_mime_data() const { return *m_dnd_mime_data; } Core::MimeData const& dnd_mime_data() const { return *m_dnd_mime_data; }