diff --git a/Base/res/icons/audio-muted.png b/Base/res/icons/audio-muted.png new file mode 100644 index 0000000000..6b4cde9546 Binary files /dev/null and b/Base/res/icons/audio-muted.png differ diff --git a/Base/res/icons/audio-unmuted.png b/Base/res/icons/audio-unmuted.png new file mode 100644 index 0000000000..fd512d6ea7 Binary files /dev/null and b/Base/res/icons/audio-unmuted.png differ diff --git a/Servers/WindowServer/Makefile b/Servers/WindowServer/Makefile index 4f88b53189..da66886329 100644 --- a/Servers/WindowServer/Makefile +++ b/Servers/WindowServer/Makefile @@ -26,7 +26,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread -lpthread + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread -lpthread -laudio -lipc .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Servers/WindowServer/WSMenuManager.cpp b/Servers/WindowServer/WSMenuManager.cpp index efae9eb5fa..1a8526ed24 100644 --- a/Servers/WindowServer/WSMenuManager.cpp +++ b/Servers/WindowServer/WSMenuManager.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,6 +9,11 @@ WSMenuManager::WSMenuManager() { + m_audio_client = make(); + + 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 = false; @@ -74,6 +80,8 @@ void WSMenuManager::draw() }); int username_width = Font::default_bold_font().width(m_username); + + // FIXME: This rect should only be computed once. Rect username_rect { menubar_rect.right() - wm.menubar_menu_margin() / 2 - Font::default_bold_font().width(m_username), menubar_rect.y(), @@ -92,6 +100,8 @@ void WSMenuManager::draw() tm->tm_min, tm->tm_sec); int time_width = wm.font().width(time_text); + + // FIXME: This rect should only be computed once. Rect time_rect { username_rect.left() - wm.menubar_menu_margin() / 2 - time_width, menubar_rect.y(), @@ -101,8 +111,15 @@ void WSMenuManager::draw() painter.draw_text(time_rect, time_text, wm.font(), TextAlignment::CenterRight, Color::Black); + // FIXME: This rect should only be computed once. 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); + + // FIXME: This rect should only be computed once. + m_audio_rect = { cpu_rect.left() - 20, cpu_rect.y(), 12, 16 }; + + auto& audio_bitmap = m_audio_muted ? *m_muted_bitmap : *m_unmuted_bitmap; + painter.blit(m_audio_rect.location(), audio_bitmap, audio_bitmap.rect()); } void WSMenuManager::tick_clock() @@ -132,6 +149,18 @@ void WSMenuManager::event(CEvent& event) } return true; }); + + if (mouse_event.type() == WSEvent::MouseDown + && mouse_event.button() == MouseButton::Left + && m_audio_rect.contains(mouse_event.position())) { + + // FIXME: This should listen for notifications from the AudioServer, once those actually exist. + // Right now, we won't notice if another program changes the AudioServer muted state. + m_audio_muted = !m_audio_muted; + m_audio_client->set_muted(m_audio_muted); + draw(); + m_window->invalidate(); + } } return CObject::event(event); } diff --git a/Servers/WindowServer/WSMenuManager.h b/Servers/WindowServer/WSMenuManager.h index 2ae7e492ae..4c65d85402 100644 --- a/Servers/WindowServer/WSMenuManager.h +++ b/Servers/WindowServer/WSMenuManager.h @@ -6,6 +6,8 @@ #include #include +class AClientConnection; + class WSMenuManager final : public CObject { C_OBJECT(WSMenuManager) public: @@ -50,6 +52,14 @@ private: WeakPtr m_current_menu; Vector> m_open_menu_stack; + RefPtr m_muted_bitmap; + RefPtr m_unmuted_bitmap; + + OwnPtr m_audio_client; + + Rect m_audio_rect; + bool m_needs_window_resize { false }; bool m_bar_open { false }; + bool m_audio_muted { false }; };