WSClientConnection.cpp 14 KB

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