WSClientConnection.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  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 <WindowServer/WSClipboard.h>
  10. #include <WindowServer/WSScreen.h>
  11. #include <SharedBuffer.h>
  12. #include <sys/ioctl.h>
  13. #include <unistd.h>
  14. #include <errno.h>
  15. #include <stdio.h>
  16. HashMap<int, WSClientConnection*>* s_connections;
  17. void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
  18. {
  19. if (!s_connections)
  20. return;
  21. for (auto& it : *s_connections) {
  22. callback(*it.value);
  23. }
  24. }
  25. WSClientConnection* WSClientConnection::from_client_id(int client_id)
  26. {
  27. if (!s_connections)
  28. return nullptr;
  29. auto it = s_connections->find(client_id);
  30. if (it == s_connections->end())
  31. return nullptr;
  32. return (*it).value;
  33. }
  34. WSClientConnection::WSClientConnection(int fd)
  35. : m_fd(fd)
  36. {
  37. static int s_next_client_id = 0;
  38. m_client_id = ++s_next_client_id;
  39. if (!s_connections)
  40. s_connections = new HashMap<int, WSClientConnection*>;
  41. s_connections->set(m_client_id, this);
  42. WSAPI_ServerMessage message;
  43. message.type = WSAPI_ServerMessage::Type::Greeting;
  44. message.greeting.server_pid = getpid();
  45. message.greeting.screen_rect = WSScreen::the().rect();
  46. post_message(message);
  47. }
  48. WSClientConnection::~WSClientConnection()
  49. {
  50. s_connections->remove(m_client_id);
  51. int rc = close(m_fd);
  52. ASSERT(rc == 0);
  53. }
  54. void WSClientConnection::post_error(const String& error_message)
  55. {
  56. dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", m_client_id, error_message.characters());
  57. WSAPI_ServerMessage message;
  58. message.type = WSAPI_ServerMessage::Type::Error;
  59. ASSERT(error_message.length() < (ssize_t)sizeof(message.text));
  60. strcpy(message.text, error_message.characters());
  61. message.text_length = error_message.length();
  62. post_message(message);
  63. }
  64. void WSClientConnection::post_message(const WSAPI_ServerMessage& message)
  65. {
  66. int nwritten = write(m_fd, &message, sizeof(message));
  67. if (nwritten < 0) {
  68. if (errno == EPIPE) {
  69. dbgprintf("WSClientConnection::post_message: Disconnected from peer.\n");
  70. return;
  71. }
  72. perror("WSClientConnection::post_message write");
  73. ASSERT_NOT_REACHED();
  74. }
  75. ASSERT(nwritten == sizeof(message));
  76. }
  77. void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
  78. {
  79. WSAPI_ServerMessage message;
  80. message.type = WSAPI_ServerMessage::Type::ScreenRectChanged;
  81. message.screen.rect = rect;
  82. post_message(message);
  83. }
  84. void WSClientConnection::on_message(const WSMessage& message)
  85. {
  86. if (message.is_client_request()) {
  87. on_request(static_cast<const WSAPIClientRequest&>(message));
  88. return;
  89. }
  90. if (message.type() == WSMessage::WM_ClientDisconnected) {
  91. int client_id = static_cast<const 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(const 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(const 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(const 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(const WSAPIDestroyMenuRequest& request)
  134. {
  135. int menu_id = static_cast<const 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(const 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(const 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(const WSAPIAddMenuItemRequest& request)
  189. {
  190. int menu_id = request.menu_id();
  191. unsigned identifier = request.identifier();
  192. auto it = m_menus.find(menu_id);
  193. if (it == m_menus.end()) {
  194. post_error("Bad menu ID");
  195. return;
  196. }
  197. auto& menu = *(*it).value;
  198. menu.add_item(make<WSMenuItem>(identifier, request.text(), request.shortcut_text()));
  199. WSAPI_ServerMessage response;
  200. response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
  201. response.menu.menu_id = menu_id;
  202. response.menu.identifier = identifier;
  203. post_message(response);
  204. }
  205. void WSClientConnection::handle_request(const WSAPIAddMenuSeparatorRequest& request)
  206. {
  207. int menu_id = request.menu_id();
  208. auto it = m_menus.find(menu_id);
  209. if (it == m_menus.end()) {
  210. post_error("Bad menu ID");
  211. return;
  212. }
  213. auto& menu = *(*it).value;
  214. menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
  215. WSAPI_ServerMessage response;
  216. response.type = WSAPI_ServerMessage::Type::DidAddMenuSeparator;
  217. response.menu.menu_id = menu_id;
  218. post_message(response);
  219. }
  220. void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& request)
  221. {
  222. int window_id = request.window_id();
  223. auto it = m_windows.find(window_id);
  224. if (it == m_windows.end()) {
  225. post_error("Bad window ID");
  226. return;
  227. }
  228. auto& window = *(*it).value;
  229. window.set_opacity(request.opacity());
  230. }
  231. void WSClientConnection::handle_request(const WSAPISetWallpaperRequest& request)
  232. {
  233. bool success = WSWindowManager::the().set_wallpaper(request.wallpaper());
  234. WSAPI_ServerMessage response;
  235. response.type = WSAPI_ServerMessage::Type::DidSetWallpaper;
  236. response.value = success;
  237. post_message(response);
  238. }
  239. void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&)
  240. {
  241. auto path = WSWindowManager::the().wallpaper_path();
  242. WSAPI_ServerMessage response;
  243. response.type = WSAPI_ServerMessage::Type::DidGetWallpaper;
  244. ASSERT(path.length() < (int)sizeof(response.text));
  245. strncpy(response.text, path.characters(), path.length());
  246. response.text_length = path.length();
  247. post_message(response);
  248. }
  249. void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& request)
  250. {
  251. int window_id = request.window_id();
  252. auto it = m_windows.find(window_id);
  253. if (it == m_windows.end()) {
  254. post_error("Bad window ID");
  255. return;
  256. }
  257. auto& window = *(*it).value;
  258. window.set_title(request.title());
  259. }
  260. void WSClientConnection::handle_request(const WSAPIGetWindowTitleRequest& 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. WSAPI_ServerMessage response;
  270. response.type = WSAPI_ServerMessage::Type::DidGetWindowTitle;
  271. response.window_id = window.window_id();
  272. ASSERT(window.title().length() < (ssize_t)sizeof(response.text));
  273. strcpy(response.text, window.title().characters());
  274. response.text_length = window.title().length();
  275. post_message(response);
  276. }
  277. void WSClientConnection::handle_request(const WSAPISetWindowRectRequest& request)
  278. {
  279. int window_id = request.window_id();
  280. auto it = m_windows.find(window_id);
  281. if (it == m_windows.end()) {
  282. post_error("Bad window ID");
  283. return;
  284. }
  285. auto& window = *(*it).value;
  286. window.set_rect(request.rect());
  287. post_paint_request(window, request.rect());
  288. }
  289. void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& request)
  290. {
  291. int window_id = request.window_id();
  292. auto it = m_windows.find(window_id);
  293. if (it == m_windows.end()) {
  294. post_error("Bad window ID");
  295. return;
  296. }
  297. auto& window = *(*it).value;
  298. WSAPI_ServerMessage response;
  299. response.type = WSAPI_ServerMessage::Type::DidGetWindowRect;
  300. response.window_id = window.window_id();
  301. response.window.rect = window.rect();
  302. post_message(response);
  303. }
  304. void WSClientConnection::handle_request(const WSAPISetClipboardContentsRequest& request)
  305. {
  306. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  307. if (!shared_buffer) {
  308. post_error("Bad shared buffer ID");
  309. return;
  310. }
  311. WSClipboard::the().set_data(*shared_buffer, request.size());
  312. WSAPI_ServerMessage response;
  313. response.type = WSAPI_ServerMessage::Type::DidSetClipboardContents;
  314. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  315. post_message(response);
  316. }
  317. void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
  318. {
  319. WSAPI_ServerMessage response;
  320. response.type = WSAPI_ServerMessage::Type::DidGetClipboardContents;
  321. response.clipboard.shared_buffer_id = -1;
  322. response.clipboard.contents_size = 0;
  323. if (WSClipboard::the().size()) {
  324. // FIXME: Optimize case where an app is copy/pasting within itself.
  325. // We can just reuse the SharedBuffer then, since it will have the same peer PID.
  326. // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
  327. RetainPtr<SharedBuffer> shared_buffer = SharedBuffer::create(m_pid, WSClipboard::the().size());
  328. ASSERT(shared_buffer);
  329. memcpy(shared_buffer->data(), WSClipboard::the().data(), WSClipboard::the().size());
  330. shared_buffer->seal();
  331. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  332. response.clipboard.contents_size = WSClipboard::the().size();
  333. // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
  334. // After we respond to GetClipboardContents, we have to wait for the client to retain the buffer on his side.
  335. m_last_sent_clipboard_content = move(shared_buffer);
  336. }
  337. post_message(response);
  338. }
  339. void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
  340. {
  341. int window_id = m_next_window_id++;
  342. auto window = make<WSWindow>(*this, request.window_type(), window_id, request.is_modal());
  343. window->set_has_alpha_channel(request.has_alpha_channel());
  344. window->set_resizable(request.is_resizable());
  345. window->set_title(request.title());
  346. window->set_rect(request.rect());
  347. window->set_opacity(request.opacity());
  348. window->set_size_increment(request.size_increment());
  349. window->set_base_size(request.base_size());
  350. window->invalidate();
  351. m_windows.set(window_id, move(window));
  352. WSAPI_ServerMessage response;
  353. response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
  354. response.window_id = window_id;
  355. post_message(response);
  356. }
  357. void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request)
  358. {
  359. int window_id = request.window_id();
  360. auto it = m_windows.find(window_id);
  361. if (it == m_windows.end()) {
  362. post_error("Bad window ID");
  363. return;
  364. }
  365. auto& window = *(*it).value;
  366. WSWindowManager::the().invalidate(window);
  367. m_windows.remove(it);
  368. }
  369. void WSClientConnection::post_paint_request(const WSWindow& window, const Rect& rect)
  370. {
  371. WSAPI_ServerMessage response;
  372. response.type = WSAPI_ServerMessage::Type::Paint;
  373. response.window_id = window.window_id();
  374. response.paint.rect = rect;
  375. response.paint.window_size = window.size();
  376. post_message(response);
  377. }
  378. void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
  379. {
  380. int window_id = request.window_id();
  381. auto it = m_windows.find(window_id);
  382. if (it == m_windows.end()) {
  383. post_error("Bad window ID");
  384. return;
  385. }
  386. auto& window = *(*it).value;
  387. post_paint_request(window, request.rect());
  388. }
  389. void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
  390. {
  391. int window_id = request.window_id();
  392. auto it = m_windows.find(window_id);
  393. if (it == m_windows.end()) {
  394. post_error("Bad window ID");
  395. return;
  396. }
  397. auto& window = *(*it).value;
  398. if (!window.has_painted_since_last_resize()) {
  399. if (window.last_lazy_resize_rect().size() == request.rect().size()) {
  400. window.set_has_painted_since_last_resize(true);
  401. WSMessageLoop::the().post_message(window, make<WSResizeEvent>(window.last_lazy_resize_rect(), window.rect()));
  402. }
  403. }
  404. WSWindowManager::the().invalidate(window, request.rect());
  405. }
  406. void WSClientConnection::handle_request(const WSAPIGetWindowBackingStoreRequest& 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("Bad window ID");
  412. return;
  413. }
  414. auto& window = *(*it).value;
  415. auto* backing_store = window.backing_store();
  416. WSAPI_ServerMessage response;
  417. response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore;
  418. response.window_id = window_id;
  419. response.backing.bpp = sizeof(RGBA32);
  420. response.backing.pitch = backing_store->pitch();
  421. response.backing.size = backing_store->size();
  422. response.backing.has_alpha_channel = backing_store->has_alpha_channel();
  423. response.backing.shared_buffer_id = backing_store->shared_buffer_id();
  424. post_message(response);
  425. }
  426. void WSClientConnection::handle_request(const WSAPISetWindowBackingStoreRequest& request)
  427. {
  428. int window_id = request.window_id();
  429. auto it = m_windows.find(window_id);
  430. if (it == m_windows.end()) {
  431. post_error("Bad window ID");
  432. return;
  433. }
  434. auto& window = *(*it).value;
  435. if (window.last_backing_store() && window.last_backing_store()->shared_buffer_id() == request.shared_buffer_id()) {
  436. window.swap_backing_stores();
  437. } else {
  438. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  439. if (!shared_buffer)
  440. return;
  441. auto backing_store = GraphicsBitmap::create_with_shared_buffer(
  442. request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
  443. *shared_buffer,
  444. request.size());
  445. window.set_backing_store(move(backing_store));
  446. }
  447. if (request.flush_immediately())
  448. window.invalidate();
  449. WSAPI_ServerMessage response;
  450. response.type = WSAPI_ServerMessage::Type::DidSetWindowBackingStore;
  451. response.window_id = window_id;
  452. response.backing.shared_buffer_id = request.shared_buffer_id();
  453. post_message(response);
  454. }
  455. void WSClientConnection::handle_request(const WSAPISetGlobalCursorTrackingRequest& request)
  456. {
  457. int window_id = request.window_id();
  458. auto it = m_windows.find(window_id);
  459. if (it == m_windows.end()) {
  460. post_error("Bad window ID");
  461. return;
  462. }
  463. auto& window = *(*it).value;
  464. window.set_global_cursor_tracking_enabled(request.value());
  465. }
  466. void WSClientConnection::handle_request(const WSAPISetWindowOverrideCursorRequest& request)
  467. {
  468. int window_id = request.window_id();
  469. auto it = m_windows.find(window_id);
  470. if (it == m_windows.end()) {
  471. post_error("Bad window ID");
  472. return;
  473. }
  474. auto& window = *(*it).value;
  475. window.set_override_cursor(WSCursor::create(request.cursor()));
  476. }
  477. void WSClientConnection::on_request(const WSAPIClientRequest& request)
  478. {
  479. switch (request.type()) {
  480. case WSMessage::APICreateMenubarRequest:
  481. return handle_request(static_cast<const WSAPICreateMenubarRequest&>(request));
  482. case WSMessage::APIDestroyMenubarRequest:
  483. return handle_request(static_cast<const WSAPIDestroyMenubarRequest&>(request));
  484. case WSMessage::APICreateMenuRequest:
  485. return handle_request(static_cast<const WSAPICreateMenuRequest&>(request));
  486. case WSMessage::APIDestroyMenuRequest:
  487. return handle_request(static_cast<const WSAPIDestroyMenuRequest&>(request));
  488. case WSMessage::APISetApplicationMenubarRequest:
  489. return handle_request(static_cast<const WSAPISetApplicationMenubarRequest&>(request));
  490. case WSMessage::APIAddMenuToMenubarRequest:
  491. return handle_request(static_cast<const WSAPIAddMenuToMenubarRequest&>(request));
  492. case WSMessage::APIAddMenuItemRequest:
  493. return handle_request(static_cast<const WSAPIAddMenuItemRequest&>(request));
  494. case WSMessage::APIAddMenuSeparatorRequest:
  495. return handle_request(static_cast<const WSAPIAddMenuSeparatorRequest&>(request));
  496. case WSMessage::APISetWindowTitleRequest:
  497. return handle_request(static_cast<const WSAPISetWindowTitleRequest&>(request));
  498. case WSMessage::APIGetWindowTitleRequest:
  499. return handle_request(static_cast<const WSAPIGetWindowTitleRequest&>(request));
  500. case WSMessage::APISetWindowRectRequest:
  501. return handle_request(static_cast<const WSAPISetWindowRectRequest&>(request));
  502. case WSMessage::APIGetWindowRectRequest:
  503. return handle_request(static_cast<const WSAPIGetWindowRectRequest&>(request));
  504. case WSMessage::APISetClipboardContentsRequest:
  505. return handle_request(static_cast<const WSAPISetClipboardContentsRequest&>(request));
  506. case WSMessage::APIGetClipboardContentsRequest:
  507. return handle_request(static_cast<const WSAPIGetClipboardContentsRequest&>(request));
  508. case WSMessage::APICreateWindowRequest:
  509. return handle_request(static_cast<const WSAPICreateWindowRequest&>(request));
  510. case WSMessage::APIDestroyWindowRequest:
  511. return handle_request(static_cast<const WSAPIDestroyWindowRequest&>(request));
  512. case WSMessage::APIInvalidateRectRequest:
  513. return handle_request(static_cast<const WSAPIInvalidateRectRequest&>(request));
  514. case WSMessage::APIDidFinishPaintingNotification:
  515. return handle_request(static_cast<const WSAPIDidFinishPaintingNotification&>(request));
  516. case WSMessage::APIGetWindowBackingStoreRequest:
  517. return handle_request(static_cast<const WSAPIGetWindowBackingStoreRequest&>(request));
  518. case WSMessage::APISetGlobalCursorTrackingRequest:
  519. return handle_request(static_cast<const WSAPISetGlobalCursorTrackingRequest&>(request));
  520. case WSMessage::APISetWindowOpacityRequest:
  521. return handle_request(static_cast<const WSAPISetWindowOpacityRequest&>(request));
  522. case WSMessage::APISetWindowBackingStoreRequest:
  523. return handle_request(static_cast<const WSAPISetWindowBackingStoreRequest&>(request));
  524. case WSMessage::APISetWallpaperRequest:
  525. return handle_request(static_cast<const WSAPISetWallpaperRequest&>(request));
  526. case WSMessage::APIGetWallpaperRequest:
  527. return handle_request(static_cast<const WSAPIGetWallpaperRequest&>(request));
  528. case WSMessage::APISetWindowOverrideCursorRequest:
  529. return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
  530. default:
  531. break;
  532. }
  533. }
  534. bool WSClientConnection::is_showing_modal_window() const
  535. {
  536. for (auto& it : m_windows) {
  537. auto& window = *it.value;
  538. if (window.is_visible() && window.is_modal())
  539. return true;
  540. }
  541. return false;
  542. }