diff --git a/Base/home/anon/WindowManager.ini b/Base/home/anon/WindowManager.ini index 385d063a1b..040070b1f2 100644 --- a/Base/home/anon/WindowManager.ini +++ b/Base/home/anon/WindowManager.ini @@ -22,3 +22,6 @@ DoubleClickSpeed=250 [Background] Mode=scaled + +[Applet] +Order=Clock,Audio,CPUGraph,UserName diff --git a/Servers/WindowServer/AppletManager.cpp b/Servers/WindowServer/AppletManager.cpp new file mode 100644 index 0000000000..5c404f692a --- /dev/null +++ b/Servers/WindowServer/AppletManager.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020-2020, Hüseyin Aslıtürk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "AppletManager.h" +#include +#include +#include + +namespace WindowServer { + +static AppletManager* s_the; +Vector order_vector; + +AppletManager::AppletManager() +{ + s_the = this; + + auto wm_config = Core::ConfigFile::get_for_app("WindowManager"); + auto order = wm_config->read_entry("Applet", "Order"); + order_vector = order.split(','); +} + +AppletManager::~AppletManager() +{ +} + +AppletManager& AppletManager::the() +{ + ASSERT(s_the); + return *s_the; +} + +void AppletManager::event(Core::Event& event) +{ + auto& mouse_event = static_cast(event); + + for (auto& applet : m_applets) { + if (!applet) + continue; + if (!applet->rect_in_menubar().contains(mouse_event.position())) + continue; + auto local_event = mouse_event.translated(-applet->rect_in_menubar().location()); + applet->event(local_event); + } +} + +void AppletManager::add_applet(Window& applet) +{ + m_applets.append(applet.make_weak_ptr()); + + quick_sort(m_applets.begin(), m_applets.end(), [](auto& a, auto& b) { + int index_a = order_vector.find_first_index(a->title()); + int index_b = order_vector.find_first_index(b->title()); + + return index_a > index_b; + }); + + calculate_applet_rects(MenuManager::the().window()); +} + +void AppletManager::calculate_applet_rects(Window& window) +{ + auto menubar_rect = window.rect(); + int right_edge_x = menubar_rect.width() - 4; + for (auto& existing_applet : m_applets) { + + Gfx::Rect new_applet_rect(right_edge_x - existing_applet->size().width(), 0, existing_applet->size().width(), existing_applet->size().height()); + Gfx::Rect dummy_menubar_rect(0, 0, 0, 18); + new_applet_rect.center_vertically_within(dummy_menubar_rect); + + existing_applet->set_rect_in_menubar(new_applet_rect); + right_edge_x = existing_applet->rect_in_menubar().x() - 4; + } +} + +void AppletManager::remove_applet(Window& applet) +{ + m_applets.remove_first_matching([&](auto& entry) { + return &applet == entry.ptr(); + }); +} + +void AppletManager::draw() +{ + for (auto& applet : m_applets) { + if (!applet) + continue; + draw_applet(*applet); + } +} + +void AppletManager::draw_applet(const Window& applet) +{ + if (!applet.backing_store()) + return; + + Gfx::Painter painter(*MenuManager::the().window().backing_store()); + painter.fill_rect(applet.rect_in_menubar(), WindowManager::the().palette().window()); + painter.blit(applet.rect_in_menubar().location(), *applet.backing_store(), applet.backing_store()->rect()); +} + +void AppletManager::invalidate_applet(const Window& applet, const Gfx::Rect& rect) +{ + draw_applet(applet); + MenuManager::the().window().invalidate(rect.translated(applet.rect_in_menubar().location())); +} + +} diff --git a/Servers/WindowServer/AppletManager.h b/Servers/WindowServer/AppletManager.h new file mode 100644 index 0000000000..4619fd0030 --- /dev/null +++ b/Servers/WindowServer/AppletManager.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020-2020, Hüseyin Aslıtürk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +namespace WindowServer { + +class AppletManager : public Core::Object { + C_OBJECT(AppletManager) +public: + AppletManager(); + ~AppletManager(); + + static AppletManager& the(); + + virtual void event(Core::Event&) override; + + void add_applet(Window& applet); + void remove_applet(Window& applet); + void draw(); + void invalidate_applet(const Window& applet, const Gfx::Rect& rect); + void calculate_applet_rects(Window& window); + +private: + void draw_applet(const Window& applet); + + Vector> m_applets; +}; + +} diff --git a/Servers/WindowServer/ClientConnection.cpp b/Servers/WindowServer/ClientConnection.cpp index 0c4e4e3746..a29ea584e9 100644 --- a/Servers/WindowServer/ClientConnection.cpp +++ b/Servers/WindowServer/ClientConnection.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -438,7 +439,7 @@ OwnPtr ClientConnection::handle(co window->set_base_size(message.base_size()); window->invalidate(); if (window->type() == WindowType::MenuApplet) - MenuManager::the().add_applet(*window); + AppletManager::the().add_applet(*window); m_windows.set(window_id, move(window)); return make(window_id); } @@ -453,7 +454,7 @@ OwnPtr ClientConnection::handle(c auto& window = *(*it).value; if (window.type() == WindowType::MenuApplet) - MenuManager::the().remove_applet(window); + AppletManager::the().remove_applet(window); WindowManager::the().invalidate(window); remove_child(window); diff --git a/Servers/WindowServer/Makefile b/Servers/WindowServer/Makefile index 4883f8802c..064e2bd0f2 100644 --- a/Servers/WindowServer/Makefile +++ b/Servers/WindowServer/Makefile @@ -1,4 +1,5 @@ OBJS = \ + AppletManager.o \ Button.o \ ClientConnection.o \ Clipboard.o \ diff --git a/Servers/WindowServer/MenuManager.cpp b/Servers/WindowServer/MenuManager.cpp index 843b204856..e3b9f2162f 100644 --- a/Servers/WindowServer/MenuManager.cpp +++ b/Servers/WindowServer/MenuManager.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -215,7 +216,7 @@ void MenuManager::draw() if (m_needs_window_resize) { m_window->set_rect(menubar_rect); - calculate_applet_rects(); + AppletManager::the().calculate_applet_rects(window()); m_needs_window_resize = false; } @@ -241,11 +242,7 @@ void MenuManager::draw() return IterationDecision::Continue; }); - for (auto& applet : m_applets) { - if (!applet) - continue; - draw_applet(*applet); - } + AppletManager::the().draw(); } void MenuManager::refresh() @@ -256,25 +253,6 @@ void MenuManager::refresh() window().invalidate(); } -void MenuManager::calculate_applet_rects() -{ - dbg() << "Recalculate applet rects." << m_applets.size(); - - auto menubar_rect = m_window->rect(); - int right_edge_x = menubar_rect.width() - 4; - for (auto& existing_applet : m_applets) { - if (!existing_applet) - continue; - - Gfx::Rect new_applet_rect(right_edge_x - existing_applet->size().width(), 0, existing_applet->size().width(), existing_applet->size().height()); - Gfx::Rect dummy_menubar_rect(0, 0, 0, 18); - new_applet_rect.center_vertically_within(dummy_menubar_rect); - - existing_applet->set_rect_in_menubar(new_applet_rect); - right_edge_x = existing_applet->rect_in_menubar().x() - 4; - } -} - void MenuManager::event(Core::Event& event) { if (WindowManager::the().active_window_is_modal()) @@ -291,14 +269,7 @@ void MenuManager::event(Core::Event& event) return IterationDecision::Continue; }); - for (auto& applet : m_applets) { - if (!applet) - continue; - if (!applet->rect_in_menubar().contains(mouse_event.position())) - continue; - auto local_event = mouse_event.translated(-applet->rect_in_menubar().location()); - applet->event(local_event); - } + AppletManager::the().event(event); } if (static_cast(event).is_key_event()) { @@ -460,34 +431,6 @@ void MenuManager::close_bar() m_bar_open = false; } -void MenuManager::add_applet(Window& applet) -{ - m_applets.append(applet.make_weak_ptr()); - calculate_applet_rects(); -} - -void MenuManager::remove_applet(Window& applet) -{ - m_applets.remove_first_matching([&](auto& entry) { - return &applet == entry.ptr(); - }); -} - -void MenuManager::draw_applet(const Window& applet) -{ - if (!applet.backing_store()) - return; - Gfx::Painter painter(*window().backing_store()); - painter.fill_rect(applet.rect_in_menubar(), WindowManager::the().palette().window()); - painter.blit(applet.rect_in_menubar().location(), *applet.backing_store(), applet.backing_store()->rect()); -} - -void MenuManager::invalidate_applet(const Window& applet, const Gfx::Rect& rect) -{ - draw_applet(applet); - window().invalidate(rect.translated(applet.rect_in_menubar().location())); -} - Gfx::Rect MenuManager::menubar_rect() const { return { 0, 0, Screen::the().rect().width(), 18 }; diff --git a/Servers/WindowServer/MenuManager.h b/Servers/WindowServer/MenuManager.h index 8019496352..78c6bc5ab1 100644 --- a/Servers/WindowServer/MenuManager.h +++ b/Servers/WindowServer/MenuManager.h @@ -43,7 +43,6 @@ public: virtual ~MenuManager() override; void refresh(); - void calculate_applet_rects(); virtual void event(Core::Event&) override; @@ -72,15 +71,13 @@ public: void close_all_menus_from_client(Badge, ClientConnection&); - void add_applet(Window&); - void remove_applet(Window&); - void invalidate_applet(const Window&, const Gfx::Rect&); - Color menu_selection_color() const { return m_menu_selection_color; } Menu& system_menu() { return *m_system_menu; } Menu* find_internal_menu_by_id(int); int theme_index() const { return m_theme_index; } + Window& window() { return *m_window; } + template void for_each_active_menubar_menu(Callback callback) { @@ -96,21 +93,17 @@ private: void close_menus(const Vector&); - Window& window() { return *m_window; } const Window& window() const { return *m_window; } void handle_menu_mouse_event(Menu&, const MouseEvent&); void draw(); - void draw_applet(const Window&); RefPtr m_window; WeakPtr m_current_menu; Vector> m_open_menu_stack; - Vector> m_applets; - bool m_needs_window_resize { false }; bool m_bar_open { false }; diff --git a/Servers/WindowServer/WindowManager.cpp b/Servers/WindowServer/WindowManager.cpp index 7ed0204aa1..d3c69330f1 100644 --- a/Servers/WindowServer/WindowManager.cpp +++ b/Servers/WindowServer/WindowManager.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1123,7 +1124,7 @@ void WindowManager::invalidate(const Window& window) void WindowManager::invalidate(const Window& window, const Gfx::Rect& rect) { if (window.type() == WindowType::MenuApplet) { - MenuManager::the().invalidate_applet(window, rect); + AppletManager::the().invalidate_applet(window, rect); return; } diff --git a/Servers/WindowServer/main.cpp b/Servers/WindowServer/main.cpp index e92e618d33..935cc0d7e9 100644 --- a/Servers/WindowServer/main.cpp +++ b/Servers/WindowServer/main.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "AppletManager.h" #include "Compositor.h" #include "EventLoop.h" #include "Screen.h" @@ -98,6 +99,7 @@ int main(int, char**) wm_config->read_num_entry("Screen", "Height", 768)); WindowServer::Compositor::the(); auto wm = WindowServer::WindowManager::construct(*palette); + auto am = WindowServer::AppletManager::construct(); auto mm = WindowServer::MenuManager::construct(); if (unveil("/tmp", "") < 0) {