summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Services/Taskbar/TaskbarWindow.cpp90
-rw-r--r--Services/Taskbar/TaskbarWindow.h4
-rw-r--r--Services/Taskbar/WindowIdentifier.h6
-rw-r--r--Services/Taskbar/WindowList.cpp22
-rw-r--r--Services/Taskbar/WindowList.h16
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;
};