WSClientConnection.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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() < 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() < 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. m_windows.set(window_id, move(window));
  296. WSAPI_ServerMessage response;
  297. response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
  298. response.window_id = window_id;
  299. post_message(response);
  300. }
  301. void WSClientConnection::handle_request(WSAPIDestroyWindowRequest& request)
  302. {
  303. int window_id = request.window_id();
  304. auto it = m_windows.find(window_id);
  305. if (it == m_windows.end()) {
  306. post_error("Bad window ID");
  307. return;
  308. }
  309. auto& window = *(*it).value;
  310. WSWindowManager::the().invalidate(window);
  311. m_windows.remove(it);
  312. }
  313. void WSClientConnection::handle_request(WSAPIInvalidateRectRequest& request)
  314. {
  315. int window_id = request.window_id();
  316. auto it = m_windows.find(window_id);
  317. if (it == m_windows.end()) {
  318. post_error("Bad window ID");
  319. return;
  320. }
  321. WSAPI_ServerMessage response;
  322. response.type = WSAPI_ServerMessage::Type::Paint;
  323. response.window_id = window_id;
  324. response.paint.rect = request.rect();
  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 backing_store = GraphicsBitmap::create_with_shared_buffer(
  374. request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
  375. request.shared_buffer_id(),
  376. request.size());
  377. if (!backing_store)
  378. return;
  379. window.set_backing_store(move(backing_store));
  380. window.invalidate();
  381. }
  382. void WSClientConnection::handle_request(WSAPISetGlobalCursorTrackingRequest& request)
  383. {
  384. int window_id = request.window_id();
  385. auto it = m_windows.find(window_id);
  386. if (it == m_windows.end()) {
  387. post_error("Bad window ID");
  388. return;
  389. }
  390. auto& window = *(*it).value;
  391. window.set_global_cursor_tracking_enabled(request.value());
  392. }
  393. void WSClientConnection::on_request(WSAPIClientRequest& request)
  394. {
  395. switch (request.type()) {
  396. case WSMessage::APICreateMenubarRequest:
  397. return handle_request(static_cast<WSAPICreateMenubarRequest&>(request));
  398. case WSMessage::APIDestroyMenubarRequest:
  399. return handle_request(static_cast<WSAPIDestroyMenubarRequest&>(request));
  400. case WSMessage::APICreateMenuRequest:
  401. return handle_request(static_cast<WSAPICreateMenuRequest&>(request));
  402. case WSMessage::APIDestroyMenuRequest:
  403. return handle_request(static_cast<WSAPIDestroyMenuRequest&>(request));
  404. case WSMessage::APISetApplicationMenubarRequest:
  405. return handle_request(static_cast<WSAPISetApplicationMenubarRequest&>(request));
  406. case WSMessage::APIAddMenuToMenubarRequest:
  407. return handle_request(static_cast<WSAPIAddMenuToMenubarRequest&>(request));
  408. case WSMessage::APIAddMenuItemRequest:
  409. return handle_request(static_cast<WSAPIAddMenuItemRequest&>(request));
  410. case WSMessage::APIAddMenuSeparatorRequest:
  411. return handle_request(static_cast<WSAPIAddMenuSeparatorRequest&>(request));
  412. case WSMessage::APISetWindowTitleRequest:
  413. return handle_request(static_cast<WSAPISetWindowTitleRequest&>(request));
  414. case WSMessage::APIGetWindowTitleRequest:
  415. return handle_request(static_cast<WSAPIGetWindowTitleRequest&>(request));
  416. case WSMessage::APISetWindowRectRequest:
  417. return handle_request(static_cast<WSAPISetWindowRectRequest&>(request));
  418. case WSMessage::APIGetWindowRectRequest:
  419. return handle_request(static_cast<WSAPIGetWindowRectRequest&>(request));
  420. case WSMessage::APICreateWindowRequest:
  421. return handle_request(static_cast<WSAPICreateWindowRequest&>(request));
  422. case WSMessage::APIDestroyWindowRequest:
  423. return handle_request(static_cast<WSAPIDestroyWindowRequest&>(request));
  424. case WSMessage::APIInvalidateRectRequest:
  425. return handle_request(static_cast<WSAPIInvalidateRectRequest&>(request));
  426. case WSMessage::APIDidFinishPaintingNotification:
  427. return handle_request(static_cast<WSAPIDidFinishPaintingNotification&>(request));
  428. case WSMessage::APIGetWindowBackingStoreRequest:
  429. return handle_request(static_cast<WSAPIGetWindowBackingStoreRequest&>(request));
  430. case WSMessage::APISetGlobalCursorTrackingRequest:
  431. return handle_request(static_cast<WSAPISetGlobalCursorTrackingRequest&>(request));
  432. case WSMessage::APISetWindowOpacityRequest:
  433. return handle_request(static_cast<WSAPISetWindowOpacityRequest&>(request));
  434. case WSMessage::APISetWindowBackingStoreRequest:
  435. return handle_request(static_cast<WSAPISetWindowBackingStoreRequest&>(request));
  436. default:
  437. break;
  438. }
  439. }