opuntiaOS - an operating system targeting x86 and ARMv7
at master 186 lines 7.1 kB view raw
1/* 2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors. 3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com> 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#pragma once 10#include "../../shared/Connections/WSConnection.h" 11#include "../Components/ControlBar/ControlBar.h" 12#include "../Components/MenuBar/MenuBar.h" 13#include "../Components/Security/Violations.h" 14#include "../Devices/Screen.h" 15#include "../IPC/Connection.h" 16#include "../IPC/Event.h" 17#include "../IPC/ServerDecoder.h" 18#include "../Managers/Compositor.h" 19#include "../SystemApps/SystemApp.h" 20#include "../Target/Generic/Window.h" 21#include <algorithm> 22#include <libfoundation/EventLoop.h> 23#include <libfoundation/EventReceiver.h> 24#include <libipc/ServerConnection.h> 25#include <list> 26#include <vector> 27 28namespace WinServer { 29 30class WindowManager : public LFoundation::EventReceiver { 31#ifdef TARGET_DESKTOP 32 using Window = WinServer::Desktop::Window; 33#elif TARGET_MOBILE 34 using Window = WinServer::Mobile::Window; 35#endif 36 37public: 38 inline static WindowManager& the() 39 { 40 extern WindowManager* s_WinServer_WindowManager_the; 41 return *s_WinServer_WindowManager_the; 42 } 43 44 WindowManager(); 45 46 void add_window(Window* window); 47 void remove_window(Window* window); 48 49 void resize_window(Window& window, const LG::Size& size); 50 void close_window(Window& window) { send_event(new WindowCloseRequestMessage(window.connection_id(), window.id())); } 51 void minimize_window(Window& window); 52 void maximize_window(Window& window); 53 54 template <typename Callback> 55 void minimize_windows(Callback callback) 56 { 57 std::vector<Window*> hided; 58 for (auto* window : m_windows) { 59 if (window && window->type() == WindowType::Standard && callback(window)) { 60 window->set_visible(false); 61 hided.push_back(window); 62 on_window_became_invisible(window); 63 remove_attention_from_window(window); 64 } 65 } 66 67 for (auto* window : hided) { 68 m_windows.erase(std::find(m_windows.begin(), m_windows.end(), window)); 69 m_windows.push_back(window); 70 } 71 } 72 73 Window* top_window_in_view(WindowType type) const; 74 inline Window* window(int id) 75 { 76 for (auto* window : m_windows) { 77 if (window->id() == id) { 78 return window; 79 } 80 } 81 return nullptr; 82 } 83 84 inline void move_window(Window* window, int x_offset, int y_offset) 85 { 86 y_offset = std::max(y_offset, (int)visible_area().min_y() - (int)Desktop::WindowFrame::std_top_border_frame_size() - window->bounds().min_y()); 87 if (m_dock.has_value()) [[likely]] { 88 y_offset = std::min(y_offset, (int)(visible_area().max_y() - window->content_bounds().min_y())); 89 } 90 window->bounds().offset_by(x_offset, y_offset); 91 window->content_bounds().offset_by(x_offset, y_offset); 92 } 93 94 inline void do_bring_to_front(Window& window) 95 { 96 auto* window_ptr = &window; 97 m_windows.erase(std::find(m_windows.begin(), m_windows.end(), window_ptr)); 98 m_windows.push_front(window_ptr); 99 } 100 void bring_to_front(Window& window); 101 102 inline std::list<Window*>& windows() { return m_windows; } 103 inline const std::list<Window*>& windows() const { return m_windows; } 104 inline int next_win_id() { return ++m_next_win_id; } 105 106 const LG::Rect& visible_area() const { return m_visible_area; } 107 void shrink_visible_area(int top, int bottom) { m_visible_area.set_y(m_visible_area.min_y() + top), m_visible_area.set_height(m_visible_area.height() - top - bottom); } 108 109 void receive_event(std::unique_ptr<LFoundation::Event> event) override; 110 111 // Notifiers 112 bool notify_listner_about_window_creation(const Window& window, int changed_window_id); 113 bool notify_listner_about_window_status(const Window& window, int changed_window_id, WindowStatusUpdateType type); 114 bool notify_listner_about_changed_icon(const Window&, int changed_window_id); 115 bool notify_listner_about_changed_title(const Window&, int changed_window_id); 116 117 void notify_window_creation(int changed_window_id); 118 void notify_window_status_changed(int changed_window_id, WindowStatusUpdateType type); 119 void notify_window_icon_changed(int changed_window_id); 120 void notify_window_title_changed(int changed_window_id); 121 122 inline void ask_to_set_active_window(Window* win) { set_active_window(win); } 123 inline void ask_to_set_active_window(Window& win) { set_active_window(win); } 124 125 void on_window_misbehave(Window& window, ViolationClass); 126 void on_window_style_change(Window& win); 127 void on_window_menubar_change(Window& window); 128 129 // Popup & Menubar 130 inline Popup& popup() { return m_compositor.popup(); } 131 inline const Popup& popup() const { return m_compositor.popup(); } 132 inline MenuBar& menu_bar() { return m_compositor.menu_bar(); } 133 inline const MenuBar& menu_bar() const { return m_compositor.menu_bar(); } 134 135private: 136 void add_system_window(Window* window); 137 void bring_system_windows_to_front(); 138 void setup_dock(Window* window); 139 void setup_applist(Window* window); 140 141 void remove_attention_from_window(Window* window); 142 143 void start_window_move(Window& window); 144 bool continue_window_move(); 145 146 void update_mouse_position(std::unique_ptr<LFoundation::Event> mouse_event); 147 void receive_mouse_event(std::unique_ptr<LFoundation::Event> event); 148 void receive_keyboard_event(std::unique_ptr<LFoundation::Event> event); 149 150 inline Window* movable_window() { return m_movable_window; } 151 inline Window* hovered_window() { return m_hovered_window; } 152 inline void set_hovered_window(Window* win) { m_hovered_window = win; } 153 154 inline Window* active_window() { return m_active_window; } 155 inline void set_active_window(Window* win) { on_active_window_will_change(), bring_to_front(*win), m_active_window = win, on_active_window_did_change(); } 156 inline void set_active_window(Window& win) { on_active_window_will_change(), bring_to_front(win), m_active_window = &win, on_active_window_did_change(); } 157 inline void set_active_window(std::nullptr_t) { on_active_window_will_change(), m_active_window = nullptr, on_active_window_did_change(); } 158 159 void on_window_became_invisible(Window* window); 160 void on_active_window_will_change(); 161 void on_active_window_did_change(); 162 163 inline void send_event(Message* msg) { m_event_loop.add(m_connection, new SendEvent(msg)); } 164 165 std::list<Window*> m_windows; 166 167 Screen& m_screen; 168 Connection& m_connection; 169 Compositor& m_compositor; 170 CursorManager& m_cursor_manager; 171 LFoundation::EventLoop& m_event_loop; 172 std::vector<MenuDir> m_std_menubar_content; 173 174 LG::Rect m_visible_area; 175 176 SystemApp m_dock; 177 SystemApp m_applist; 178 179 // TODO: implement with std::weak_ptr. 180 Window* m_movable_window {}; 181 Window* m_active_window {}; 182 Window* m_hovered_window {}; 183 int m_next_win_id { 0 }; 184}; 185 186} // namespace WinServer