mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:17:34 +00:00
WindowServer: Fix menu location on screens other than main screen
The menus always thought they were being outside of the main screen, which caused them to be left and/or top aligned. This also fixes the calculation of the available space by using the screen rectangle where it will be displayed.
This commit is contained in:
parent
2d4eb40f59
commit
30f531a55f
4 changed files with 34 additions and 26 deletions
|
@ -118,13 +118,30 @@ void Menu::redraw()
|
||||||
menu_window()->invalidate();
|
menu_window()->invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Window& Menu::ensure_menu_window()
|
Window& Menu::ensure_menu_window(Gfx::IntPoint const& position)
|
||||||
{
|
{
|
||||||
if (m_menu_window)
|
auto& screen = Screen::closest_to_location(position);
|
||||||
return *m_menu_window;
|
|
||||||
|
|
||||||
int width = this->content_width();
|
int width = this->content_width();
|
||||||
|
|
||||||
|
auto calculate_window_rect = [&]() -> Gfx::IntRect {
|
||||||
|
int window_height_available = screen.height() - frame_thickness() * 2;
|
||||||
|
int max_window_height = (window_height_available / item_height()) * item_height() + frame_thickness() * 2;
|
||||||
|
int content_height = m_items.is_empty() ? 0 : (m_items.last().rect().bottom() + 1) + frame_thickness();
|
||||||
|
int window_height = min(max_window_height, content_height);
|
||||||
|
if (window_height < content_height) {
|
||||||
|
m_scrollable = true;
|
||||||
|
m_max_scroll_offset = item_count() - window_height / item_height() + 2;
|
||||||
|
}
|
||||||
|
return { position, { width, window_height } };
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_menu_window) {
|
||||||
|
// We might be on a different screen than previously, so recalculate the
|
||||||
|
// menu's rectangle as we have more or less screen available now
|
||||||
|
m_menu_window->set_rect(calculate_window_rect());
|
||||||
|
return *m_menu_window;
|
||||||
|
}
|
||||||
|
|
||||||
Gfx::IntPoint next_item_location(frame_thickness(), frame_thickness());
|
Gfx::IntPoint next_item_location(frame_thickness(), frame_thickness());
|
||||||
for (auto& item : m_items) {
|
for (auto& item : m_items) {
|
||||||
int height = 0;
|
int height = 0;
|
||||||
|
@ -136,18 +153,9 @@ Window& Menu::ensure_menu_window()
|
||||||
next_item_location.translate_by(0, height);
|
next_item_location.translate_by(0, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int window_height_available = Screen::main().height() - frame_thickness() * 2; // TODO: we don't know yet on what screen!
|
|
||||||
int max_window_height = (window_height_available / item_height()) * item_height() + frame_thickness() * 2;
|
|
||||||
int content_height = m_items.is_empty() ? 0 : (m_items.last().rect().bottom() + 1) + frame_thickness();
|
|
||||||
int window_height = min(max_window_height, content_height);
|
|
||||||
if (window_height < content_height) {
|
|
||||||
m_scrollable = true;
|
|
||||||
m_max_scroll_offset = item_count() - window_height / item_height() + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto window = Window::construct(*this, WindowType::Menu);
|
auto window = Window::construct(*this, WindowType::Menu);
|
||||||
window->set_visible(false);
|
window->set_visible(false);
|
||||||
window->set_rect(0, 0, width, window_height);
|
window->set_rect(calculate_window_rect());
|
||||||
m_menu_window = move(window);
|
m_menu_window = move(window);
|
||||||
draw();
|
draw();
|
||||||
return *m_menu_window;
|
return *m_menu_window;
|
||||||
|
@ -287,7 +295,7 @@ void Menu::update_for_new_hovered_item(bool make_input)
|
||||||
hovered_item->submenu()->do_popup(hovered_item->rect().top_right().translated(menu_window()->rect().location()), make_input, true);
|
hovered_item->submenu()->do_popup(hovered_item->rect().top_right().translated(menu_window()->rect().location()), make_input, true);
|
||||||
} else {
|
} else {
|
||||||
MenuManager::the().close_everyone_not_in_lineage(*this);
|
MenuManager::the().close_everyone_not_in_lineage(*this);
|
||||||
ensure_menu_window();
|
VERIFY(menu_window());
|
||||||
set_visible(true);
|
set_visible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,19 +588,19 @@ void Menu::do_popup(const Gfx::IntPoint& position, bool make_input, bool as_subm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& window = ensure_menu_window();
|
auto& screen = Screen::closest_to_location(position);
|
||||||
|
auto& window = ensure_menu_window(position);
|
||||||
redraw_if_theme_changed();
|
redraw_if_theme_changed();
|
||||||
|
|
||||||
const int margin = 30;
|
const int margin = 30;
|
||||||
auto& screen = Screen::closest_to_location(position);
|
|
||||||
Gfx::IntPoint adjusted_pos = position;
|
Gfx::IntPoint adjusted_pos = position;
|
||||||
|
|
||||||
if (adjusted_pos.x() + window.width() >= screen.width() - margin) {
|
if (adjusted_pos.x() + window.width() > screen.rect().right() - margin) {
|
||||||
adjusted_pos = adjusted_pos.translated(-window.width(), 0);
|
adjusted_pos = adjusted_pos.translated(-window.width(), 0);
|
||||||
} else {
|
} else {
|
||||||
adjusted_pos.set_x(adjusted_pos.x() + 1);
|
adjusted_pos.set_x(adjusted_pos.x() + 1);
|
||||||
}
|
}
|
||||||
if (adjusted_pos.y() + window.height() >= screen.height() - margin) {
|
if (adjusted_pos.y() + window.height() > screen.rect().bottom() - margin) {
|
||||||
adjusted_pos = adjusted_pos.translated(0, -min(window.height(), adjusted_pos.y()));
|
adjusted_pos = adjusted_pos.translated(0, -min(window.height(), adjusted_pos.y()));
|
||||||
if (as_submenu)
|
if (as_submenu)
|
||||||
adjusted_pos = adjusted_pos.translated(0, item_height());
|
adjusted_pos = adjusted_pos.translated(0, item_height());
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
void set_rect_in_window_menubar(const Gfx::IntRect& rect) { m_rect_in_window_menubar = rect; }
|
void set_rect_in_window_menubar(const Gfx::IntRect& rect) { m_rect_in_window_menubar = rect; }
|
||||||
|
|
||||||
Window* menu_window() { return m_menu_window.ptr(); }
|
Window* menu_window() { return m_menu_window.ptr(); }
|
||||||
Window& ensure_menu_window();
|
Window& ensure_menu_window(Gfx::IntPoint const&);
|
||||||
|
|
||||||
Window* window_menu_of() { return m_window_menu_of; }
|
Window* window_menu_of() { return m_window_menu_of; }
|
||||||
void set_window_menu_of(Window& window) { m_window_menu_of = window; }
|
void set_window_menu_of(Window& window) { m_window_menu_of = window; }
|
||||||
|
|
|
@ -101,7 +101,7 @@ void MenuManager::event(Core::Event& event)
|
||||||
else {
|
else {
|
||||||
auto* target_menu = previous_menu(m_current_menu);
|
auto* target_menu = previous_menu(m_current_menu);
|
||||||
if (target_menu) {
|
if (target_menu) {
|
||||||
target_menu->ensure_menu_window().move_to(target_menu->rect_in_window_menubar().bottom_left().translated(wm.window_with_active_menu()->frame().rect().location()).translated(wm.window_with_active_menu()->frame().menubar_rect().location()));
|
target_menu->ensure_menu_window(target_menu->rect_in_window_menubar().bottom_left().translated(wm.window_with_active_menu()->frame().rect().location()).translated(wm.window_with_active_menu()->frame().menubar_rect().location()));
|
||||||
open_menu(*target_menu);
|
open_menu(*target_menu);
|
||||||
wm.window_with_active_menu()->invalidate_menubar();
|
wm.window_with_active_menu()->invalidate_menubar();
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ void MenuManager::event(Core::Event& event)
|
||||||
else if (m_open_menu_stack.size() <= 1 && wm.window_with_active_menu()) {
|
else if (m_open_menu_stack.size() <= 1 && wm.window_with_active_menu()) {
|
||||||
auto* target_menu = next_menu(m_current_menu);
|
auto* target_menu = next_menu(m_current_menu);
|
||||||
if (target_menu) {
|
if (target_menu) {
|
||||||
target_menu->ensure_menu_window().move_to(target_menu->rect_in_window_menubar().bottom_left().translated(wm.window_with_active_menu()->frame().rect().location()).translated(wm.window_with_active_menu()->frame().menubar_rect().location()));
|
target_menu->ensure_menu_window(target_menu->rect_in_window_menubar().bottom_left().translated(wm.window_with_active_menu()->frame().rect().location()).translated(wm.window_with_active_menu()->frame().menubar_rect().location()));
|
||||||
open_menu(*target_menu);
|
open_menu(*target_menu);
|
||||||
wm.window_with_active_menu()->invalidate_menubar();
|
wm.window_with_active_menu()->invalidate_menubar();
|
||||||
close_everyone_not_in_lineage(*target_menu);
|
close_everyone_not_in_lineage(*target_menu);
|
||||||
|
@ -300,9 +300,9 @@ void MenuManager::open_menu(Menu& menu, bool as_current_menu)
|
||||||
|
|
||||||
if (!menu.is_empty()) {
|
if (!menu.is_empty()) {
|
||||||
menu.redraw_if_theme_changed();
|
menu.redraw_if_theme_changed();
|
||||||
if (!menu.menu_window())
|
auto* window = menu.menu_window();
|
||||||
menu.ensure_menu_window();
|
VERIFY(window);
|
||||||
menu.set_visible(true);
|
window->set_visible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_open_menu_stack.find_if([&menu](auto& other) { return &menu == other.ptr(); }).is_end())
|
if (m_open_menu_stack.find_if([&menu](auto& other) { return &menu == other.ptr(); }).is_end())
|
||||||
|
|
|
@ -845,7 +845,7 @@ void WindowFrame::open_menubar_menu(Menu& menu)
|
||||||
{
|
{
|
||||||
auto menubar_rect = this->menubar_rect();
|
auto menubar_rect = this->menubar_rect();
|
||||||
MenuManager::the().close_everyone();
|
MenuManager::the().close_everyone();
|
||||||
menu.ensure_menu_window().move_to(menu.rect_in_window_menubar().bottom_left().translated(rect().location()).translated(menubar_rect.location()));
|
menu.ensure_menu_window(menu.rect_in_window_menubar().bottom_left().translated(rect().location()).translated(menubar_rect.location()));
|
||||||
MenuManager::the().open_menu(menu);
|
MenuManager::the().open_menu(menu);
|
||||||
WindowManager::the().set_window_with_active_menu(&m_window);
|
WindowManager::the().set_window_with_active_menu(&m_window);
|
||||||
invalidate(menubar_rect);
|
invalidate(menubar_rect);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue