diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index db63cce5ac..27deac338b 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -319,20 +319,26 @@ void Window::set_occluded(bool occluded) WindowManager::the().notify_occlusion_state_changed(*this); } -void Window::set_maximized(bool maximized) +void Window::set_maximized(bool maximized, Optional fixed_point) { if (m_maximized == maximized) return; if (maximized && (!is_resizable() || resize_aspect_ratio().has_value())) return; - set_tiled(WindowTileType::None); + m_tiled = WindowTileType::None; m_maximized = maximized; update_menu_item_text(PopupMenuItem::Maximize); if (maximized) { m_unmaximized_rect = m_rect; set_rect(WindowManager::the().maximized_window_rect(*this)); } else { - set_rect(m_unmaximized_rect); + if (fixed_point.has_value()) { + auto new_rect = Gfx::IntRect(m_rect); + new_rect.set_size_around(m_unmaximized_rect.size(), fixed_point.value()); + set_rect(new_rect); + } else { + set_rect(m_unmaximized_rect); + } } m_frame.did_set_maximized({}, maximized); Core::EventLoop::current().post_event(*this, make(m_rect)); @@ -627,14 +633,14 @@ void Window::set_fullscreen(bool fullscreen) Gfx::IntRect Window::tiled_rect(WindowTileType tiled) const { + ASSERT(tiled != WindowTileType::None); + int frame_width = (m_frame.rect().width() - m_rect.width()) / 2; int title_bar_height = m_frame.title_bar_rect().height(); int menu_height = WindowManager::the().maximized_window_rect(*this).y(); int max_height = WindowManager::the().maximized_window_rect(*this).height(); switch (tiled) { - case WindowTileType::None: - return m_untiled_rect; case WindowTileType::Left: return Gfx::IntRect(0, menu_height, @@ -680,8 +686,27 @@ Gfx::IntRect Window::tiled_rect(WindowTileType tiled) const } } +bool Window::set_untiled(const Gfx::IntPoint& fixed_point) +{ + if (m_tiled == WindowTileType::None) + return false; + ASSERT(!resize_aspect_ratio().has_value()); + + m_tiled = WindowTileType::None; + + auto new_rect = Gfx::IntRect(m_rect); + new_rect.set_size_around(m_untiled_rect.size(), fixed_point); + set_rect(new_rect); + + Core::EventLoop::current().post_event(*this, make(m_rect)); + + return true; +} + void Window::set_tiled(WindowTileType tiled) { + ASSERT(tiled != WindowTileType::None); + if (m_tiled == tiled) return; diff --git a/Userland/Services/WindowServer/Window.h b/Userland/Services/WindowServer/Window.h index 662fdb6314..0f2df1847d 100644 --- a/Userland/Services/WindowServer/Window.h +++ b/Userland/Services/WindowServer/Window.h @@ -103,13 +103,14 @@ public: void set_resizable(bool); bool is_maximized() const { return m_maximized; } - void set_maximized(bool); + void set_maximized(bool, Optional fixed_point = {}); bool is_fullscreen() const { return m_fullscreen; } void set_fullscreen(bool); WindowTileType tiled() const { return m_tiled; } void set_tiled(WindowTileType); + bool set_untiled(const Gfx::IntPoint& fixed_point); bool is_occluded() const { return m_occluded; } void set_occluded(bool); @@ -220,7 +221,16 @@ public: void set_size_increment(const Gfx::IntSize& increment) { m_size_increment = increment; } const Optional& resize_aspect_ratio() const { return m_resize_aspect_ratio; } - void set_resize_aspect_ratio(const Optional& ratio) { m_resize_aspect_ratio = ratio; } + void set_resize_aspect_ratio(const Optional& ratio) + { + // "Tiled" means that we take up a chunk of space relative to the screen. + // The screen can change, so "tiled" and "fixed aspect ratio" are mutually exclusive. + // Similarly for "maximized" and "fixed aspect ratio". + // In order to resolve this, undo those properties first: + set_untiled(position()); + set_maximized(false); + m_resize_aspect_ratio = ratio; + } Gfx::IntSize base_size() const { return m_base_size; } void set_base_size(const Gfx::IntSize& size) { m_base_size = size; } diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp index d6d96d09f7..6d9f9dbd1e 100644 --- a/Userland/Services/WindowServer/WindowManager.cpp +++ b/Userland/Services/WindowServer/WindowManager.cpp @@ -530,9 +530,7 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove m_move_origin = event.position(); if (m_move_origin.y() <= secondary_deadzone) return true; - auto width_before_resize = m_move_window->width(); - m_move_window->set_maximized(false); - m_move_window->move_to(m_move_origin.x() - (m_move_window->width() * ((float)m_move_origin.x() / width_before_resize)), m_move_origin.y()); + m_move_window->set_maximized(false, event.position()); m_move_window_origin = m_move_window->position(); } } else { @@ -558,15 +556,18 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove m_move_window->set_tiled(WindowTileType::Top); } else if (is_resizable && event.y() >= desktop.bottom() - secondary_deadzone) { m_move_window->set_tiled(WindowTileType::Bottom); - } else if (pixels_moved_from_start > 5 || m_move_window->tiled() == WindowTileType::None) { - m_move_window->set_tiled(WindowTileType::None); + } else if (m_move_window->tiled() == WindowTileType::None) { Gfx::IntPoint pos = m_move_window_origin.translated(event.position() - m_move_origin); m_move_window->set_position_without_repaint(pos); - if (m_move_window->rect().contains(event.position())) - hovered_window = m_move_window; + } else if (pixels_moved_from_start > 5) { + m_move_window->set_untiled(event.position()); + m_move_origin = event.position(); + m_move_window_origin = m_move_window->position(); } - return true; } + if (m_move_window->rect().contains(event.position())) + hovered_window = m_move_window; + return true; } return false; }