1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:37:35 +00:00

WindowServer: Allow for more flexible tiling

The desktop can now be split up into halves (both vertical and
horizontal) and quarters by dragging a window into the corresponding
edge or corner.

This makes tiling behave more like you would expect from similiar
window managers.
This commit is contained in:
Julian Offenhäuser 2020-12-05 02:26:21 +01:00 committed by Andreas Kling
parent 4ec77ba929
commit 503aebaefc
3 changed files with 64 additions and 14 deletions

View file

@ -598,19 +598,53 @@ void Window::set_fullscreen(bool fullscreen)
Gfx::IntRect Window::tiled_rect(WindowTileType tiled) const Gfx::IntRect Window::tiled_rect(WindowTileType tiled) const
{ {
int frame_width = (m_frame.rect().width() - m_rect.width()) / 2; 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) { switch (tiled) {
case WindowTileType::None: case WindowTileType::None:
return m_untiled_rect; return m_untiled_rect;
case WindowTileType::Left: case WindowTileType::Left:
return Gfx::IntRect(0, return Gfx::IntRect(0,
WindowManager::the().maximized_window_rect(*this).y(), menu_height,
Screen::the().width() / 2 - frame_width, Screen::the().width() / 2 - frame_width,
WindowManager::the().maximized_window_rect(*this).height()); max_height);
case WindowTileType::Right: case WindowTileType::Right:
return Gfx::IntRect(Screen::the().width() / 2 + frame_width, return Gfx::IntRect(Screen::the().width() / 2 + frame_width,
WindowManager::the().maximized_window_rect(*this).y(), menu_height,
Screen::the().width() / 2 - frame_width, Screen::the().width() / 2 - frame_width,
WindowManager::the().maximized_window_rect(*this).height()); max_height);
case WindowTileType::Top:
return Gfx::IntRect(0,
menu_height,
Screen::the().width() - frame_width,
(max_height - title_bar_height) / 2 - frame_width);
case WindowTileType::Bottom:
return Gfx::IntRect(0,
menu_height + (title_bar_height + max_height) / 2 + frame_width,
Screen::the().width() - frame_width,
(max_height - title_bar_height) / 2 - frame_width);
case WindowTileType::TopLeft:
return Gfx::IntRect(0,
menu_height,
Screen::the().width() / 2 - frame_width,
(max_height - title_bar_height) / 2 - frame_width);
case WindowTileType::TopRight:
return Gfx::IntRect(Screen::the().width() / 2 + frame_width,
menu_height,
Screen::the().width() / 2 - frame_width,
(max_height - title_bar_height) / 2 - frame_width);
case WindowTileType::BottomLeft:
return Gfx::IntRect(0,
menu_height + (title_bar_height + max_height) / 2 + frame_width,
Screen::the().width() / 2 - frame_width,
(max_height - title_bar_height) / 2);
case WindowTileType::BottomRight:
return Gfx::IntRect(Screen::the().width() / 2 + frame_width,
menu_height + (title_bar_height + max_height) / 2 + frame_width,
Screen::the().width() / 2 - frame_width,
(max_height - title_bar_height) / 2);
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }

View file

@ -55,6 +55,12 @@ enum class WindowTileType {
None = 0, None = 0,
Left, Left,
Right, Right,
Top,
Bottom,
TopLeft,
TopRight,
BottomLeft,
BottomRight
}; };
enum class PopupMenuItem { enum class PopupMenuItem {

View file

@ -528,7 +528,8 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove
#endif #endif
const int maximization_deadzone = 2; const int tiling_deadzone = 10;
const int secondary_deadzone = 2;
if (m_move_window->is_maximized()) { if (m_move_window->is_maximized()) {
auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin); auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin);
@ -536,7 +537,7 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove
if (pixels_moved_from_start > 5) { if (pixels_moved_from_start > 5) {
// dbg() << "[WM] de-maximizing window"; // dbg() << "[WM] de-maximizing window";
m_move_origin = event.position(); m_move_origin = event.position();
if (m_move_origin.y() <= maximization_deadzone) if (m_move_origin.y() <= secondary_deadzone)
return true; return true;
auto width_before_resize = m_move_window->width(); auto width_before_resize = m_move_window->width();
m_move_window->set_maximized(false); m_move_window->set_maximized(false);
@ -546,17 +547,26 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event, Window*& hove
} else { } else {
bool is_resizable = m_move_window->is_resizable(); bool is_resizable = m_move_window->is_resizable();
auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin); auto pixels_moved_from_start = event.position().pixels_moved(m_move_origin);
const int tiling_deadzone = 5; auto desktop = desktop_rect();
if (is_resizable && event.y() <= maximization_deadzone) {
m_move_window->set_tiled(WindowTileType::None);
m_move_window->set_maximized(true);
return true;
}
if (is_resizable && event.x() <= tiling_deadzone) { if (is_resizable && event.x() <= tiling_deadzone) {
m_move_window->set_tiled(WindowTileType::Left); if (event.y() <= tiling_deadzone + desktop.top())
m_move_window->set_tiled(WindowTileType::TopLeft);
else if (event.y() >= desktop.height() - tiling_deadzone)
m_move_window->set_tiled(WindowTileType::BottomLeft);
else
m_move_window->set_tiled(WindowTileType::Left);
} else if (is_resizable && event.x() >= Screen::the().width() - tiling_deadzone) { } else if (is_resizable && event.x() >= Screen::the().width() - tiling_deadzone) {
m_move_window->set_tiled(WindowTileType::Right); if (event.y() <= tiling_deadzone + desktop.top())
m_move_window->set_tiled(WindowTileType::TopRight);
else if (event.y() >= desktop.height() - tiling_deadzone)
m_move_window->set_tiled(WindowTileType::BottomRight);
else
m_move_window->set_tiled(WindowTileType::Right);
} else if (is_resizable && event.y() <= secondary_deadzone + desktop.top()) {
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) { } else if (pixels_moved_from_start > 5 || m_move_window->tiled() == WindowTileType::None) {
m_move_window->set_tiled(WindowTileType::None); m_move_window->set_tiled(WindowTileType::None);
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);