WSClientConnection.cpp 15 KB

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