opuntiaOS - an operating system targeting x86 and ARMv7
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[window server] Add mobile homescreen and control bar

+421 -22
base/res/icons/apps/about.icon/48x48.png

This is a binary file and will not be displayed.

base/res/icons/apps/activity_monitor.icon/48x48.png

This is a binary file and will not be displayed.

base/res/icons/apps/logo.icon/48x48.png

This is a binary file and will not be displayed.

base/res/icons/apps/missing.icon/48x48.png

This is a binary file and will not be displayed.

base/res/icons/apps/terminal.icon/48x48.png

This is a binary file and will not be displayed.

base/res/system/mobile/control.png

This is a binary file and will not be displayed.

base/res/system/mobile/cursor.png

This is a binary file and will not be displayed.

+1
build/userland/BUILD.gn
··· 89 89 "//userland/activity_monitor:activity_monitor", 90 90 "//userland/cat:cat", 91 91 "//userland/dock:dock", 92 + "//userland/homescreen:homescreen", 92 93 "//userland/init:init", 93 94 "//userland/initgui:initgui", 94 95 "//userland/kill:kill",
+4
libs/libui/include/libui/View.h
··· 20 20 21 21 struct SafeArea { 22 22 static const int Top = 8; 23 + #ifdef TARGET_DESKTOP 23 24 static const int Bottom = 8; 25 + #elif TARGET_MOBILE 26 + static const int Bottom = 20; 27 + #endif 24 28 static const int Left = 8; 25 29 static const int Right = 8; 26 30 };
+1 -1
libs/libui/include/libui/Window.h
··· 22 22 23 23 enum WindowType { 24 24 Standard = 0, 25 - Dock = 1, 25 + Homescreen = 1, 26 26 }; 27 27 28 28 class Connection;
+4 -1
servers/window_server/BUILD.gn
··· 26 26 } 27 27 if (device_type == "mobile") { 28 28 cflags = [ "-DTARGET_MOBILE" ] 29 - sources += [ "src/Mobile/Window.cpp" ] 29 + sources += [ 30 + "src/Components/ControlBar/ControlBar.cpp", 31 + "src/Mobile/Window.cpp", 32 + ] 30 33 } 31 34 32 35 configs = [ "//build/userland:userland_flags" ]
+1 -1
servers/window_server/src/Components/Base/BaseWindow.h
··· 19 19 20 20 enum WindowType : int { 21 21 Standard = 0, 22 - Dock = 1, 22 + Homescreen = 1, 23 23 }; 24 24 25 25 enum WindowStatusUpdateType : int {
+32
servers/window_server/src/Components/ControlBar/ControlBar.cpp
··· 1 + /* 2 + * Copyright (C) 2020-2021 Nikita Melekhin. All rights reserved. 3 + * 4 + * Use of this source code is governed by a BSD-style license that can be 5 + * found in the LICENSE file. 6 + */ 7 + 8 + #include "ControlBar.h" 9 + #include "../../Compositor.h" 10 + #include <libg/ImageLoaders/PNGLoader.h> 11 + 12 + namespace WinServer { 13 + 14 + static ControlBar* s_the; 15 + 16 + ControlBar& ControlBar::the() 17 + { 18 + return *s_the; 19 + } 20 + 21 + ControlBar::ControlBar() 22 + : m_bounds(0, Screen::the().bounds().height() - height(), Screen::the().bounds().width(), height()) 23 + { 24 + s_the = this; 25 + LG::PNG::PNGLoader loader; 26 + m_logo = loader.load_from_file("/res/system/mobile/control.png"); 27 + int x = width() / 2 - m_logo.width() / 2; 28 + int y = Screen::the().bounds().height() - height() + height() / 2 - m_logo.height() / 2; 29 + m_button_bounds = LG::Rect(x, y, m_logo.width(), m_logo.height()); 30 + } 31 + 32 + } // namespace WinServer
+44
servers/window_server/src/Components/ControlBar/ControlBar.h
··· 1 + /* 2 + * Copyright (C) 2020-2021 Nikita Melekhin. All rights reserved. 3 + * 4 + * Use of this source code is governed by a BSD-style license that can be 5 + * found in the LICENSE file. 6 + */ 7 + 8 + #pragma once 9 + #include "../../CursorManager.h" 10 + #include "../../Desktop/Window.h" 11 + #include <libfoundation/Logger.h> 12 + #include <libg/Context.h> 13 + #include <libg/PixelBitmap.h> 14 + #include <libg/Point.h> 15 + #include <vector> 16 + 17 + namespace WinServer { 18 + 19 + class ControlBar { 20 + public: 21 + static ControlBar& the(); 22 + ControlBar(); 23 + 24 + static constexpr size_t height() { return 20; } 25 + static constexpr size_t padding() { return 4; } 26 + static constexpr size_t menubar_content_offset() { return 20; } 27 + 28 + size_t width() const { return m_bounds.width(); } 29 + LG::Rect& bounds() { return m_bounds; } 30 + const LG::Rect& bounds() const { return m_bounds; } 31 + const LG::Rect& control_button_bounds() const { return m_button_bounds; } 32 + 33 + [[gnu::always_inline]] inline void draw(LG::Context& ctx) 34 + { 35 + ctx.draw({ control_button_bounds().min_x(), control_button_bounds().min_y() }, m_logo); 36 + } 37 + 38 + private: 39 + LG::Rect m_bounds; 40 + LG::Rect m_button_bounds; 41 + LG::PixelBitmap m_logo; 42 + }; 43 + 44 + } // namespace WinServer
+13 -1
servers/window_server/src/Compositor.cpp
··· 7 7 8 8 #include "Compositor.h" 9 9 #include "Components/Base/BaseWindow.h" 10 + #include "Components/ControlBar/ControlBar.h" 10 11 #include "Components/MenuBar/MenuBar.h" 11 12 #include "CursorManager.h" 12 13 #include "ResourceManager.h" ··· 29 30 : m_cursor_manager(CursorManager::the()) 30 31 , m_resource_manager(ResourceManager::the()) 31 32 , m_menu_bar(MenuBar::the()) 33 + #ifdef TARGET_MOBILE 34 + , m_control_bar(ControlBar::the()) 35 + #endif // TARGET_MOBILE 32 36 { 33 37 s_the = this; 34 38 invalidate(Screen::the().bounds()); ··· 95 99 ctx.draw(window.content_bounds().origin(), window.content_bitmap()); 96 100 ctx.reset_clip(); 97 101 }; 98 - #endif // #ifdef TARGET_DESKTOP 102 + #endif // TARGET_DESKTOP 99 103 100 104 for (int i = 0; i < invalidated_areas.size(); i++) { 101 105 draw_wallpaper_for_area(invalidated_areas[i]); ··· 116 120 m_menu_bar.draw(ctx); 117 121 ctx.reset_clip(); 118 122 } 123 + 124 + #ifdef TARGET_MOBILE 125 + for (int i = 0; i < invalidated_areas.size(); i++) { 126 + ctx.add_clip(invalidated_areas[i]); 127 + m_control_bar.draw(ctx); 128 + ctx.reset_clip(); 129 + } 130 + #endif // TARGET_MOBILE 119 131 120 132 auto mouse_draw_position = m_cursor_manager.draw_position(); 121 133 auto& current_mouse_bitmap = m_cursor_manager.current_cursor();
+11 -1
servers/window_server/src/Compositor.h
··· 16 16 class CursorManager; 17 17 class ResourceManager; 18 18 class MenuBar; 19 + #ifdef TARGET_MOBILE 20 + class ControlBar; 21 + #endif // TARGET_MOBILE 19 22 20 23 class Compositor { 21 24 public: ··· 49 52 inline const ResourceManager& resource_manager() const { return m_resource_manager; } 50 53 inline MenuBar& menu_bar() { return m_menu_bar; } 51 54 inline const MenuBar& menu_bar() const { return m_menu_bar; } 55 + #ifdef TARGET_MOBILE 56 + inline ControlBar& control_bar() { return m_control_bar; } 57 + inline const ControlBar& control_bar() const { return m_control_bar; } 58 + #endif // TARGET_MOBILE 52 59 53 60 private: 54 61 void copy_changes_to_second_buffer(const std::vector<LG::Rect>& areas); 55 62 63 + std::vector<LG::Rect> m_invalidated_areas; 56 64 MenuBar& m_menu_bar; 57 65 CursorManager& m_cursor_manager; 58 66 ResourceManager& m_resource_manager; 59 - std::vector<LG::Rect> m_invalidated_areas; 67 + #ifdef TARGET_MOBILE 68 + ControlBar& m_control_bar; 69 + #endif // TARGET_MOBILE 60 70 }; 61 71 62 72 } // namespace WinServer
+4
servers/window_server/src/CursorManager.cpp
··· 22 22 { 23 23 s_the = this; 24 24 LG::PNG::PNGLoader loader; 25 + #ifdef TARGET_DESKTOP 25 26 m_std_cursor = loader.load_from_file("/res/system/arrow.png"); 27 + #elif TARGET_MOBILE 28 + m_std_cursor = loader.load_from_file("/res/system/mobile/cursor.png"); 29 + #endif 26 30 } 27 31 28 32 } // namespace WinServer
+19 -7
servers/window_server/src/CursorManager.h
··· 6 6 */ 7 7 8 8 #pragma once 9 - #include "Screen.h" 10 9 #include "Event.h" 10 + #include "Screen.h" 11 11 #include <algorithm> 12 12 #include <libg/PixelBitmap.h> 13 13 #include <libg/Point.h> ··· 34 34 35 35 inline const LG::PixelBitmap& current_cursor() const { return std_cursor(); } 36 36 inline const LG::PixelBitmap& std_cursor() const { return m_std_cursor; } 37 + #ifdef TARGET_DESKTOP 37 38 inline LG::Point<int> draw_position() { return { m_mouse_x - 2, m_mouse_y - 2 }; } 39 + #elif TARGET_MOBILE 40 + inline LG::Point<int> draw_position() { return { m_mouse_x - 6, m_mouse_y - 6 }; } 41 + #endif 38 42 39 - inline int x() const { return m_mouse_x; } 43 + inline int x() const 44 + { 45 + return m_mouse_x; 46 + } 40 47 inline int y() const { return m_mouse_y; } 41 48 42 49 template <Params param> ··· 72 79 } 73 80 m_mouse_left_button_pressed = val; 74 81 } else { 75 - []<bool flag = false>() { static_assert(flag, "Could not call set() with such param!"); } (); 82 + []<bool flag = false>() { static_assert(flag, "Could not call set() with such param!"); } 83 + (); 76 84 } 77 85 } 78 86 ··· 86 94 } else if constexpr (param == CursorManager::Params::LeftButton) { 87 95 m_mask_changed_objects |= CursorManager::ChangedValues::LeftButton; 88 96 } else { 89 - []<bool flag = false>() { static_assert(flag, "Could not set_changed() for the param!"); } (); 97 + []<bool flag = false>() { static_assert(flag, "Could not set_changed() for the param!"); } 98 + (); 90 99 } 91 100 } 92 101 ··· 129 138 } else if constexpr (param == CursorManager::Params::OffsetY) { 130 139 return m_mouse_offset_y; 131 140 } else { 132 - []<bool flag = false>() { static_assert(flag, "Could call get() only for coords-like params!"); } (); 141 + []<bool flag = false>() { static_assert(flag, "Could call get() only for coords-like params!"); } 142 + (); 133 143 } 134 144 } 135 145 ··· 139 149 if constexpr (param == CursorManager::Params::LeftButton) { 140 150 return m_mouse_left_button_pressed; 141 151 } else { 142 - []<bool flag = false>() { static_assert(flag, "Could call pressed() only for buttons!"); } (); 152 + []<bool flag = false>() { static_assert(flag, "Could call pressed() only for buttons!"); } 153 + (); 143 154 } 144 155 } 145 156 ··· 157 168 } else if constexpr (param == CursorManager::Params::Buttons) { 158 169 return (m_mask_changed_objects & CursorManager::ChangedValues::LeftButton) | (m_mask_changed_objects & CursorManager::ChangedValues::RightButton); 159 170 } else { 160 - []<bool flag = false>() { static_assert(flag, "Could not call is_changed() for the param!"); } (); 171 + []<bool flag = false>() { static_assert(flag, "Could not call is_changed() for the param!"); } 172 + (); 161 173 } 162 174 } 163 175
+2 -4
servers/window_server/src/ServerDecoder.cpp
··· 43 43 auto* window = new Mobile::Window(msg.key(), win_id, msg); 44 44 wm.add_window(window); 45 45 wm.notify_window_icon_changed(window->id()); 46 - if (window->type() == WindowType::Standard) { 47 - wm.move_window(window, 0, MenuBar::height()); 48 - } 46 + wm.move_window(window, 0, MenuBar::height()); 49 47 return new CreateWindowMessageReply(msg.key(), win_id); 50 48 } 51 49 #endif ··· 127 125 if (!window || !target_window) { 128 126 return nullptr; 129 127 } 130 - if (window->type() == WindowType::Dock) { 128 + if (window->type() == WindowType::Homescreen) { 131 129 // Only dock can ask for that now. 132 130 wm.bring_to_front(*target_window); 133 131 }
+18 -3
servers/window_server/src/WindowManager.cpp
··· 51 51 #elif TARGET_MOBILE 52 52 void WindowManager::setup_dock(Window* window) 53 53 { 54 - window->bounds().set_y(m_screen.bounds().max_y() - window->bounds().height() + 1); 55 - window->content_bounds().set_y(m_screen.bounds().max_y() - window->bounds().height() + 1); 56 - window->set_event_mask(WindowEvent::IconChange | WindowEvent::WindowStatus); 57 54 m_dock_window = window->weak_ptr(); 58 55 } 59 56 #endif // TARGET_MOBILE ··· 163 160 { 164 161 auto* mouse_event = (MouseEvent*)event.release(); 165 162 update_mouse_position(mouse_event); 163 + 164 + if (m_compositor.control_bar().control_button_bounds().contains(m_cursor_manager.x(), m_cursor_manager.y()) && active_window()) { 165 + if (m_cursor_manager.pressed<CursorManager::Params::LeftButton>()) { 166 + remove_window(active_window().ptr()); 167 + } 168 + goto end; 169 + } 170 + 171 + // Tap emulation 172 + if (m_cursor_manager.is_changed<CursorManager::Params::Buttons>() && active_window()) { 173 + auto window = active_window(); 174 + LG::Point<int> point(m_cursor_manager.x(), m_cursor_manager.y()); 175 + point.offset_by(-window->content_bounds().origin()); 176 + bool is_left_pressed = m_cursor_manager.pressed<CursorManager::Params::LeftButton>(); 177 + Logger::debug << "Tapping " << point.x() << " " << point.y() << std::endl; 178 + m_event_loop.add(m_connection, new SendEvent(new MouseActionMessage(window->connection_id(), window->id(), !is_left_pressed, point.x(), point.y()))); 179 + } 180 + end: 166 181 delete mouse_event; 167 182 } 168 183 #endif // TARGET_MOBILE
+12 -2
servers/window_server/src/WindowManager.h
··· 7 7 8 8 #pragma once 9 9 #include "../shared/Connections/WSConnection.h" 10 + #include "Components/ControlBar/ControlBar.h" 10 11 #include "Components/MenuBar/MenuBar.h" 11 12 #include "Compositor.h" 12 13 #include "Connection.h" ··· 40 41 41 42 inline void add_window(Window* window) 42 43 { 43 - if (window->type() == WindowType::Dock) { 44 + if (window->type() == WindowType::Homescreen) { 44 45 setup_dock(window); 45 46 } 46 47 m_windows.push_back(window); ··· 50 51 51 52 inline void remove_window(Window* window) 52 53 { 54 + if (m_dock_window.ptr() == window) { 55 + return; 56 + } 53 57 if (movable_window().ptr() == window) { 54 58 m_movable_window = nullptr; 55 59 } ··· 63 67 m_compositor.menu_bar().set_menubar_content(&m_std_menubar_content, m_compositor); 64 68 m_compositor.invalidate(window->bounds()); 65 69 notify_window_status_changed(window->id(), WindowStatusUpdateType::Removed); 70 + #ifdef TARGET_MOBILE 71 + auto* top_window = get_top_standard_window_in_view(); 72 + if (top_window) { 73 + m_active_window = top_window->weak_ptr(); 74 + } 75 + #endif 66 76 delete window; 67 77 } 68 78 ··· 109 119 { 110 120 auto* prev_window = get_top_standard_window_in_view(); 111 121 do_bring_to_front(window); 122 + #ifdef TARGET_DESKTOP 112 123 if (m_dock_window) { 113 124 do_bring_to_front(*m_dock_window); 114 125 } 115 - #ifdef TARGET_DESKTOP 116 126 window.frame().set_active(true); 117 127 m_compositor.invalidate(window.bounds()); 118 128 if (prev_window && prev_window->id() != window.id()) {
+8
servers/window_server/src/main.cpp
··· 5 5 * found in the LICENSE file. 6 6 */ 7 7 8 + #include "Components/ControlBar/ControlBar.h" 8 9 #include "Components/MenuBar/MenuBar.h" 9 10 #include "Components/MenuBar/Widgets/Clock/Clock.h" 10 11 #include "Compositor.h" ··· 23 24 void start_dock() 24 25 { 25 26 if (fork()) { 27 + #ifdef TARGET_DESKTOP 26 28 execve("/bin/dock", nullptr, nullptr); 29 + #elif TARGET_MOBILE 30 + execve("/bin/homescreen", nullptr, nullptr); 31 + #endif 27 32 std::abort(); 28 33 } 29 34 } ··· 37 42 new WinServer::CursorManager(); 38 43 new WinServer::ResourceManager(); 39 44 new WinServer::MenuBar(); 45 + #ifdef TARGET_MOBILE 46 + new WinServer::ControlBar(); 47 + #endif 40 48 new WinServer::Compositor(); 41 49 new WinServer::WindowManager(); 42 50 new WinServer::Devices();
+1 -1
userland/dock/DockWindow.h
··· 6 6 class DockWindow : public UI::Window { 7 7 public: 8 8 DockWindow() 9 - : UI::Window(LG::Size(1024, 36), UI::WindowType::Dock) 9 + : UI::Window(LG::Size(1024, 36), UI::WindowType::Homescreen) 10 10 { 11 11 } 12 12
+5
userland/homescreen/.info.mk
··· 1 + APPS += DOCK 2 + 3 + DOCK_NAME = dock 4 + DOCK_LIBS = cxx ui 5 + DOCK_INSTALL_PATH = bin/
+26
userland/homescreen/AppDelegate.cpp
··· 1 + #include "HomeScreenView.h" 2 + #include "HomeScreenViewController.h" 3 + #include "HomeScreenWindow.h" 4 + #include <libui/AppDelegate.h> 5 + 6 + class AppDelegate : public UI::AppDelegate { 7 + public: 8 + AppDelegate() = default; 9 + virtual ~AppDelegate() = default; 10 + 11 + LG::Size preferred_desktop_window_size() const override { return LG::Size(400, 300); } 12 + 13 + bool application() override 14 + { 15 + auto& window = std::oneos::construct<HomeScreenWindow>(window_size()); 16 + window.set_bitmap_format(LG::PixelBitmapFormat::RGBA); // Turning on Alpha channel 17 + auto& dock_view = window.create_superview<HomeScreenView, HomeScreenViewController>(); 18 + 19 + window.set_title("Homescreen"); 20 + return true; 21 + } 22 + 23 + private: 24 + }; 25 + 26 + SET_APP_DELEGATE(AppDelegate);
+16
userland/homescreen/BUILD.gn
··· 1 + import("//build/userland/TEMPLATE.gni") 2 + 3 + oneOS_executable("homescreen") { 4 + install_path = "bin/" 5 + sources = [ 6 + "AppDelegate.cpp", 7 + "HomeScreenView.cpp", 8 + ] 9 + configs = [ "//build/userland:userland_flags" ] 10 + deplibs = [ 11 + "libcxx", 12 + "libfoundation", 13 + "libg", 14 + "libui", 15 + ] 16 + }
+18
userland/homescreen/FastLaunchEntity.h
··· 1 + #pragma once 2 + #include <libg/PixelBitmap.h> 3 + #include <libg/string.h> 4 + 5 + class FastLaunchEntity { 6 + public: 7 + FastLaunchEntity() = default; 8 + 9 + void set_icon(LG::PixelBitmap&& icon) { m_icon = std::move(icon); } 10 + const LG::PixelBitmap& icon() const { return m_icon; } 11 + 12 + void set_path_to_exec(LG::string&& path) { m_path_to_exec = std::move(path); } 13 + const LG::string& path_to_exec() const { return m_path_to_exec; } 14 + 15 + private: 16 + LG::PixelBitmap m_icon; 17 + LG::string m_path_to_exec {}; 18 + };
+24
userland/homescreen/HomeScreenEntity.h
··· 1 + #pragma once 2 + #include <libg/PixelBitmap.h> 3 + 4 + class HomeScreenEntity { 5 + public: 6 + HomeScreenEntity() = default; 7 + 8 + HomeScreenEntity(int window_id) 9 + : m_window_id(window_id) 10 + { 11 + } 12 + 13 + bool operator==(const HomeScreenEntity& other) const { return m_window_id == other.m_window_id; } 14 + bool operator!=(const HomeScreenEntity& other) const { return m_window_id != other.m_window_id; } 15 + 16 + int window_id() const { return m_window_id; } 17 + void set_icon(LG::PixelBitmap&& icon) { m_icon = std::move(icon); } 18 + const LG::PixelBitmap& icon() const { return m_icon; } 19 + 20 + private: 21 + int m_window_id { 0 }; 22 + LG::PixelBitmap m_icon; 23 + int m_window_status { 0 }; 24 + };
+84
userland/homescreen/HomeScreenView.cpp
··· 1 + #include "HomeScreenView.h" 2 + #include <algorithm> 3 + #include <cstdlib> 4 + #include <libfoundation/EventLoop.h> 5 + #include <libfoundation/KeyboardMapping.h> 6 + #include <libg/Color.h> 7 + #include <libg/ImageLoaders/PNGLoader.h> 8 + #include <libui/App.h> 9 + #include <libui/Context.h> 10 + #include <unistd.h> 11 + 12 + static HomeScreenView* this_view; 13 + static int icons_per_line = 4; 14 + static int icons_per_column = 5; 15 + 16 + HomeScreenView::HomeScreenView(View* superview, const LG::Rect& frame) 17 + : View(superview, frame) 18 + { 19 + } 20 + 21 + void HomeScreenView::display(const LG::Rect& rect) 22 + { 23 + // FIXME: Rendering is a bit studip now, will rewrite it 24 + // completely when stackview is available. 25 + UI::Context ctx(*this); 26 + ctx.add_clip(rect); 27 + 28 + ctx.set_fill_color(LG::Color(222, 222, 222, 0)); 29 + ctx.fill(bounds()); 30 + 31 + // Drawing launched icons 32 + int spacing_x = (bounds().width() - 48 * icons_per_line) / 6; 33 + int spacing_y = (bounds().height() - 48 * icons_per_column) / 7; 34 + int offsetx = spacing_x + 4; 35 + int offsety = spacing_y; 36 + int drawn = 0; 37 + for (auto& entity : m_fast_launch_entites) { 38 + ctx.draw({ offsetx, offsety }, entity.icon()); 39 + offsetx += entity.icon().bounds().width() + spacing_x; 40 + drawn++; 41 + if (drawn == icons_per_line) { 42 + offsetx = spacing_x + 4; 43 + offsety += spacing_y; 44 + } 45 + } 46 + } 47 + 48 + void HomeScreenView::new_fast_launch_entity(const LG::string& icon_path, LG::string&& exec_path) 49 + { 50 + LG::PNG::PNGLoader loader; 51 + m_fast_launch_entites.push_back(FastLaunchEntity()); 52 + m_fast_launch_entites.back().set_icon(loader.load_from_file(icon_path + "/48x48.png")); 53 + m_fast_launch_entites.back().set_path_to_exec(std::move(exec_path)); 54 + set_needs_display(); 55 + } 56 + 57 + void HomeScreenView::launch(const FastLaunchEntity& ent) 58 + { 59 + if (fork() == 0) { 60 + execve(ent.path_to_exec().c_str(), 0, 0); 61 + std::abort(); 62 + } 63 + } 64 + 65 + void HomeScreenView::click_began(const LG::Point<int>& location) 66 + { 67 + int spacing_x = (bounds().width() - 48 * icons_per_line) / 6; 68 + int spacing_y = (bounds().height() - 48 * icons_per_column) / 7; 69 + int offsetx = spacing_x + 4; 70 + int offsety = spacing_y; 71 + int drawn = 0; 72 + for (auto& entity : m_fast_launch_entites) { 73 + auto it = LG::Rect(offsetx, offsety, 48, 48); 74 + if (it.contains(location)) { 75 + launch(entity); 76 + } 77 + offsetx += entity.icon().bounds().width() + spacing_x; 78 + drawn++; 79 + if (drawn == icons_per_line) { 80 + offsetx = spacing_x + 4; 81 + offsety += spacing_y; 82 + } 83 + } 84 + }
+24
userland/homescreen/HomeScreenView.h
··· 1 + #pragma once 2 + #include "FastLaunchEntity.h" 3 + #include "HomeScreenEntity.h" 4 + #include <libg/Font.h> 5 + #include <libui/View.h> 6 + #include <list> 7 + #include <string> 8 + 9 + class HomeScreenView : public UI::View { 10 + UI_OBJECT(); 11 + 12 + public: 13 + HomeScreenView(View* superview, const LG::Rect& frame); 14 + 15 + void display(const LG::Rect& rect) override; 16 + void click_began(const LG::Point<int>& location) override; 17 + 18 + void new_fast_launch_entity(const LG::string& icon_path, LG::string&& exec_path); 19 + 20 + private: 21 + void launch(const FastLaunchEntity& ent); 22 + 23 + std::list<FastLaunchEntity> m_fast_launch_entites {}; 24 + };
+37
userland/homescreen/HomeScreenViewController.h
··· 1 + /* 2 + * Copyright (C) 2020-2021 Nikita Melekhin. All rights reserved. 3 + * 4 + * Use of this source code is governed by a BSD-style license that can be 5 + * found in the LICENSE file. 6 + */ 7 + 8 + #pragma once 9 + #include "HomeScreenView.h" 10 + #include <libui/App.h> 11 + #include <libui/Button.h> 12 + #include <libui/Label.h> 13 + #include <libui/View.h> 14 + #include <libui/ViewController.h> 15 + #include <libui/Window.h> 16 + #include <memory> 17 + #include <sys/types.h> 18 + 19 + class HomeScreenViewController : public UI::ViewController<HomeScreenView> { 20 + public: 21 + HomeScreenViewController(HomeScreenView& view) 22 + : UI::ViewController<HomeScreenView>(view) 23 + { 24 + } 25 + virtual ~HomeScreenViewController() = default; 26 + 27 + virtual void view_did_load() override 28 + { 29 + view().set_background_color(LG::Color(222, 222, 222, 180)); 30 + view().new_fast_launch_entity("/res/icons/apps/about.icon", "/bin/about"); // FIXME: Parse some init file 31 + view().new_fast_launch_entity("/res/icons/apps/terminal.icon", "/bin/terminal"); 32 + view().new_fast_launch_entity("/res/icons/apps/activity_monitor.icon", "/bin/activity_monitor"); 33 + view().set_needs_display(); 34 + } 35 + 36 + private: 37 + };
+12
userland/homescreen/HomeScreenWindow.h
··· 1 + #pragma once 2 + 3 + #include <libg/Size.h> 4 + #include <libui/Window.h> 5 + 6 + class HomeScreenWindow : public UI::Window { 7 + public: 8 + HomeScreenWindow(const LG::Size& size) 9 + : UI::Window(size, UI::WindowType::Homescreen) 10 + { 11 + } 12 + };