opuntiaOS - an operating system targeting x86 and ARMv7
at master 228 lines 7.8 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#include "ServerDecoder.h" 10#include "../Components/Security/Violations.h" 11#include "../Managers/WindowManager.h" 12#include "../Target/Generic/Window.h" 13 14namespace WinServer { 15 16std::unique_ptr<Message> WindowServerDecoder::handle(GreetMessage& msg) 17{ 18 return new GreetMessageReply(msg.key(), Connection::the().alloc_connection()); 19} 20 21#ifdef TARGET_DESKTOP 22std::unique_ptr<Message> WindowServerDecoder::handle(CreateWindowMessage& msg) 23{ 24 auto& wm = WindowManager::the(); 25 auto& compositor = Compositor::the(); 26 int win_id = wm.next_win_id(); 27 auto* window = new Desktop::Window(msg.key(), win_id, msg); 28 window->set_app_title(msg.title().move_string()); 29 window->set_icon_path(msg.icon_path().move_string()); 30 window->set_style(StatusBarStyle(msg.menubar_style(), msg.color())); 31 wm.add_window(window); 32 if (window->type() == WindowType::Standard) { 33 // After moving windows, we have to invalidate bounds() to make sure that 34 // the whole window is rendered (coords are changes after move). 35 wm.move_window(window, 8 * win_id, MenuBar::height() + 8 * win_id); 36 compositor.invalidate(window->bounds()); 37 } 38 39 wm.notify_window_icon_changed(window->id()); 40 wm.notify_window_title_changed(window->id()); 41 return new CreateWindowMessageReply(msg.key(), win_id); 42} 43#elif TARGET_MOBILE 44std::unique_ptr<Message> WindowServerDecoder::handle(CreateWindowMessage& msg) 45{ 46 auto& wm = WindowManager::the(); 47 int win_id = wm.next_win_id(); 48 auto* window = new Mobile::Window(msg.key(), win_id, msg); 49 window->set_style(StatusBarStyle(msg.menubar_style(), msg.color())); 50 window->set_icon_path(msg.icon_path().move_string()); 51 window->set_style(StatusBarStyle(msg.menubar_style(), msg.color())); 52 wm.add_window(window); 53 wm.move_window(window, 0, MenuBar::height()); 54 wm.notify_window_icon_changed(window->id()); 55 wm.notify_window_title_changed(window->id()); 56 return new CreateWindowMessageReply(msg.key(), win_id); 57} 58#endif 59 60std::unique_ptr<Message> WindowServerDecoder::handle(SetBufferMessage& msg) 61{ 62 auto* window = WindowManager::the().window(msg.window_id()); 63 if (!window) { 64 return nullptr; 65 } 66 67 LG::Size new_size = { msg.bounds().width(), msg.bounds().height() }; 68 window->did_size_change(new_size); 69 window->set_buffer(msg.buffer_id(), new_size, LG::PixelBitmapFormat(msg.format())); 70 return nullptr; 71} 72 73std::unique_ptr<Message> WindowServerDecoder::handle(DestroyWindowMessage& msg) 74{ 75 auto& wm = WindowManager::the(); 76 auto* window = wm.window(msg.window_id()); 77 if (!window) { 78 wm.on_window_misbehave(*window, ViolationClass::Ignorable); 79 return new DestroyWindowMessageReply(msg.key(), 1); 80 } 81 82 if (window->connection_id() != msg.key()) { 83 wm.on_window_misbehave(*window, ViolationClass::Serious); 84 return new DestroyWindowMessageReply(msg.key(), 1); 85 } 86 wm.remove_window(window); 87 return new DestroyWindowMessageReply(msg.key(), 0); 88} 89 90std::unique_ptr<Message> WindowServerDecoder::handle(InvalidateMessage& msg) 91{ 92 auto& wm = WindowManager::the(); 93 auto* window = wm.window(msg.window_id()); 94 if (!window) { 95 return nullptr; 96 } 97 auto rect = msg.rect(); 98 rect.offset_by(window->content_bounds().origin()); 99 rect.intersect(window->content_bounds()); 100 Compositor::the().invalidate(rect); 101 return nullptr; 102} 103 104#ifdef TARGET_DESKTOP 105std::unique_ptr<Message> WindowServerDecoder::handle(SetTitleMessage& msg) 106{ 107 auto& wm = WindowManager::the(); 108 auto* window = wm.window(msg.window_id()); 109 if (!window) { 110 return nullptr; 111 } 112 window->set_app_title(msg.title().string()); 113 114 auto& compositor = Compositor::the(); 115 compositor.invalidate(compositor.menu_bar().bounds()); 116 wm.notify_window_title_changed(window->id()); 117 return nullptr; 118} 119#elif TARGET_MOBILE 120std::unique_ptr<Message> WindowServerDecoder::handle(SetTitleMessage& msg) 121{ 122 return nullptr; 123} 124#endif 125 126std::unique_ptr<Message> WindowServerDecoder::handle(SetBarStyleMessage& msg) 127{ 128 auto& wm = WindowManager::the(); 129 auto* window = wm.window(msg.window_id()); 130 if (!window) { 131 return nullptr; 132 } 133 134 window->set_style(StatusBarStyle(msg.menubar_style(), msg.color())); 135 return nullptr; 136} 137 138#ifdef TARGET_DESKTOP 139std::unique_ptr<Message> WindowServerDecoder::handle(MenuBarCreateMenuMessage& msg) 140{ 141 auto& wm = WindowManager::the(); 142 auto* window = wm.window(msg.window_id()); 143 if (!window) { 144 return new MenuBarCreateMenuMessageReply(msg.key(), -1, 0); 145 } 146 147 int id = window->menubar_content().size(); 148 window->menubar_content().push_back(MenuDir(msg.title().string(), id)); 149 window->on_menubar_change(); 150 return new MenuBarCreateMenuMessageReply(msg.key(), 0, id); 151} 152 153std::unique_ptr<Message> WindowServerDecoder::handle(MenuBarCreateItemMessage& msg) 154{ 155 auto& wm = WindowManager::the(); 156 auto* window = wm.window(msg.window_id()); 157 if (!window) { 158 return new MenuBarCreateItemMessageReply(msg.key(), -1); 159 } 160 161 auto menu_id = msg.menu_id(); 162 if (menu_id == 0 || window->menubar_content().size() <= menu_id) { 163 return new MenuBarCreateItemMessageReply(msg.key(), -2); 164 } 165 166 auto callback = [window, menu_id](int item_id) { LFoundation::EventLoop::the().add(Connection::the(), 167 new SendEvent(new MenuBarActionMessage(window->connection_id(), window->id(), menu_id, item_id))); }; 168 window->menubar_content()[menu_id].add_item(PopupItem { msg.item_id(), msg.title().string(), callback }); 169 // TODO: Currently we don't redraw popup after a new item was added. 170 return new MenuBarCreateItemMessageReply(msg.key(), 0); 171} 172#elif TARGET_MOBILE 173std::unique_ptr<Message> WindowServerDecoder::handle(MenuBarCreateMenuMessage& msg) 174{ 175 return new MenuBarCreateMenuMessageReply(msg.key(), -100, 0); 176} 177 178std::unique_ptr<Message> WindowServerDecoder::handle(MenuBarCreateItemMessage& msg) 179{ 180 return new MenuBarCreateItemMessageReply(msg.key(), -100); 181} 182#endif 183 184std::unique_ptr<Message> WindowServerDecoder::handle(PopupShowMenuMessage& msg) 185{ 186 auto& wm = WindowManager::the(); 187 auto* window = wm.window(msg.window_id()); 188 189 if (!window) { 190 return new PopupShowMenuMessageReply(msg.key(), -1, -1); 191 } 192 193 std::vector<std::string> res; 194 for (int i = 0; i < msg.data().vector().size(); i++) { 195 res.push_back(msg.data().vector()[i].move_string()); 196 } 197 198 PopupData popup_data; 199 int item_id = 0; 200 int menu_id = 0; 201 202 for (auto& title : res) { 203 auto callback = [window, menu_id](int item_id) { LFoundation::EventLoop::the().add(Connection::the(), 204 new SendEvent(new PopupActionMessage(window->connection_id(), window->id(), menu_id, item_id))); }; 205 popup_data.push_back(PopupItem { item_id, title, callback }); 206 item_id++; 207 } 208 209 wm.popup().show({ msg.point() }, popup_data); 210 return new PopupShowMenuMessageReply(msg.key(), 0, 0); 211} 212 213std::unique_ptr<Message> WindowServerDecoder::handle(AskBringToFrontMessage& msg) 214{ 215 auto& wm = WindowManager::the(); 216 auto* window = wm.window(msg.window_id()); 217 auto* target_window = wm.window(msg.target_window_id()); 218 if (!window || !target_window) { 219 return nullptr; 220 } 221 if (window->type() == WindowType::Homescreen) { 222 // Only dock can ask for that now. 223 wm.ask_to_set_active_window(*target_window); 224 } 225 return nullptr; 226} 227 228} // namespace WinServer