From 239fd334059823619e0af199e9b5618a320e15f9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 8 May 2020 22:00:41 +0200 Subject: Services: Move Taskbar and SystemMenu from Applications to Services --- Services/Taskbar/Makefile | 11 ++ Services/Taskbar/TaskbarButton.cpp | 53 +++++++++ Services/Taskbar/TaskbarButton.h | 44 +++++++ Services/Taskbar/TaskbarWindow.cpp | 221 ++++++++++++++++++++++++++++++++++++ Services/Taskbar/TaskbarWindow.h | 47 ++++++++ Services/Taskbar/WindowIdentifier.h | 57 ++++++++++ Services/Taskbar/WindowList.cpp | 68 +++++++++++ Services/Taskbar/WindowList.h | 96 ++++++++++++++++ Services/Taskbar/main.cpp | 56 +++++++++ 9 files changed, 653 insertions(+) create mode 100644 Services/Taskbar/Makefile create mode 100644 Services/Taskbar/TaskbarButton.cpp create mode 100644 Services/Taskbar/TaskbarButton.h create mode 100644 Services/Taskbar/TaskbarWindow.cpp create mode 100644 Services/Taskbar/TaskbarWindow.h create mode 100644 Services/Taskbar/WindowIdentifier.h create mode 100644 Services/Taskbar/WindowList.cpp create mode 100644 Services/Taskbar/WindowList.h create mode 100644 Services/Taskbar/main.cpp (limited to 'Services/Taskbar') diff --git a/Services/Taskbar/Makefile b/Services/Taskbar/Makefile new file mode 100644 index 0000000000..f40e2a3032 --- /dev/null +++ b/Services/Taskbar/Makefile @@ -0,0 +1,11 @@ +OBJS = \ + TaskbarWindow.o \ + TaskbarButton.o \ + WindowList.o \ + main.o + +PROGRAM = Taskbar + +LIB_DEPS = GUI Gfx IPC Core + +include ../../Makefile.common diff --git a/Services/Taskbar/TaskbarButton.cpp b/Services/Taskbar/TaskbarButton.cpp new file mode 100644 index 0000000000..68e0441211 --- /dev/null +++ b/Services/Taskbar/TaskbarButton.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TaskbarButton.h" +#include +#include + +TaskbarButton::TaskbarButton(const WindowIdentifier& identifier) + : m_identifier(identifier) +{ +} + +TaskbarButton::~TaskbarButton() +{ +} + +void TaskbarButton::context_menu_event(GUI::ContextMenuEvent&) +{ + GUI::WindowServerConnection::the().post_message(Messages::WindowServer::WM_PopupWindowMenu(m_identifier.client_id(), m_identifier.window_id(), screen_relative_rect().location())); +} + +void TaskbarButton::resize_event(GUI::ResizeEvent& event) +{ + GUI::WindowServerConnection::the().post_message( + Messages::WindowServer::WM_SetWindowTaskbarRect( + m_identifier.client_id(), + m_identifier.window_id(), + screen_relative_rect())); + return GUI::Button::resize_event(event); +} diff --git a/Services/Taskbar/TaskbarButton.h b/Services/Taskbar/TaskbarButton.h new file mode 100644 index 0000000000..d8852cfcc1 --- /dev/null +++ b/Services/Taskbar/TaskbarButton.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WindowIdentifier.h" +#include + +class TaskbarButton final : public GUI::Button { + C_OBJECT(TaskbarButton) +public: + virtual ~TaskbarButton() override; + +private: + explicit TaskbarButton(const WindowIdentifier&); + + virtual void context_menu_event(GUI::ContextMenuEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; + + WindowIdentifier m_identifier; +}; diff --git a/Services/Taskbar/TaskbarWindow.cpp b/Services/Taskbar/TaskbarWindow.cpp new file mode 100644 index 0000000000..7e2638ebd0 --- /dev/null +++ b/Services/Taskbar/TaskbarWindow.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TaskbarWindow.h" +#include "TaskbarButton.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define EVENT_DEBUG + +TaskbarWindow::TaskbarWindow() +{ + set_window_type(GUI::WindowType::Taskbar); + set_title("Taskbar"); + + on_screen_rect_change(GUI::Desktop::the().rect()); + + GUI::Desktop::the().on_rect_change = [this](const Gfx::Rect& rect) { on_screen_rect_change(rect); }; + + auto& widget = set_main_widget(); + widget.set_fill_with_background_color(true); + widget.set_layout(); + widget.layout()->set_margins({ 3, 2, 3, 2 }); + widget.layout()->set_spacing(3); + widget.set_frame_thickness(1); + widget.set_frame_shape(Gfx::FrameShape::Panel); + widget.set_frame_shadow(Gfx::FrameShadow::Raised); + + 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(); +} + +TaskbarWindow::~TaskbarWindow() +{ +} + +void TaskbarWindow::create_quick_launch_bar() +{ + auto& quick_launch_bar = main_widget()->add(); + quick_launch_bar.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); + quick_launch_bar.set_layout(); + quick_launch_bar.layout()->set_spacing(3); + quick_launch_bar.layout()->set_margins({ 3, 0, 3, 0 }); + quick_launch_bar.set_frame_thickness(0); + + int total_width = 6; + bool first = true; + + auto config = Core::ConfigFile::get_for_app("Taskbar"); + constexpr const char* quick_launch = "QuickLaunch"; + + // FIXME: Core::ConfigFile does not keep the order of the entries. + for (auto& name : config->keys(quick_launch)) { + auto af_name = config->read_entry(quick_launch, name); + ASSERT(!af_name.is_null()); + auto af_path = String::format("/res/apps/%s", af_name.characters()); + auto af = Core::ConfigFile::open(af_path); + auto app_executable = af->read_entry("App", "Executable"); + auto app_icon_path = af->read_entry("Icons", "16x16"); + + auto& button = quick_launch_bar.add(); + button.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); + button.set_preferred_size(22, 22); + button.set_button_style(Gfx::ButtonStyle::CoolBar); + + button.set_icon(Gfx::Bitmap::load_from_file(app_icon_path)); + button.set_tooltip(name); + button.on_click = [app_executable] { + pid_t pid = fork(); + if (pid < 0) { + perror("fork"); + } else if (pid == 0) { + if (chdir(Core::StandardPaths::home_directory().characters()) < 0) { + perror("chdir"); + exit(1); + } + execl(app_executable.characters(), app_executable.characters(), nullptr); + perror("execl"); + ASSERT_NOT_REACHED(); + } + }; + + if (!first) + total_width += 3; + first = false; + total_width += 22; + } + + quick_launch_bar.set_preferred_size(total_width, 22); +} + +void TaskbarWindow::on_screen_rect_change(const Gfx::Rect& rect) +{ + Gfx::Rect new_rect { rect.x(), rect.bottom() - taskbar_height() + 1, rect.width(), taskbar_height() }; + set_rect(new_rect); +} + +NonnullRefPtr TaskbarWindow::create_button(const WindowIdentifier& identifier) +{ + auto& button = main_widget()->add(identifier); + button.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); + button.set_preferred_size(140, 22); + button.set_text_alignment(Gfx::TextAlignment::CenterLeft); + button.set_icon(*m_default_icon); + return button; +} + +static bool should_include_window(GUI::WindowType window_type, bool is_frameless) +{ + return window_type == GUI::WindowType::Normal && !is_frameless; +} + +void TaskbarWindow::wm_event(GUI::WMEvent& event) +{ + WindowIdentifier identifier { event.client_id(), event.window_id() }; + switch (event.type()) { + case GUI::Event::WM_WindowRemoved: { +#ifdef EVENT_DEBUG + auto& removed_event = static_cast(event); + dbgprintf("WM_WindowRemoved: client_id=%d, window_id=%d\n", + removed_event.client_id(), + removed_event.window_id()); +#endif + WindowList::the().remove_window(identifier); + update(); + break; + } + case GUI::Event::WM_WindowRectChanged: { +#ifdef EVENT_DEBUG + auto& changed_event = static_cast(event); + dbgprintf("WM_WindowRectChanged: client_id=%d, window_id=%d, rect=%s\n", + changed_event.client_id(), + changed_event.window_id(), + changed_event.rect().to_string().characters()); +#endif + break; + } + + case GUI::Event::WM_WindowIconBitmapChanged: { + auto& changed_event = static_cast(event); +#ifdef EVENT_DEBUG + dbgprintf("WM_WindowIconBitmapChanged: client_id=%d, window_id=%d, icon_buffer_id=%d\n", + changed_event.client_id(), + changed_event.window_id(), + changed_event.icon_buffer_id()); +#endif + 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())); + } + break; + } + + case GUI::Event::WM_WindowStateChanged: { + auto& changed_event = static_cast(event); +#ifdef EVENT_DEBUG + dbgprintf("WM_WindowStateChanged: client_id=%d, window_id=%d, title=%s, rect=%s, is_active=%u, is_minimized=%u\n", + changed_event.client_id(), + changed_event.window_id(), + changed_event.title().characters(), + changed_event.rect().to_string().characters(), + changed_event.is_active(), + changed_event.is_minimized()); +#endif + if (!should_include_window(changed_event.window_type(), changed_event.is_frameless())) + break; + 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()); + window.set_minimized(changed_event.is_minimized()); + if (window.is_minimized()) { + window.button()->set_foreground_color(Color::DarkGray); + window.button()->set_text(String::format("[%s]", changed_event.title().characters())); + } else { + window.button()->set_foreground_color(Color::Black); + window.button()->set_text(changed_event.title()); + } + window.button()->set_checked(changed_event.is_active()); + break; + } + default: + break; + } +} diff --git a/Services/Taskbar/TaskbarWindow.h b/Services/Taskbar/TaskbarWindow.h new file mode 100644 index 0000000000..5825012439 --- /dev/null +++ b/Services/Taskbar/TaskbarWindow.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WindowList.h" +#include +#include + +class TaskbarWindow final : public GUI::Window { + C_OBJECT(TaskbarWindow) +public: + TaskbarWindow(); + virtual ~TaskbarWindow() override; + + int taskbar_height() const { return 28; } + +private: + void create_quick_launch_bar(); + void on_screen_rect_change(const Gfx::Rect&); + NonnullRefPtr create_button(const WindowIdentifier&); + + virtual void wm_event(GUI::WMEvent&) override; + + RefPtr m_default_icon; +}; diff --git a/Services/Taskbar/WindowIdentifier.h b/Services/Taskbar/WindowIdentifier.h new file mode 100644 index 0000000000..cdb645449a --- /dev/null +++ b/Services/Taskbar/WindowIdentifier.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +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 : public GenericTraits { + static unsigned hash(const WindowIdentifier& w) { return pair_int_hash(w.client_id(), w.window_id()); } +}; +} diff --git a/Services/Taskbar/WindowList.cpp b/Services/Taskbar/WindowList.cpp new file mode 100644 index 0000000000..948dcb0452 --- /dev/null +++ b/Services/Taskbar/WindowList.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WindowList.h" +#include + +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); + if (it != m_windows.end()) + return it->value; + return nullptr; +} + +Window& WindowList::ensure_window(const WindowIdentifier& identifier) +{ + auto it = m_windows.find(identifier); + if (it != m_windows.end()) + return *it->value; + auto window = make(identifier); + window->set_button(aid_create_button(identifier)); + window->button()->on_click = [window = window.ptr(), identifier] { + 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; +} + +void WindowList::remove_window(const WindowIdentifier& identifier) +{ + m_windows.remove(identifier); +} diff --git a/Services/Taskbar/WindowList.h b/Services/Taskbar/WindowList.h new file mode 100644 index 0000000000..90d842c3f4 --- /dev/null +++ b/Services/Taskbar/WindowList.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WindowIdentifier.h" +#include +#include +#include +#include + +class Window { +public: + explicit Window(const WindowIdentifier& identifier) + : m_identifier(identifier) + { + } + + ~Window() + { + if (m_button) + m_button->remove_from_parent(); + } + + WindowIdentifier identifier() const { return m_identifier; } + + String title() const { return m_title; } + void set_title(const String& title) { m_title = title; } + + Gfx::Rect rect() const { return m_rect; } + void set_rect(const Gfx::Rect& rect) { m_rect = rect; } + + GUI::Button* button() { return m_button; } + void set_button(GUI::Button* button) { m_button = button; } + + void set_active(bool active) { m_active = active; } + bool is_active() const { return m_active; } + + void set_minimized(bool minimized) { m_minimized = minimized; } + bool is_minimized() const { return m_minimized; } + + const Gfx::Bitmap* icon() const { return m_icon.ptr(); } + +private: + WindowIdentifier m_identifier; + String m_title; + Gfx::Rect m_rect; + RefPtr m_button; + RefPtr m_icon; + bool m_active { false }; + bool m_minimized { false }; +}; + +class WindowList { +public: + static WindowList& the(); + + template + void for_each_window(Callback callback) + { + for (auto& it : m_windows) + callback(*it.value); + } + + Window* window(const WindowIdentifier&); + Window& ensure_window(const WindowIdentifier&); + void remove_window(const WindowIdentifier&); + + Function(const WindowIdentifier&)> aid_create_button; + +private: + HashMap> m_windows; +}; diff --git a/Services/Taskbar/main.cpp b/Services/Taskbar/main.cpp new file mode 100644 index 0000000000..33b96cb465 --- /dev/null +++ b/Services/Taskbar/main.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TaskbarWindow.h" +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + if (pledge("stdio shared_buffer accept proc exec rpath unix cpath fattr", nullptr) < 0) { + perror("pledge"); + return 1; + } + + GUI::Application app(argc, argv); + + if (pledge("stdio shared_buffer accept proc exec rpath", nullptr) < 0) { + perror("pledge"); + return 1; + } + + TaskbarWindow window; + window.show(); + + signal(SIGCHLD, [](int signo) { + (void)signo; + wait(nullptr); + }); + + return app.exec(); +} -- cgit v1.2.3