1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 07:27:45 +00:00

WindowServer+TaskBar: Add a taskbar window button popup menu.

This patch only hooks up the minimize and unminimize actions.
This commit is contained in:
Andreas Kling 2019-04-23 23:14:14 +02:00
parent c5c4e54a67
commit 956bd23aae
17 changed files with 158 additions and 56 deletions

View file

@ -2,6 +2,7 @@ include ../../Makefile.common
OBJS = \
TaskbarWindow.o \
TaskbarButton.o \
WindowList.o \
main.o

View file

@ -0,0 +1,48 @@
#include "TaskbarButton.h"
#include <WindowServer/WSAPITypes.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GMenu.h>
#include <LibGUI/GEventLoop.h>
static void set_window_minimized_state(const WindowIdentifier& identifier, bool minimized)
{
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::WM_SetWindowMinimized;
message.wm.client_id = identifier.client_id();
message.wm.window_id = identifier.window_id();
message.wm.minimized = minimized;
bool success = GEventLoop::post_message_to_server(message);
ASSERT(success);
}
TaskbarButton::TaskbarButton(const WindowIdentifier& identifier, GWidget* parent)
: GButton(parent)
, m_identifier(identifier)
{
}
TaskbarButton::~TaskbarButton()
{
}
void TaskbarButton::context_menu_event(GContextMenuEvent&)
{
ensure_menu().popup(screen_relative_rect().location(), /* top_anchored */ false);
}
GMenu& TaskbarButton::ensure_menu()
{
if (!m_menu) {
m_menu = make<GMenu>("");
m_menu->add_action(GAction::create("Minimize", [this] (auto&) {
set_window_minimized_state(m_identifier, true);
}));
m_menu->add_action(GAction::create("Unminimize", [this] (auto&) {
set_window_minimized_state(m_identifier, false);
}));
m_menu->add_action(GAction::create("Close", [this] (auto&) {
dbgprintf("FIXME: Close!\n");
}));
}
return *m_menu;
}

View file

@ -0,0 +1,18 @@
#pragma once
#include <LibGUI/GButton.h>
#include "WindowIdentifier.h"
class TaskbarButton final : public GButton {
public:
TaskbarButton(const WindowIdentifier&, GWidget* parent);
virtual ~TaskbarButton() override;
private:
virtual void context_menu_event(GContextMenuEvent&) override;
GMenu& ensure_menu();
WindowIdentifier m_identifier;
OwnPtr<GMenu> m_menu;
};

View file

@ -1,4 +1,5 @@
#include "TaskbarWindow.h"
#include "TaskbarButton.h"
#include <LibGUI/GWindow.h>
#include <LibGUI/GDesktop.h>
#include <LibGUI/GEventLoop.h>
@ -30,8 +31,8 @@ TaskbarWindow::TaskbarWindow()
widget->set_frame_shadow(FrameShadow::Raised);
set_main_widget(widget);
m_window_list.aid_create_button = [this] {
return create_button();
WindowList::the().aid_create_button = [this] (auto& identifier) {
return create_button(identifier);
};
}
@ -45,9 +46,9 @@ void TaskbarWindow::on_screen_rect_change(const Rect& rect)
set_rect(new_rect);
}
GButton* TaskbarWindow::create_button()
GButton* TaskbarWindow::create_button(const WindowIdentifier& identifier)
{
auto* button = new GButton(main_widget());
auto* button = new TaskbarButton(identifier, main_widget());
button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
button->set_preferred_size({ 140, 22 });
button->set_checkable(true);
@ -72,7 +73,7 @@ void TaskbarWindow::wm_event(GWMEvent& event)
removed_event.window_id()
);
#endif
m_window_list.remove_window(identifier);
WindowList::the().remove_window(identifier);
update();
break;
}
@ -96,7 +97,7 @@ void TaskbarWindow::wm_event(GWMEvent& event)
changed_event.icon_path().characters()
);
#endif
if (auto* window = m_window_list.window(identifier)) {
if (auto* window = WindowList::the().window(identifier)) {
window->set_icon_path(changed_event.icon_path());
window->button()->set_icon(window->icon());
}
@ -117,7 +118,7 @@ void TaskbarWindow::wm_event(GWMEvent& event)
#endif
if (!should_include_window(changed_event.window_type()))
break;
auto& window = m_window_list.ensure_window(identifier);
auto& window = WindowList::the().ensure_window(identifier);
window.set_title(changed_event.title());
window.set_rect(changed_event.rect());
window.set_active(changed_event.is_active());

View file

@ -13,9 +13,7 @@ public:
private:
void on_screen_rect_change(const Rect&);
GButton* create_button();
GButton* create_button(const WindowIdentifier&);
virtual void wm_event(GWMEvent&) override;
WindowList m_window_list;
};

View file

@ -2,6 +2,14 @@
#include <WindowServer/WSAPITypes.h>
#include <LibGUI/GEventLoop.h>
WindowList& WindowList::the()
{
static WindowList* s_the;
if (!s_the)
s_the = new WindowList;
return *s_the;
}
Window* WindowList::window(const WindowIdentifier& identifier)
{
auto it = m_windows.find(identifier);
@ -16,7 +24,7 @@ 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());
window->set_button(aid_create_button(identifier));
window->button()->on_click = [identifier] (GButton&) {
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::WM_SetActiveWindow;

View file

@ -2,37 +2,9 @@
#include <AK/AKString.h>
#include <AK/HashMap.h>
#include <AK/Traits.h>
#include <SharedGraphics/Rect.h>
#include <LibGUI/GButton.h>
class WindowIdentifier {
public:
WindowIdentifier(int client_id, int window_id)
: m_client_id(client_id)
, m_window_id(window_id)
{
}
int client_id() const { return m_client_id; }
int window_id() const { return m_window_id; }
bool operator==(const WindowIdentifier& other) const
{
return m_client_id == other.m_client_id && m_window_id == other.m_window_id;
}
private:
int m_client_id { -1 };
int m_window_id { -1 };
};
namespace AK {
template<>
struct Traits<WindowIdentifier> {
static unsigned hash(const WindowIdentifier& w) { return pair_int_hash(w.client_id(), w.window_id()); }
static void dump(const WindowIdentifier& w) { kprintf("WindowIdentifier(%d, %d)", w.client_id(), w.window_id()); }
};
}
#include "WindowIdentifier.h"
class Window {
public:
@ -90,6 +62,8 @@ private:
class WindowList {
public:
static WindowList& the();
template<typename Callback> void for_each_window(Callback callback)
{
for (auto& it : m_windows)
@ -100,7 +74,7 @@ public:
Window& ensure_window(const WindowIdentifier&);
void remove_window(const WindowIdentifier&);
Function<GButton*()> aid_create_button;
Function<GButton*(const WindowIdentifier&)> aid_create_button;
private:
HashMap<WindowIdentifier, OwnPtr<Window>> m_windows;