mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	WindowServer: Let the window switcher render itself as a WSWindow.
Much better than drawing directly into the back buffer.
This commit is contained in:
		
							parent
							
								
									f3ff402cf3
								
							
						
					
					
						commit
						b85fe0bd07
					
				
					 8 changed files with 89 additions and 59 deletions
				
			
		|  | @ -69,7 +69,7 @@ WSWindow& WSMenu::ensure_menu_window() | ||||||
|             next_item_location.move_by(0, height); |             next_item_location.move_by(0, height); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         auto window = make<WSWindow>(*this); |         auto window = make<WSWindow>(*this, WSWindowType::Menu); | ||||||
|         window->set_opacity(0.95f); |         window->set_opacity(0.95f); | ||||||
|         window->set_rect(0, 0, width(), height()); |         window->set_rect(0, 0, width(), height()); | ||||||
|         m_menu_window = move(window); |         m_menu_window = move(window); | ||||||
|  | @ -107,7 +107,7 @@ void WSMenu::draw() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSMenu::on_window_message(WSMessage& message) | void WSMenu::on_message(WSMessage& message) | ||||||
| { | { | ||||||
|     ASSERT(menu_window()); |     ASSERT(menu_window()); | ||||||
|     if (message.type() == WSMessage::MouseMove) { |     if (message.type() == WSMessage::MouseMove) { | ||||||
|  |  | ||||||
|  | @ -4,7 +4,8 @@ | ||||||
| #include <AK/Vector.h> | #include <AK/Vector.h> | ||||||
| #include <AK/WeakPtr.h> | #include <AK/WeakPtr.h> | ||||||
| #include <SharedGraphics/Rect.h> | #include <SharedGraphics/Rect.h> | ||||||
| #include "WSMenuItem.h" | #include <WindowServer/WSMenuItem.h> | ||||||
|  | #include <WindowServer/WSMessageReceiver.h> | ||||||
| 
 | 
 | ||||||
| class WSClientConnection; | class WSClientConnection; | ||||||
| class WSMenuBar; | class WSMenuBar; | ||||||
|  | @ -12,10 +13,10 @@ class WSMessage; | ||||||
| class WSWindow; | class WSWindow; | ||||||
| class Font; | class Font; | ||||||
| 
 | 
 | ||||||
| class WSMenu : public Weakable<WSMenu> { | class WSMenu final : public WSMessageReceiver { | ||||||
| public: | public: | ||||||
|     WSMenu(WSClientConnection*, int menu_id, String&& name); |     WSMenu(WSClientConnection*, int menu_id, String&& name); | ||||||
|     ~WSMenu(); |     virtual ~WSMenu() override; | ||||||
| 
 | 
 | ||||||
|     WSClientConnection* client() { return m_client; } |     WSClientConnection* client() { return m_client; } | ||||||
|     const WSClientConnection* client() const { return m_client; } |     const WSClientConnection* client() const { return m_client; } | ||||||
|  | @ -58,7 +59,6 @@ public: | ||||||
|     int left_padding() const { return 14; } |     int left_padding() const { return 14; } | ||||||
|     int right_padding() const { return 14; } |     int right_padding() const { return 14; } | ||||||
| 
 | 
 | ||||||
|     void on_window_message(WSMessage&); |  | ||||||
|     void draw(); |     void draw(); | ||||||
|     const Font& font() const; |     const Font& font() const; | ||||||
| 
 | 
 | ||||||
|  | @ -73,6 +73,8 @@ public: | ||||||
|     void close(); |     void close(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     virtual void on_message(WSMessage&) override; | ||||||
|  | 
 | ||||||
|     int padding_between_text_and_shortcut() const { return 50; } |     int padding_between_text_and_shortcut() const { return 50; } | ||||||
|     void did_activate(WSMenuItem&); |     void did_activate(WSMenuItem&); | ||||||
|     WSClientConnection* m_client { nullptr }; |     WSClientConnection* m_client { nullptr }; | ||||||
|  |  | ||||||
|  | @ -5,9 +5,9 @@ | ||||||
| #include <WindowServer/WSAPITypes.h> | #include <WindowServer/WSAPITypes.h> | ||||||
| #include <WindowServer/WSClientConnection.h> | #include <WindowServer/WSClientConnection.h> | ||||||
| 
 | 
 | ||||||
| WSWindow::WSWindow(WSMenu& menu) | WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type) | ||||||
|     : m_type(WSWindowType::Menu) |     : m_internal_owner(&internal_owner) | ||||||
|     , m_menu(&menu) |     , m_type(type) | ||||||
| { | { | ||||||
|     WSWindowManager::the().add_window(*this); |     WSWindowManager::the().add_window(*this); | ||||||
| } | } | ||||||
|  | @ -36,12 +36,11 @@ void WSWindow::set_title(String&& title) | ||||||
| void WSWindow::set_rect(const Rect& rect) | void WSWindow::set_rect(const Rect& rect) | ||||||
| { | { | ||||||
|     Rect old_rect; |     Rect old_rect; | ||||||
|     ASSERT(m_client || m_menu); |  | ||||||
|     if (m_rect == rect) |     if (m_rect == rect) | ||||||
|         return; |         return; | ||||||
|     old_rect = m_rect; |     old_rect = m_rect; | ||||||
|     m_rect = rect; |     m_rect = rect; | ||||||
|     if (m_menu && (!m_backing_store || old_rect.size() != rect.size())) { |     if (!m_client && (!m_backing_store || old_rect.size() != rect.size())) { | ||||||
|         m_backing_store = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size()); |         m_backing_store = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size()); | ||||||
|     } |     } | ||||||
|     WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); |     WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); | ||||||
|  | @ -61,10 +60,8 @@ static WSAPI_MouseButton to_api(MouseButton button) | ||||||
| 
 | 
 | ||||||
| void WSWindow::on_message(WSMessage& message) | void WSWindow::on_message(WSMessage& message) | ||||||
| { | { | ||||||
|     if (m_menu) { |     if (m_internal_owner) | ||||||
|         m_menu->on_window_message(message); |         return m_internal_owner->on_message(message); | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     WSAPI_ServerMessage server_message; |     WSAPI_ServerMessage server_message; | ||||||
|     server_message.window_id = window_id(); |     server_message.window_id = window_id(); | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ class WSMenu; | ||||||
| class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> { | class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> { | ||||||
| public: | public: | ||||||
|     WSWindow(WSClientConnection&, int window_id); |     WSWindow(WSClientConnection&, int window_id); | ||||||
|     explicit WSWindow(WSMenu&); |     WSWindow(WSMessageReceiver&, WSWindowType); | ||||||
|     virtual ~WSWindow() override; |     virtual ~WSWindow() override; | ||||||
| 
 | 
 | ||||||
|     WSClientConnection* client() { return m_client; } |     WSClientConnection* client() { return m_client; } | ||||||
|  | @ -85,6 +85,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     WSClientConnection* m_client { nullptr }; |     WSClientConnection* m_client { nullptr }; | ||||||
|  |     WSMessageReceiver* m_internal_owner { nullptr }; | ||||||
|     String m_title; |     String m_title; | ||||||
|     Rect m_rect; |     Rect m_rect; | ||||||
|     WSWindowType m_type { WSWindowType::Normal }; |     WSWindowType m_type { WSWindowType::Normal }; | ||||||
|  | @ -92,7 +93,6 @@ private: | ||||||
|     bool m_visible { true }; |     bool m_visible { true }; | ||||||
|     bool m_has_alpha_channel { false }; |     bool m_has_alpha_channel { false }; | ||||||
|     bool m_has_painted_since_last_resize { false }; |     bool m_has_painted_since_last_resize { false }; | ||||||
|     WSMenu* m_menu { nullptr }; |  | ||||||
|     RetainPtr<GraphicsBitmap> m_backing_store; |     RetainPtr<GraphicsBitmap> m_backing_store; | ||||||
|     int m_window_id { -1 }; |     int m_window_id { -1 }; | ||||||
|     float m_opacity { 1 }; |     float m_opacity { 1 }; | ||||||
|  |  | ||||||
|  | @ -82,6 +82,16 @@ static inline Rect outer_window_rect(const Rect& window) | ||||||
|     return rect; |     return rect; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline Rect outer_window_rect(const WSWindow& window) | ||||||
|  | { | ||||||
|  |     if (window.type() == WSWindowType::Menu) | ||||||
|  |         return menu_window_rect(window.rect()); | ||||||
|  |     if (window.type() == WSWindowType::WindowSwitcher) | ||||||
|  |         return window.rect(); | ||||||
|  |     ASSERT(window.type() == WSWindowType::Normal); | ||||||
|  |     return outer_window_rect(window.rect()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static WSWindowManager* s_the; | static WSWindowManager* s_the; | ||||||
| 
 | 
 | ||||||
| WSWindowManager& WSWindowManager::the() | WSWindowManager& WSWindowManager::the() | ||||||
|  | @ -384,9 +394,12 @@ void WSWindowManager::paint_window_frame(WSWindow& window) | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (window.type() == WSWindowType::WindowSwitcher) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     auto titlebar_rect = title_bar_rect(window.rect()); |     auto titlebar_rect = title_bar_rect(window.rect()); | ||||||
|     auto titlebar_inner_rect = title_bar_text_rect(window.rect()); |     auto titlebar_inner_rect = title_bar_text_rect(window.rect()); | ||||||
|     auto outer_rect = outer_window_rect(window.rect()); |     auto outer_rect = outer_window_rect(window); | ||||||
|     auto border_rect = border_window_rect(window.rect()); |     auto border_rect = border_window_rect(window.rect()); | ||||||
|     auto close_button_rect = close_button_rect_for_window(window.rect()); |     auto close_button_rect = close_button_rect_for_window(window.rect()); | ||||||
| 
 | 
 | ||||||
|  | @ -466,8 +479,8 @@ void WSWindowManager::add_window(WSWindow& window) | ||||||
|     m_windows_in_order.append(&window); |     m_windows_in_order.append(&window); | ||||||
|     if (!active_window()) |     if (!active_window()) | ||||||
|         set_active_window(&window); |         set_active_window(&window); | ||||||
|     if (m_switcher.is_visible()) |     if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) | ||||||
|         m_switcher.invalidate(); |         m_switcher.refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::move_to_front(WSWindow& window) | void WSWindowManager::move_to_front(WSWindow& window) | ||||||
|  | @ -488,25 +501,25 @@ void WSWindowManager::remove_window(WSWindow& window) | ||||||
|     m_windows_in_order.remove(&window); |     m_windows_in_order.remove(&window); | ||||||
|     if (!active_window() && !m_windows.is_empty()) |     if (!active_window() && !m_windows.is_empty()) | ||||||
|         set_active_window(*m_windows.begin()); |         set_active_window(*m_windows.begin()); | ||||||
|     if (m_switcher.is_visible()) |     if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) | ||||||
|         m_switcher.invalidate(); |         m_switcher.refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::notify_title_changed(WSWindow& window) | void WSWindowManager::notify_title_changed(WSWindow& window) | ||||||
| { | { | ||||||
|     printf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); |     dbgprintf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); | ||||||
|     invalidate(outer_window_rect(window.rect())); |     invalidate(outer_window_rect(window)); | ||||||
|     if (m_switcher.is_visible()) |     if (m_switcher.is_visible()) | ||||||
|         m_switcher.invalidate(); |         m_switcher.refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect, const Rect& new_rect) | void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect, const Rect& new_rect) | ||||||
| { | { | ||||||
|     printf("[WM] WSWindow %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", &window, old_rect.x(), old_rect.y(), old_rect.width(), old_rect.height(), new_rect.x(), new_rect.y(), new_rect.width(), new_rect.height()); |     dbgprintf("[WM] WSWindow %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", &window, old_rect.x(), old_rect.y(), old_rect.width(), old_rect.height(), new_rect.x(), new_rect.y(), new_rect.width(), new_rect.height()); | ||||||
|     invalidate(outer_window_rect(old_rect)); |     invalidate(outer_window_rect(old_rect)); | ||||||
|     invalidate(outer_window_rect(new_rect)); |     invalidate(outer_window_rect(new_rect)); | ||||||
|     if (m_switcher.is_visible()) |     if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) | ||||||
|         m_switcher.invalidate(); |         m_switcher.refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event) | void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, WSMouseEvent& event) | ||||||
|  | @ -578,7 +591,7 @@ void WSWindowManager::start_window_resize(WSWindow& window, WSMouseEvent& event) | ||||||
|         { ResizeDirection::Left, ResizeDirection::None, ResizeDirection::Right }, |         { ResizeDirection::Left, ResizeDirection::None, ResizeDirection::Right }, | ||||||
|         { ResizeDirection::DownLeft, ResizeDirection::Down, ResizeDirection::DownRight }, |         { ResizeDirection::DownLeft, ResizeDirection::Down, ResizeDirection::DownRight }, | ||||||
|     }; |     }; | ||||||
|     Rect outer_rect = outer_window_rect(window.rect()); |     Rect outer_rect = outer_window_rect(window); | ||||||
|     ASSERT(outer_rect.contains(event.position())); |     ASSERT(outer_rect.contains(event.position())); | ||||||
|     int window_relative_x = event.x() - outer_rect.x(); |     int window_relative_x = event.x() - outer_rect.x(); | ||||||
|     int window_relative_y = event.y() - outer_rect.y(); |     int window_relative_y = event.y() - outer_rect.y(); | ||||||
|  | @ -752,7 +765,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for_each_visible_window_from_front_to_back([&] (WSWindow& window) { |     for_each_visible_window_from_front_to_back([&] (WSWindow& window) { | ||||||
|         if (window.type() != WSWindowType::Menu && outer_window_rect(window.rect()).contains(event.position())) { |         if (window.type() == WSWindowType::Normal && outer_window_rect(window).contains(event.position())) { | ||||||
|             if (m_keyboard_modifiers == Mod_Logo && event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) { |             if (m_keyboard_modifiers == Mod_Logo && event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) { | ||||||
|                 start_window_drag(window, event); |                 start_window_drag(window, event); | ||||||
|                 return IterationDecision::Abort; |                 return IterationDecision::Abort; | ||||||
|  | @ -762,7 +775,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ | ||||||
|                 return IterationDecision::Abort; |                 return IterationDecision::Abort; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (window.type() != WSWindowType::Menu && title_bar_rect(window.rect()).contains(event.position())) { |         if (window.type() == WSWindowType::Normal && title_bar_rect(window.rect()).contains(event.position())) { | ||||||
|             if (event.type() == WSMessage::MouseDown) { |             if (event.type() == WSMessage::MouseDown) { | ||||||
|                 move_to_front(window); |                 move_to_front(window); | ||||||
|                 set_active_window(&window); |                 set_active_window(&window); | ||||||
|  | @ -777,7 +790,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (window.rect().contains(event.position())) { |         if (window.rect().contains(event.position())) { | ||||||
|             if (window.type() != WSWindowType::Menu && event.type() == WSMessage::MouseDown) { |             if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown) { | ||||||
|                 move_to_front(window); |                 move_to_front(window); | ||||||
|                 set_active_window(&window); |                 set_active_window(&window); | ||||||
|             } |             } | ||||||
|  | @ -815,14 +828,14 @@ void WSWindowManager::compose() | ||||||
|                 //        Maybe there's some way we could know this?
 |                 //        Maybe there's some way we could know this?
 | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             if (outer_window_rect(window->rect()).contains(r)) |             if (outer_window_rect(*window).contains(r)) | ||||||
|                 return true; |                 return true; | ||||||
|         } |         } | ||||||
|         return false; |         return false; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     auto any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) { |     auto any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) { | ||||||
|         auto window_rect = outer_window_rect(window.rect()); |         auto window_rect = outer_window_rect(window); | ||||||
|         for (auto& dirty_rect : dirty_rects.rects()) { |         for (auto& dirty_rect : dirty_rects.rects()) { | ||||||
|             if (dirty_rect.intersects(window_rect)) |             if (dirty_rect.intersects(window_rect)) | ||||||
|                 return true; |                 return true; | ||||||
|  | @ -876,7 +889,9 @@ void WSWindowManager::compose() | ||||||
|         compose_window(*m_highlight_window); |         compose_window(*m_highlight_window); | ||||||
| 
 | 
 | ||||||
|     draw_menubar(); |     draw_menubar(); | ||||||
|     draw_window_switcher(); |     if (m_switcher.is_visible()) | ||||||
|  |         compose_window(*m_switcher.switcher_window()); | ||||||
|  | 
 | ||||||
|     draw_cursor(); |     draw_cursor(); | ||||||
| 
 | 
 | ||||||
|     if (m_flash_flush) { |     if (m_flash_flush) { | ||||||
|  | @ -949,7 +964,7 @@ void WSWindowManager::draw_menubar() | ||||||
| void WSWindowManager::draw_window_switcher() | void WSWindowManager::draw_window_switcher() | ||||||
| { | { | ||||||
|     if (m_switcher.is_visible()) |     if (m_switcher.is_visible()) | ||||||
|         m_switcher.draw(*m_back_painter); |         m_switcher.draw(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::draw_cursor() | void WSWindowManager::draw_cursor() | ||||||
|  | @ -1009,8 +1024,8 @@ void WSWindowManager::set_highlight_window(WSWindow* window) | ||||||
| 
 | 
 | ||||||
| void WSWindowManager::set_active_window(WSWindow* window) | void WSWindowManager::set_active_window(WSWindow* window) | ||||||
| { | { | ||||||
|     if (window->type() == WSWindowType::Menu) { |     if (window->type() != WSWindowType::Normal) { | ||||||
|         dbgprintf("WSWindowManager: Attempted to make a menu window active.\n"); |         dbgprintf("WSWindowManager: Attempted to make a non-normal window active.\n"); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1079,7 +1094,11 @@ void WSWindowManager::invalidate(const WSWindow& window) | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (window.type() == WSWindowType::Normal) { |     if (window.type() == WSWindowType::Normal) { | ||||||
|         invalidate(outer_window_rect(window.rect())); |         invalidate(outer_window_rect(window)); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (window.type() == WSWindowType::WindowSwitcher) { | ||||||
|  |         invalidate(window.rect()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     ASSERT_NOT_REACHED(); |     ASSERT_NOT_REACHED(); | ||||||
|  | @ -1091,7 +1110,7 @@ void WSWindowManager::invalidate(const WSWindow& window, const Rect& rect) | ||||||
|         invalidate(window); |         invalidate(window); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     auto outer_rect = outer_window_rect(window.rect()); |     auto outer_rect = outer_window_rect(window); | ||||||
|     auto inner_rect = rect; |     auto inner_rect = rect; | ||||||
|     inner_rect.move_by(window.position()); |     inner_rect.move_by(window.position()); | ||||||
|     // FIXME: This seems slightly wrong; the inner rect shouldn't intersect the border part of the outer rect.
 |     // FIXME: This seems slightly wrong; the inner rect shouldn't intersect the border part of the outer rect.
 | ||||||
|  | @ -1107,13 +1126,13 @@ void WSWindowManager::flush(const Rect& a_rect) | ||||||
|     dbgprintf("[WM] flush #%u (%d,%d %dx%d)\n", ++m_flush_count, rect.x(), rect.y(), rect.width(), rect.height()); |     dbgprintf("[WM] flush #%u (%d,%d %dx%d)\n", ++m_flush_count, rect.x(), rect.y(), rect.width(), rect.height()); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     RGBA32* front_ptr = m_front_bitmap->scanline(rect.y()) + rect.x(); |     const RGBA32* front_ptr = m_front_bitmap->scanline(rect.y()) + rect.x(); | ||||||
|     RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); |     RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); | ||||||
|     size_t pitch = m_back_bitmap->pitch(); |     size_t pitch = m_back_bitmap->pitch(); | ||||||
| 
 | 
 | ||||||
|     for (int y = 0; y < rect.height(); ++y) { |     for (int y = 0; y < rect.height(); ++y) { | ||||||
|         fast_dword_copy(back_ptr, front_ptr, rect.width()); |         fast_dword_copy(back_ptr, front_ptr, rect.width()); | ||||||
|         front_ptr = (RGBA32*)((byte*)front_ptr + pitch); |         front_ptr = (const RGBA32*)((const byte*)front_ptr + pitch); | ||||||
|         back_ptr = (RGBA32*)((byte*)back_ptr + pitch); |         back_ptr = (RGBA32*)((byte*)back_ptr + pitch); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -16,11 +16,11 @@ void WSWindowSwitcher::set_visible(bool visible) | ||||||
|     if (m_visible == visible) |     if (m_visible == visible) | ||||||
|         return; |         return; | ||||||
|     m_visible = visible; |     m_visible = visible; | ||||||
|     if (!m_visible) { |     if (m_switcher_window) | ||||||
|         WSWindowManager::the().invalidate(m_rect); |         m_switcher_window->set_visible(visible); | ||||||
|  |     if (!m_visible) | ||||||
|         return; |         return; | ||||||
|     } |     refresh(); | ||||||
|     invalidate(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| WSWindow* WSWindowSwitcher::selected_window() | WSWindow* WSWindowSwitcher::selected_window() | ||||||
|  | @ -53,15 +53,15 @@ void WSWindowSwitcher::on_key_event(const WSKeyEvent& event) | ||||||
|     auto* highlight_window = m_windows.at(m_selected_index).ptr(); |     auto* highlight_window = m_windows.at(m_selected_index).ptr(); | ||||||
|     ASSERT(highlight_window); |     ASSERT(highlight_window); | ||||||
|     WSWindowManager::the().set_highlight_window(highlight_window); |     WSWindowManager::the().set_highlight_window(highlight_window); | ||||||
|  |     draw(); | ||||||
|     WSWindowManager::the().invalidate(m_rect); |     WSWindowManager::the().invalidate(m_rect); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowSwitcher::draw(Painter& painter) | void WSWindowSwitcher::draw() | ||||||
| { | { | ||||||
|     painter.translate(m_rect.location()); |     Painter painter(*m_switcher_window->backing_store()); | ||||||
|     painter.fill_rect({ { }, m_rect.size() }, Color::LightGray); |     painter.fill_rect({ { }, m_rect.size() }, Color::LightGray); | ||||||
|     painter.draw_rect({ { }, m_rect.size() }, Color::DarkGray); |     painter.draw_rect({ { }, m_rect.size() }, Color::DarkGray); | ||||||
| 
 |  | ||||||
|     for (int index = 0; index < m_windows.size(); ++index) { |     for (int index = 0; index < m_windows.size(); ++index) { | ||||||
|         auto& window = *m_windows.at(index); |         auto& window = *m_windows.at(index); | ||||||
|         Rect item_rect { |         Rect item_rect { | ||||||
|  | @ -80,16 +80,14 @@ void WSWindowSwitcher::draw(Painter& painter) | ||||||
|             text_color = Color::Black; |             text_color = Color::Black; | ||||||
|             rect_text_color = Color::DarkGray; |             rect_text_color = Color::DarkGray; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         painter.set_font(Font::default_bold_font()); |         painter.set_font(Font::default_bold_font()); | ||||||
|         painter.draw_text(item_rect, window.title(), TextAlignment::CenterLeft, text_color); |         painter.draw_text(item_rect, window.title(), TextAlignment::CenterLeft, text_color); | ||||||
|         painter.set_font(WSWindowManager::the().font()); |         painter.set_font(WSWindowManager::the().font()); | ||||||
|         painter.draw_text(item_rect, window.rect().to_string(), TextAlignment::CenterRight, rect_text_color); |         painter.draw_text(item_rect, window.rect().to_string(), TextAlignment::CenterRight, rect_text_color); | ||||||
|     } |     } | ||||||
|     painter.translate(-m_rect.x(), -m_rect.y()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WSWindowSwitcher::invalidate() | void WSWindowSwitcher::refresh() | ||||||
| { | { | ||||||
|     WSWindow* selected_window = nullptr; |     WSWindow* selected_window = nullptr; | ||||||
|     if (m_selected_index > 0 && m_windows[m_selected_index]) |     if (m_selected_index > 0 && m_windows[m_selected_index]) | ||||||
|  | @ -114,5 +112,13 @@ void WSWindowSwitcher::invalidate() | ||||||
|     m_rect.set_width(longest_title * WSWindowManager::the().font().glyph_width() + space_for_window_rect + padding() * 2); |     m_rect.set_width(longest_title * WSWindowManager::the().font().glyph_width() + space_for_window_rect + padding() * 2); | ||||||
|     m_rect.set_height(window_count * item_height() + padding() * 2); |     m_rect.set_height(window_count * item_height() + padding() * 2); | ||||||
|     m_rect.center_within(WSWindowManager::the().m_screen_rect); |     m_rect.center_within(WSWindowManager::the().m_screen_rect); | ||||||
|     WSWindowManager::the().invalidate(m_rect); |     if (!m_switcher_window) | ||||||
|  |         m_switcher_window = make<WSWindow>(*this, WSWindowType::WindowSwitcher); | ||||||
|  |     m_switcher_window->set_rect(m_rect); | ||||||
|  |     draw(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void WSWindowSwitcher::on_message(WSMessage& message) | ||||||
|  | { | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,15 +3,16 @@ | ||||||
| #include <SharedGraphics/Rect.h> | #include <SharedGraphics/Rect.h> | ||||||
| #include <AK/Vector.h> | #include <AK/Vector.h> | ||||||
| #include <AK/WeakPtr.h> | #include <AK/WeakPtr.h> | ||||||
|  | #include <WindowServer/WSMessageReceiver.h> | ||||||
| 
 | 
 | ||||||
| class Painter; | class Painter; | ||||||
| class WSKeyEvent; | class WSKeyEvent; | ||||||
| class WSWindow; | class WSWindow; | ||||||
| 
 | 
 | ||||||
| class WSWindowSwitcher { | class WSWindowSwitcher : public WSMessageReceiver { | ||||||
| public: | public: | ||||||
|     WSWindowSwitcher(); |     WSWindowSwitcher(); | ||||||
|     ~WSWindowSwitcher(); |     virtual ~WSWindowSwitcher() override; | ||||||
| 
 | 
 | ||||||
|     bool is_visible() const { return m_visible; } |     bool is_visible() const { return m_visible; } | ||||||
|     void set_visible(bool); |     void set_visible(bool); | ||||||
|  | @ -20,17 +21,21 @@ public: | ||||||
|     void hide() { set_visible(false); } |     void hide() { set_visible(false); } | ||||||
| 
 | 
 | ||||||
|     void on_key_event(const WSKeyEvent&); |     void on_key_event(const WSKeyEvent&); | ||||||
|     void invalidate(); |     void refresh(); | ||||||
| 
 | 
 | ||||||
|     void draw(Painter&); |     void draw(); | ||||||
| 
 | 
 | ||||||
|     int item_height() { return 20; } |     int item_height() { return 20; } | ||||||
|     int padding() { return 8; } |     int padding() { return 8; } | ||||||
| 
 | 
 | ||||||
|     WSWindow* selected_window(); |     WSWindow* selected_window(); | ||||||
| 
 | 
 | ||||||
| private: |     WSWindow* switcher_window() { return m_switcher_window.ptr(); } | ||||||
| 
 | 
 | ||||||
|  | private: | ||||||
|  |     virtual void on_message(WSMessage&) override; | ||||||
|  | 
 | ||||||
|  |     OwnPtr<WSWindow> m_switcher_window; | ||||||
|     Rect m_rect; |     Rect m_rect; | ||||||
|     bool m_visible { false }; |     bool m_visible { false }; | ||||||
|     Vector<WeakPtr<WSWindow>> m_windows; |     Vector<WeakPtr<WSWindow>> m_windows; | ||||||
|  |  | ||||||
|  | @ -3,5 +3,6 @@ | ||||||
| enum class WSWindowType { | enum class WSWindowType { | ||||||
|     Invalid = 0, |     Invalid = 0, | ||||||
|     Normal, |     Normal, | ||||||
|     Menu |     Menu, | ||||||
|  |     WindowSwitcher, | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling