diff --git a/Base/etc/SystemServer.ini b/Base/etc/SystemServer.ini index 342c67a6d40..f46923f0fde 100644 --- a/Base/etc/SystemServer.ini +++ b/Base/etc/SystemServer.ini @@ -28,6 +28,10 @@ User=anon KeepAlive=1 User=anon +[Audio.MenuApplet] +KeepAlive=1 +User=anon + [AudioServer] Socket=/tmp/portal/audio # TODO: we may want to start it lazily, but right now WindowServer connects to it immediately on startup diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh index 769d0ca5df7..d9a6f34e44c 100755 --- a/Kernel/build-root-filesystem.sh +++ b/Kernel/build-root-filesystem.sh @@ -109,6 +109,7 @@ cp ../Servers/TTYServer/TTYServer mnt/bin/TTYServer cp ../Servers/TelnetServer/TelnetServer mnt/bin/TelnetServer cp ../Servers/ProtocolServer/ProtocolServer mnt/bin/ProtocolServer cp ../Shell/Shell mnt/bin/Shell +cp ../MenuApplets/Audio/Audio.MenuApplet mnt/bin/ cp ../MenuApplets/CPUGraph/CPUGraph.MenuApplet mnt/bin/ echo "done" diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index d0d88792512..d89464eb367 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -93,6 +93,7 @@ build_targets="$build_targets ../Shell" build_targets="$build_targets ../Userland" +build_targets="$build_targets ../MenuApplets/Audio" build_targets="$build_targets ../MenuApplets/CPUGraph" build_targets="$build_targets ." # the kernel diff --git a/MenuApplets/Audio/Audio.MenuApplet b/MenuApplets/Audio/Audio.MenuApplet new file mode 100755 index 00000000000..dd4c89fcf98 Binary files /dev/null and b/MenuApplets/Audio/Audio.MenuApplet differ diff --git a/MenuApplets/Audio/Makefile b/MenuApplets/Audio/Makefile new file mode 100755 index 00000000000..cd0292e1ef7 --- /dev/null +++ b/MenuApplets/Audio/Makefile @@ -0,0 +1,7 @@ +include ../../Makefile.common + +OBJS = main.o + +APP = Audio.MenuApplet + +include ../Makefile.common diff --git a/MenuApplets/Audio/main.cpp b/MenuApplets/Audio/main.cpp new file mode 100644 index 00000000000..bbd55f750ce --- /dev/null +++ b/MenuApplets/Audio/main.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +class AudioWidget final : public GWidget { + C_OBJECT(AudioWidget) +public: + AudioWidget() + : GWidget(nullptr) + { + m_audio_client = make(); + m_audio_client->on_muted_state_change = [this](bool muted) { + dbg() << "Muted state changed: " << muted; + if (m_audio_muted == muted) + return; + m_audio_muted = muted; + update(); + }; + m_unmuted_bitmap = GraphicsBitmap::load_from_file("/res/icons/audio-unmuted.png"); + m_muted_bitmap = GraphicsBitmap::load_from_file("/res/icons/audio-muted.png"); + } + + virtual ~AudioWidget() override {} + +private: + virtual void mousedown_event(GMouseEvent& event) override + { + if (event.button() != GMouseButton::Left) + return; + dbg() << "set_muted: " << !m_audio_muted; + m_audio_client->set_muted(!m_audio_muted); + update(); + } + + virtual void paint_event(GPaintEvent& event) override + { + GPainter painter(*this); + painter.add_clip_rect(event.rect()); + painter.clear_rect(event.rect(), Color::from_rgba(0)); + auto& audio_bitmap = m_audio_muted ? *m_muted_bitmap : *m_unmuted_bitmap; + painter.blit({}, audio_bitmap, audio_bitmap.rect()); + } + + OwnPtr m_audio_client; + RefPtr m_muted_bitmap; + RefPtr m_unmuted_bitmap; + bool m_audio_muted { false }; +}; + +int main(int argc, char** argv) +{ + GApplication app(argc, argv); + + auto window = GWindow::construct(); + window->set_has_alpha_channel(true); + window->set_window_type(GWindowType::MenuApplet); + window->resize(12, 16); + + auto widget = AudioWidget::construct(); + window->set_main_widget(widget); + window->show(); + return app.exec(); +} diff --git a/Servers/WindowServer/WSMenuBar.h b/Servers/WindowServer/WSMenuBar.h index c26a3447b02..57dffef118f 100644 --- a/Servers/WindowServer/WSMenuBar.h +++ b/Servers/WindowServer/WSMenuBar.h @@ -23,7 +23,7 @@ public: void for_each_menu(Callback callback) { for (auto& menu : m_menus) { - if (!callback(*menu)) + if (callback(*menu) == IterationDecision::Break) return; } } diff --git a/Servers/WindowServer/WSMenuManager.cpp b/Servers/WindowServer/WSMenuManager.cpp index 730c7e841bc..cccb76782cf 100644 --- a/Servers/WindowServer/WSMenuManager.cpp +++ b/Servers/WindowServer/WSMenuManager.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -10,20 +9,6 @@ WSMenuManager::WSMenuManager() { - m_audio_client = make(); - m_audio_client->on_muted_state_change = [this](bool muted) { - if (m_audio_muted == muted) - return; - m_audio_muted = muted; - if (m_window) { - draw(); - m_window->invalidate(); - } - }; - - m_unmuted_bitmap = GraphicsBitmap::load_from_file("/res/icons/audio-unmuted.png"); - m_muted_bitmap = GraphicsBitmap::load_from_file("/res/icons/audio-muted.png"); - m_username = getlogin(); m_needs_window_resize = true; @@ -71,7 +56,6 @@ void WSMenuManager::draw() menubar_rect.height() }; - int time_width = Font::default_font().width("2222-22-22 22:22:22"); m_time_rect = { m_username_rect.left() - menubar_menu_margin() / 2 - time_width, @@ -80,18 +64,16 @@ void WSMenuManager::draw() menubar_rect.height() }; - m_audio_rect = { m_time_rect.right() - time_width - 20, m_time_rect.y() + 1, 12, 16 }; - - int right_edge_x = m_audio_rect.x() - 4; + int right_edge_x = m_time_rect.left() - 4; for (auto& existing_applet : m_applets) { - if (! existing_applet) + if (!existing_applet) continue; - + Rect new_applet_rect(right_edge_x - existing_applet->size().width(), 0, existing_applet->size().width(), existing_applet->size().height()); 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); + existing_applet->set_rect_in_menubar(new_applet_rect); right_edge_x = existing_applet->rect_in_menubar().x() - 4; } @@ -118,7 +100,7 @@ void WSMenuManager::draw() TextAlignment::CenterLeft, text_color); ++index; - return true; + return IterationDecision::Continue; }); painter.draw_text(m_username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, Color::Black); @@ -133,12 +115,8 @@ void WSMenuManager::draw() tm->tm_min, tm->tm_sec); - painter.draw_text(m_time_rect, time_text, wm.font(), TextAlignment::CenterRight, Color::Black); - auto& audio_bitmap = m_audio_muted ? *m_muted_bitmap : *m_unmuted_bitmap; - painter.blit(m_audio_rect.location(), audio_bitmap, audio_bitmap.rect()); - for (auto& applet : m_applets) { if (!applet) continue; @@ -165,21 +143,23 @@ void WSMenuManager::event(CEvent& event) return CObject::event(event); if (event.type() == WSEvent::MouseMove || event.type() == WSEvent::MouseUp || event.type() == WSEvent::MouseDown || event.type() == WSEvent::MouseWheel) { + auto& mouse_event = static_cast(event); WSWindowManager::the().for_each_active_menubar_menu([&](WSMenu& menu) { if (menu.rect_in_menubar().contains(mouse_event.position())) { handle_menu_mouse_event(menu, mouse_event); - return false; + return IterationDecision::Break; } - return true; + return IterationDecision::Continue; }); - if (mouse_event.type() == WSEvent::MouseDown - && mouse_event.button() == MouseButton::Left - && m_audio_rect.contains(mouse_event.position())) { - m_audio_client->set_muted(!m_audio_muted); - draw(); - m_window->invalidate(); + 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); } } return CObject::event(event); @@ -300,7 +280,7 @@ void WSMenuManager::close_bar() void WSMenuManager::add_applet(WSWindow& applet) { - int right_edge_x = m_audio_rect.x() - 4; + int right_edge_x = m_time_rect.left() - 4; for (auto& existing_applet : m_applets) { if (existing_applet) right_edge_x = existing_applet->rect_in_menubar().x() - 4; diff --git a/Servers/WindowServer/WSMenuManager.h b/Servers/WindowServer/WSMenuManager.h index 740cd3be1a4..24c3adf15e9 100644 --- a/Servers/WindowServer/WSMenuManager.h +++ b/Servers/WindowServer/WSMenuManager.h @@ -58,18 +58,11 @@ private: WeakPtr m_current_menu; Vector> m_open_menu_stack; - RefPtr m_muted_bitmap; - RefPtr m_unmuted_bitmap; - Vector> m_applets; - OwnPtr m_audio_client; - - Rect m_audio_rect; Rect m_username_rect; Rect m_time_rect; bool m_needs_window_resize { false }; bool m_bar_open { false }; - bool m_audio_muted { false }; }; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index ea750907d9f..99498344a84 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -260,7 +260,7 @@ void WSWindowManager::set_current_menubar(WSMenuBar* menubar) menu.set_text_rect_in_menubar({ next_menu_location, { text_width, menubar_rect().height() } }); next_menu_location.move_by(menu.rect_in_menubar().width(), 0); ++index; - return true; + return IterationDecision::Continue; }); m_menu_manager.refresh(); } diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 88e8bc7d874..b7c6531a94f 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -149,7 +149,8 @@ public: template void for_each_active_menubar_menu(Callback callback) { - callback(*m_system_menu); + if (callback(*m_system_menu) == IterationDecision::Break) + return; if (m_current_menubar) m_current_menubar->for_each_menu(callback); }