WSClientConnection.cpp 16 KB

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