WSClientConnection.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #include <WindowServer/WSClientConnection.h>
  2. #include <WindowServer/WSMessageLoop.h>
  3. #include <WindowServer/WSMenuBar.h>
  4. #include <WindowServer/WSMenu.h>
  5. #include <WindowServer/WSMenuItem.h>
  6. #include <WindowServer/WSWindow.h>
  7. #include <WindowServer/WSWindowManager.h>
  8. #include <Kernel/GUITypes.h>
  9. #include <Kernel/MemoryManager.h>
  10. Lockable<HashMap<int, WSClientConnection*>>* s_connections;
  11. WSClientConnection* WSClientConnection::from_client_id(int client_id)
  12. {
  13. if (!s_connections)
  14. return nullptr;
  15. LOCKER(s_connections->lock());
  16. auto it = s_connections->resource().find(client_id);
  17. if (it == s_connections->resource().end())
  18. return nullptr;
  19. return (*it).value;
  20. }
  21. WSClientConnection* WSClientConnection::ensure_for_client_id(int client_id)
  22. {
  23. if (auto* client = from_client_id(client_id))
  24. return client;
  25. return new WSClientConnection(client_id);
  26. }
  27. WSClientConnection::WSClientConnection(int client_id)
  28. : m_client_id(client_id)
  29. {
  30. if (!s_connections)
  31. s_connections = new Lockable<HashMap<int, WSClientConnection*>>;
  32. LOCKER(s_connections->lock());
  33. s_connections->resource().set(client_id, this);
  34. m_process = ((Process*)m_client_id)->make_weak_ptr();
  35. }
  36. WSClientConnection::~WSClientConnection()
  37. {
  38. LOCKER(s_connections->lock());
  39. s_connections->resource().remove(m_client_id);
  40. }
  41. void WSClientConnection::post_error(const String& error_message)
  42. {
  43. dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", m_client_id, error_message.characters());
  44. GUI_ServerMessage message;
  45. message.type = GUI_ServerMessage::Type::Error;
  46. ASSERT(error_message.length() < sizeof(message.text));
  47. strcpy(message.text, error_message.characters());
  48. message.text_length = error_message.length();
  49. WSMessageLoop::the().post_message_to_client(m_client_id, message);
  50. }
  51. void WSClientConnection::post_message(GUI_ServerMessage&& message)
  52. {
  53. if (!m_process)
  54. return;
  55. LOCKER(m_process->gui_events_lock());
  56. m_process->gui_events().append(move(message));
  57. }
  58. RetainPtr<GraphicsBitmap> WSClientConnection::create_bitmap(const Size& size)
  59. {
  60. if (!m_process)
  61. return nullptr;
  62. return GraphicsBitmap::create(*m_process, size);
  63. }
  64. void WSClientConnection::on_message(WSMessage& message)
  65. {
  66. if (message.is_client_request()) {
  67. on_request(static_cast<WSAPIClientRequest&>(message));
  68. return;
  69. }
  70. if (message.type() == WSMessage::WM_ClientDisconnected) {
  71. int client_id = static_cast<WSClientDisconnectedNotification&>(message).client_id();
  72. dbgprintf("WSClientConnection: Client disconnected: %d\n", client_id);
  73. delete this;
  74. return;
  75. }
  76. }
  77. void WSClientConnection::handle_request(WSAPICreateMenubarRequest& request)
  78. {
  79. int menubar_id = m_next_menubar_id++;
  80. auto menubar = make<WSMenuBar>(request.client_id(), menubar_id);
  81. m_menubars.set(menubar_id, move(menubar));
  82. GUI_ServerMessage response;
  83. response.type = GUI_ServerMessage::Type::DidCreateMenubar;
  84. response.menu.menubar_id = menubar_id;
  85. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  86. }
  87. void WSClientConnection::handle_request(WSAPIDestroyMenubarRequest& request)
  88. {
  89. int menubar_id = request.menubar_id();
  90. auto it = m_menubars.find(menubar_id);
  91. if (it == m_menubars.end()) {
  92. post_error("Bad menubar ID");
  93. return;
  94. }
  95. auto& menubar = *(*it).value;
  96. WSWindowManager::the().close_menubar(menubar);
  97. m_menubars.remove(it);
  98. GUI_ServerMessage response;
  99. response.type = GUI_ServerMessage::Type::DidDestroyMenubar;
  100. response.menu.menubar_id = menubar_id;
  101. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  102. }
  103. void WSClientConnection::handle_request(WSAPICreateMenuRequest& request)
  104. {
  105. int menu_id = m_next_menu_id++;
  106. auto menu = make<WSMenu>(request.client_id(), menu_id, request.text());
  107. m_menus.set(menu_id, move(menu));
  108. GUI_ServerMessage response;
  109. response.type = GUI_ServerMessage::Type::DidCreateMenu;
  110. response.menu.menu_id = menu_id;
  111. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  112. }
  113. void WSClientConnection::handle_request(WSAPIDestroyMenuRequest& request)
  114. {
  115. int menu_id = static_cast<WSAPIDestroyMenuRequest&>(request).menu_id();
  116. auto it = m_menus.find(menu_id);
  117. if (it == m_menus.end()) {
  118. post_error("Bad menu ID");
  119. return;
  120. }
  121. auto& menu = *(*it).value;
  122. WSWindowManager::the().close_menu(menu);
  123. m_menus.remove(it);
  124. GUI_ServerMessage response;
  125. response.type = GUI_ServerMessage::Type::DidDestroyMenu;
  126. response.menu.menu_id = menu_id;
  127. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  128. }
  129. void WSClientConnection::handle_request(WSAPISetApplicationMenubarRequest& request)
  130. {
  131. int menubar_id = request.menubar_id();
  132. auto it = m_menubars.find(menubar_id);
  133. if (it == m_menubars.end()) {
  134. post_error("Bad menubar ID");
  135. return;
  136. }
  137. auto& menubar = *(*it).value;
  138. m_app_menubar = menubar.make_weak_ptr();
  139. WSWindowManager::the().notify_client_changed_app_menubar(*this);
  140. GUI_ServerMessage response;
  141. response.type = GUI_ServerMessage::Type::DidSetApplicationMenubar;
  142. response.menu.menubar_id = menubar_id;
  143. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  144. }
  145. void WSClientConnection::handle_request(WSAPIAddMenuToMenubarRequest& request)
  146. {
  147. int menubar_id = request.menubar_id();
  148. int menu_id = request.menu_id();
  149. auto it = m_menubars.find(menubar_id);
  150. auto jt = m_menus.find(menu_id);
  151. if (it == m_menubars.end()) {
  152. post_error("Bad menubar ID");
  153. return;
  154. }
  155. if (jt == m_menus.end()) {
  156. post_error("Bad menu ID");
  157. return;
  158. }
  159. auto& menubar = *(*it).value;
  160. auto& menu = *(*jt).value;
  161. menubar.add_menu(&menu);
  162. GUI_ServerMessage response;
  163. response.type = GUI_ServerMessage::Type::DidAddMenuToMenubar;
  164. response.menu.menubar_id = menubar_id;
  165. response.menu.menu_id = menu_id;
  166. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  167. }
  168. void WSClientConnection::handle_request(WSAPIAddMenuItemRequest& request)
  169. {
  170. int menu_id = request.menu_id();
  171. unsigned identifier = request.identifier();
  172. String text = request.text();
  173. auto it = m_menus.find(menu_id);
  174. if (it == m_menus.end()) {
  175. post_error("Bad menu ID");
  176. return;
  177. }
  178. auto& menu = *(*it).value;
  179. menu.add_item(make<WSMenuItem>(identifier, move(text)));
  180. GUI_ServerMessage response;
  181. response.type = GUI_ServerMessage::Type::DidAddMenuItem;
  182. response.menu.menu_id = menu_id;
  183. response.menu.identifier = identifier;
  184. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  185. }
  186. void WSClientConnection::handle_request(WSAPIAddMenuSeparatorRequest& request)
  187. {
  188. int menu_id = request.menu_id();
  189. auto it = m_menus.find(menu_id);
  190. if (it == m_menus.end()) {
  191. post_error("Bad menu ID");
  192. return;
  193. }
  194. auto& menu = *(*it).value;
  195. menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
  196. GUI_ServerMessage response;
  197. response.type = GUI_ServerMessage::Type::DidAddMenuSeparator;
  198. response.menu.menu_id = menu_id;
  199. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  200. }
  201. void WSClientConnection::handle_request(WSAPISetWindowTitleRequest& request)
  202. {
  203. int window_id = request.window_id();
  204. auto it = m_windows.find(window_id);
  205. if (it == m_windows.end()) {
  206. post_error("Bad window ID");
  207. return;
  208. }
  209. auto& window = *(*it).value;
  210. window.set_title(request.title());
  211. }
  212. void WSClientConnection::handle_request(WSAPIGetWindowTitleRequest& request)
  213. {
  214. int window_id = request.window_id();
  215. auto it = m_windows.find(window_id);
  216. if (it == m_windows.end()) {
  217. post_error("Bad window ID");
  218. return;
  219. }
  220. auto& window = *(*it).value;
  221. GUI_ServerMessage response;
  222. response.type = GUI_ServerMessage::Type::DidGetWindowTitle;
  223. response.window_id = window.window_id();
  224. ASSERT(window.title().length() < sizeof(response.text));
  225. strcpy(response.text, window.title().characters());
  226. response.text_length = window.title().length();
  227. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  228. }
  229. void WSClientConnection::handle_request(WSAPISetWindowRectRequest& request)
  230. {
  231. int window_id = request.window_id();
  232. auto it = m_windows.find(window_id);
  233. if (it == m_windows.end()) {
  234. post_error("Bad window ID");
  235. return;
  236. }
  237. auto& window = *(*it).value;
  238. window.set_rect(request.rect());
  239. }
  240. void WSClientConnection::handle_request(WSAPIGetWindowRectRequest& request)
  241. {
  242. int window_id = request.window_id();
  243. auto it = m_windows.find(window_id);
  244. if (it == m_windows.end()) {
  245. post_error("Bad window ID");
  246. return;
  247. }
  248. auto& window = *(*it).value;
  249. GUI_ServerMessage response;
  250. response.type = GUI_ServerMessage::Type::DidGetWindowRect;
  251. response.window_id = window.window_id();
  252. response.window.rect = window.rect();
  253. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  254. }
  255. void WSClientConnection::handle_request(WSAPICreateWindowRequest& request)
  256. {
  257. int window_id = m_next_window_id++;
  258. auto window = make<WSWindow>(request.client_id(), window_id);
  259. window->set_title(request.title());
  260. window->set_rect(request.rect());
  261. m_windows.set(window_id, move(window));
  262. GUI_ServerMessage response;
  263. response.type = GUI_ServerMessage::Type::DidCreateWindow;
  264. response.window_id = window_id;
  265. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  266. }
  267. void WSClientConnection::handle_request(WSAPIDestroyWindowRequest& request)
  268. {
  269. int window_id = request.window_id();
  270. auto it = m_windows.find(window_id);
  271. if (it == m_windows.end()) {
  272. post_error("Bad window ID");
  273. return;
  274. }
  275. auto& window = *(*it).value;
  276. WSWindowManager::the().invalidate(window);
  277. m_windows.remove(it);
  278. }
  279. void WSClientConnection::handle_request(WSAPIInvalidateRectRequest& request)
  280. {
  281. int window_id = request.window_id();
  282. auto it = m_windows.find(window_id);
  283. if (it == m_windows.end()) {
  284. post_error("Bad window ID");
  285. return;
  286. }
  287. GUI_ServerMessage response;
  288. response.type = GUI_ServerMessage::Type::Paint;
  289. response.window_id = window_id;
  290. response.paint.rect = request.rect();
  291. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  292. }
  293. void WSClientConnection::handle_request(WSAPIDidFinishPaintingNotification& request)
  294. {
  295. int window_id = request.window_id();
  296. auto it = m_windows.find(window_id);
  297. if (it == m_windows.end()) {
  298. post_error("Bad window ID");
  299. return;
  300. }
  301. auto& window = *(*it).value;
  302. WSWindowManager::the().invalidate(window, request.rect());
  303. }
  304. void WSClientConnection::handle_request(WSAPIGetWindowBackingStoreRequest& request)
  305. {
  306. int window_id = request.window_id();
  307. auto it = m_windows.find(window_id);
  308. if (it == m_windows.end()) {
  309. post_error("Bad window ID");
  310. return;
  311. }
  312. auto& window = *(*it).value;
  313. auto* backing_store = window.backing();
  314. // FIXME: It shouldn't work this way!
  315. backing_store->retain();
  316. GUI_ServerMessage response;
  317. response.type = GUI_ServerMessage::Type::DidGetWindowBackingStore;
  318. response.window_id = window_id;
  319. response.backing.backing_store_id = backing_store;
  320. response.backing.bpp = sizeof(RGBA32);
  321. response.backing.pitch = backing_store->pitch();
  322. response.backing.size = backing_store->size();
  323. response.backing.pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr());
  324. WSMessageLoop::the().post_message_to_client(request.client_id(), response);
  325. }
  326. void WSClientConnection::handle_request(WSAPIReleaseWindowBackingStoreRequest& request)
  327. {
  328. int backing_store_id = request.backing_store_id();
  329. // FIXME: It shouldn't work this way!
  330. auto* backing_store = (GraphicsBitmap*)backing_store_id;
  331. backing_store->release();
  332. }
  333. void WSClientConnection::handle_request(WSAPISetGlobalCursorTrackingRequest& request)
  334. {
  335. int window_id = request.window_id();
  336. auto it = m_windows.find(window_id);
  337. if (it == m_windows.end()) {
  338. post_error("Bad window ID");
  339. return;
  340. }
  341. auto& window = *(*it).value;
  342. window.set_global_cursor_tracking_enabled(request.value());
  343. }
  344. void WSClientConnection::on_request(WSAPIClientRequest& request)
  345. {
  346. switch (request.type()) {
  347. case WSMessage::APICreateMenubarRequest:
  348. return handle_request(static_cast<WSAPICreateMenubarRequest&>(request));
  349. case WSMessage::APIDestroyMenubarRequest:
  350. return handle_request(static_cast<WSAPIDestroyMenubarRequest&>(request));
  351. case WSMessage::APICreateMenuRequest:
  352. return handle_request(static_cast<WSAPICreateMenuRequest&>(request));
  353. case WSMessage::APIDestroyMenuRequest:
  354. return handle_request(static_cast<WSAPIDestroyMenuRequest&>(request));
  355. case WSMessage::APISetApplicationMenubarRequest:
  356. return handle_request(static_cast<WSAPISetApplicationMenubarRequest&>(request));
  357. case WSMessage::APIAddMenuToMenubarRequest:
  358. return handle_request(static_cast<WSAPIAddMenuToMenubarRequest&>(request));
  359. case WSMessage::APIAddMenuItemRequest:
  360. return handle_request(static_cast<WSAPIAddMenuItemRequest&>(request));
  361. case WSMessage::APIAddMenuSeparatorRequest:
  362. return handle_request(static_cast<WSAPIAddMenuSeparatorRequest&>(request));
  363. case WSMessage::APISetWindowTitleRequest:
  364. return handle_request(static_cast<WSAPISetWindowTitleRequest&>(request));
  365. case WSMessage::APIGetWindowTitleRequest:
  366. return handle_request(static_cast<WSAPIGetWindowTitleRequest&>(request));
  367. case WSMessage::APISetWindowRectRequest:
  368. return handle_request(static_cast<WSAPISetWindowRectRequest&>(request));
  369. case WSMessage::APIGetWindowRectRequest:
  370. return handle_request(static_cast<WSAPIGetWindowRectRequest&>(request));
  371. case WSMessage::APICreateWindowRequest:
  372. return handle_request(static_cast<WSAPICreateWindowRequest&>(request));
  373. case WSMessage::APIDestroyWindowRequest:
  374. return handle_request(static_cast<WSAPIDestroyWindowRequest&>(request));
  375. case WSMessage::APIInvalidateRectRequest:
  376. return handle_request(static_cast<WSAPIInvalidateRectRequest&>(request));
  377. case WSMessage::APIDidFinishPaintingNotification:
  378. return handle_request(static_cast<WSAPIDidFinishPaintingNotification&>(request));
  379. case WSMessage::APIGetWindowBackingStoreRequest:
  380. return handle_request(static_cast<WSAPIGetWindowBackingStoreRequest&>(request));
  381. case WSMessage::APIReleaseWindowBackingStoreRequest:
  382. return handle_request(static_cast<WSAPIReleaseWindowBackingStoreRequest&>(request));
  383. case WSMessage::APISetGlobalCursorTrackingRequest:
  384. return handle_request(static_cast<WSAPISetGlobalCursorTrackingRequest&>(request));
  385. default:
  386. break;
  387. }
  388. }