mirror of
https://github.com/RGBCube/serenity
synced 2025-06-19 17:22:06 +00:00
WindowServer: Various window pop-up menu fixes & QoL tweaks
This commit is contained in:
parent
eab34a7de3
commit
74ae6ac94b
5 changed files with 74 additions and 9 deletions
|
@ -5,12 +5,13 @@
|
|||
#include <AK/WeakPtr.h>
|
||||
#include <LibCore/CObject.h>
|
||||
#include <LibDraw/Rect.h>
|
||||
#include <WindowServer/WSCursor.h>
|
||||
#include <WindowServer/WSMenuItem.h>
|
||||
#include <WindowServer/WSWindow.h>
|
||||
|
||||
class WSClientConnection;
|
||||
class WSMenuBar;
|
||||
class WSEvent;
|
||||
class WSWindow;
|
||||
class Font;
|
||||
|
||||
class WSMenu final : public CObject {
|
||||
|
@ -30,6 +31,7 @@ public:
|
|||
bool is_empty() const { return m_items.is_empty(); }
|
||||
int item_count() const { return m_items.size(); }
|
||||
const WSMenuItem& item(int index) const { return m_items.at(index); }
|
||||
WSMenuItem& item(int index) { return m_items.at(index); }
|
||||
|
||||
void add_item(NonnullOwnPtr<WSMenuItem>&& item) { m_items.append(move(item)); }
|
||||
|
||||
|
@ -51,6 +53,11 @@ public:
|
|||
WSWindow* menu_window() { return m_menu_window.ptr(); }
|
||||
WSWindow& ensure_menu_window();
|
||||
|
||||
WSWindow* window_menu_of() { return m_window_menu_of; }
|
||||
void set_window_menu_of(WSWindow& window) { m_window_menu_of = window.make_weak_ptr(); }
|
||||
bool is_window_menu_open() { return m_is_window_menu_open; }
|
||||
void set_window_menu_open(bool is_open) { m_is_window_menu_open = is_open; }
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
|
@ -94,5 +101,7 @@ private:
|
|||
WSMenuItem* m_hovered_item { nullptr };
|
||||
NonnullOwnPtrVector<WSMenuItem> m_items;
|
||||
RefPtr<WSWindow> m_menu_window;
|
||||
WeakPtr<WSWindow> m_window_menu_of;
|
||||
bool m_is_window_menu_open = { false };
|
||||
int m_theme_index_at_last_paint { -1 };
|
||||
};
|
||||
|
|
|
@ -99,6 +99,23 @@ void WSWindow::handle_mouse_event(const WSMouseEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
void WSWindow::update_menu_item_text(PopupMenuItem item)
|
||||
{
|
||||
if (m_window_menu) {
|
||||
m_window_menu->item((int)item).set_text(item == PopupMenuItem::Minimize ?
|
||||
(m_minimized ? "Unminimize" : "Minimize") : (m_maximized ? "Restore" : "Maximize"));
|
||||
m_window_menu->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void WSWindow::update_menu_item_enabled(PopupMenuItem item)
|
||||
{
|
||||
if (m_window_menu) {
|
||||
m_window_menu->item((int)item).set_enabled(item == PopupMenuItem::Minimize ? m_minimizable : m_resizable);
|
||||
m_window_menu->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void WSWindow::set_minimized(bool minimized)
|
||||
{
|
||||
if (m_minimized == minimized)
|
||||
|
@ -106,6 +123,7 @@ void WSWindow::set_minimized(bool minimized)
|
|||
if (minimized && !m_minimizable)
|
||||
return;
|
||||
m_minimized = minimized;
|
||||
update_menu_item_text(PopupMenuItem::Minimize);
|
||||
start_minimize_animation();
|
||||
if (!minimized)
|
||||
request_update({ {}, size() });
|
||||
|
@ -118,6 +136,7 @@ void WSWindow::set_minimizable(bool minimizable)
|
|||
if (m_minimizable == minimizable)
|
||||
return;
|
||||
m_minimizable = minimizable;
|
||||
update_menu_item_enabled(PopupMenuItem::Minimize);
|
||||
// TODO: Hide/show (or alternatively change enabled state of) window minimize button dynamically depending on value of m_minimizable
|
||||
}
|
||||
|
||||
|
@ -144,6 +163,7 @@ void WSWindow::set_maximized(bool maximized)
|
|||
if (maximized && !is_resizable())
|
||||
return;
|
||||
m_maximized = maximized;
|
||||
update_menu_item_text(PopupMenuItem::Maximize);
|
||||
auto old_rect = m_rect;
|
||||
if (maximized) {
|
||||
m_unmaximized_rect = m_rect;
|
||||
|
@ -160,6 +180,7 @@ void WSWindow::set_resizable(bool resizable)
|
|||
if (m_resizable == resizable)
|
||||
return;
|
||||
m_resizable = resizable;
|
||||
update_menu_item_enabled(PopupMenuItem::Maximize);
|
||||
// TODO: Hide/show (or alternatively change enabled state of) window maximize button dynamically depending on value of is_resizable()
|
||||
}
|
||||
|
||||
|
@ -271,18 +292,28 @@ void WSWindow::popup_window_menu(const Point& position)
|
|||
{
|
||||
if (!m_window_menu) {
|
||||
m_window_menu = WSMenu::construct(nullptr, -1, "(Window Menu)");
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 1, "Minimize"));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 2, "Unminimize"));
|
||||
m_window_menu->set_window_menu_of(*this);
|
||||
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 1, m_minimized ? "Unminimize" : "Minimize"));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 2, m_maximized ? "Restore" : "Maximize"));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, WSMenuItem::Type::Separator));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 3, "Close"));
|
||||
|
||||
m_window_menu->item((int)PopupMenuItem::Minimize).set_enabled(m_minimizable);
|
||||
m_window_menu->item((int)PopupMenuItem::Maximize).set_enabled(m_resizable);
|
||||
|
||||
m_window_menu->on_item_activation = [&](auto& item) {
|
||||
switch (item.identifier()) {
|
||||
case 1:
|
||||
set_minimized(true);
|
||||
set_minimized(!m_minimized);
|
||||
if (!m_minimized)
|
||||
WSWindowManager::the().move_to_front_and_make_active(*this);
|
||||
break;
|
||||
case 2:
|
||||
set_maximized(!m_maximized);
|
||||
if (m_minimized)
|
||||
set_minimized(false);
|
||||
WSWindowManager::the().move_to_front_and_make_active(*this);
|
||||
break;
|
||||
case 3:
|
||||
request_close();
|
||||
|
|
|
@ -27,6 +27,11 @@ enum class WindowTileType {
|
|||
Right,
|
||||
};
|
||||
|
||||
enum class PopupMenuItem {
|
||||
Minimize = 0,
|
||||
Maximize,
|
||||
};
|
||||
|
||||
class WSWindow final : public CObject
|
||||
, public InlineLinkedListNode<WSWindow> {
|
||||
C_OBJECT(WSWindow)
|
||||
|
@ -190,6 +195,8 @@ public:
|
|||
|
||||
private:
|
||||
void handle_mouse_event(const WSMouseEvent&);
|
||||
void update_menu_item_text(PopupMenuItem item);
|
||||
void update_menu_item_enabled(PopupMenuItem item);
|
||||
|
||||
WSClientConnection* m_client { nullptr };
|
||||
String m_title;
|
||||
|
|
|
@ -284,7 +284,9 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event)
|
|||
if (m_window.type() != WSWindowType::Normal)
|
||||
return;
|
||||
|
||||
if (event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left && title_bar_icon_rect().contains(event.position())) {
|
||||
if (event.type() == WSEvent::MouseDown && (event.button() == MouseButton::Left || event.button() == MouseButton::Right) &&
|
||||
title_bar_icon_rect().contains(event.position())) {
|
||||
wm.move_to_front_and_make_active(m_window);
|
||||
m_window.popup_window_menu(event.position().translated(rect().location()));
|
||||
return;
|
||||
}
|
||||
|
@ -305,8 +307,14 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event)
|
|||
if (button.relative_rect().contains(event.position()))
|
||||
return button.on_mouse_event(event.translated(-button.relative_rect().location()));
|
||||
}
|
||||
if (event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left)
|
||||
if (event.type() == WSEvent::MouseDown) {
|
||||
if (event.button() == MouseButton::Right) {
|
||||
m_window.popup_window_menu(event.position().translated(rect().location()));
|
||||
return;
|
||||
}
|
||||
if (event.button() == MouseButton::Left)
|
||||
wm.start_window_move(m_window, event.translated(rect().location()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -883,8 +883,18 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& hovere
|
|||
if (!event_is_inside_current_menu) {
|
||||
if (topmost_menu->hovered_item())
|
||||
topmost_menu->clear_hovered_item();
|
||||
if (event.type() == WSEvent::MouseDown || event.type() == WSEvent::MouseUp)
|
||||
if (event.type() == WSEvent::MouseDown || event.type() == WSEvent::MouseUp) {
|
||||
auto* window_menu_of = topmost_menu->window_menu_of();
|
||||
if (window_menu_of) {
|
||||
bool event_is_inside_taskbar_button = window_menu_of->taskbar_rect().contains(event.position());
|
||||
if (event_is_inside_taskbar_button && !topmost_menu->is_window_menu_open()) {
|
||||
topmost_menu->set_window_menu_open(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_menu_manager.close_bar();
|
||||
topmost_menu->set_window_menu_open(false);
|
||||
}
|
||||
if (event.type() == WSEvent::MouseMove) {
|
||||
for (auto& menu : m_menu_manager.open_menu_stack()) {
|
||||
if (!menu)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue