mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:17:45 +00:00
WindowServer: Fix many subtle bugs in tiling/maximizing
- Unmaximization/untiling had nearly but not quite code duplication; this patch replaces the actual "regrabbing" logic with Rect::set_size_around. - When undoing maximization/untiling, it used to be possible to to grab a window "outside" of its frame, and thus drag it off the screen. This is no longer possible. Fixes #4644. - As a side effect, when untiling from the bottom/left/right, the regrab is now a much smoother experience. - Setting the resize aspect ratio while being tiled now untiles and umaximizes the window, as these things are incompatible. Fixes an undocumented bug (steps to reproduce: maximize, then set aspect ratio). - When unmaximizing, spurious WindowLeft events were sent, because that path didn't set hovered_window. Fixes an undocumented bug. Since these things are interwoven, this is all a single commit.
This commit is contained in:
parent
e8997e1de9
commit
2de471b9f0
3 changed files with 51 additions and 15 deletions
|
@ -319,21 +319,27 @@ 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<Gfx::IntPoint> 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 {
|
||||
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<ResizeEvent>(m_rect));
|
||||
set_default_positioned(false);
|
||||
|
@ -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<ResizeEvent>(m_rect));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::set_tiled(WindowTileType tiled)
|
||||
{
|
||||
ASSERT(tiled != WindowTileType::None);
|
||||
|
||||
if (m_tiled == tiled)
|
||||
return;
|
||||
|
||||
|
|
|
@ -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<Gfx::IntPoint> 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<Gfx::IntSize>& resize_aspect_ratio() const { return m_resize_aspect_ratio; }
|
||||
void set_resize_aspect_ratio(const Optional<Gfx::IntSize>& ratio) { m_resize_aspect_ratio = ratio; }
|
||||
void set_resize_aspect_ratio(const Optional<Gfx::IntSize>& 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; }
|
||||
|
|
|
@ -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,16 +556,19 @@ 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);
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
if (m_move_window->rect().contains(event.position()))
|
||||
hovered_window = m_move_window;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue