mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 01:22:43 +00:00 
			
		
		
		
	WindowServer+CPUGraph: Make menu applets be "regular" windows
Instead of implementing menu applets as their own thing, they are now WSWindows of WSWindowType::MenuApplet. This makes it much easier to work with them on the client side, since you can just create a GWindow with the right type and you're in the menubar doing applet stuff :^)
This commit is contained in:
		
							parent
							
								
									648ed76085
								
							
						
					
					
						commit
						df129bbe0e
					
				
					 13 changed files with 97 additions and 202 deletions
				
			
		|  | @ -9,4 +9,5 @@ enum class GWindowType { | ||||||
|     Taskbar, |     Taskbar, | ||||||
|     Tooltip, |     Tooltip, | ||||||
|     Menubar, |     Menubar, | ||||||
|  |     MenuApplet, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -1,87 +1,83 @@ | ||||||
| #include <AK/CircularQueue.h> | #include <AK/CircularQueue.h> | ||||||
| #include <LibCore/CProcessStatisticsReader.h> | #include <LibCore/CProcessStatisticsReader.h> | ||||||
| #include <LibCore/CTimer.h> |  | ||||||
| #include <LibDraw/GraphicsBitmap.h> |  | ||||||
| #include <LibGUI/GApplication.h> | #include <LibGUI/GApplication.h> | ||||||
| #include <LibGUI/GPainter.h> | #include <LibGUI/GPainter.h> | ||||||
| #include <LibGUI/GWindowServerConnection.h> | #include <LibGUI/GWidget.h> | ||||||
|  | #include <LibGUI/GWindow.h> | ||||||
| 
 | 
 | ||||||
| NonnullRefPtr<GraphicsBitmap> create_shared_bitmap(const Size& size) | class GraphWidget final : public GWidget { | ||||||
| { |     C_OBJECT(GraphWidget) | ||||||
|     ASSERT(GWindowServerConnection::the().server_pid()); | public: | ||||||
|     ASSERT(!size.is_empty()); |     GraphWidget() | ||||||
|     size_t pitch = round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16); |         : GWidget(nullptr) | ||||||
|     size_t size_in_bytes = size.height() * pitch; |     { | ||||||
|     auto shared_buffer = SharedBuffer::create_with_size(size_in_bytes); |         start_timer(1000); | ||||||
|     ASSERT(shared_buffer); |     } | ||||||
|     shared_buffer->share_with(GWindowServerConnection::the().server_pid()); |  | ||||||
|     return GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *shared_buffer, size); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| static void get_cpu_usage(unsigned& busy, unsigned& idle) |     virtual ~GraphWidget() override {} | ||||||
| { |  | ||||||
|     busy = 0; |  | ||||||
|     idle = 0; |  | ||||||
| 
 | 
 | ||||||
|     auto all_processes = CProcessStatisticsReader::get_all(); | private: | ||||||
|  |     virtual void timer_event(CTimerEvent&) override | ||||||
|  |     { | ||||||
|  |         unsigned busy; | ||||||
|  |         unsigned idle; | ||||||
|  |         get_cpu_usage(busy, idle); | ||||||
|  |         unsigned busy_diff = busy - m_last_busy; | ||||||
|  |         unsigned idle_diff = idle - m_last_idle; | ||||||
|  |         m_last_busy = busy; | ||||||
|  |         m_last_idle = idle; | ||||||
|  |         float cpu = (float)busy_diff / (float)(busy_diff + idle_diff); | ||||||
|  |         m_cpu_history.enqueue(cpu); | ||||||
|  |         update(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (auto& it : all_processes) { |     virtual void paint_event(GPaintEvent& event) override | ||||||
|         for (auto& jt : it.value.threads) { |     { | ||||||
|             if (it.value.pid == 0) |         GPainter painter(*this); | ||||||
|                 idle += jt.times_scheduled; |         painter.add_clip_rect(event.rect()); | ||||||
|             else |         painter.fill_rect(event.rect(), Color::Black); | ||||||
|                 busy += jt.times_scheduled; |         int i = m_cpu_history.capacity() - m_cpu_history.size(); | ||||||
|  |         for (auto cpu_usage : m_cpu_history) { | ||||||
|  |             painter.draw_line( | ||||||
|  |                 { i, rect().bottom() }, | ||||||
|  |                 { i, (int)(height() - (cpu_usage * (float)height())) }, | ||||||
|  |                 Color::from_rgb(0xaa6d4b)); | ||||||
|  |             ++i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | 
 | ||||||
|  |     static void get_cpu_usage(unsigned& busy, unsigned& idle) | ||||||
|  |     { | ||||||
|  |         busy = 0; | ||||||
|  |         idle = 0; | ||||||
|  | 
 | ||||||
|  |         auto all_processes = CProcessStatisticsReader::get_all(); | ||||||
|  | 
 | ||||||
|  |         for (auto& it : all_processes) { | ||||||
|  |             for (auto& jt : it.value.threads) { | ||||||
|  |                 if (it.value.pid == 0) | ||||||
|  |                     idle += jt.times_scheduled; | ||||||
|  |                 else | ||||||
|  |                     busy += jt.times_scheduled; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     CircularQueue<float, 30> m_cpu_history; | ||||||
|  |     unsigned m_last_busy { 0 }; | ||||||
|  |     unsigned m_last_idle { 0 }; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| int main(int argc, char** argv) | int main(int argc, char** argv) | ||||||
| { | { | ||||||
|     GApplication app(argc, argv); |     GApplication app(argc, argv); | ||||||
| 
 | 
 | ||||||
|     Size applet_size(30, 16); |     auto window = GWindow::construct(); | ||||||
|     Rect applet_rect({}, applet_size); |     window->set_window_type(GWindowType::MenuApplet); | ||||||
| 
 |     window->resize(30, 16); | ||||||
|     CircularQueue<float, 30> cpu_history; |  | ||||||
| 
 |  | ||||||
|     i32 applet_id = GWindowServerConnection::the().send_sync<WindowServer::CreateMenuApplet>(applet_size)->applet_id(); |  | ||||||
|     auto bitmap = create_shared_bitmap(applet_size); |  | ||||||
| 
 |  | ||||||
|     GWindowServerConnection::the().send_sync<WindowServer::SetMenuAppletBackingStore>(applet_id, bitmap->shared_buffer_id()); |  | ||||||
| 
 |  | ||||||
|     unsigned last_busy = 0; |  | ||||||
|     unsigned last_idle = 0; |  | ||||||
| 
 |  | ||||||
|     auto repaint = [&] { |  | ||||||
|         unsigned busy; |  | ||||||
|         unsigned idle; |  | ||||||
|         get_cpu_usage(busy, idle); |  | ||||||
|         unsigned busy_diff = busy - last_busy; |  | ||||||
|         unsigned idle_diff = idle - last_idle; |  | ||||||
|         last_busy = busy; |  | ||||||
|         last_idle = idle; |  | ||||||
|         float cpu = (float)busy_diff / (float)(busy_diff + idle_diff); |  | ||||||
|         cpu_history.enqueue(cpu); |  | ||||||
| 
 |  | ||||||
|         GPainter painter(*bitmap); |  | ||||||
|         painter.fill_rect(applet_rect, Color::Black); |  | ||||||
|         int i = cpu_history.capacity() - cpu_history.size(); |  | ||||||
|         for (auto cpu_usage : cpu_history) { |  | ||||||
|             painter.draw_line( |  | ||||||
|                 { applet_rect.x() + i, applet_rect.bottom() }, |  | ||||||
|                 { applet_rect.x() + i, (int)(applet_rect.y() + (applet_rect.height() - (cpu_usage * (float)applet_rect.height()))) }, |  | ||||||
|                 Color::from_rgb(0xaa6d4b)); |  | ||||||
|             ++i; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         GWindowServerConnection::the().send_sync<WindowServer::InvalidateMenuAppletRect>(applet_id, applet_rect); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     repaint(); |  | ||||||
| 
 |  | ||||||
|     auto timer = CTimer::construct(1000, [&] { |  | ||||||
|         repaint(); |  | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|  |     auto widget = GraphWidget::construct(); | ||||||
|  |     window->set_main_widget(widget); | ||||||
|  |     window->show(); | ||||||
|     return app.exec(); |     return app.exec(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -16,7 +16,6 @@ OBJS = \ | ||||||
|     WSButton.o \
 |     WSButton.o \
 | ||||||
|     WSCompositor.o \
 |     WSCompositor.o \
 | ||||||
|     WSMenuManager.o \
 |     WSMenuManager.o \
 | ||||||
|     WSMenuApplet.o \
 |  | ||||||
|     main.o |     main.o | ||||||
| 
 | 
 | ||||||
| APP = WindowServer | APP = WindowServer | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ | ||||||
| #include <WindowServer/WSCompositor.h> | #include <WindowServer/WSCompositor.h> | ||||||
| #include <WindowServer/WSEventLoop.h> | #include <WindowServer/WSEventLoop.h> | ||||||
| #include <WindowServer/WSMenu.h> | #include <WindowServer/WSMenu.h> | ||||||
| #include <WindowServer/WSMenuApplet.h> |  | ||||||
| #include <WindowServer/WSMenuBar.h> | #include <WindowServer/WSMenuBar.h> | ||||||
| #include <WindowServer/WSMenuItem.h> | #include <WindowServer/WSMenuItem.h> | ||||||
| #include <WindowServer/WSScreen.h> | #include <WindowServer/WSScreen.h> | ||||||
|  | @ -407,6 +406,8 @@ OwnPtr<WindowServer::CreateWindowResponse> WSClientConnection::handle(const Wind | ||||||
|     window->set_size_increment(message.size_increment()); |     window->set_size_increment(message.size_increment()); | ||||||
|     window->set_base_size(message.base_size()); |     window->set_base_size(message.base_size()); | ||||||
|     window->invalidate(); |     window->invalidate(); | ||||||
|  |     if (window->type() == WSWindowType::MenuApplet) | ||||||
|  |         WSWindowManager::the().menu_manager().add_applet(*window); | ||||||
|     m_windows.set(window_id, move(window)); |     m_windows.set(window_id, move(window)); | ||||||
|     return make<WindowServer::CreateWindowResponse>(window_id); |     return make<WindowServer::CreateWindowResponse>(window_id); | ||||||
| } | } | ||||||
|  | @ -419,6 +420,10 @@ OwnPtr<WindowServer::DestroyWindowResponse> WSClientConnection::handle(const Win | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     } |     } | ||||||
|     auto& window = *(*it).value; |     auto& window = *(*it).value; | ||||||
|  | 
 | ||||||
|  |     if (window.type() == WSWindowType::MenuApplet) | ||||||
|  |         WSWindowManager::the().menu_manager().remove_applet(window); | ||||||
|  | 
 | ||||||
|     WSWindowManager::the().invalidate(window); |     WSWindowManager::the().invalidate(window); | ||||||
|     remove_child(window); |     remove_child(window); | ||||||
|     ASSERT(it->value.ptr() == &window); |     ASSERT(it->value.ptr() == &window); | ||||||
|  | @ -629,56 +634,6 @@ void WSClientConnection::handle(const WindowServer::WM_SetWindowTaskbarRect& mes | ||||||
|     window.set_taskbar_rect(message.rect()); |     window.set_taskbar_rect(message.rect()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| OwnPtr<WindowServer::CreateMenuAppletResponse> WSClientConnection::handle(const WindowServer::CreateMenuApplet& message) |  | ||||||
| { |  | ||||||
|     auto applet = make<WSMenuApplet>(message.size()); |  | ||||||
|     auto applet_id = applet->applet_id(); |  | ||||||
|     WSWindowManager::the().menu_manager().add_applet(*applet); |  | ||||||
|     m_menu_applets.set(applet_id, move(applet)); |  | ||||||
|     return make<WindowServer::CreateMenuAppletResponse>(applet_id); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| OwnPtr<WindowServer::DestroyMenuAppletResponse> WSClientConnection::handle(const WindowServer::DestroyMenuApplet& message) |  | ||||||
| { |  | ||||||
|     auto it = m_menu_applets.find(message.applet_id()); |  | ||||||
|     if (it == m_menu_applets.end()) { |  | ||||||
|         did_misbehave("DestroyApplet: Invalid applet ID"); |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     WSWindowManager::the().menu_manager().remove_applet(*it->value); |  | ||||||
|     m_menu_applets.remove(message.applet_id()); |  | ||||||
|     return make<WindowServer::DestroyMenuAppletResponse>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| OwnPtr<WindowServer::SetMenuAppletBackingStoreResponse> WSClientConnection::handle(const WindowServer::SetMenuAppletBackingStore& message) |  | ||||||
| { |  | ||||||
|     auto it = m_menu_applets.find(message.applet_id()); |  | ||||||
|     if (it == m_menu_applets.end()) { |  | ||||||
|         did_misbehave("SetAppletBackingStore: Invalid applet ID"); |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(message.shared_buffer_id()); |  | ||||||
|     ssize_t size_in_bytes = it->value->size().area() * sizeof(RGBA32); |  | ||||||
|     if (size_in_bytes > shared_buffer->size()) { |  | ||||||
|         did_misbehave("SetAppletBackingStore: Shared buffer is too small for applet size"); |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     auto bitmap = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *shared_buffer, it->value->size()); |  | ||||||
|     it->value->set_bitmap(bitmap); |  | ||||||
|     return make<WindowServer::SetMenuAppletBackingStoreResponse>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| OwnPtr<WindowServer::InvalidateMenuAppletRectResponse> WSClientConnection::handle(const WindowServer::InvalidateMenuAppletRect& message) |  | ||||||
| { |  | ||||||
|     auto it = m_menu_applets.find(message.applet_id()); |  | ||||||
|     if (it == m_menu_applets.end()) { |  | ||||||
|         did_misbehave("InvalidateAppletRect: Invalid applet ID"); |  | ||||||
|         return nullptr; |  | ||||||
|     } |  | ||||||
|     it->value->invalidate(message.rect()); |  | ||||||
|     return make<WindowServer::InvalidateMenuAppletRectResponse>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| OwnPtr<WindowServer::StartDragResponse> WSClientConnection::handle(const WindowServer::StartDrag& message) | OwnPtr<WindowServer::StartDragResponse> WSClientConnection::handle(const WindowServer::StartDrag& message) | ||||||
| { | { | ||||||
|     auto& wm = WSWindowManager::the(); |     auto& wm = WSWindowManager::the(); | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ | ||||||
| #include <WindowServer/WSEvent.h> | #include <WindowServer/WSEvent.h> | ||||||
| #include <WindowServer/WindowServerEndpoint.h> | #include <WindowServer/WindowServerEndpoint.h> | ||||||
| 
 | 
 | ||||||
| class WSMenuApplet; |  | ||||||
| class WSWindow; | class WSWindow; | ||||||
| class WSMenu; | class WSMenu; | ||||||
| class WSMenuBar; | class WSMenuBar; | ||||||
|  | @ -88,13 +87,8 @@ private: | ||||||
|     virtual OwnPtr<WindowServer::DismissMenuResponse> handle(const WindowServer::DismissMenu&) override; |     virtual OwnPtr<WindowServer::DismissMenuResponse> handle(const WindowServer::DismissMenu&) override; | ||||||
|     virtual OwnPtr<WindowServer::SetWindowIconBitmapResponse> handle(const WindowServer::SetWindowIconBitmap&) override; |     virtual OwnPtr<WindowServer::SetWindowIconBitmapResponse> handle(const WindowServer::SetWindowIconBitmap&) override; | ||||||
|     virtual void handle(const WindowServer::WM_SetWindowTaskbarRect&) override; |     virtual void handle(const WindowServer::WM_SetWindowTaskbarRect&) override; | ||||||
|     virtual OwnPtr<WindowServer::CreateMenuAppletResponse> handle(const WindowServer::CreateMenuApplet&) override; |  | ||||||
|     virtual OwnPtr<WindowServer::DestroyMenuAppletResponse> handle(const WindowServer::DestroyMenuApplet&) override; |  | ||||||
|     virtual OwnPtr<WindowServer::SetMenuAppletBackingStoreResponse> handle(const WindowServer::SetMenuAppletBackingStore&) override; |  | ||||||
|     virtual OwnPtr<WindowServer::InvalidateMenuAppletRectResponse> handle(const WindowServer::InvalidateMenuAppletRect&) override; |  | ||||||
|     virtual OwnPtr<WindowServer::StartDragResponse> handle(const WindowServer::StartDrag&) override; |     virtual OwnPtr<WindowServer::StartDragResponse> handle(const WindowServer::StartDrag&) override; | ||||||
| 
 | 
 | ||||||
|     HashMap<i32, NonnullOwnPtr<WSMenuApplet>> m_menu_applets; |  | ||||||
|     HashMap<int, NonnullRefPtr<WSWindow>> m_windows; |     HashMap<int, NonnullRefPtr<WSWindow>> m_windows; | ||||||
|     HashMap<int, NonnullOwnPtr<WSMenuBar>> m_menubars; |     HashMap<int, NonnullOwnPtr<WSMenuBar>> m_menubars; | ||||||
|     HashMap<int, NonnullRefPtr<WSMenu>> m_menus; |     HashMap<int, NonnullRefPtr<WSMenu>> m_menus; | ||||||
|  |  | ||||||
|  | @ -1,25 +0,0 @@ | ||||||
| #include <WindowServer/WSMenuApplet.h> |  | ||||||
| #include <WindowServer/WSMenuManager.h> |  | ||||||
| #include <WindowServer/WSWindowManager.h> |  | ||||||
| 
 |  | ||||||
| static i32 s_next_applet_id = 1; |  | ||||||
| 
 |  | ||||||
| WSMenuApplet::WSMenuApplet(const Size& size) |  | ||||||
|     : m_applet_id(s_next_applet_id++) |  | ||||||
|     , m_size(size) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| WSMenuApplet::~WSMenuApplet() |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void WSMenuApplet::set_bitmap(GraphicsBitmap* bitmap) |  | ||||||
| { |  | ||||||
|     m_bitmap = bitmap; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void WSMenuApplet::invalidate(const Rect& rect) |  | ||||||
| { |  | ||||||
|     WSWindowManager::the().menu_manager().invalidate_applet(*this, rect); |  | ||||||
| } |  | ||||||
|  | @ -1,33 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <AK/Noncopyable.h> |  | ||||||
| #include <AK/Weakable.h> |  | ||||||
| #include <LibDraw/Rect.h> |  | ||||||
| #include <LibDraw/Size.h> |  | ||||||
| 
 |  | ||||||
| class GraphicsBitmap; |  | ||||||
| 
 |  | ||||||
| class WSMenuApplet : public Weakable<WSMenuApplet> { |  | ||||||
|     AK_MAKE_NONCOPYABLE(WSMenuApplet) |  | ||||||
|     AK_MAKE_NONMOVABLE(WSMenuApplet) |  | ||||||
| public: |  | ||||||
|     explicit WSMenuApplet(const Size&); |  | ||||||
|     ~WSMenuApplet(); |  | ||||||
| 
 |  | ||||||
|     i32 applet_id() const { return m_applet_id; } |  | ||||||
|     Size size() const { return m_size; } |  | ||||||
| 
 |  | ||||||
|     void set_bitmap(GraphicsBitmap*); |  | ||||||
|     const GraphicsBitmap* bitmap() const { return m_bitmap; } |  | ||||||
| 
 |  | ||||||
|     void invalidate(const Rect&); |  | ||||||
| 
 |  | ||||||
|     const Rect& rect_in_menubar() const { return m_rect_in_menubar; } |  | ||||||
|     void set_rect_in_menubar(const Rect& rect) { m_rect_in_menubar = rect; } |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     i32 m_applet_id { -1 }; |  | ||||||
|     Size m_size; |  | ||||||
|     Rect m_rect_in_menubar; |  | ||||||
|     RefPtr<GraphicsBitmap> m_bitmap; |  | ||||||
| }; |  | ||||||
|  | @ -298,7 +298,7 @@ void WSMenuManager::close_bar() | ||||||
|     m_bar_open = false; |     m_bar_open = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSMenuManager::add_applet(WSMenuApplet& applet) | void WSMenuManager::add_applet(WSWindow& applet) | ||||||
| { | { | ||||||
|     int right_edge_x = m_audio_rect.x() - 4; |     int right_edge_x = m_audio_rect.x() - 4; | ||||||
|     for (auto& existing_applet : m_applets) { |     for (auto& existing_applet : m_applets) { | ||||||
|  | @ -314,22 +314,22 @@ void WSMenuManager::add_applet(WSMenuApplet& applet) | ||||||
|     m_applets.append(applet.make_weak_ptr()); |     m_applets.append(applet.make_weak_ptr()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSMenuManager::remove_applet(WSMenuApplet& applet) | void WSMenuManager::remove_applet(WSWindow& applet) | ||||||
| { | { | ||||||
|     m_applets.remove_first_matching([&](auto& entry) { |     m_applets.remove_first_matching([&](auto& entry) { | ||||||
|         return &applet == entry.ptr(); |         return &applet == entry.ptr(); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSMenuManager::draw_applet(const WSMenuApplet& applet) | void WSMenuManager::draw_applet(const WSWindow& applet) | ||||||
| { | { | ||||||
|     if (!applet.bitmap()) |     if (!applet.backing_store()) | ||||||
|         return; |         return; | ||||||
|     Painter painter(*window().backing_store()); |     Painter painter(*window().backing_store()); | ||||||
|     painter.blit(applet.rect_in_menubar().location(), *applet.bitmap(), applet.bitmap()->rect()); |     painter.blit(applet.rect_in_menubar().location(), *applet.backing_store(), applet.backing_store()->rect()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSMenuManager::invalidate_applet(WSMenuApplet& applet, const Rect& rect) | void WSMenuManager::invalidate_applet(const WSWindow& applet, const Rect& rect) | ||||||
| { | { | ||||||
|     // FIXME: This should only invalidate the applet's own rect, not the whole menubar.
 |     // FIXME: This should only invalidate the applet's own rect, not the whole menubar.
 | ||||||
|     (void)rect; |     (void)rect; | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| #include "WSMenu.h" | #include "WSMenu.h" | ||||||
| #include <LibCore/CObject.h> | #include <LibCore/CObject.h> | ||||||
| #include <LibCore/CTimer.h> | #include <LibCore/CTimer.h> | ||||||
| #include <WindowServer/WSMenuApplet.h> |  | ||||||
| #include <WindowServer/WSWindow.h> | #include <WindowServer/WSWindow.h> | ||||||
| 
 | 
 | ||||||
| class AClientConnection; | class AClientConnection; | ||||||
|  | @ -36,9 +35,9 @@ public: | ||||||
|     void close_everyone_not_in_lineage(WSMenu&); |     void close_everyone_not_in_lineage(WSMenu&); | ||||||
|     void close_menu_and_descendants(WSMenu&); |     void close_menu_and_descendants(WSMenu&); | ||||||
| 
 | 
 | ||||||
|     void add_applet(WSMenuApplet&); |     void add_applet(WSWindow&); | ||||||
|     void remove_applet(WSMenuApplet&); |     void remove_applet(WSWindow&); | ||||||
|     void invalidate_applet(WSMenuApplet&, const Rect&); |     void invalidate_applet(const WSWindow&, const Rect&); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void close_menus(const Vector<WSMenu*>&); |     void close_menus(const Vector<WSMenu*>&); | ||||||
|  | @ -49,7 +48,7 @@ private: | ||||||
|     void handle_menu_mouse_event(WSMenu&, const WSMouseEvent&); |     void handle_menu_mouse_event(WSMenu&, const WSMouseEvent&); | ||||||
| 
 | 
 | ||||||
|     void draw(); |     void draw(); | ||||||
|     void draw_applet(const WSMenuApplet&); |     void draw_applet(const WSWindow&); | ||||||
|     void tick_clock(); |     void tick_clock(); | ||||||
| 
 | 
 | ||||||
|     RefPtr<WSWindow> m_window; |     RefPtr<WSWindow> m_window; | ||||||
|  | @ -62,7 +61,7 @@ private: | ||||||
|     RefPtr<GraphicsBitmap> m_muted_bitmap; |     RefPtr<GraphicsBitmap> m_muted_bitmap; | ||||||
|     RefPtr<GraphicsBitmap> m_unmuted_bitmap; |     RefPtr<GraphicsBitmap> m_unmuted_bitmap; | ||||||
| 
 | 
 | ||||||
|     Vector<WeakPtr<WSMenuApplet>> m_applets; |     Vector<WeakPtr<WSWindow>> m_applets; | ||||||
| 
 | 
 | ||||||
|     OwnPtr<AClientConnection> m_audio_client; |     OwnPtr<AClientConnection> m_audio_client; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -118,12 +118,19 @@ public: | ||||||
| 
 | 
 | ||||||
|     virtual void event(CEvent&) override; |     virtual void event(CEvent&) override; | ||||||
| 
 | 
 | ||||||
|  |     // Only used by WSWindowType::MenuApplet. Perhaps it could be a WSWindow subclass? I don't know.
 | ||||||
|  |     void set_rect_in_menubar(const Rect& rect) { m_rect_in_menubar = rect; } | ||||||
|  |     const Rect& rect_in_menubar() const { return m_rect_in_menubar; } | ||||||
|  | 
 | ||||||
|  |     const GraphicsBitmap* backing_store() const { return m_backing_store.ptr(); } | ||||||
|     GraphicsBitmap* backing_store() { return m_backing_store.ptr(); } |     GraphicsBitmap* backing_store() { return m_backing_store.ptr(); } | ||||||
|  | 
 | ||||||
|     void set_backing_store(RefPtr<GraphicsBitmap>&& backing_store) |     void set_backing_store(RefPtr<GraphicsBitmap>&& backing_store) | ||||||
|     { |     { | ||||||
|         m_last_backing_store = move(m_backing_store); |         m_last_backing_store = move(m_backing_store); | ||||||
|         m_backing_store = move(backing_store); |         m_backing_store = move(backing_store); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     void swap_backing_stores() |     void swap_backing_stores() | ||||||
|     { |     { | ||||||
|         swap(m_backing_store, m_last_backing_store); |         swap(m_backing_store, m_last_backing_store); | ||||||
|  | @ -200,6 +207,7 @@ private: | ||||||
|     unsigned m_wm_event_mask { 0 }; |     unsigned m_wm_event_mask { 0 }; | ||||||
|     DisjointRectSet m_pending_paint_rects; |     DisjointRectSet m_pending_paint_rects; | ||||||
|     Rect m_unmaximized_rect; |     Rect m_unmaximized_rect; | ||||||
|  |     Rect m_rect_in_menubar; | ||||||
|     RefPtr<WSMenu> m_window_menu; |     RefPtr<WSMenu> m_window_menu; | ||||||
|     int m_minimize_animation_step { -1 }; |     int m_minimize_animation_step { -1 }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -1072,6 +1072,11 @@ void WSWindowManager::invalidate(const WSWindow& window) | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::invalidate(const WSWindow& window, const Rect& rect) | void WSWindowManager::invalidate(const WSWindow& window, const Rect& rect) | ||||||
| { | { | ||||||
|  |     if (window.type() == WSWindowType::MenuApplet) { | ||||||
|  |         menu_manager().invalidate_applet(window, rect); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (rect.is_empty()) { |     if (rect.is_empty()) { | ||||||
|         invalidate(window); |         invalidate(window); | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|  | @ -9,4 +9,5 @@ enum class WSWindowType { | ||||||
|     Taskbar, |     Taskbar, | ||||||
|     Tooltip, |     Tooltip, | ||||||
|     Menubar, |     Menubar, | ||||||
|  |     MenuApplet, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -16,11 +16,6 @@ endpoint WindowServer = 2 | ||||||
| 
 | 
 | ||||||
|     UpdateMenuItem(i32 menu_id, i32 identifier, i32 submenu_id, String text, bool enabled, bool checkable, bool checked, String shortcut) => () |     UpdateMenuItem(i32 menu_id, i32 identifier, i32 submenu_id, String text, bool enabled, bool checkable, bool checked, String shortcut) => () | ||||||
| 
 | 
 | ||||||
|     CreateMenuApplet(Size size) => (i32 applet_id) |  | ||||||
|     DestroyMenuApplet(i32 applet_id) => () |  | ||||||
|     SetMenuAppletBackingStore(i32 applet_id, i32 shared_buffer_id) => () |  | ||||||
|     InvalidateMenuAppletRect(i32 applet_id, Rect rect) => () |  | ||||||
| 
 |  | ||||||
|     CreateWindow( |     CreateWindow( | ||||||
|         Rect rect, |         Rect rect, | ||||||
|         bool has_alpha_channel, |         bool has_alpha_channel, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling