WSClientConnection.cpp 31 KB

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