diff options
-rw-r--r-- | Services/Taskbar/TaskbarWindow.cpp | 90 | ||||
-rw-r--r-- | Services/Taskbar/TaskbarWindow.h | 4 | ||||
-rw-r--r-- | Services/Taskbar/WindowIdentifier.h | 6 | ||||
-rw-r--r-- | Services/Taskbar/WindowList.cpp | 22 | ||||
-rw-r--r-- | Services/Taskbar/WindowList.h | 16 |
5 files changed, 114 insertions, 24 deletions
diff --git a/Services/Taskbar/TaskbarWindow.cpp b/Services/Taskbar/TaskbarWindow.cpp index c6121f04e1..6347a67260 100644 --- a/Services/Taskbar/TaskbarWindow.cpp +++ b/Services/Taskbar/TaskbarWindow.cpp @@ -35,6 +35,7 @@ #include <LibGUI/Frame.h> #include <LibGUI/Painter.h> #include <LibGUI/Window.h> +#include <LibGUI/WindowServerConnection.h> #include <LibGfx/Palette.h> #include <stdio.h> @@ -74,10 +75,6 @@ TaskbarWindow::TaskbarWindow() m_default_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window.png"); - WindowList::the().aid_create_button = [this](auto& identifier) { - return create_button(identifier); - }; - create_quick_launch_bar(); } @@ -161,6 +158,67 @@ static bool should_include_window(GUI::WindowType window_type, bool is_frameless return window_type == GUI::WindowType::Normal && !is_frameless; } +void TaskbarWindow::add_window_button(::Window& window, const WindowIdentifier& identifier) +{ + if (window.button()) + return; + window.set_button(create_button(identifier)); + auto* button = window.button(); + button->on_click = [window = &window, identifier, button](auto) { + // We need to look at the button's checked state here to figure + // out if the application is active or not. That's because this + // button's window may not actually be active when a modal window + // is displayed, in which case window->is_active() would return + // false because window is the modal window's owner (which is not + // active) + if (window->is_minimized() || !button->is_checked()) { + GUI::WindowServerConnection::the().post_message(Messages::WindowServer::WM_SetActiveWindow(identifier.client_id(), identifier.window_id())); + } else { + GUI::WindowServerConnection::the().post_message(Messages::WindowServer::WM_SetWindowMinimized(identifier.client_id(), identifier.window_id(), true)); + } + }; +} + +void TaskbarWindow::remove_window_button(::Window& window) +{ + auto* button = window.button(); + if (!button) + return; + window.set_button(nullptr); + button->remove_from_parent(); +} + +void TaskbarWindow::update_window_button(::Window& window, bool show_as_active) +{ + auto* button = window.button(); + if (!button) + return; + + if (window.is_minimized()) { + button->set_foreground_color(Color::DarkGray); + } else { + button->set_foreground_color(Color::Black); + } + button->set_text(window.title()); + button->set_checked(show_as_active); +} + +::Window* TaskbarWindow::find_window_owner(::Window& window) const +{ + if (!window.is_modal()) + return &window; + + ::Window* parent = nullptr; + auto* current_window = &window; + while (current_window) { + parent = WindowList::the().find_parent(*current_window); + if (!parent || !parent->is_modal()) + break; + current_window = parent; + } + return parent; +} + void TaskbarWindow::wm_event(GUI::WMEvent& event) { WindowIdentifier identifier { event.client_id(), event.window_id() }; @@ -198,7 +256,8 @@ void TaskbarWindow::wm_event(GUI::WMEvent& event) if (auto* window = WindowList::the().window(identifier)) { auto buffer = SharedBuffer::create_from_shbuf_id(changed_event.icon_buffer_id()); ASSERT(buffer); - window->button()->set_icon(Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGBA32, *buffer, changed_event.icon_size())); + if (window->button()) + window->button()->set_icon(Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGBA32, *buffer, changed_event.icon_size())); } break; } @@ -217,18 +276,27 @@ void TaskbarWindow::wm_event(GUI::WMEvent& event) if (!should_include_window(changed_event.window_type(), changed_event.is_frameless())) break; auto& window = WindowList::the().ensure_window(identifier); + window.set_parent_identifier({ changed_event.parent_client_id(), changed_event.parent_window_id() }); + if (!window.is_modal()) + add_window_button(window, identifier); + else + remove_window_button(window); window.set_title(changed_event.title()); window.set_rect(changed_event.rect()); + window.set_modal(changed_event.is_modal()); window.set_active(changed_event.is_active()); window.set_minimized(changed_event.is_minimized()); window.set_progress(changed_event.progress()); - if (window.is_minimized()) { - window.button()->set_foreground_color(Color::DarkGray); - } else { - window.button()->set_foreground_color(Color::Black); + + auto* window_owner = find_window_owner(window); + if (window_owner == &window) { + update_window_button(window, window.is_active()); + } else if (window_owner) { + // check the window owner's button if the modal's window button + // would have been checked + ASSERT(window.is_modal()); + update_window_button(*window_owner, window.is_active()); } - window.button()->set_text(changed_event.title()); - window.button()->set_checked(changed_event.is_active()); break; } default: diff --git a/Services/Taskbar/TaskbarWindow.h b/Services/Taskbar/TaskbarWindow.h index ae290ebd72..f688bcde13 100644 --- a/Services/Taskbar/TaskbarWindow.h +++ b/Services/Taskbar/TaskbarWindow.h @@ -42,6 +42,10 @@ private: void create_quick_launch_bar(); void on_screen_rect_change(const Gfx::IntRect&); NonnullRefPtr<GUI::Button> create_button(const WindowIdentifier&); + void add_window_button(::Window&, const WindowIdentifier&); + void remove_window_button(::Window&); + void update_window_button(::Window&, bool); + ::Window* find_window_owner(::Window&) const; virtual void wm_event(GUI::WMEvent&) override; diff --git a/Services/Taskbar/WindowIdentifier.h b/Services/Taskbar/WindowIdentifier.h index cdb645449a..c6e996992c 100644 --- a/Services/Taskbar/WindowIdentifier.h +++ b/Services/Taskbar/WindowIdentifier.h @@ -30,6 +30,7 @@ class WindowIdentifier { public: + WindowIdentifier() = default; WindowIdentifier(int client_id, int window_id) : m_client_id(client_id) , m_window_id(window_id) @@ -44,6 +45,11 @@ public: return m_client_id == other.m_client_id && m_window_id == other.m_window_id; } + bool is_valid() const + { + return m_client_id != -1 && m_window_id != -1; + } + private: int m_client_id { -1 }; int m_window_id { -1 }; diff --git a/Services/Taskbar/WindowList.cpp b/Services/Taskbar/WindowList.cpp index 1a60990286..2f09f228e5 100644 --- a/Services/Taskbar/WindowList.cpp +++ b/Services/Taskbar/WindowList.cpp @@ -25,7 +25,6 @@ */ #include "WindowList.h" -#include <LibGUI/WindowServerConnection.h> WindowList& WindowList::the() { @@ -35,6 +34,19 @@ WindowList& WindowList::the() return *s_the; } +Window* WindowList::find_parent(const Window& window) +{ + if (!window.parent_identifier().is_valid()) + return nullptr; + for (auto& it : m_windows) + { + auto& w = *it.value; + if (w.identifier() == window.parent_identifier()) + return &w; + } + return nullptr; +} + Window* WindowList::window(const WindowIdentifier& identifier) { auto it = m_windows.find(identifier); @@ -49,14 +61,6 @@ Window& WindowList::ensure_window(const WindowIdentifier& identifier) if (it != m_windows.end()) return *it->value; auto window = make<Window>(identifier); - window->set_button(aid_create_button(identifier)); - window->button()->on_click = [window = window.ptr(), identifier](auto) { - if (window->is_minimized() || !window->is_active()) { - GUI::WindowServerConnection::the().post_message(Messages::WindowServer::WM_SetActiveWindow(identifier.client_id(), identifier.window_id())); - } else { - GUI::WindowServerConnection::the().post_message(Messages::WindowServer::WM_SetWindowMinimized(identifier.client_id(), identifier.window_id(), true)); - } - }; auto& window_ref = *window; m_windows.set(identifier, move(window)); return window_ref; diff --git a/Services/Taskbar/WindowList.h b/Services/Taskbar/WindowList.h index 7938057d79..975917cf2d 100644 --- a/Services/Taskbar/WindowList.h +++ b/Services/Taskbar/WindowList.h @@ -45,7 +45,10 @@ public: m_button->remove_from_parent(); } - WindowIdentifier identifier() const { return m_identifier; } + const WindowIdentifier& identifier() const { return m_identifier; } + + void set_parent_identifier(const WindowIdentifier& parent_identifier) { m_parent_identifier = parent_identifier; } + const WindowIdentifier& parent_identifier() const { return m_parent_identifier; } String title() const { return m_title; } void set_title(const String& title) { m_title = title; } @@ -62,12 +65,16 @@ public: void set_minimized(bool minimized) { m_minimized = minimized; } bool is_minimized() const { return m_minimized; } + void set_modal(bool modal) { m_modal = modal; } + bool is_modal() const { return m_modal; } + void set_progress(int progress) { if (m_progress == progress) return; m_progress = progress; - m_button->update(); + if (m_button) + m_button->update(); } int progress() const { return m_progress; } @@ -76,12 +83,14 @@ public: private: WindowIdentifier m_identifier; + WindowIdentifier m_parent_identifier; String m_title; Gfx::IntRect m_rect; RefPtr<GUI::Button> m_button; RefPtr<Gfx::Bitmap> m_icon; bool m_active { false }; bool m_minimized { false }; + bool m_modal { false }; int m_progress { -1 }; }; @@ -96,12 +105,11 @@ public: callback(*it.value); } + Window* find_parent(const Window&); Window* window(const WindowIdentifier&); Window& ensure_window(const WindowIdentifier&); void remove_window(const WindowIdentifier&); - Function<NonnullRefPtr<GUI::Button>(const WindowIdentifier&)> aid_create_button; - private: HashMap<WindowIdentifier, NonnullOwnPtr<Window>> m_windows; }; |