diff --git a/Applications/Taskbar/TaskbarWindow.cpp b/Applications/Taskbar/TaskbarWindow.cpp index b139c1fed3..b93e329831 100644 --- a/Applications/Taskbar/TaskbarWindow.cpp +++ b/Applications/Taskbar/TaskbarWindow.cpp @@ -19,6 +19,10 @@ TaskbarWindow::TaskbarWindow() auto* widget = new TaskbarWidget(m_window_list); set_main_widget(widget); + + m_window_list.aid_create_button = [this] { + return create_button(); + }; } TaskbarWindow::~TaskbarWindow() @@ -31,25 +35,34 @@ void TaskbarWindow::on_screen_rect_change(const Rect& rect) set_rect(new_rect); } +GButton* TaskbarWindow::create_button() +{ + auto* button = new GButton(main_widget()); + button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); + button->set_preferred_size({ 100, 22 }); + button->set_checkable(true); + return button; +} + void TaskbarWindow::wm_event(GWMEvent& event) { WindowIdentifier identifier { event.client_id(), event.window_id() }; switch (event.type()) { case GEvent::WM_WindowAdded: { auto& added_event = static_cast(event); - printf("WM_WindowAdded: client_id=%d, window_id=%d, title=%s, rect=%s\n", + printf("WM_WindowAdded: client_id=%d, window_id=%d, title=%s, rect=%s, is_active=%u\n", added_event.client_id(), added_event.window_id(), added_event.title().characters(), - added_event.rect().to_string().characters() + added_event.rect().to_string().characters(), + added_event.is_active() ); auto& window = m_window_list.ensure_window(identifier); window.set_title(added_event.title()); window.set_rect(added_event.rect()); - window.set_button(new GButton(main_widget())); - window.button()->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); - window.button()->set_preferred_size({ 100, 22 }); + window.set_active(added_event.is_active()); window.button()->set_caption(window.title()); + window.button()->set_checked(window.is_active()); update(); break; } @@ -65,16 +78,19 @@ void TaskbarWindow::wm_event(GWMEvent& event) } case GEvent::WM_WindowStateChanged: { auto& changed_event = static_cast(event); - printf("WM_WindowStateChanged: client_id=%d, window_id=%d, title=%s, rect=%s\n", + printf("WM_WindowStateChanged: client_id=%d, window_id=%d, title=%s, rect=%s, is_active=%u\n", changed_event.client_id(), changed_event.window_id(), changed_event.title().characters(), - changed_event.rect().to_string().characters() + changed_event.rect().to_string().characters(), + changed_event.is_active() ); auto& window = m_window_list.ensure_window(identifier); window.set_title(changed_event.title()); window.set_rect(changed_event.rect()); + window.set_active(changed_event.is_active()); window.button()->set_caption(changed_event.title()); + window.button()->set_checked(changed_event.is_active()); break; } default: diff --git a/Applications/Taskbar/TaskbarWindow.h b/Applications/Taskbar/TaskbarWindow.h index c8f5f052d9..681d7b9181 100644 --- a/Applications/Taskbar/TaskbarWindow.h +++ b/Applications/Taskbar/TaskbarWindow.h @@ -13,6 +13,7 @@ public: private: void on_screen_rect_change(const Rect&); + GButton* create_button(); virtual void wm_event(GWMEvent&) override; diff --git a/Applications/Taskbar/WindowList.cpp b/Applications/Taskbar/WindowList.cpp index d0b9ac3a40..8afed41468 100644 --- a/Applications/Taskbar/WindowList.cpp +++ b/Applications/Taskbar/WindowList.cpp @@ -6,6 +6,7 @@ Window& WindowList::ensure_window(const WindowIdentifier& identifier) if (it != m_windows.end()) return *it->value; auto window = make(identifier); + window->set_button(aid_create_button()); auto& window_ref = *window; m_windows.set(identifier, move(window)); return window_ref; diff --git a/Applications/Taskbar/WindowList.h b/Applications/Taskbar/WindowList.h index 7f5484376b..c48b287087 100644 --- a/Applications/Taskbar/WindowList.h +++ b/Applications/Taskbar/WindowList.h @@ -57,11 +57,15 @@ public: GButton* button() { return m_button; } void set_button(GButton* button) { m_button = button; } + void set_active(bool active) { m_active = active; } + bool is_active() const { return m_active; } + private: WindowIdentifier m_identifier; String m_title; Rect m_rect; GButton* m_button { nullptr }; + bool m_active { false }; }; class WindowList { @@ -75,6 +79,8 @@ public: Window& ensure_window(const WindowIdentifier&); void remove_window(const WindowIdentifier&); + Function aid_create_button; + private: HashMap> m_windows; }; diff --git a/LibGUI/GEvent.h b/LibGUI/GEvent.h index b39b7a81a1..1d1d02bd81 100644 --- a/LibGUI/GEvent.h +++ b/LibGUI/GEvent.h @@ -74,19 +74,22 @@ private: class GWMWindowAddedEvent : public GWMEvent { public: - GWMWindowAddedEvent(int client_id, int window_id, const String& title, const Rect& rect) + GWMWindowAddedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active) : GWMEvent(GEvent::Type::WM_WindowAdded, client_id, window_id) , m_title(title) , m_rect(rect) + , m_active(is_active) { } String title() const { return m_title; } Rect rect() const { return m_rect; } + bool is_active() const { return m_active; } private: String m_title; Rect m_rect; + bool m_active; }; class GWMWindowRemovedEvent : public GWMEvent { @@ -99,19 +102,22 @@ public: class GWMWindowStateChangedEvent : public GWMEvent { public: - GWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect) + GWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active) : GWMEvent(GEvent::Type::WM_WindowStateChanged, client_id, window_id) , m_title(title) , m_rect(rect) + , m_active(is_active) { } String title() const { return m_title; } Rect rect() const { return m_rect; } + bool is_active() const { return m_active; } private: String m_title; Rect m_rect; + bool m_active; }; class QuitEvent final : public GEvent { diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index a7c02b8bb6..406bf7e80c 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -271,9 +271,9 @@ void GEventLoop::handle_menu_event(const WSAPI_ServerMessage& event) void GEventLoop::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& window) { if (event.type == WSAPI_ServerMessage::WM_WindowAdded) - return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect)); + return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active)); if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged) - return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect)); + return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active)); if (event.type == WSAPI_ServerMessage::WM_WindowRemoved) return post_event(window, make(event.wm.client_id, event.wm.window_id)); ASSERT_NOT_REACHED(); diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index 209b0f851c..f8a49de14d 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -110,6 +110,7 @@ struct WSAPI_ServerMessage { int client_id; int window_id; WSAPI_Rect rect; + bool is_active; } wm; struct { WSAPI_Rect rect; diff --git a/Servers/WindowServer/WSMessage.h b/Servers/WindowServer/WSMessage.h index 5d63a89359..3911a48d6f 100644 --- a/Servers/WindowServer/WSMessage.h +++ b/Servers/WindowServer/WSMessage.h @@ -605,19 +605,22 @@ private: class WSWMWindowAddedEvent : public WSWMEvent { public: - WSWMWindowAddedEvent(int client_id, int window_id, const String& title, const Rect& rect) + WSWMWindowAddedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active) : WSWMEvent(WSMessage::WM_WindowAdded, client_id, window_id) , m_title(title) , m_rect(rect) + , m_active(is_active) { } String title() const { return m_title; } Rect rect() const { return m_rect; } + bool is_active() const { return m_active; } private: String m_title; Rect m_rect; + bool m_active; }; class WSWMWindowRemovedEvent : public WSWMEvent { @@ -630,17 +633,20 @@ public: class WSWMWindowStateChangedEvent : public WSWMEvent { public: - WSWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect) + WSWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active) : WSWMEvent(WSMessage::WM_WindowStateChanged, client_id, window_id) , m_title(title) , m_rect(rect) + , m_active(is_active) { } String title() const { return m_title; } Rect rect() const { return m_rect; } + bool is_active() const { return m_active; } private: String m_title; Rect m_rect; + bool m_active; }; diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index b648b2503a..1b80fc0ae6 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -146,6 +146,7 @@ void WSWindow::on_message(const WSMessage& message) server_message.type = WSAPI_ServerMessage::Type::WM_WindowAdded; server_message.wm.client_id = added_event.client_id(); server_message.wm.window_id = added_event.window_id(); + server_message.wm.is_active = added_event.is_active(); ASSERT(added_event.title().length() < sizeof(server_message.text)); memcpy(server_message.text, added_event.title().characters(), added_event.title().length()); server_message.text_length = added_event.title().length(); @@ -164,6 +165,7 @@ void WSWindow::on_message(const WSMessage& message) server_message.type = WSAPI_ServerMessage::Type::WM_WindowStateChanged; server_message.wm.client_id = changed_event.client_id(); server_message.wm.window_id = changed_event.window_id(); + server_message.wm.is_active = changed_event.is_active(); ASSERT(changed_event.title().length() < sizeof(server_message.text)); memcpy(server_message.text, changed_event.title().characters(), changed_event.title().length()); server_message.text_length = changed_event.title().length(); diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 2400e854af..07eb848587 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -18,10 +18,6 @@ #include #include "WSCursor.h" -#ifdef KERNEL -#include -#endif - //#define DEBUG_COUNTERS //#define DEBUG_WID_IN_TITLE_BAR //#define RESIZE_DEBUG @@ -510,7 +506,7 @@ void WSWindowManager::add_window(WSWindow& window) for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { if (window.client()) - WSMessageLoop::the().post_message(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect())); + WSMessageLoop::the().post_message(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect(), window.is_active())); return IterationDecision::Continue; }); } @@ -548,6 +544,15 @@ void WSWindowManager::remove_window(WSWindow& window) }); } +void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window) +{ + for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { + if (window.client()) + WSMessageLoop::the().post_message(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect(), window.is_active())); + return IterationDecision::Continue; + }); +} + void WSWindowManager::notify_title_changed(WSWindow& window) { dbgprintf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); @@ -555,11 +560,7 @@ void WSWindowManager::notify_title_changed(WSWindow& window) if (m_switcher.is_visible()) m_switcher.refresh(); - for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { - if (window.client()) - WSMessageLoop::the().post_message(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect())); - return IterationDecision::Continue; - }); + tell_wm_listeners_window_state_changed(window); } void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect, const Rect& new_rect) @@ -572,11 +573,7 @@ void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) m_switcher.refresh(); - for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { - if (window.client()) - WSMessageLoop::the().post_message(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect())); - return IterationDecision::Continue; - }); + tell_wm_listeners_window_state_changed(window); } void WSWindowManager::handle_menu_mouse_event(WSMenu& menu, const WSMouseEvent& event) @@ -1139,7 +1136,8 @@ void WSWindowManager::set_active_window(WSWindow* window) if (window == m_active_window.ptr()) return; - if (auto* previously_active_window = m_active_window.ptr()) { + auto* previously_active_window = m_active_window.ptr(); + if (previously_active_window) { WSMessageLoop::the().post_message(*previously_active_window, make(WSMessage::WindowDeactivated)); invalidate(*previously_active_window); } @@ -1151,6 +1149,9 @@ void WSWindowManager::set_active_window(WSWindow* window) auto* client = window->client(); ASSERT(client); set_current_menubar(client->app_menubar()); + if (previously_active_window) + tell_wm_listeners_window_state_changed(*previously_active_window); + tell_wm_listeners_window_state_changed(*m_active_window); } } diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 8cc58c7b09..e6d99d32bd 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -120,6 +120,7 @@ private: void paint_window_frame(const WSWindow&); void flip_buffers(); void tick_clock(); + void tell_wm_listeners_window_state_changed(WSWindow&); WSScreen& m_screen; Rect m_screen_rect;