WSClientConnection.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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 <WindowServer/WSClipboard.h>
  10. #include <SharedBuffer.h>
  11. #include <sys/ioctl.h>
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <stdio.h>
  15. HashMap<int, WSClientConnection*>* s_connections;
  16. void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
  17. {
  18. if (!s_connections)
  19. return;
  20. for (auto& it : *s_connections) {
  21. callback(*it.value);
  22. }
  23. }
  24. WSClientConnection* WSClientConnection::from_client_id(int client_id)
  25. {
  26. if (!s_connections)
  27. return nullptr;
  28. auto it = s_connections->find(client_id);
  29. if (it == s_connections->end())
  30. return nullptr;
  31. return (*it).value;
  32. }
  33. WSClientConnection::WSClientConnection(int fd)
  34. : m_fd(fd)
  35. {
  36. static int s_next_client_id = 0;
  37. m_client_id = ++s_next_client_id;
  38. int rc = ioctl(m_fd, 413, (int)&m_pid);
  39. ASSERT(rc == 0);
  40. if (!s_connections)
  41. s_connections = new HashMap<int, WSClientConnection*>;
  42. s_connections->set(m_client_id, this);
  43. WSAPI_ServerMessage message;
  44. message.type = WSAPI_ServerMessage::Type::Greeting;
  45. message.greeting.server_pid = getpid();
  46. post_message(message);
  47. }
  48. WSClientConnection::~WSClientConnection()
  49. {
  50. s_connections->remove(m_client_id);
  51. int rc = close(m_fd);
  52. ASSERT(rc == 0);
  53. }
  54. void WSClientConnection::post_error(const String& error_message)
  55. {
  56. dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", m_client_id, error_message.characters());
  57. WSAPI_ServerMessage message;
  58. message.type = WSAPI_ServerMessage::Type::Error;
  59. ASSERT(error_message.length() < (ssize_t)sizeof(message.text));
  60. strcpy(message.text, error_message.characters());
  61. message.text_length = error_message.length();
  62. post_message(message);
  63. }
  64. void WSClientConnection::post_message(const WSAPI_ServerMessage& message)
  65. {
  66. int nwritten = write(m_fd, &message, sizeof(message));
  67. if (nwritten < 0) {
  68. if (errno == EPIPE) {
  69. dbgprintf("WSClientConnection::post_message: Disconnected from peer.\n");
  70. return;
  71. }
  72. perror("WSClientConnection::post_message write");
  73. ASSERT_NOT_REACHED();
  74. }
  75. ASSERT(nwritten == sizeof(message));
  76. }
  77. RetainPtr<GraphicsBitmap> WSClientConnection::create_shared_bitmap(GraphicsBitmap::Format format, const Size& size)
  78. {
  79. auto shared_buffer = SharedBuffer::create(m_pid, size.area() * sizeof(RGBA32));
  80. ASSERT(shared_buffer);
  81. return GraphicsBitmap::create_with_shared_buffer(format, *shared_buffer, size);
  82. }
  83. void WSClientConnection::on_message(WSMessage& message)
  84. {
  85. if (message.is_client_request()) {
  86. on_request(static_cast<WSAPIClientRequest&>(message));
  87. return;
  88. }
  89. if (message.type() == WSMessage::WM_ClientDisconnected) {
  90. int client_id = static_cast<WSClientDisconnectedNotification&>(message).client_id();
  91. dbgprintf("WSClientConnection: Client disconnected: %d\n", client_id);
  92. delete this;
  93. return;
  94. }
  95. }
  96. void WSClientConnection::handle_request(WSAPICreateMenubarRequest&)
  97. {
  98. int menubar_id = m_next_menubar_id++;
  99. auto menubar = make<WSMenuBar>(*this, menubar_id);
  100. m_menubars.set(menubar_id, move(menubar));
  101. WSAPI_ServerMessage response;
  102. response.type = WSAPI_ServerMessage::Type::DidCreateMenubar;
  103. response.menu.menubar_id = menubar_id;
  104. post_message(response);
  105. }
  106. void WSClientConnection::handle_request(WSAPIDestroyMenubarRequest& request)
  107. {
  108. int menubar_id = request.menubar_id();
  109. auto it = m_menubars.find(menubar_id);
  110. if (it == m_menubars.end()) {
  111. post_error("Bad menubar ID");
  112. return;
  113. }
  114. auto& menubar = *(*it).value;
  115. WSWindowManager::the().close_menubar(menubar);
  116. m_menubars.remove(it);
  117. WSAPI_ServerMessage response;
  118. response.type = WSAPI_ServerMessage::Type::DidDestroyMenubar;
  119. response.menu.menubar_id = menubar_id;
  120. post_message(response);
  121. }
  122. void WSClientConnection::handle_request(WSAPICreateMenuRequest& request)
  123. {
  124. int menu_id = m_next_menu_id++;
  125. auto menu = make<WSMenu>(this, menu_id, request.text());
  126. m_menus.set(menu_id, move(menu));
  127. WSAPI_ServerMessage response;
  128. response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
  129. response.menu.menu_id = menu_id;
  130. post_message(response);
  131. }
  132. void WSClientConnection::handle_request(WSAPIDestroyMenuRequest& request)
  133. {
  134. int menu_id = static_cast<WSAPIDestroyMenuRequest&>(request).menu_id();
  135. auto it = m_menus.find(menu_id);
  136. if (it == m_menus.end()) {
  137. post_error("Bad menu ID");
  138. return;
  139. }
  140. auto& menu = *(*it).value;
  141. WSWindowManager::the().close_menu(menu);
  142. m_menus.remove(it);
  143. WSAPI_ServerMessage response;
  144. response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
  145. response.menu.menu_id = menu_id;
  146. post_message(response);
  147. }
  148. void WSClientConnection::handle_request(WSAPISetApplicationMenubarRequest& request)
  149. {
  150. int menubar_id = request.menubar_id();
  151. auto it = m_menubars.find(menubar_id);
  152. if (it == m_menubars.end()) {
  153. post_error("Bad menubar ID");
  154. return;
  155. }
  156. auto& menubar = *(*it).value;
  157. m_app_menubar = menubar.make_weak_ptr();
  158. WSWindowManager::the().notify_client_changed_app_menubar(*this);
  159. WSAPI_ServerMessage response;
  160. response.type = WSAPI_ServerMessage::Type::DidSetApplicationMenubar;
  161. response.menu.menubar_id = menubar_id;
  162. post_message(response);
  163. }
  164. void WSClientConnection::handle_request(WSAPIAddMenuToMenubarRequest& request)
  165. {
  166. int menubar_id = request.menubar_id();
  167. int menu_id = request.menu_id();
  168. auto it = m_menubars.find(menubar_id);
  169. auto jt = m_menus.find(menu_id);
  170. if (it == m_menubars.end()) {
  171. post_error("Bad menubar ID");
  172. return;
  173. }
  174. if (jt == m_menus.end()) {
  175. post_error("Bad menu ID");
  176. return;
  177. }
  178. auto& menubar = *(*it).value;
  179. auto& menu = *(*jt).value;
  180. menubar.add_menu(&menu);
  181. WSAPI_ServerMessage response;
  182. response.type = WSAPI_ServerMessage::Type::DidAddMenuToMenubar;
  183. response.menu.menubar_id = menubar_id;
  184. response.menu.menu_id = menu_id;
  185. post_message(response);
  186. }
  187. void WSClientConnection::handle_request(WSAPIAddMenuItemRequest& request)
  188. {
  189. int menu_id = request.menu_id();
  190. unsigned identifier = request.identifier();
  191. auto it = m_menus.find(menu_id);
  192. if (it == m_menus.end()) {
  193. post_error("Bad menu ID");
  194. return;
  195. }
  196. auto& menu = *(*it).value;
  197. menu.add_item(make<WSMenuItem>(identifier, request.text(), request.shortcut_text()));
  198. WSAPI_ServerMessage response;
  199. response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
  200. response.menu.menu_id = menu_id;
  201. response.menu.identifier = identifier;
  202. post_message(response);
  203. }
  204. void WSClientConnection::handle_request(WSAPIAddMenuSeparatorRequest& request)
  205. {
  206. int menu_id = request.menu_id();
  207. auto it = m_menus.find(menu_id);
  208. if (it == m_menus.end()) {
  209. post_error("Bad menu ID");
  210. return;
  211. }
  212. auto& menu = *(*it).value;
  213. menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
  214. WSAPI_ServerMessage response;
  215. response.type = WSAPI_ServerMessage::Type::DidAddMenuSeparator;
  216. response.menu.menu_id = menu_id;
  217. post_message(response);
  218. }
  219. void WSClientConnection::handle_request(WSAPISetWindowOpacityRequest& request)
  220. {
  221. int window_id = request.window_id();
  222. auto it = m_windows.find(window_id);
  223. if (it == m_windows.end()) {
  224. post_error("Bad window ID");
  225. return;
  226. }
  227. auto& window = *(*it).value;
  228. window.set_opacity(request.opacity());
  229. }
  230. void WSClientConnection::handle_request(WSAPISetWindowTitleRequest& request)
  231. {
  232. int window_id = request.window_id();
  233. auto it = m_windows.find(window_id);
  234. if (it == m_windows.end()) {
  235. post_error("Bad window ID");
  236. return;
  237. }
  238. auto& window = *(*it).value;
  239. window.set_title(request.title());
  240. }
  241. void WSClientConnection::handle_request(WSAPIGetWindowTitleRequest& request)
  242. {
  243. int window_id = request.window_id();
  244. auto it = m_windows.find(window_id);
  245. if (it == m_windows.end()) {
  246. post_error("Bad window ID");
  247. return;
  248. }
  249. auto& window = *(*it).value;
  250. WSAPI_ServerMessage response;
  251. response.type = WSAPI_ServerMessage::Type::DidGetWindowTitle;
  252. response.window_id = window.window_id();
  253. ASSERT(window.title().length() < (ssize_t)sizeof(response.text));
  254. strcpy(response.text, window.title().characters());
  255. response.text_length = window.title().length();
  256. post_message(response);
  257. }
  258. void WSClientConnection::handle_request(WSAPISetWindowRectRequest& request)
  259. {
  260. int window_id = request.window_id();
  261. auto it = m_windows.find(window_id);
  262. if (it == m_windows.end()) {
  263. post_error("Bad window ID");
  264. return;
  265. }
  266. auto& window = *(*it).value;
  267. window.set_rect(request.rect());
  268. }
  269. void WSClientConnection::handle_request(WSAPIGetWindowRectRequest& request)
  270. {
  271. int window_id = request.window_id();
  272. auto it = m_windows.find(window_id);
  273. if (it == m_windows.end()) {
  274. post_error("Bad window ID");
  275. return;
  276. }
  277. auto& window = *(*it).value;
  278. WSAPI_ServerMessage response;
  279. response.type = WSAPI_ServerMessage::Type::DidGetWindowRect;
  280. response.window_id = window.window_id();
  281. response.window.rect = window.rect();
  282. post_message(response);
  283. }
  284. void WSClientConnection::handle_request(WSAPISetClipboardContentsRequest& request)
  285. {
  286. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  287. if (!shared_buffer) {
  288. post_error("Bad shared buffer ID");
  289. return;
  290. }
  291. WSClipboard::the().set_data(*shared_buffer, request.size());
  292. WSAPI_ServerMessage response;
  293. response.type = WSAPI_ServerMessage::Type::DidSetClipboardContents;
  294. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  295. post_message(response);
  296. }
  297. void WSClientConnection::handle_request(WSAPIGetClipboardContentsRequest&)
  298. {
  299. WSAPI_ServerMessage response;
  300. response.type = WSAPI_ServerMessage::Type::DidGetClipboardContents;
  301. response.clipboard.shared_buffer_id = -1;
  302. response.clipboard.contents_size = 0;
  303. if (WSClipboard::the().size()) {
  304. // FIXME: Optimize case where an app is copy/pasting within itself.
  305. // We can just reuse the SharedBuffer then, since it will have the same peer PID.
  306. // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
  307. RetainPtr<SharedBuffer> shared_buffer = SharedBuffer::create(m_pid, WSClipboard::the().size());
  308. ASSERT(shared_buffer);
  309. memcpy(shared_buffer->data(), WSClipboard::the().data(), WSClipboard::the().size());
  310. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  311. response.clipboard.contents_size = WSClipboard::the().size();
  312. // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
  313. // After we respond to GetClipboardContents, we have to wait for the client to retain the buffer on his side.
  314. m_last_sent_clipboard_content = move(shared_buffer);
  315. }
  316. post_message(response);
  317. }
  318. void WSClientConnection::handle_request(WSAPICreateWindowRequest& request)
  319. {
  320. int window_id = m_next_window_id++;
  321. auto window = make<WSWindow>(*this, window_id);
  322. window->set_has_alpha_channel(request.has_alpha_channel());
  323. window->set_title(request.title());
  324. window->set_rect(request.rect());
  325. window->set_opacity(request.opacity());
  326. window->set_size_increment(request.size_increment());
  327. window->set_base_size(request.base_size());
  328. m_windows.set(window_id, move(window));
  329. WSAPI_ServerMessage response;
  330. response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
  331. response.window_id = window_id;
  332. post_message(response);
  333. }
  334. void WSClientConnection::handle_request(WSAPIDestroyWindowRequest& 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. WSWindowManager::the().invalidate(window);
  344. m_windows.remove(it);
  345. }
  346. void WSClientConnection::handle_request(WSAPIInvalidateRectRequest& request)
  347. {
  348. int window_id = request.window_id();
  349. auto it = m_windows.find(window_id);
  350. if (it == m_windows.end()) {
  351. post_error("Bad window ID");
  352. return;
  353. }
  354. auto& window = *(*it).value;
  355. WSAPI_ServerMessage response;
  356. response.type = WSAPI_ServerMessage::Type::Paint;
  357. response.window_id = window_id;
  358. response.paint.rect = request.rect();
  359. response.paint.window_size = window.size();
  360. post_message(response);
  361. }
  362. void WSClientConnection::handle_request(WSAPIDidFinishPaintingNotification& request)
  363. {
  364. int window_id = request.window_id();
  365. auto it = m_windows.find(window_id);
  366. if (it == m_windows.end()) {
  367. post_error("Bad window ID");
  368. return;
  369. }
  370. auto& window = *(*it).value;
  371. if (!window.has_painted_since_last_resize()) {
  372. if (window.last_lazy_resize_rect().size() == request.rect().size()) {
  373. window.set_has_painted_since_last_resize(true);
  374. WSMessageLoop::the().post_message(window, make<WSResizeEvent>(window.last_lazy_resize_rect(), window.rect()));
  375. }
  376. }
  377. WSWindowManager::the().invalidate(window, request.rect());
  378. }
  379. void WSClientConnection::handle_request(WSAPIGetWindowBackingStoreRequest& request)
  380. {
  381. int window_id = request.window_id();
  382. auto it = m_windows.find(window_id);
  383. if (it == m_windows.end()) {
  384. post_error("Bad window ID");
  385. return;
  386. }
  387. auto& window = *(*it).value;
  388. auto* backing_store = window.backing_store();
  389. WSAPI_ServerMessage response;
  390. response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore;
  391. response.window_id = window_id;
  392. response.backing.bpp = sizeof(RGBA32);
  393. response.backing.pitch = backing_store->pitch();
  394. response.backing.size = backing_store->size();
  395. response.backing.has_alpha_channel = backing_store->has_alpha_channel();
  396. response.backing.shared_buffer_id = backing_store->shared_buffer_id();
  397. post_message(response);
  398. }
  399. void WSClientConnection::handle_request(WSAPISetWindowBackingStoreRequest& request)
  400. {
  401. int window_id = request.window_id();
  402. auto it = m_windows.find(window_id);
  403. if (it == m_windows.end()) {
  404. post_error("Bad window ID");
  405. return;
  406. }
  407. auto& window = *(*it).value;
  408. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  409. if (!shared_buffer)
  410. return;
  411. auto backing_store = GraphicsBitmap::create_with_shared_buffer(
  412. request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
  413. *shared_buffer,
  414. request.size());
  415. if (!backing_store)
  416. return;
  417. window.set_backing_store(move(backing_store));
  418. window.invalidate();
  419. }
  420. void WSClientConnection::handle_request(WSAPISetGlobalCursorTrackingRequest& request)
  421. {
  422. int window_id = request.window_id();
  423. auto it = m_windows.find(window_id);
  424. if (it == m_windows.end()) {
  425. post_error("Bad window ID");
  426. return;
  427. }
  428. auto& window = *(*it).value;
  429. window.set_global_cursor_tracking_enabled(request.value());
  430. }
  431. void WSClientConnection::on_request(WSAPIClientRequest& request)
  432. {
  433. switch (request.type()) {
  434. case WSMessage::APICreateMenubarRequest:
  435. return handle_request(static_cast<WSAPICreateMenubarRequest&>(request));
  436. case WSMessage::APIDestroyMenubarRequest:
  437. return handle_request(static_cast<WSAPIDestroyMenubarRequest&>(request));
  438. case WSMessage::APICreateMenuRequest:
  439. return handle_request(static_cast<WSAPICreateMenuRequest&>(request));
  440. case WSMessage::APIDestroyMenuRequest:
  441. return handle_request(static_cast<WSAPIDestroyMenuRequest&>(request));
  442. case WSMessage::APISetApplicationMenubarRequest:
  443. return handle_request(static_cast<WSAPISetApplicationMenubarRequest&>(request));
  444. case WSMessage::APIAddMenuToMenubarRequest:
  445. return handle_request(static_cast<WSAPIAddMenuToMenubarRequest&>(request));
  446. case WSMessage::APIAddMenuItemRequest:
  447. return handle_request(static_cast<WSAPIAddMenuItemRequest&>(request));
  448. case WSMessage::APIAddMenuSeparatorRequest:
  449. return handle_request(static_cast<WSAPIAddMenuSeparatorRequest&>(request));
  450. case WSMessage::APISetWindowTitleRequest:
  451. return handle_request(static_cast<WSAPISetWindowTitleRequest&>(request));
  452. case WSMessage::APIGetWindowTitleRequest:
  453. return handle_request(static_cast<WSAPIGetWindowTitleRequest&>(request));
  454. case WSMessage::APISetWindowRectRequest:
  455. return handle_request(static_cast<WSAPISetWindowRectRequest&>(request));
  456. case WSMessage::APIGetWindowRectRequest:
  457. return handle_request(static_cast<WSAPIGetWindowRectRequest&>(request));
  458. case WSMessage::APISetClipboardContentsRequest:
  459. return handle_request(static_cast<WSAPISetClipboardContentsRequest&>(request));
  460. case WSMessage::APIGetClipboardContentsRequest:
  461. return handle_request(static_cast<WSAPIGetClipboardContentsRequest&>(request));
  462. case WSMessage::APICreateWindowRequest:
  463. return handle_request(static_cast<WSAPICreateWindowRequest&>(request));
  464. case WSMessage::APIDestroyWindowRequest:
  465. return handle_request(static_cast<WSAPIDestroyWindowRequest&>(request));
  466. case WSMessage::APIInvalidateRectRequest:
  467. return handle_request(static_cast<WSAPIInvalidateRectRequest&>(request));
  468. case WSMessage::APIDidFinishPaintingNotification:
  469. return handle_request(static_cast<WSAPIDidFinishPaintingNotification&>(request));
  470. case WSMessage::APIGetWindowBackingStoreRequest:
  471. return handle_request(static_cast<WSAPIGetWindowBackingStoreRequest&>(request));
  472. case WSMessage::APISetGlobalCursorTrackingRequest:
  473. return handle_request(static_cast<WSAPISetGlobalCursorTrackingRequest&>(request));
  474. case WSMessage::APISetWindowOpacityRequest:
  475. return handle_request(static_cast<WSAPISetWindowOpacityRequest&>(request));
  476. case WSMessage::APISetWindowBackingStoreRequest:
  477. return handle_request(static_cast<WSAPISetWindowBackingStoreRequest&>(request));
  478. default:
  479. break;
  480. }
  481. }