WSClientConnection.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. #include <WindowServer/WSClientConnection.h>
  2. #include <WindowServer/WSEventLoop.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 <WindowServer/WSScreen.h>
  11. #include <WindowServer/WSWindowSwitcher.h>
  12. #include <SharedBuffer.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/uio.h>
  15. #include <unistd.h>
  16. #include <errno.h>
  17. #include <stdio.h>
  18. HashMap<int, WSClientConnection*>* s_connections;
  19. void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
  20. {
  21. if (!s_connections)
  22. return;
  23. for (auto& it : *s_connections) {
  24. callback(*it.value);
  25. }
  26. }
  27. WSClientConnection* WSClientConnection::from_client_id(int client_id)
  28. {
  29. if (!s_connections)
  30. return nullptr;
  31. auto it = s_connections->find(client_id);
  32. if (it == s_connections->end())
  33. return nullptr;
  34. return (*it).value;
  35. }
  36. WSClientConnection::WSClientConnection(int fd)
  37. : m_fd(fd)
  38. {
  39. static int s_next_client_id = 0;
  40. m_client_id = ++s_next_client_id;
  41. if (!s_connections)
  42. s_connections = new HashMap<int, WSClientConnection*>;
  43. s_connections->set(m_client_id, this);
  44. WSAPI_ServerMessage message;
  45. message.type = WSAPI_ServerMessage::Type::Greeting;
  46. message.greeting.server_pid = getpid();
  47. message.greeting.your_client_id = m_client_id;
  48. message.greeting.screen_rect = WSScreen::the().rect();
  49. post_message(message);
  50. }
  51. WSClientConnection::~WSClientConnection()
  52. {
  53. s_connections->remove(m_client_id);
  54. int rc = close(m_fd);
  55. ASSERT(rc == 0);
  56. }
  57. void WSClientConnection::post_error(const String& error_message)
  58. {
  59. dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", m_client_id, error_message.characters());
  60. WSAPI_ServerMessage message;
  61. message.type = WSAPI_ServerMessage::Type::Error;
  62. ASSERT(error_message.length() < (ssize_t)sizeof(message.text));
  63. strcpy(message.text, error_message.characters());
  64. message.text_length = error_message.length();
  65. post_message(message);
  66. }
  67. void WSClientConnection::post_message(const WSAPI_ServerMessage& message, const ByteBuffer& extra_data)
  68. {
  69. if (!extra_data.is_empty())
  70. const_cast<WSAPI_ServerMessage&>(message).extra_size = extra_data.size();
  71. struct iovec iov[2];
  72. int iov_count = 1;
  73. iov[0].iov_base = (void*)&message;
  74. iov[0].iov_len = sizeof(message);
  75. if (!extra_data.is_empty()) {
  76. iov[1].iov_base = (void*)extra_data.data();
  77. iov[1].iov_len = extra_data.size();
  78. ++iov_count;
  79. }
  80. int nwritten = writev(m_fd, iov, iov_count);
  81. if (nwritten < 0) {
  82. if (errno == EPIPE) {
  83. dbgprintf("WSClientConnection::post_message: Disconnected from peer.\n");
  84. return;
  85. }
  86. perror("WSClientConnection::post_message writev");
  87. ASSERT_NOT_REACHED();
  88. }
  89. ASSERT(nwritten == sizeof(message) + extra_data.size());
  90. }
  91. void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
  92. {
  93. WSAPI_ServerMessage message;
  94. message.type = WSAPI_ServerMessage::Type::ScreenRectChanged;
  95. message.screen.rect = rect;
  96. post_message(message);
  97. }
  98. void WSClientConnection::event(CEvent& event)
  99. {
  100. if (static_cast<WSEvent&>(event).is_client_request()) {
  101. on_request(static_cast<const WSAPIClientRequest&>(event));
  102. return;
  103. }
  104. if (event.type() == WSEvent::WM_ClientDisconnected) {
  105. int client_id = static_cast<const WSClientDisconnectedNotification&>(event).client_id();
  106. dbgprintf("WSClientConnection: Client disconnected: %d\n", client_id);
  107. delete this;
  108. return;
  109. }
  110. CObject::event(event);
  111. }
  112. void WSClientConnection::did_misbehave()
  113. {
  114. dbgprintf("WSClientConnection{%p} (id=%d, pid=%d) misbehaved, disconnecting.\n", this, m_client_id, m_pid);
  115. // FIXME: We should make sure we avoid processing any further messages from this client.
  116. delete_later();
  117. }
  118. void WSClientConnection::handle_request(const WSAPICreateMenubarRequest&)
  119. {
  120. int menubar_id = m_next_menubar_id++;
  121. auto menubar = make<WSMenuBar>(*this, menubar_id);
  122. m_menubars.set(menubar_id, move(menubar));
  123. WSAPI_ServerMessage response;
  124. response.type = WSAPI_ServerMessage::Type::DidCreateMenubar;
  125. response.menu.menubar_id = menubar_id;
  126. post_message(response);
  127. }
  128. void WSClientConnection::handle_request(const WSAPIDestroyMenubarRequest& request)
  129. {
  130. int menubar_id = request.menubar_id();
  131. auto it = m_menubars.find(menubar_id);
  132. if (it == m_menubars.end()) {
  133. post_error("WSAPIDestroyMenubarRequest: Bad menubar ID");
  134. return;
  135. }
  136. auto& menubar = *(*it).value;
  137. WSWindowManager::the().close_menubar(menubar);
  138. m_menubars.remove(it);
  139. WSAPI_ServerMessage response;
  140. response.type = WSAPI_ServerMessage::Type::DidDestroyMenubar;
  141. response.menu.menubar_id = menubar_id;
  142. post_message(response);
  143. }
  144. void WSClientConnection::handle_request(const WSAPICreateMenuRequest& request)
  145. {
  146. int menu_id = m_next_menu_id++;
  147. auto menu = make<WSMenu>(this, menu_id, request.text());
  148. m_menus.set(menu_id, move(menu));
  149. WSAPI_ServerMessage response;
  150. response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
  151. response.menu.menu_id = menu_id;
  152. post_message(response);
  153. }
  154. void WSClientConnection::handle_request(const WSAPIDestroyMenuRequest& request)
  155. {
  156. int menu_id = static_cast<const WSAPIDestroyMenuRequest&>(request).menu_id();
  157. auto it = m_menus.find(menu_id);
  158. if (it == m_menus.end()) {
  159. post_error("WSAPIDestroyMenuRequest: Bad menu ID");
  160. return;
  161. }
  162. auto& menu = *(*it).value;
  163. WSWindowManager::the().close_menu(menu);
  164. m_menus.remove(it);
  165. WSAPI_ServerMessage response;
  166. response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
  167. response.menu.menu_id = menu_id;
  168. post_message(response);
  169. }
  170. void WSClientConnection::handle_request(const WSAPISetApplicationMenubarRequest& request)
  171. {
  172. int menubar_id = request.menubar_id();
  173. auto it = m_menubars.find(menubar_id);
  174. if (it == m_menubars.end()) {
  175. post_error("WSAPISetApplicationMenubarRequest: Bad menubar ID");
  176. return;
  177. }
  178. auto& menubar = *(*it).value;
  179. m_app_menubar = menubar.make_weak_ptr();
  180. WSWindowManager::the().notify_client_changed_app_menubar(*this);
  181. WSAPI_ServerMessage response;
  182. response.type = WSAPI_ServerMessage::Type::DidSetApplicationMenubar;
  183. response.menu.menubar_id = menubar_id;
  184. post_message(response);
  185. }
  186. void WSClientConnection::handle_request(const WSAPIAddMenuToMenubarRequest& request)
  187. {
  188. int menubar_id = request.menubar_id();
  189. int menu_id = request.menu_id();
  190. auto it = m_menubars.find(menubar_id);
  191. auto jt = m_menus.find(menu_id);
  192. if (it == m_menubars.end()) {
  193. post_error("WSAPIAddMenuToMenubarRequest: Bad menubar ID");
  194. return;
  195. }
  196. if (jt == m_menus.end()) {
  197. post_error("WSAPIAddMenuToMenubarRequest: Bad menu ID");
  198. return;
  199. }
  200. auto& menubar = *(*it).value;
  201. auto& menu = *(*jt).value;
  202. menubar.add_menu(menu);
  203. WSAPI_ServerMessage response;
  204. response.type = WSAPI_ServerMessage::Type::DidAddMenuToMenubar;
  205. response.menu.menubar_id = menubar_id;
  206. response.menu.menu_id = menu_id;
  207. post_message(response);
  208. }
  209. void WSClientConnection::handle_request(const WSAPIAddMenuItemRequest& request)
  210. {
  211. int menu_id = request.menu_id();
  212. unsigned identifier = request.identifier();
  213. auto it = m_menus.find(menu_id);
  214. if (it == m_menus.end()) {
  215. post_error("WSAPIAddMenuItemRequest: Bad menu ID");
  216. return;
  217. }
  218. auto& menu = *(*it).value;
  219. menu.add_item(make<WSMenuItem>(menu, identifier, request.text(), request.shortcut_text(), request.is_enabled(), request.is_checkable(), request.is_checked()));
  220. WSAPI_ServerMessage response;
  221. response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
  222. response.menu.menu_id = menu_id;
  223. response.menu.identifier = identifier;
  224. post_message(response);
  225. }
  226. void WSClientConnection::handle_request(const WSAPIPopupMenuRequest& request)
  227. {
  228. int menu_id = request.menu_id();
  229. auto position = request.position();
  230. auto it = m_menus.find(menu_id);
  231. if (it == m_menus.end()) {
  232. post_error("WSAPIPopupMenuRequest: Bad menu ID");
  233. return;
  234. }
  235. auto& menu = *(*it).value;
  236. menu.popup(position);
  237. }
  238. void WSClientConnection::handle_request(const WSAPIDismissMenuRequest& request)
  239. {
  240. int menu_id = request.menu_id();
  241. auto it = m_menus.find(menu_id);
  242. if (it == m_menus.end()) {
  243. post_error("WSAPIDismissMenuRequest: Bad menu ID");
  244. return;
  245. }
  246. auto& menu = *(*it).value;
  247. menu.close();
  248. }
  249. void WSClientConnection::handle_request(const WSAPIUpdateMenuItemRequest& request)
  250. {
  251. int menu_id = request.menu_id();
  252. unsigned identifier = request.identifier();
  253. auto it = m_menus.find(menu_id);
  254. if (it == m_menus.end()) {
  255. post_error("WSAPIUpdateMenuItemRequest: Bad menu ID");
  256. return;
  257. }
  258. auto& menu = *(*it).value;
  259. auto* menu_item = menu.item_with_identifier(request.identifier());
  260. if (!menu_item) {
  261. post_error("WSAPIUpdateMenuItemRequest: Bad menu item identifier");
  262. return;
  263. }
  264. menu_item->set_text(request.text());
  265. menu_item->set_shortcut_text(request.shortcut_text());
  266. menu_item->set_enabled(request.is_enabled());
  267. menu_item->set_checkable(request.is_checkable());
  268. if (request.is_checkable())
  269. menu_item->set_checked(request.is_checked());
  270. WSAPI_ServerMessage response;
  271. response.type = WSAPI_ServerMessage::Type::DidUpdateMenuItem;
  272. response.menu.menu_id = menu_id;
  273. response.menu.identifier = identifier;
  274. post_message(response);
  275. }
  276. void WSClientConnection::handle_request(const WSAPIAddMenuSeparatorRequest& request)
  277. {
  278. int menu_id = request.menu_id();
  279. auto it = m_menus.find(menu_id);
  280. if (it == m_menus.end()) {
  281. post_error("WSAPIAddMenuSeparatorRequest: Bad menu ID");
  282. return;
  283. }
  284. auto& menu = *(*it).value;
  285. menu.add_item(make<WSMenuItem>(menu, WSMenuItem::Separator));
  286. WSAPI_ServerMessage response;
  287. response.type = WSAPI_ServerMessage::Type::DidAddMenuSeparator;
  288. response.menu.menu_id = menu_id;
  289. post_message(response);
  290. }
  291. void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& request)
  292. {
  293. int window_id = request.window_id();
  294. auto it = m_windows.find(window_id);
  295. if (it == m_windows.end()) {
  296. post_error("WSAPISetWindowOpacityRequest: Bad window ID");
  297. return;
  298. }
  299. auto& window = *(*it).value;
  300. window.set_opacity(request.opacity());
  301. }
  302. void WSClientConnection::handle_request(const WSAPISetWallpaperRequest& request)
  303. {
  304. WSWindowManager::the().set_wallpaper(request.wallpaper(), [&] (bool success) {
  305. WSAPI_ServerMessage response;
  306. response.type = WSAPI_ServerMessage::Type::DidSetWallpaper;
  307. response.value = success;
  308. post_message(response);
  309. });
  310. }
  311. void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&)
  312. {
  313. auto path = WSWindowManager::the().wallpaper_path();
  314. WSAPI_ServerMessage response;
  315. response.type = WSAPI_ServerMessage::Type::DidGetWallpaper;
  316. ASSERT(path.length() < (int)sizeof(response.text));
  317. strncpy(response.text, path.characters(), path.length());
  318. response.text_length = path.length();
  319. post_message(response);
  320. }
  321. void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& request)
  322. {
  323. int window_id = request.window_id();
  324. auto it = m_windows.find(window_id);
  325. if (it == m_windows.end()) {
  326. post_error("WSAPISetWindowTitleRequest: Bad window ID");
  327. return;
  328. }
  329. auto& window = *(*it).value;
  330. window.set_title(request.title());
  331. }
  332. void WSClientConnection::handle_request(const WSAPIGetWindowTitleRequest& request)
  333. {
  334. int window_id = request.window_id();
  335. auto it = m_windows.find(window_id);
  336. if (it == m_windows.end()) {
  337. post_error("WSAPIGetWindowTitleRequest: Bad window ID");
  338. return;
  339. }
  340. auto& window = *(*it).value;
  341. WSAPI_ServerMessage response;
  342. response.type = WSAPI_ServerMessage::Type::DidGetWindowTitle;
  343. response.window_id = window.window_id();
  344. ASSERT(window.title().length() < (ssize_t)sizeof(response.text));
  345. strcpy(response.text, window.title().characters());
  346. response.text_length = window.title().length();
  347. post_message(response);
  348. }
  349. void WSClientConnection::handle_request(const WSAPISetWindowIconRequest& request)
  350. {
  351. int window_id = request.window_id();
  352. auto it = m_windows.find(window_id);
  353. if (it == m_windows.end()) {
  354. post_error("WSAPISetWindowIconRequest: Bad window ID");
  355. return;
  356. }
  357. auto& window = *(*it).value;
  358. if (request.icon_path().is_empty()) {
  359. window.set_default_icon();
  360. } else {
  361. auto icon = GraphicsBitmap::load_from_file(request.icon_path());
  362. if (!icon)
  363. return;
  364. window.set_icon(request.icon_path(), *icon);
  365. }
  366. window.frame().invalidate_title_bar();
  367. WSWindowManager::the().tell_wm_listeners_window_icon_changed(window);
  368. }
  369. void WSClientConnection::handle_request(const WSAPISetWindowRectRequest& request)
  370. {
  371. int window_id = request.window_id();
  372. auto it = m_windows.find(window_id);
  373. if (it == m_windows.end()) {
  374. post_error("WSAPISetWindowRectRequest: Bad window ID");
  375. return;
  376. }
  377. auto& window = *(*it).value;
  378. if (window.is_fullscreen()) {
  379. dbgprintf("WSClientConnection: Ignoring SetWindowRect request for fullscreen window\n");
  380. return;
  381. }
  382. window.set_rect(request.rect());
  383. window.request_update(request.rect());
  384. }
  385. void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& 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("WSAPIGetWindowRectRequest: Bad window ID");
  391. return;
  392. }
  393. auto& window = *(*it).value;
  394. WSAPI_ServerMessage response;
  395. response.type = WSAPI_ServerMessage::Type::DidGetWindowRect;
  396. response.window_id = window.window_id();
  397. response.window.rect = window.rect();
  398. post_message(response);
  399. }
  400. void WSClientConnection::handle_request(const WSAPISetClipboardContentsRequest& request)
  401. {
  402. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  403. if (!shared_buffer) {
  404. post_error("WSAPISetClipboardContentsRequest: Bad shared buffer ID");
  405. return;
  406. }
  407. WSClipboard::the().set_data(*shared_buffer, request.size());
  408. WSAPI_ServerMessage response;
  409. response.type = WSAPI_ServerMessage::Type::DidSetClipboardContents;
  410. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  411. post_message(response);
  412. }
  413. void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
  414. {
  415. WSAPI_ServerMessage response;
  416. response.type = WSAPI_ServerMessage::Type::DidGetClipboardContents;
  417. response.clipboard.shared_buffer_id = -1;
  418. response.clipboard.contents_size = 0;
  419. if (WSClipboard::the().size()) {
  420. // FIXME: Optimize case where an app is copy/pasting within itself.
  421. // We can just reuse the SharedBuffer then, since it will have the same peer PID.
  422. // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
  423. RetainPtr<SharedBuffer> shared_buffer = SharedBuffer::create(m_pid, WSClipboard::the().size());
  424. ASSERT(shared_buffer);
  425. memcpy(shared_buffer->data(), WSClipboard::the().data(), WSClipboard::the().size());
  426. shared_buffer->seal();
  427. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  428. response.clipboard.contents_size = WSClipboard::the().size();
  429. // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
  430. // After we respond to GetClipboardContents, we have to wait for the client to retain the buffer on his side.
  431. m_last_sent_clipboard_content = move(shared_buffer);
  432. }
  433. post_message(response);
  434. }
  435. void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
  436. {
  437. int window_id = m_next_window_id++;
  438. auto window = make<WSWindow>(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
  439. window->set_background_color(request.background_color());
  440. window->set_has_alpha_channel(request.has_alpha_channel());
  441. window->set_title(request.title());
  442. if (!request.is_fullscreen())
  443. window->set_rect(request.rect());
  444. window->set_opacity(request.opacity());
  445. window->set_size_increment(request.size_increment());
  446. window->set_base_size(request.base_size());
  447. window->invalidate();
  448. m_windows.set(window_id, move(window));
  449. WSAPI_ServerMessage response;
  450. response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
  451. response.window_id = window_id;
  452. post_message(response);
  453. }
  454. void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request)
  455. {
  456. int window_id = request.window_id();
  457. auto it = m_windows.find(window_id);
  458. if (it == m_windows.end()) {
  459. post_error("WSAPIDestroyWindowRequest: Bad window ID");
  460. return;
  461. }
  462. auto& window = *(*it).value;
  463. WSWindowManager::the().invalidate(window);
  464. m_windows.remove(it);
  465. WSAPI_ServerMessage response;
  466. response.type = WSAPI_ServerMessage::Type::DidDestroyWindow;
  467. response.window_id = window.window_id();
  468. post_message(response);
  469. }
  470. void WSClientConnection::post_paint_message(WSWindow& window)
  471. {
  472. auto rect_set = window.take_pending_paint_rects();
  473. if (window.is_minimized())
  474. return;
  475. WSAPI_ServerMessage message;
  476. message.type = WSAPI_ServerMessage::Type::Paint;
  477. message.window_id = window.window_id();
  478. auto& rects = rect_set.rects();
  479. message.rect_count = rects.size();
  480. for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, rects.size()); ++i)
  481. message.rects[i] = rects[i];
  482. message.paint.window_size = window.size();
  483. ByteBuffer extra_data;
  484. if (rects.size() > WSAPI_ServerMessage::max_inline_rect_count)
  485. extra_data = ByteBuffer::wrap(&rects[WSAPI_ServerMessage::max_inline_rect_count], (rects.size() - WSAPI_ServerMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
  486. post_message(message, extra_data);
  487. }
  488. void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
  489. {
  490. int window_id = request.window_id();
  491. auto it = m_windows.find(window_id);
  492. if (it == m_windows.end()) {
  493. post_error("WSAPIInvalidateRectRequest: Bad window ID");
  494. return;
  495. }
  496. auto& window = *(*it).value;
  497. for (int i = 0; i < request.rects().size(); ++i)
  498. window.request_update(request.rects()[i].intersected({ { }, window.size() }));
  499. }
  500. void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
  501. {
  502. int window_id = request.window_id();
  503. auto it = m_windows.find(window_id);
  504. if (it == m_windows.end()) {
  505. post_error("WSAPIDidFinishPaintingNotification: Bad window ID");
  506. return;
  507. }
  508. auto& window = *(*it).value;
  509. for (auto& rect : request.rects())
  510. WSWindowManager::the().invalidate(window, rect);
  511. WSWindowSwitcher::the().refresh_if_needed();
  512. }
  513. void WSClientConnection::handle_request(const WSAPIGetWindowBackingStoreRequest& request)
  514. {
  515. int window_id = request.window_id();
  516. auto it = m_windows.find(window_id);
  517. if (it == m_windows.end()) {
  518. post_error("WSAPIGetWindowBackingStoreRequest: Bad window ID");
  519. return;
  520. }
  521. auto& window = *(*it).value;
  522. auto* backing_store = window.backing_store();
  523. WSAPI_ServerMessage response;
  524. response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore;
  525. response.window_id = window_id;
  526. response.backing.bpp = sizeof(RGBA32);
  527. response.backing.pitch = backing_store->pitch();
  528. response.backing.size = backing_store->size();
  529. response.backing.has_alpha_channel = backing_store->has_alpha_channel();
  530. response.backing.shared_buffer_id = backing_store->shared_buffer_id();
  531. post_message(response);
  532. }
  533. void WSClientConnection::handle_request(const WSAPISetWindowBackingStoreRequest& request)
  534. {
  535. int window_id = request.window_id();
  536. auto it = m_windows.find(window_id);
  537. if (it == m_windows.end()) {
  538. post_error("WSAPISetWindowBackingStoreRequest: Bad window ID");
  539. return;
  540. }
  541. auto& window = *(*it).value;
  542. if (window.last_backing_store() && window.last_backing_store()->shared_buffer_id() == request.shared_buffer_id()) {
  543. window.swap_backing_stores();
  544. } else {
  545. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  546. if (!shared_buffer)
  547. return;
  548. auto backing_store = GraphicsBitmap::create_with_shared_buffer(
  549. request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
  550. *shared_buffer,
  551. request.size());
  552. window.set_backing_store(move(backing_store));
  553. }
  554. if (request.flush_immediately())
  555. window.invalidate();
  556. WSAPI_ServerMessage response;
  557. response.type = WSAPI_ServerMessage::Type::DidSetWindowBackingStore;
  558. response.window_id = window_id;
  559. response.backing.shared_buffer_id = request.shared_buffer_id();
  560. post_message(response);
  561. }
  562. void WSClientConnection::handle_request(const WSAPISetGlobalCursorTrackingRequest& request)
  563. {
  564. int window_id = request.window_id();
  565. auto it = m_windows.find(window_id);
  566. if (it == m_windows.end()) {
  567. post_error("WSAPISetGlobalCursorTrackingRequest: Bad window ID");
  568. return;
  569. }
  570. auto& window = *(*it).value;
  571. window.set_global_cursor_tracking_enabled(request.value());
  572. }
  573. void WSClientConnection::handle_request(const WSAPISetWindowOverrideCursorRequest& request)
  574. {
  575. int window_id = request.window_id();
  576. auto it = m_windows.find(window_id);
  577. if (it == m_windows.end()) {
  578. post_error("WSAPISetWindowOverrideCursorRequest: Bad window ID");
  579. return;
  580. }
  581. auto& window = *(*it).value;
  582. window.set_override_cursor(WSCursor::create(request.cursor()));
  583. }
  584. void WSClientConnection::handle_request(const WSAPISetWindowHasAlphaChannelRequest& request)
  585. {
  586. int window_id = request.window_id();
  587. auto it = m_windows.find(window_id);
  588. if (it == m_windows.end()) {
  589. post_error("WSAPISetWindowHasAlphaChannelRequest: Bad window ID");
  590. return;
  591. }
  592. auto& window = *(*it).value;
  593. window.set_has_alpha_channel(request.value());
  594. WSAPI_ServerMessage response;
  595. response.type = WSAPI_ServerMessage::Type::DidSetWindowHasAlphaChannel;
  596. response.window_id = window_id;
  597. response.value = request.value();
  598. post_message(response);
  599. }
  600. void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& request)
  601. {
  602. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  603. if (!client) {
  604. post_error("WSWMAPISetActiveWindowRequest: Bad client ID");
  605. return;
  606. }
  607. auto it = client->m_windows.find(request.target_window_id());
  608. if (it == client->m_windows.end()) {
  609. post_error("WSWMAPISetActiveWindowRequest: Bad window ID");
  610. return;
  611. }
  612. auto& window = *(*it).value;
  613. window.set_minimized(false);
  614. WSWindowManager::the().move_to_front_and_make_active(window);
  615. }
  616. void WSClientConnection::handle_request(const WSWMAPIStartWindowResizeRequest& request)
  617. {
  618. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  619. if (!client) {
  620. post_error("WSWMAPIStartWindowResizeRequest: Bad client ID");
  621. return;
  622. }
  623. auto it = client->m_windows.find(request.target_window_id());
  624. if (it == client->m_windows.end()) {
  625. post_error("WSWMAPIStartWindowResizeRequest: Bad window ID");
  626. return;
  627. }
  628. auto& window = *(*it).value;
  629. // FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button.
  630. // Maybe the client should be allowed to specify what initiated this request?
  631. WSWindowManager::the().start_window_resize(window, WSScreen::the().cursor_location(), MouseButton::Left);
  632. }
  633. void WSClientConnection::handle_request(const WSWMAPISetWindowMinimizedRequest& request)
  634. {
  635. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  636. if (!client) {
  637. post_error("WSWMAPISetWindowMinimizedRequest: Bad client ID");
  638. return;
  639. }
  640. auto it = client->m_windows.find(request.target_window_id());
  641. if (it == client->m_windows.end()) {
  642. post_error("WSWMAPISetWindowMinimizedRequest: Bad window ID");
  643. return;
  644. }
  645. auto& window = *(*it).value;
  646. window.set_minimized(request.is_minimized());
  647. }
  648. void WSClientConnection::on_request(const WSAPIClientRequest& request)
  649. {
  650. switch (request.type()) {
  651. case WSEvent::APICreateMenubarRequest:
  652. return handle_request(static_cast<const WSAPICreateMenubarRequest&>(request));
  653. case WSEvent::APIDestroyMenubarRequest:
  654. return handle_request(static_cast<const WSAPIDestroyMenubarRequest&>(request));
  655. case WSEvent::APICreateMenuRequest:
  656. return handle_request(static_cast<const WSAPICreateMenuRequest&>(request));
  657. case WSEvent::APIDestroyMenuRequest:
  658. return handle_request(static_cast<const WSAPIDestroyMenuRequest&>(request));
  659. case WSEvent::APISetApplicationMenubarRequest:
  660. return handle_request(static_cast<const WSAPISetApplicationMenubarRequest&>(request));
  661. case WSEvent::APIAddMenuToMenubarRequest:
  662. return handle_request(static_cast<const WSAPIAddMenuToMenubarRequest&>(request));
  663. case WSEvent::APIAddMenuItemRequest:
  664. return handle_request(static_cast<const WSAPIAddMenuItemRequest&>(request));
  665. case WSEvent::APIAddMenuSeparatorRequest:
  666. return handle_request(static_cast<const WSAPIAddMenuSeparatorRequest&>(request));
  667. case WSEvent::APIUpdateMenuItemRequest:
  668. return handle_request(static_cast<const WSAPIUpdateMenuItemRequest&>(request));
  669. case WSEvent::APISetWindowTitleRequest:
  670. return handle_request(static_cast<const WSAPISetWindowTitleRequest&>(request));
  671. case WSEvent::APIGetWindowTitleRequest:
  672. return handle_request(static_cast<const WSAPIGetWindowTitleRequest&>(request));
  673. case WSEvent::APISetWindowRectRequest:
  674. return handle_request(static_cast<const WSAPISetWindowRectRequest&>(request));
  675. case WSEvent::APIGetWindowRectRequest:
  676. return handle_request(static_cast<const WSAPIGetWindowRectRequest&>(request));
  677. case WSEvent::APISetWindowIconRequest:
  678. return handle_request(static_cast<const WSAPISetWindowIconRequest&>(request));
  679. case WSEvent::APISetClipboardContentsRequest:
  680. return handle_request(static_cast<const WSAPISetClipboardContentsRequest&>(request));
  681. case WSEvent::APIGetClipboardContentsRequest:
  682. return handle_request(static_cast<const WSAPIGetClipboardContentsRequest&>(request));
  683. case WSEvent::APICreateWindowRequest:
  684. return handle_request(static_cast<const WSAPICreateWindowRequest&>(request));
  685. case WSEvent::APIDestroyWindowRequest:
  686. return handle_request(static_cast<const WSAPIDestroyWindowRequest&>(request));
  687. case WSEvent::APIInvalidateRectRequest:
  688. return handle_request(static_cast<const WSAPIInvalidateRectRequest&>(request));
  689. case WSEvent::APIDidFinishPaintingNotification:
  690. return handle_request(static_cast<const WSAPIDidFinishPaintingNotification&>(request));
  691. case WSEvent::APIGetWindowBackingStoreRequest:
  692. return handle_request(static_cast<const WSAPIGetWindowBackingStoreRequest&>(request));
  693. case WSEvent::APISetGlobalCursorTrackingRequest:
  694. return handle_request(static_cast<const WSAPISetGlobalCursorTrackingRequest&>(request));
  695. case WSEvent::APISetWindowOpacityRequest:
  696. return handle_request(static_cast<const WSAPISetWindowOpacityRequest&>(request));
  697. case WSEvent::APISetWindowBackingStoreRequest:
  698. return handle_request(static_cast<const WSAPISetWindowBackingStoreRequest&>(request));
  699. case WSEvent::APISetWallpaperRequest:
  700. return handle_request(static_cast<const WSAPISetWallpaperRequest&>(request));
  701. case WSEvent::APIGetWallpaperRequest:
  702. return handle_request(static_cast<const WSAPIGetWallpaperRequest&>(request));
  703. case WSEvent::APISetWindowOverrideCursorRequest:
  704. return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
  705. case WSEvent::WMAPISetActiveWindowRequest:
  706. return handle_request(static_cast<const WSWMAPISetActiveWindowRequest&>(request));
  707. case WSEvent::WMAPISetWindowMinimizedRequest:
  708. return handle_request(static_cast<const WSWMAPISetWindowMinimizedRequest&>(request));
  709. case WSEvent::WMAPIStartWindowResizeRequest:
  710. return handle_request(static_cast<const WSWMAPIStartWindowResizeRequest&>(request));
  711. case WSEvent::APIPopupMenuRequest:
  712. return handle_request(static_cast<const WSAPIPopupMenuRequest&>(request));
  713. case WSEvent::APIDismissMenuRequest:
  714. return handle_request(static_cast<const WSAPIDismissMenuRequest&>(request));
  715. case WSEvent::APISetWindowHasAlphaChannelRequest:
  716. return handle_request(static_cast<const WSAPISetWindowHasAlphaChannelRequest&>(request));
  717. default:
  718. break;
  719. }
  720. }
  721. bool WSClientConnection::is_showing_modal_window() const
  722. {
  723. for (auto& it : m_windows) {
  724. auto& window = *it.value;
  725. if (window.is_visible() && window.is_modal())
  726. return true;
  727. }
  728. return false;
  729. }