WSClientConnection.cpp 16 KB

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