Serenity Operating System
at master 190 lines 6.7 kB view raw
1/* 2 * Copyright (c) 2021, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <WindowServer/AppletManager.h> 8#include <WindowServer/ConnectionFromClient.h> 9#include <WindowServer/Screen.h> 10#include <WindowServer/WMConnectionFromClient.h> 11 12namespace WindowServer { 13 14HashMap<int, NonnullRefPtr<WMConnectionFromClient>> WMConnectionFromClient::s_connections {}; 15 16WMConnectionFromClient::WMConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id) 17 : IPC::ConnectionFromClient<WindowManagerClientEndpoint, WindowManagerServerEndpoint>(*this, move(client_socket), client_id) 18{ 19 s_connections.set(client_id, *this); 20} 21 22WMConnectionFromClient::~WMConnectionFromClient() 23{ 24 // The WM has gone away, so take away the applet manager (cause there's nowhere 25 // to draw it in). 26 AppletManager::the().set_position({}); 27} 28 29void WMConnectionFromClient::die() 30{ 31 deferred_invoke([this] { 32 s_connections.remove(client_id()); 33 }); 34} 35 36void WMConnectionFromClient::set_applet_area_position(Gfx::IntPoint position) 37{ 38 if (m_window_id < 0) { 39 did_misbehave("SetAppletAreaPosition: WM didn't assign window as manager yet"); 40 // FIXME: return ok boolean? 41 return; 42 } 43 44 AppletManager::the().set_position(position); 45 46 WindowServer::ConnectionFromClient::for_each_client([](auto& connection) { 47 if (auto result = connection.post_message(Messages::WindowClient::AppletAreaRectChanged(AppletManager::the().window()->rect())); result.is_error()) { 48 dbgln("WMConnectionFromClient::set_applet_area_position: {}", result.error()); 49 } 50 }); 51} 52 53void WMConnectionFromClient::set_active_window(i32 client_id, i32 window_id) 54{ 55 auto* client = WindowServer::ConnectionFromClient::from_client_id(client_id); 56 if (!client) { 57 did_misbehave("SetActiveWindow: Bad client ID"); 58 return; 59 } 60 auto it = client->m_windows.find(window_id); 61 if (it == client->m_windows.end()) { 62 did_misbehave("SetActiveWindow: Bad window ID"); 63 return; 64 } 65 auto& window = *(*it).value; 66 WindowManager::the().move_to_front_and_make_active(window); 67} 68 69void WMConnectionFromClient::popup_window_menu(i32 client_id, i32 window_id, Gfx::IntPoint screen_position) 70{ 71 auto* client = WindowServer::ConnectionFromClient::from_client_id(client_id); 72 if (!client) { 73 did_misbehave("PopupWindowMenu: Bad client ID"); 74 return; 75 } 76 auto it = client->m_windows.find(window_id); 77 if (it == client->m_windows.end()) { 78 did_misbehave("PopupWindowMenu: Bad window ID"); 79 return; 80 } 81 auto& window = *(*it).value; 82 if (auto* modal_window = window.blocking_modal_window()) { 83 modal_window->popup_window_menu(screen_position, WindowMenuDefaultAction::BasedOnWindowState); 84 } else { 85 window.popup_window_menu(screen_position, WindowMenuDefaultAction::BasedOnWindowState); 86 } 87} 88 89void WMConnectionFromClient::start_window_resize(i32 client_id, i32 window_id, i32 resize_direction) 90{ 91 auto* client = WindowServer::ConnectionFromClient::from_client_id(client_id); 92 if (!client) { 93 did_misbehave("WM_StartWindowResize: Bad client ID"); 94 return; 95 } 96 auto it = client->m_windows.find(window_id); 97 if (it == client->m_windows.end()) { 98 did_misbehave("WM_StartWindowResize: Bad window ID"); 99 return; 100 } 101 auto& window = *(*it).value; 102 // FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button. 103 // Maybe the client should be allowed to specify what initiated this request? 104 WindowManager::the().start_window_resize(window, ScreenInput::the().cursor_location(), MouseButton::Primary, (ResizeDirection)resize_direction); 105} 106 107void WMConnectionFromClient::set_window_minimized(i32 client_id, i32 window_id, bool minimized) 108{ 109 auto* client = WindowServer::ConnectionFromClient::from_client_id(client_id); 110 if (!client) { 111 did_misbehave("WM_SetWindowMinimized: Bad client ID"); 112 return; 113 } 114 auto it = client->m_windows.find(window_id); 115 if (it == client->m_windows.end()) { 116 did_misbehave("WM_SetWindowMinimized: Bad window ID"); 117 return; 118 } 119 auto& window = *(*it).value; 120 WindowManager::the().minimize_windows(window, minimized); 121} 122 123void WMConnectionFromClient::toggle_show_desktop() 124{ 125 bool should_hide = false; 126 auto& current_window_stack = WindowManager::the().current_window_stack(); 127 current_window_stack.for_each_window([&](auto& window) { 128 if (window.type() == WindowType::Normal && window.is_minimizable()) { 129 if (!window.is_hidden() && !window.is_minimized()) { 130 should_hide = true; 131 return IterationDecision::Break; 132 } 133 } 134 return IterationDecision::Continue; 135 }); 136 137 current_window_stack.for_each_window([&](auto& window) { 138 if (window.type() == WindowType::Normal && window.is_minimizable()) { 139 auto state = window.minimized_state(); 140 if (state == WindowMinimizedState::None || state == WindowMinimizedState::Hidden) { 141 WindowManager::the().hide_windows(window, should_hide); 142 } 143 } 144 return IterationDecision::Continue; 145 }); 146} 147 148void WMConnectionFromClient::set_event_mask(u32 event_mask) 149{ 150 m_event_mask = event_mask; 151} 152 153void WMConnectionFromClient::set_manager_window(i32 window_id) 154{ 155 m_window_id = window_id; 156 157 // Let the window manager know that we obtained a manager window, and should 158 // receive information about other windows. 159 WindowManager::the().greet_window_manager(*this); 160} 161 162void WMConnectionFromClient::set_workspace(u32 row, u32 col) 163{ 164 WindowManager::the().switch_to_window_stack(row, col); 165} 166 167void WMConnectionFromClient::set_window_taskbar_rect(i32 client_id, i32 window_id, Gfx::IntRect const& rect) 168{ 169 // Because the Taskbar (which should be the only user of this API) does not own the 170 // window or the client id, there is a possibility that it may send this message for 171 // a window or client that may have been destroyed already. This is not an error, 172 // and we should not call did_misbehave() for either. 173 auto* client = WindowServer::ConnectionFromClient::from_client_id(client_id); 174 if (!client) 175 return; 176 177 auto it = client->m_windows.find(window_id); 178 if (it == client->m_windows.end()) 179 return; 180 181 auto& window = *(*it).value; 182 window.set_taskbar_rect(rect); 183} 184 185void WMConnectionFromClient::set_keymap(DeprecatedString const& keymap) 186{ 187 WindowManager::the().keymap_switcher()->set_keymap(keymap); 188} 189 190}