From 01248d28ef8b399f57dc83d361483c7f8f0f6a01 Mon Sep 17 00:00:00 2001 From: Peter Elliott Date: Sun, 18 Jul 2021 12:45:59 -0600 Subject: Applets: Add DesktopPicker applet This applet displays a grid of desktops, and shows the user what virtual desktop they are on. When clicked, the desktop will be changed. --- Userland/Applets/CMakeLists.txt | 1 + Userland/Applets/DesktopPicker/CMakeLists.txt | 13 +++ .../Applets/DesktopPicker/DesktopStatusWindow.cpp | 110 +++++++++++++++++++++ .../Applets/DesktopPicker/DesktopStatusWindow.h | 25 +++++ Userland/Applets/DesktopPicker/main.cpp | 40 ++++++++ 5 files changed, 189 insertions(+) create mode 100644 Userland/Applets/DesktopPicker/CMakeLists.txt create mode 100644 Userland/Applets/DesktopPicker/DesktopStatusWindow.cpp create mode 100644 Userland/Applets/DesktopPicker/DesktopStatusWindow.h create mode 100644 Userland/Applets/DesktopPicker/main.cpp (limited to 'Userland/Applets') diff --git a/Userland/Applets/CMakeLists.txt b/Userland/Applets/CMakeLists.txt index fcf793b20f..6cef5c7793 100644 --- a/Userland/Applets/CMakeLists.txt +++ b/Userland/Applets/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(Audio) add_subdirectory(ClipboardHistory) add_subdirectory(Network) add_subdirectory(ResourceGraph) +add_subdirectory(DesktopPicker) diff --git a/Userland/Applets/DesktopPicker/CMakeLists.txt b/Userland/Applets/DesktopPicker/CMakeLists.txt new file mode 100644 index 0000000000..afe13c2ce4 --- /dev/null +++ b/Userland/Applets/DesktopPicker/CMakeLists.txt @@ -0,0 +1,13 @@ +serenity_component( + DesktopPicker.Applet + REQUIRED + TARGETS DesktopPicker.Applet +) + +set(SOURCES + DesktopStatusWindow.cpp + main.cpp +) + +serenity_bin(DesktopPicker.Applet) +target_link_libraries(DesktopPicker.Applet LibGUI LibCore LibGfx) diff --git a/Userland/Applets/DesktopPicker/DesktopStatusWindow.cpp b/Userland/Applets/DesktopPicker/DesktopStatusWindow.cpp new file mode 100644 index 0000000000..89a56de0ef --- /dev/null +++ b/Userland/Applets/DesktopPicker/DesktopStatusWindow.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021, Peter Elliott + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "DesktopStatusWindow.h" +#include +#include +#include +#include +#include + +class DesktopStatusWidget : public GUI::Widget { + C_OBJECT(DesktopStatusWidget); + +public: + virtual ~DesktopStatusWidget() override + { + } + + Gfx::IntRect rect_for_desktop(unsigned row, unsigned col) const + { + auto& desktop = GUI::Desktop::the(); + + auto vcols = desktop.virtual_desktop_columns(); + auto vrows = desktop.virtual_desktop_rows(); + + auto desktop_width = (width() - gap() * (vcols - 1)) / vcols; + auto desktop_height = (height() - gap() * (vrows - 1)) / vrows; + + return { + col * (desktop_width + gap()), row * (desktop_height + gap()), + desktop_width, desktop_height + }; + } + + virtual void paint_event(GUI::PaintEvent& event) override + { + GUI::Widget::paint_event(event); + + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + painter.fill_rect({ 0, 0, width(), height() }, palette().button()); + + auto& desktop = GUI::Desktop::the(); + + auto active_color = palette().active_window_border1(); + auto inactive_color = palette().inactive_window_border1(); + + for (unsigned row = 0; row < desktop.virtual_desktop_rows(); ++row) { + for (unsigned col = 0; col < desktop.virtual_desktop_columns(); ++col) { + painter.fill_rect(rect_for_desktop(row, col), + (row == current_row() && col == current_col()) ? active_color : inactive_color); + } + } + } + + virtual void mousedown_event(GUI::MouseEvent& event) override + { + auto base_rect = rect_for_desktop(0, 0); + auto row = event.y() / (base_rect.height() + gap()); + auto col = event.x() / (base_rect.width() + gap()); + + // Handle case where divider is clicked. + if (rect_for_desktop(row, col).contains(event.position())) + GUI::WindowManagerServerConnection::the().async_set_virtual_desktop(row, col); + } + + unsigned current_row() const { return m_current_row; } + void set_current_row(unsigned row) { m_current_row = row; } + unsigned current_col() const { return m_current_col; } + void set_current_col(unsigned col) { m_current_col = col; } + + unsigned gap() const { return m_gap; } + +private: + DesktopStatusWidget() + { + } + + unsigned m_gap { 1 }; + + unsigned m_current_row; + unsigned m_current_col; +}; + +DesktopStatusWindow::DesktopStatusWindow() +{ + GUI::Desktop::the().on_receive_screen_rects([&](GUI::Desktop&) { + update(); + }); + set_window_type(GUI::WindowType::Applet); + set_has_alpha_channel(true); + m_widget = &set_main_widget(); +} + +DesktopStatusWindow::~DesktopStatusWindow() +{ +} + +void DesktopStatusWindow::wm_event(GUI::WMEvent& event) +{ + if (event.type() == GUI::Event::WM_VirtualDesktopChanged) { + auto& changed_event = static_cast(event); + m_widget->set_current_row(changed_event.current_row()); + m_widget->set_current_col(changed_event.current_column()); + update(); + } +} diff --git a/Userland/Applets/DesktopPicker/DesktopStatusWindow.h b/Userland/Applets/DesktopPicker/DesktopStatusWindow.h new file mode 100644 index 0000000000..323dc10b24 --- /dev/null +++ b/Userland/Applets/DesktopPicker/DesktopStatusWindow.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, Peter Elliott + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +class DesktopStatusWidget; + +class DesktopStatusWindow : public GUI::Window { + C_OBJECT(DesktopStatusWindow); + +public: + virtual ~DesktopStatusWindow() override; + + virtual void wm_event(GUI::WMEvent&) override; + +private: + DesktopStatusWindow(); + + DesktopStatusWidget* m_widget; +}; diff --git a/Userland/Applets/DesktopPicker/main.cpp b/Userland/Applets/DesktopPicker/main.cpp new file mode 100644 index 0000000000..61bc2c47a6 --- /dev/null +++ b/Userland/Applets/DesktopPicker/main.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, Peter Elliott + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "DesktopStatusWindow.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + if (pledge("stdio recvfd sendfd rpath unix", nullptr) < 0) { + perror("pledge"); + return 1; + } + + auto app = GUI::Application::construct(argc, argv); + + // We need to obtain the WM connection here as well before the pledge shortening. + GUI::WindowManagerServerConnection::the(); + + if (pledge("stdio recvfd sendfd rpath", nullptr) < 0) { + perror("pledge"); + return 1; + } + + auto window = DesktopStatusWindow::construct(); + window->resize(28, 16); + window->show(); + window->make_window_manager(WindowServer::WMEventMask::VirtualDesktopChanges); + + return app->exec(); +} -- cgit v1.2.3