mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:27:35 +00:00
LibGUI+WindowServer: Provide default placement to windows
This prevents windows from being opened directly on top of eachother, and provides default behavior for when window position is not specified. The new behavior is as follows: - Windows that have been created without a set position are assigned one by WindowServer. - The assigned position is either offset from the last window that is still in an assigned position, or a default position if no such window is available.
This commit is contained in:
parent
586ada7a14
commit
5ae9eee4a3
8 changed files with 62 additions and 4 deletions
|
@ -62,7 +62,7 @@ Window::Window(Core::Object* parent)
|
|||
: Core::Object(parent)
|
||||
{
|
||||
all_windows->set(this);
|
||||
m_rect_when_windowless = { 100, 400, 140, 140 };
|
||||
m_rect_when_windowless = { -5000, -5000, 140, 140 };
|
||||
m_title_when_windowless = "GUI::Window";
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ void Window::show()
|
|||
m_override_cursor = StandardCursor::None;
|
||||
auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::CreateWindow>(
|
||||
m_rect_when_windowless,
|
||||
!m_moved_by_client,
|
||||
m_has_alpha_channel,
|
||||
m_modal,
|
||||
m_minimizable,
|
||||
|
@ -192,6 +193,10 @@ Gfx::IntRect Window::rect() const
|
|||
|
||||
void Window::set_rect(const Gfx::IntRect& a_rect)
|
||||
{
|
||||
if (a_rect.location() != m_rect_when_windowless.location()) {
|
||||
m_moved_by_client = true;
|
||||
}
|
||||
|
||||
m_rect_when_windowless = a_rect;
|
||||
if (!is_visible()) {
|
||||
if (m_main_widget)
|
||||
|
|
|
@ -262,6 +262,7 @@ private:
|
|||
bool m_visible_for_timer_purposes { true };
|
||||
bool m_visible { false };
|
||||
bool m_accessory { false };
|
||||
bool m_moved_by_client { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -407,6 +407,10 @@ OwnPtr<Messages::WindowServer::SetWindowRectResponse> ClientConnection::handle(c
|
|||
dbg() << "ClientConnection: Ignoring SetWindowRect request for fullscreen window";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (message.rect().location() != window.rect().location()) {
|
||||
window.set_default_positioned(false);
|
||||
}
|
||||
auto normalized_rect = normalize_window_rect(message.rect(), window.type());
|
||||
window.set_rect(normalized_rect);
|
||||
window.request_update(normalized_rect);
|
||||
|
@ -460,7 +464,12 @@ OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(co
|
|||
window->set_has_alpha_channel(message.has_alpha_channel());
|
||||
window->set_title(message.title());
|
||||
if (!message.fullscreen()) {
|
||||
auto normalized_rect = normalize_window_rect(message.rect(), window->type());
|
||||
auto rect = message.rect();
|
||||
if (message.auto_position() && window->type() == WindowType::Normal) {
|
||||
rect = { WindowManager::the().get_recommended_window_position({ 100, 100 }), message.rect().size() };
|
||||
window->set_default_positioned(true);
|
||||
}
|
||||
auto normalized_rect = normalize_window_rect(rect, window->type());
|
||||
window->set_rect(normalized_rect);
|
||||
}
|
||||
if (window->type() == WindowType::Desktop) {
|
||||
|
|
|
@ -273,6 +273,7 @@ void Window::set_maximized(bool maximized)
|
|||
}
|
||||
m_frame.did_set_maximized({}, maximized);
|
||||
Core::EventLoop::current().post_event(*this, make<ResizeEvent>(old_rect, m_rect));
|
||||
set_default_positioned(false);
|
||||
}
|
||||
|
||||
void Window::set_resizable(bool resizable)
|
||||
|
@ -398,7 +399,7 @@ Window* Window::is_blocked_by_modal_window()
|
|||
if (window && !window->is_destroyed()) {
|
||||
if (window->is_modal())
|
||||
return window;
|
||||
|
||||
|
||||
if (auto* blocking_modal_window = window->is_blocked_by_modal_window())
|
||||
return blocking_modal_window;
|
||||
}
|
||||
|
@ -601,7 +602,7 @@ bool Window::is_accessory() const
|
|||
return false;
|
||||
if (parent_window() != nullptr)
|
||||
return true;
|
||||
|
||||
|
||||
// If accessory window was unparented, convert to a regular window
|
||||
const_cast<Window*>(this)->set_accessory(false);
|
||||
return false;
|
||||
|
|
|
@ -259,6 +259,9 @@ public:
|
|||
bool is_destroyed() const { return m_destroyed; }
|
||||
void destroy();
|
||||
|
||||
bool default_positioned() const { return m_default_positioned; }
|
||||
void set_default_positioned(bool p) { m_default_positioned = p; }
|
||||
|
||||
private:
|
||||
void handle_mouse_event(const MouseEvent&);
|
||||
void update_menu_item_text(PopupMenuItem item);
|
||||
|
@ -293,6 +296,7 @@ private:
|
|||
bool m_fullscreen { false };
|
||||
bool m_accessory { false };
|
||||
bool m_destroyed { false };
|
||||
bool m_default_positioned { false };
|
||||
WindowTileType m_tiled { WindowTileType::None };
|
||||
Gfx::IntRect m_untiled_rect;
|
||||
bool m_occluded { false };
|
||||
|
|
|
@ -442,6 +442,7 @@ void WindowManager::start_window_move(Window& window, const MouseEvent& event)
|
|||
#endif
|
||||
move_to_front_and_make_active(window);
|
||||
m_move_window = window.make_weak_ptr();
|
||||
m_move_window->set_default_positioned(false);
|
||||
m_move_origin = event.position();
|
||||
m_move_window_origin = window.position();
|
||||
window.invalidate();
|
||||
|
@ -479,6 +480,10 @@ void WindowManager::start_window_resize(Window& window, const Gfx::IntPoint& pos
|
|||
m_resize_window_original_rect = window.rect();
|
||||
|
||||
window.invalidate();
|
||||
|
||||
if (hot_area_row == 0 || hot_area_column == 0) {
|
||||
m_resize_window->set_default_positioned(false);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::start_window_resize(Window& window, const MouseEvent& event)
|
||||
|
@ -1428,4 +1433,34 @@ void WindowManager::maximize_windows(Window& window, bool maximized)
|
|||
});
|
||||
}
|
||||
|
||||
Gfx::IntPoint WindowManager::get_recommended_window_position(const Gfx::IntPoint& desired)
|
||||
{
|
||||
// FIXME: Find a better source for the width and height to shift by.
|
||||
Gfx::IntPoint shift(8, palette().window_title_height() + 10);
|
||||
|
||||
// FIXME: Find a better source for this.
|
||||
int taskbar_height = 28;
|
||||
int menubar_height = MenuManager::the().menubar_rect().height();
|
||||
|
||||
const Window* overlap_window = nullptr;
|
||||
for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, [&](Window& window) {
|
||||
if (window.default_positioned() && (!overlap_window || overlap_window->window_id() < window.window_id())) {
|
||||
overlap_window = &window;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
Gfx::IntPoint point;
|
||||
if (overlap_window) {
|
||||
point = overlap_window->position() + shift;
|
||||
point = { point.x() % Screen::the().width(),
|
||||
(point.y() >= (Screen::the().height() - taskbar_height))
|
||||
? menubar_height + palette().window_title_height()
|
||||
: point.y() };
|
||||
} else {
|
||||
point = desired;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,6 +212,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Gfx::IntPoint get_recommended_window_position(const Gfx::IntPoint& desired);
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Cursor> get_cursor(const String& name);
|
||||
NonnullRefPtr<Cursor> get_cursor(const String& name, const Gfx::IntPoint& hotspot);
|
||||
|
|
|
@ -32,6 +32,7 @@ endpoint WindowServer = 2
|
|||
|
||||
CreateWindow(
|
||||
Gfx::IntRect rect,
|
||||
bool auto_position,
|
||||
bool has_alpha_channel,
|
||||
bool modal,
|
||||
bool minimizable,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue