diff --git a/Servers/WindowServer/Makefile b/Servers/WindowServer/Makefile index 2756f391a9..f92f14e230 100644 --- a/Servers/WindowServer/Makefile +++ b/Servers/WindowServer/Makefile @@ -27,6 +27,7 @@ WINDOWSERVER_OBJS = \ WSButton.o \ WSCPUMonitor.o \ WSCompositor.o \ + WSMenuBarKeeper.o \ main.o APP = WindowServer diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index 0a1a6ea9a6..ad2b9fd1ca 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -27,6 +27,7 @@ enum WSAPI_WindowType { WindowSwitcher, Taskbar, Tooltip, + Menubar, }; struct WSAPI_WindowBackingStoreInfo { diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 1fc1e4c4f0..e21beaf3ff 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -159,7 +159,6 @@ void WSCompositor::compose() }); draw_geometry_label(); - draw_menubar(); } draw_cursor(); @@ -332,59 +331,3 @@ void WSCompositor::draw_cursor() m_back_painter->blit(cursor_rect.location(), wm.active_cursor().bitmap(), wm.active_cursor().rect()); m_last_cursor_rect = cursor_rect; } - -void WSCompositor::draw_menubar() -{ - auto& wm = WSWindowManager::the(); - auto menubar_rect = wm.menubar_rect(); - - m_back_painter->fill_rect(menubar_rect, Color::LightGray); - m_back_painter->draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, Color::MidGray); - int index = 0; - wm.for_each_active_menubar_menu([&](WSMenu& menu) { - Color text_color = Color::Black; - if (&menu == wm.current_menu()) { - m_back_painter->fill_rect(menu.rect_in_menubar(), wm.menu_selection_color()); - text_color = Color::White; - } - m_back_painter->draw_text( - menu.text_rect_in_menubar(), - menu.name(), - index == 1 ? wm.app_menu_font() : wm.menu_font(), - TextAlignment::CenterLeft, - text_color); - ++index; - return true; - }); - - int username_width = Font::default_bold_font().width(wm.m_username); - Rect username_rect { - menubar_rect.right() - wm.menubar_menu_margin() / 2 - Font::default_bold_font().width(wm.m_username), - menubar_rect.y(), - username_width, - menubar_rect.height() - }; - m_back_painter->draw_text(username_rect, wm.m_username, Font::default_bold_font(), TextAlignment::CenterRight, Color::Black); - - time_t now = time(nullptr); - auto* tm = localtime(&now); - auto time_text = String::format("%4u-%02u-%02u %02u:%02u:%02u", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - int time_width = wm.font().width(time_text); - Rect time_rect { - username_rect.left() - wm.menubar_menu_margin() / 2 - time_width, - menubar_rect.y(), - time_width, - menubar_rect.height() - }; - - m_back_painter->draw_text(time_rect, time_text, wm.font(), TextAlignment::CenterRight, Color::Black); - - Rect cpu_rect { time_rect.right() - wm.font().width(time_text) - wm.m_cpu_monitor.capacity() - 10, time_rect.y() + 1, wm.m_cpu_monitor.capacity(), time_rect.height() - 2 }; - wm.m_cpu_monitor.paint(*m_back_painter, cpu_rect); -} diff --git a/Servers/WindowServer/WSEventLoop.cpp b/Servers/WindowServer/WSEventLoop.cpp index 479b7defac..8c103c8b5a 100644 --- a/Servers/WindowServer/WSEventLoop.cpp +++ b/Servers/WindowServer/WSEventLoop.cpp @@ -206,6 +206,9 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag case WSAPI_WindowType::Tooltip: ws_window_type = WSWindowType::Tooltip; break; + case WSAPI_WindowType::Menubar: + ws_window_type = WSWindowType::Menubar; + break; case WSAPI_WindowType::Invalid: break; // handled below } diff --git a/Servers/WindowServer/WSMenuBarKeeper.cpp b/Servers/WindowServer/WSMenuBarKeeper.cpp new file mode 100644 index 0000000000..b6167995fc --- /dev/null +++ b/Servers/WindowServer/WSMenuBarKeeper.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include + +WSMenuBarKeeper::WSMenuBarKeeper() +{ + m_username = getlogin(); + + new CTimer(300, [this] { + static time_t last_update_time; + time_t now = time(nullptr); + if (now != last_update_time || m_cpu_monitor.is_dirty()) { + tick_clock(); + last_update_time = now; + m_cpu_monitor.set_dirty(false); + } + }); +} + +WSMenuBarKeeper::~WSMenuBarKeeper() +{ +} + +void WSMenuBarKeeper::setup() +{ + m_window = make(*this, WSWindowType::Menubar); + m_window->set_rect(WSWindowManager::the().menubar_rect()); +} + +void WSMenuBarKeeper::draw() +{ + auto& wm = WSWindowManager::the(); + auto menubar_rect = wm.menubar_rect(); + + Painter painter(*window().backing_store()); + + painter.fill_rect(menubar_rect, Color::LightGray); + painter.draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, Color::MidGray); + int index = 0; + wm.for_each_active_menubar_menu([&](WSMenu& menu) { + Color text_color = Color::Black; + if (&menu == wm.current_menu()) { + painter.fill_rect(menu.rect_in_menubar(), wm.menu_selection_color()); + text_color = Color::White; + } + painter.draw_text( + menu.text_rect_in_menubar(), + menu.name(), + index == 1 ? wm.app_menu_font() : wm.menu_font(), + TextAlignment::CenterLeft, + text_color); + ++index; + return true; + }); + + int username_width = Font::default_bold_font().width(m_username); + Rect username_rect { + menubar_rect.right() - wm.menubar_menu_margin() / 2 - Font::default_bold_font().width(m_username), + menubar_rect.y(), + username_width, + menubar_rect.height() + }; + painter.draw_text(username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, Color::Black); + + time_t now = time(nullptr); + auto* tm = localtime(&now); + auto time_text = String::format("%4u-%02u-%02u %02u:%02u:%02u", + tm->tm_year + 1900, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + int time_width = wm.font().width(time_text); + Rect time_rect { + username_rect.left() - wm.menubar_menu_margin() / 2 - time_width, + menubar_rect.y(), + time_width, + menubar_rect.height() + }; + + painter.draw_text(time_rect, time_text, wm.font(), TextAlignment::CenterRight, Color::Black); + + Rect cpu_rect { time_rect.right() - wm.font().width(time_text) - m_cpu_monitor.capacity() - 10, time_rect.y() + 1, m_cpu_monitor.capacity(), time_rect.height() - 2 }; + m_cpu_monitor.paint(painter, cpu_rect); +} + +void WSMenuBarKeeper::tick_clock() +{ + refresh(); +} + +void WSMenuBarKeeper::refresh() +{ + if (!m_window) + return; + draw(); + window().invalidate(); +} + +void WSMenuBarKeeper::event(CEvent& event) +{ + return CObject::event(event); +} diff --git a/Servers/WindowServer/WSMenuBarKeeper.h b/Servers/WindowServer/WSMenuBarKeeper.h new file mode 100644 index 0000000000..19f4cbecac --- /dev/null +++ b/Servers/WindowServer/WSMenuBarKeeper.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +class WSMenuBarKeeper final : public CObject { +public: + WSMenuBarKeeper(); + virtual ~WSMenuBarKeeper() override; + + WSWindow& window() { return *m_window; } + const WSWindow& window() const { return *m_window; } + + void draw(); + void refresh(); + void setup(); + + virtual void event(CEvent&) override; + virtual const char* class_name() const override { return "WSMenuBarKeeper"; } + +private: + void tick_clock(); + + OwnPtr m_window; + WSCPUMonitor m_cpu_monitor; + String m_username; +}; diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index d478331649..1eec834d73 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -138,6 +138,8 @@ static WSAPI_WindowType to_api(WSWindowType ws_type) return WSAPI_WindowType::Taskbar; case WSWindowType::Tooltip: return WSAPI_WindowType::Tooltip; + case WSWindowType::Menubar: + return WSAPI_WindowType::Menubar; default: ASSERT_NOT_REACHED(); } diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index a796617b44..4714ed14b6 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -38,8 +38,6 @@ WSWindowManager::WSWindowManager() { s_the = this; - m_username = getlogin(); - reload_config(false); struct AppMenuItem { @@ -101,15 +99,7 @@ WSWindowManager::WSWindowManager() // NOTE: This ensures that the system menu has the correct dimensions. set_current_menubar(nullptr); - new CTimer(300, [this] { - static time_t last_update_time; - time_t now = time(nullptr); - if (now != last_update_time || m_cpu_monitor.is_dirty()) { - tick_clock(); - last_update_time = now; - m_cpu_monitor.set_dirty(false); - } - }); + m_menubar_keeper.setup(); invalidate(); WSCompositor::the().compose(); @@ -198,11 +188,6 @@ const Font& WSWindowManager::app_menu_font() const return Font::default_bold_font(); } -void WSWindowManager::tick_clock() -{ - invalidate(menubar_rect()); -} - void WSWindowManager::set_resolution(int width, int height) { WSCompositor::the().set_resolution(width, height); @@ -252,7 +237,7 @@ void WSWindowManager::set_current_menubar(WSMenuBar* menubar) ++index; return true; }); - invalidate(menubar_rect()); + m_menubar_keeper.refresh(); } void WSWindowManager::add_window(WSWindow& window) @@ -416,6 +401,7 @@ void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, const WSMouseEvent& menu_window.set_visible(true); } m_current_menu = menu.make_weak_ptr(); + m_menubar_keeper.refresh(); return; } if (event.type() == WSMouseEvent::MouseDown && event.button() == MouseButton::Left) { @@ -429,6 +415,7 @@ void WSWindowManager::close_current_menu() if (m_current_menu && m_current_menu->menu_window()) m_current_menu->menu_window()->set_visible(false); m_current_menu = nullptr; + m_menubar_keeper.refresh(); } void WSWindowManager::handle_menubar_mouse_event(const WSMouseEvent& event) @@ -1004,7 +991,7 @@ void WSWindowManager::notify_client_changed_app_menubar(WSClientConnection& clie { if (active_client() == &client) set_current_menubar(client.app_menubar()); - invalidate(menubar_rect()); + m_menubar_keeper.refresh(); } const WSCursor& WSWindowManager::active_cursor() const diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 839f2292b9..1d60e07002 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -1,6 +1,5 @@ #pragma once -#include "WSMenuBar.h" #include #include #include @@ -11,9 +10,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -131,6 +131,14 @@ public: const WSWindow* active_fullscreen_window() const { return (m_active_window && m_active_window->is_fullscreen()) ? m_active_window : nullptr; } WSWindow* active_fullscreen_window() { return (m_active_window && m_active_window->is_fullscreen()) ? m_active_window : nullptr; } + template + void for_each_active_menubar_menu(Callback callback) + { + callback(*m_system_menu); + if (m_current_menubar) + m_current_menubar->for_each_menu(callback); + } + private: Retained get_cursor(const String& name); Retained get_cursor(const String& name, const Point& hotspot); @@ -159,18 +167,9 @@ private: template void for_each_window(Callback); - template - void for_each_active_menubar_menu(Callback callback) - { - callback(*m_system_menu); - if (m_current_menubar) - m_current_menubar->for_each_menu(callback); - } - void close_current_menu(); virtual void event(CEvent&) override; void paint_window_frame(const WSWindow&); - void tick_clock(); void tell_wm_listener_about_window(WSWindow& listener, WSWindow&); void tell_wm_listener_about_window_icon(WSWindow& listener, WSWindow&); void tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow&); @@ -241,13 +240,11 @@ private: WeakPtr m_current_menu; WSWindowSwitcher m_switcher; + WSMenuBarKeeper m_menubar_keeper; - String m_username; WeakPtr m_cursor_tracking_button; WeakPtr m_hovered_button; - WSCPUMonitor m_cpu_monitor; - RetainPtr m_wm_config; }; @@ -285,6 +282,8 @@ IterationDecision WSWindowManager::for_each_visible_window_from_back_to_front(Ca return IterationDecision::Break; if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Tooltip, callback) == IterationDecision::Break) return IterationDecision::Break; + if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Menubar, callback) == IterationDecision::Break) + return IterationDecision::Break; if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Menu, callback) == IterationDecision::Break) return IterationDecision::Break; return for_each_visible_window_of_type_from_back_to_front(WSWindowType::WindowSwitcher, callback); @@ -320,6 +319,8 @@ IterationDecision WSWindowManager::for_each_visible_window_from_front_to_back(Ca return IterationDecision::Break; if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Menu, callback) == IterationDecision::Break) return IterationDecision::Break; + if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Menubar, callback) == IterationDecision::Break) + return IterationDecision::Break; if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Taskbar, callback) == IterationDecision::Break) return IterationDecision::Break; if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Tooltip, callback) == IterationDecision::Break) diff --git a/Servers/WindowServer/WSWindowType.h b/Servers/WindowServer/WSWindowType.h index 897e81f74e..9f1528ad84 100644 --- a/Servers/WindowServer/WSWindowType.h +++ b/Servers/WindowServer/WSWindowType.h @@ -7,4 +7,5 @@ enum class WSWindowType { WindowSwitcher, Taskbar, Tooltip, + Menubar, };