WSClientConnection.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. #include <LibC/SharedBuffer.h>
  2. #include <LibDraw/GraphicsBitmap.h>
  3. #include <SharedBuffer.h>
  4. #include <WindowServer/WSAPITypes.h>
  5. #include <WindowServer/WSClientConnection.h>
  6. #include <WindowServer/WSClipboard.h>
  7. #include <WindowServer/WSCompositor.h>
  8. #include <WindowServer/WSEventLoop.h>
  9. #include <WindowServer/WSMenu.h>
  10. #include <WindowServer/WSMenuBar.h>
  11. #include <WindowServer/WSMenuItem.h>
  12. #include <WindowServer/WSScreen.h>
  13. #include <WindowServer/WSWindow.h>
  14. #include <WindowServer/WSWindowManager.h>
  15. #include <WindowServer/WSWindowSwitcher.h>
  16. #include <errno.h>
  17. #include <stdio.h>
  18. #include <sys/ioctl.h>
  19. #include <sys/socket.h>
  20. #include <sys/uio.h>
  21. #include <unistd.h>
  22. HashMap<int, NonnullRefPtr<WSClientConnection>>* s_connections;
  23. void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
  24. {
  25. if (!s_connections)
  26. return;
  27. for (auto& it : *s_connections) {
  28. callback(*it.value);
  29. }
  30. }
  31. WSClientConnection* WSClientConnection::from_client_id(int client_id)
  32. {
  33. if (!s_connections)
  34. return nullptr;
  35. auto it = s_connections->find(client_id);
  36. if (it == s_connections->end())
  37. return nullptr;
  38. return (*it).value.ptr();
  39. }
  40. WSClientConnection::WSClientConnection(CLocalSocket& client_socket, int client_id)
  41. : Connection(client_socket, client_id)
  42. {
  43. if (!s_connections)
  44. s_connections = new HashMap<int, NonnullRefPtr<WSClientConnection>>;
  45. s_connections->set(client_id, *this);
  46. }
  47. WSClientConnection::~WSClientConnection()
  48. {
  49. auto windows = move(m_windows);
  50. }
  51. void WSClientConnection::send_greeting()
  52. {
  53. WSAPI_ServerMessage message;
  54. message.type = WSAPI_ServerMessage::Type::Greeting;
  55. message.greeting.server_pid = getpid();
  56. message.greeting.your_client_id = client_id();
  57. message.greeting.screen_rect = WSScreen::the().rect();
  58. post_message(message);
  59. }
  60. void WSClientConnection::die()
  61. {
  62. s_connections->remove(client_id());
  63. }
  64. void WSClientConnection::post_error(const String& error_message)
  65. {
  66. dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", client_id(), error_message.characters());
  67. WSAPI_ServerMessage message;
  68. message.type = WSAPI_ServerMessage::Type::Error;
  69. ASSERT(error_message.length() < (ssize_t)sizeof(message.text));
  70. strcpy(message.text, error_message.characters());
  71. message.text_length = error_message.length();
  72. post_message(message);
  73. }
  74. void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
  75. {
  76. WSAPI_ServerMessage message;
  77. message.type = WSAPI_ServerMessage::Type::ScreenRectChanged;
  78. message.screen.rect = rect;
  79. post_message(message);
  80. }
  81. void WSClientConnection::notify_about_clipboard_contents_changed()
  82. {
  83. auto& clipboard = WSClipboard::the();
  84. WSAPI_ServerMessage message;
  85. message.type = WSAPI_ServerMessage::Type::ClipboardContentsChanged;
  86. message.clipboard.shared_buffer_id = -1;
  87. message.clipboard.contents_size = -1;
  88. ASSERT(clipboard.data_type().length() < (ssize_t)sizeof(message.text));
  89. strcpy(message.text, clipboard.data_type().characters());
  90. message.text_length = clipboard.data_type().length();
  91. post_message(message);
  92. }
  93. void WSClientConnection::event(CEvent& event)
  94. {
  95. if (static_cast<WSEvent&>(event).is_client_request()) {
  96. on_request(static_cast<const WSAPIClientRequest&>(event));
  97. return;
  98. }
  99. Connection::event(event);
  100. }
  101. static Vector<Rect, 32> get_rects(const WSAPI_ClientMessage& message, const ByteBuffer& extra_data)
  102. {
  103. Vector<Rect, 32> rects;
  104. if (message.rect_count > (int)(WSAPI_ClientMessage::max_inline_rect_count + extra_data.size() / sizeof(WSAPI_Rect))) {
  105. return {};
  106. }
  107. for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, message.rect_count); ++i)
  108. rects.append(message.rects[i]);
  109. if (!extra_data.is_empty()) {
  110. auto* extra_rects = reinterpret_cast<const WSAPI_Rect*>(extra_data.data());
  111. for (int i = 0; i < (int)(extra_data.size() / sizeof(WSAPI_Rect)); ++i)
  112. rects.append(extra_rects[i]);
  113. }
  114. return rects;
  115. }
  116. bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, const ByteBuffer&& extra_data)
  117. {
  118. switch (message.type) {
  119. case WSAPI_ClientMessage::Type::Greeting:
  120. set_client_pid(message.greeting.client_pid);
  121. break;
  122. case WSAPI_ClientMessage::Type::CreateMenubar:
  123. CEventLoop::current().post_event(*this, make<WSAPICreateMenubarRequest>(client_id()));
  124. break;
  125. case WSAPI_ClientMessage::Type::DestroyMenubar:
  126. CEventLoop::current().post_event(*this, make<WSAPIDestroyMenubarRequest>(client_id(), message.menu.menubar_id));
  127. break;
  128. case WSAPI_ClientMessage::Type::SetApplicationMenubar:
  129. CEventLoop::current().post_event(*this, make<WSAPISetApplicationMenubarRequest>(client_id(), message.menu.menubar_id));
  130. break;
  131. case WSAPI_ClientMessage::Type::AddMenuToMenubar:
  132. CEventLoop::current().post_event(*this, make<WSAPIAddMenuToMenubarRequest>(client_id(), message.menu.menubar_id, message.menu.menu_id));
  133. break;
  134. case WSAPI_ClientMessage::Type::CreateMenu:
  135. if (message.text_length > (int)sizeof(message.text)) {
  136. did_misbehave();
  137. return false;
  138. }
  139. CEventLoop::current().post_event(*this, make<WSAPICreateMenuRequest>(client_id(), String(message.text, message.text_length)));
  140. break;
  141. case WSAPI_ClientMessage::Type::PopupMenu:
  142. CEventLoop::current().post_event(*this, make<WSAPIPopupMenuRequest>(client_id(), message.menu.menu_id, message.menu.position));
  143. break;
  144. case WSAPI_ClientMessage::Type::DismissMenu:
  145. CEventLoop::current().post_event(*this, make<WSAPIDismissMenuRequest>(client_id(), message.menu.menu_id));
  146. break;
  147. case WSAPI_ClientMessage::Type::SetWindowIconBitmap:
  148. CEventLoop::current().post_event(*this, make<WSAPISetWindowIconBitmapRequest>(client_id(), message.window_id, message.window.icon_buffer_id, message.window.icon_size));
  149. break;
  150. case WSAPI_ClientMessage::Type::DestroyMenu:
  151. CEventLoop::current().post_event(*this, make<WSAPIDestroyMenuRequest>(client_id(), message.menu.menu_id));
  152. break;
  153. case WSAPI_ClientMessage::Type::AddMenuItem:
  154. if (message.text_length > (int)sizeof(message.text)) {
  155. did_misbehave();
  156. return false;
  157. }
  158. if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
  159. did_misbehave();
  160. return false;
  161. }
  162. CEventLoop::current().post_event(*this, make<WSAPIAddMenuItemRequest>(client_id(), message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked, message.menu.icon_buffer_id, message.menu.submenu_id));
  163. break;
  164. case WSAPI_ClientMessage::Type::UpdateMenuItem:
  165. if (message.text_length > (int)sizeof(message.text)) {
  166. did_misbehave();
  167. return false;
  168. }
  169. if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
  170. did_misbehave();
  171. return false;
  172. }
  173. CEventLoop::current().post_event(*this, make<WSAPIUpdateMenuItemRequest>(client_id(), message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
  174. break;
  175. case WSAPI_ClientMessage::Type::AddMenuSeparator:
  176. CEventLoop::current().post_event(*this, make<WSAPIAddMenuSeparatorRequest>(client_id(), message.menu.menu_id));
  177. break;
  178. case WSAPI_ClientMessage::Type::CreateWindow: {
  179. if (message.text_length > (int)sizeof(message.text)) {
  180. did_misbehave();
  181. return false;
  182. }
  183. auto ws_window_type = WSWindowType::Invalid;
  184. switch (message.window.type) {
  185. case WSAPI_WindowType::Normal:
  186. ws_window_type = WSWindowType::Normal;
  187. break;
  188. case WSAPI_WindowType::Menu:
  189. ws_window_type = WSWindowType::Menu;
  190. break;
  191. case WSAPI_WindowType::WindowSwitcher:
  192. ws_window_type = WSWindowType::WindowSwitcher;
  193. break;
  194. case WSAPI_WindowType::Taskbar:
  195. ws_window_type = WSWindowType::Taskbar;
  196. break;
  197. case WSAPI_WindowType::Tooltip:
  198. ws_window_type = WSWindowType::Tooltip;
  199. break;
  200. case WSAPI_WindowType::Menubar:
  201. ws_window_type = WSWindowType::Menubar;
  202. break;
  203. case WSAPI_WindowType::Invalid:
  204. default:
  205. dbgprintf("Unknown WSAPI_WindowType: %d\n", message.window.type);
  206. did_misbehave();
  207. return false;
  208. }
  209. CEventLoop::current().post_event(*this,
  210. make<WSAPICreateWindowRequest>(client_id(),
  211. message.window.rect,
  212. String(message.text, message.text_length),
  213. message.window.has_alpha_channel,
  214. message.window.modal,
  215. message.window.resizable,
  216. message.window.fullscreen,
  217. message.window.show_titlebar,
  218. message.window.opacity,
  219. message.window.base_size,
  220. message.window.size_increment,
  221. ws_window_type,
  222. Color::from_rgba(message.window.background_color)));
  223. break;
  224. }
  225. case WSAPI_ClientMessage::Type::DestroyWindow:
  226. CEventLoop::current().post_event(*this, make<WSAPIDestroyWindowRequest>(client_id(), message.window_id));
  227. break;
  228. case WSAPI_ClientMessage::Type::SetWindowTitle:
  229. if (message.text_length > (int)sizeof(message.text)) {
  230. did_misbehave();
  231. return false;
  232. }
  233. CEventLoop::current().post_event(*this, make<WSAPISetWindowTitleRequest>(client_id(), message.window_id, String(message.text, message.text_length)));
  234. break;
  235. case WSAPI_ClientMessage::Type::GetWindowTitle:
  236. CEventLoop::current().post_event(*this, make<WSAPIGetWindowTitleRequest>(client_id(), message.window_id));
  237. break;
  238. case WSAPI_ClientMessage::Type::SetWindowRect:
  239. CEventLoop::current().post_event(*this, make<WSAPISetWindowRectRequest>(client_id(), message.window_id, message.window.rect));
  240. break;
  241. case WSAPI_ClientMessage::Type::GetWindowRect:
  242. CEventLoop::current().post_event(*this, make<WSAPIGetWindowRectRequest>(client_id(), message.window_id));
  243. break;
  244. case WSAPI_ClientMessage::Type::SetClipboardContents:
  245. if (message.text_length > (int)sizeof(message.text)) {
  246. did_misbehave();
  247. return false;
  248. }
  249. CEventLoop::current().post_event(*this, make<WSAPISetClipboardContentsRequest>(client_id(), message.clipboard.shared_buffer_id, message.clipboard.contents_size, String(message.text, message.text_length)));
  250. break;
  251. case WSAPI_ClientMessage::Type::GetClipboardContents:
  252. CEventLoop::current().post_event(*this, make<WSAPIGetClipboardContentsRequest>(client_id()));
  253. break;
  254. case WSAPI_ClientMessage::Type::InvalidateRect: {
  255. auto rects = get_rects(message, extra_data);
  256. if (rects.is_empty()) {
  257. did_misbehave();
  258. return false;
  259. }
  260. CEventLoop::current().post_event(*this, make<WSAPIInvalidateRectRequest>(client_id(), message.window_id, rects));
  261. break;
  262. }
  263. case WSAPI_ClientMessage::Type::DidFinishPainting: {
  264. auto rects = get_rects(message, extra_data);
  265. if (rects.is_empty()) {
  266. did_misbehave();
  267. return false;
  268. }
  269. CEventLoop::current().post_event(*this, make<WSAPIDidFinishPaintingNotification>(client_id(), message.window_id, rects));
  270. break;
  271. }
  272. case WSAPI_ClientMessage::Type::GetWindowBackingStore:
  273. CEventLoop::current().post_event(*this, make<WSAPIGetWindowBackingStoreRequest>(client_id(), message.window_id));
  274. break;
  275. case WSAPI_ClientMessage::Type::SetWindowBackingStore:
  276. CEventLoop::current().post_event(*this, make<WSAPISetWindowBackingStoreRequest>(client_id(), message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
  277. break;
  278. case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
  279. CEventLoop::current().post_event(*this, make<WSAPISetGlobalCursorTrackingRequest>(client_id(), message.window_id, message.value));
  280. break;
  281. case WSAPI_ClientMessage::Type::SetWallpaper:
  282. if (message.text_length > (int)sizeof(message.text)) {
  283. did_misbehave();
  284. return false;
  285. }
  286. CEventLoop::current().post_event(*this, make<WSAPISetWallpaperRequest>(client_id(), String(message.text, message.text_length)));
  287. break;
  288. case WSAPI_ClientMessage::Type::GetWallpaper:
  289. CEventLoop::current().post_event(*this, make<WSAPIGetWallpaperRequest>(client_id()));
  290. break;
  291. case WSAPI_ClientMessage::Type::SetResolution:
  292. CEventLoop::current().post_event(*this, make<WSAPISetResolutionRequest>(client_id(), message.wm_conf.resolution.width, message.wm_conf.resolution.height));
  293. break;
  294. case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
  295. CEventLoop::current().post_event(*this, make<WSAPISetWindowOverrideCursorRequest>(client_id(), message.window_id, (WSStandardCursor)message.cursor.cursor));
  296. break;
  297. case WSAPI_ClientMessage::SetWindowHasAlphaChannel:
  298. CEventLoop::current().post_event(*this, make<WSAPISetWindowHasAlphaChannelRequest>(client_id(), message.window_id, message.value));
  299. break;
  300. case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
  301. CEventLoop::current().post_event(*this, make<WSWMAPISetActiveWindowRequest>(client_id(), message.wm.client_id, message.wm.window_id));
  302. break;
  303. case WSAPI_ClientMessage::Type::WM_SetWindowMinimized:
  304. CEventLoop::current().post_event(*this, make<WSWMAPISetWindowMinimizedRequest>(client_id(), message.wm.client_id, message.wm.window_id, message.wm.minimized));
  305. break;
  306. case WSAPI_ClientMessage::Type::WM_StartWindowResize:
  307. CEventLoop::current().post_event(*this, make<WSWMAPIStartWindowResizeRequest>(client_id(), message.wm.client_id, message.wm.window_id));
  308. break;
  309. case WSAPI_ClientMessage::Type::WM_PopupWindowMenu:
  310. CEventLoop::current().post_event(*this, make<WSWMAPIPopupWindowMenuRequest>(client_id(), message.wm.client_id, message.wm.window_id, message.wm.position));
  311. break;
  312. case WSAPI_ClientMessage::Type::MoveWindowToFront:
  313. CEventLoop::current().post_event(*this, make<WSAPIMoveWindowToFrontRequest>(client_id(), message.window_id));
  314. break;
  315. case WSAPI_ClientMessage::Type::SetFullscreen:
  316. CEventLoop::current().post_event(*this, make<WSAPISetFullscreenRequest>(client_id(), message.window_id, message.value));
  317. break;
  318. default:
  319. break;
  320. }
  321. return true;
  322. }
  323. void WSClientConnection::handle_request(const WSAPICreateMenubarRequest&)
  324. {
  325. int menubar_id = m_next_menubar_id++;
  326. auto menubar = make<WSMenuBar>(*this, menubar_id);
  327. m_menubars.set(menubar_id, move(menubar));
  328. WSAPI_ServerMessage response;
  329. response.type = WSAPI_ServerMessage::Type::DidCreateMenubar;
  330. response.menu.menubar_id = menubar_id;
  331. post_message(response);
  332. }
  333. void WSClientConnection::handle_request(const WSAPIDestroyMenubarRequest& request)
  334. {
  335. int menubar_id = request.menubar_id();
  336. auto it = m_menubars.find(menubar_id);
  337. if (it == m_menubars.end()) {
  338. post_error("WSAPIDestroyMenubarRequest: Bad menubar ID");
  339. return;
  340. }
  341. auto& menubar = *(*it).value;
  342. WSWindowManager::the().close_menubar(menubar);
  343. m_menubars.remove(it);
  344. WSAPI_ServerMessage response;
  345. response.type = WSAPI_ServerMessage::Type::DidDestroyMenubar;
  346. response.menu.menubar_id = menubar_id;
  347. post_message(response);
  348. }
  349. void WSClientConnection::handle_request(const WSAPICreateMenuRequest& request)
  350. {
  351. int menu_id = m_next_menu_id++;
  352. auto menu = WSMenu::construct(this, menu_id, request.text());
  353. m_menus.set(menu_id, move(menu));
  354. WSAPI_ServerMessage response;
  355. response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
  356. response.menu.menu_id = menu_id;
  357. post_message(response);
  358. }
  359. void WSClientConnection::handle_request(const WSAPIDestroyMenuRequest& request)
  360. {
  361. int menu_id = static_cast<const WSAPIDestroyMenuRequest&>(request).menu_id();
  362. auto it = m_menus.find(menu_id);
  363. if (it == m_menus.end()) {
  364. post_error("WSAPIDestroyMenuRequest: Bad menu ID");
  365. return;
  366. }
  367. auto& menu = *(*it).value;
  368. menu.close();
  369. m_menus.remove(it);
  370. remove_child(menu);
  371. WSAPI_ServerMessage response;
  372. response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
  373. response.menu.menu_id = menu_id;
  374. post_message(response);
  375. }
  376. void WSClientConnection::handle_request(const WSAPISetApplicationMenubarRequest& request)
  377. {
  378. int menubar_id = request.menubar_id();
  379. auto it = m_menubars.find(menubar_id);
  380. if (it == m_menubars.end()) {
  381. post_error("WSAPISetApplicationMenubarRequest: Bad menubar ID");
  382. return;
  383. }
  384. auto& menubar = *(*it).value;
  385. m_app_menubar = menubar.make_weak_ptr();
  386. WSWindowManager::the().notify_client_changed_app_menubar(*this);
  387. WSAPI_ServerMessage response;
  388. response.type = WSAPI_ServerMessage::Type::DidSetApplicationMenubar;
  389. response.menu.menubar_id = menubar_id;
  390. post_message(response);
  391. }
  392. void WSClientConnection::handle_request(const WSAPIAddMenuToMenubarRequest& request)
  393. {
  394. int menubar_id = request.menubar_id();
  395. int menu_id = request.menu_id();
  396. auto it = m_menubars.find(menubar_id);
  397. auto jt = m_menus.find(menu_id);
  398. if (it == m_menubars.end()) {
  399. post_error("WSAPIAddMenuToMenubarRequest: Bad menubar ID");
  400. return;
  401. }
  402. if (jt == m_menus.end()) {
  403. post_error("WSAPIAddMenuToMenubarRequest: Bad menu ID");
  404. return;
  405. }
  406. auto& menubar = *(*it).value;
  407. auto& menu = *(*jt).value;
  408. menubar.add_menu(menu);
  409. WSAPI_ServerMessage response;
  410. response.type = WSAPI_ServerMessage::Type::DidAddMenuToMenubar;
  411. response.menu.menubar_id = menubar_id;
  412. response.menu.menu_id = menu_id;
  413. post_message(response);
  414. }
  415. void WSClientConnection::handle_request(const WSAPIAddMenuItemRequest& request)
  416. {
  417. int menu_id = request.menu_id();
  418. unsigned identifier = request.identifier();
  419. auto it = m_menus.find(menu_id);
  420. if (it == m_menus.end()) {
  421. post_error("WSAPIAddMenuItemRequest: Bad menu ID");
  422. return;
  423. }
  424. auto& menu = *(*it).value;
  425. auto menu_item = make<WSMenuItem>(menu, identifier, request.text(), request.shortcut_text(), request.is_enabled(), request.is_checkable(), request.is_checked());
  426. if (request.icon_buffer_id() != -1) {
  427. auto icon_buffer = SharedBuffer::create_from_shared_buffer_id(request.icon_buffer_id());
  428. if (!icon_buffer) {
  429. did_misbehave();
  430. return;
  431. }
  432. // FIXME: Verify that the icon buffer can accomodate a 16x16 bitmap view.
  433. auto shared_icon = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, icon_buffer.release_nonnull(), { 16, 16 });
  434. menu_item->set_icon(shared_icon);
  435. }
  436. menu_item->set_submenu_id(request.submenu_id());
  437. menu.add_item(move(menu_item));
  438. WSAPI_ServerMessage response;
  439. response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
  440. response.menu.menu_id = menu_id;
  441. response.menu.identifier = identifier;
  442. post_message(response);
  443. }
  444. void WSClientConnection::handle_request(const WSAPIPopupMenuRequest& request)
  445. {
  446. int menu_id = request.menu_id();
  447. auto position = request.position();
  448. auto it = m_menus.find(menu_id);
  449. if (it == m_menus.end()) {
  450. post_error("WSAPIPopupMenuRequest: Bad menu ID");
  451. return;
  452. }
  453. auto& menu = *(*it).value;
  454. menu.popup(position);
  455. }
  456. void WSClientConnection::handle_request(const WSAPIDismissMenuRequest& request)
  457. {
  458. int menu_id = request.menu_id();
  459. auto it = m_menus.find(menu_id);
  460. if (it == m_menus.end()) {
  461. post_error("WSAPIDismissMenuRequest: Bad menu ID");
  462. return;
  463. }
  464. auto& menu = *(*it).value;
  465. menu.close();
  466. }
  467. void WSClientConnection::handle_request(const WSAPIUpdateMenuItemRequest& request)
  468. {
  469. int menu_id = request.menu_id();
  470. unsigned identifier = request.identifier();
  471. auto it = m_menus.find(menu_id);
  472. if (it == m_menus.end()) {
  473. post_error("WSAPIUpdateMenuItemRequest: Bad menu ID");
  474. return;
  475. }
  476. auto& menu = *(*it).value;
  477. auto* menu_item = menu.item_with_identifier(request.identifier());
  478. if (!menu_item) {
  479. post_error("WSAPIUpdateMenuItemRequest: Bad menu item identifier");
  480. return;
  481. }
  482. menu_item->set_text(request.text());
  483. menu_item->set_shortcut_text(request.shortcut_text());
  484. menu_item->set_enabled(request.is_enabled());
  485. menu_item->set_checkable(request.is_checkable());
  486. if (request.is_checkable())
  487. menu_item->set_checked(request.is_checked());
  488. WSAPI_ServerMessage response;
  489. response.type = WSAPI_ServerMessage::Type::DidUpdateMenuItem;
  490. response.menu.menu_id = menu_id;
  491. response.menu.identifier = identifier;
  492. post_message(response);
  493. }
  494. void WSClientConnection::handle_request(const WSAPIAddMenuSeparatorRequest& request)
  495. {
  496. int menu_id = request.menu_id();
  497. auto it = m_menus.find(menu_id);
  498. if (it == m_menus.end()) {
  499. post_error("WSAPIAddMenuSeparatorRequest: Bad menu ID");
  500. return;
  501. }
  502. auto& menu = *(*it).value;
  503. menu.add_item(make<WSMenuItem>(menu, WSMenuItem::Separator));
  504. WSAPI_ServerMessage response;
  505. response.type = WSAPI_ServerMessage::Type::DidAddMenuSeparator;
  506. response.menu.menu_id = menu_id;
  507. post_message(response);
  508. }
  509. void WSClientConnection::handle_request(const WSAPIMoveWindowToFrontRequest& request)
  510. {
  511. int window_id = request.window_id();
  512. auto it = m_windows.find(window_id);
  513. if (it == m_windows.end()) {
  514. post_error("WSAPIMoveWindowToFrontRequest: Bad window ID");
  515. return;
  516. }
  517. auto& window = *(*it).value;
  518. WSWindowManager::the().move_to_front_and_make_active(window);
  519. }
  520. void WSClientConnection::handle_request(const WSAPISetFullscreenRequest& request)
  521. {
  522. int window_id = request.window_id();
  523. auto it = m_windows.find(window_id);
  524. if (it == m_windows.end()) {
  525. post_error("WSAPISetFullscreenRequest: Bad window ID");
  526. return;
  527. }
  528. auto& window = *(*it).value;
  529. window.set_fullscreen(request.fullscreen());
  530. WSAPI_ServerMessage response;
  531. response.type = WSAPI_ServerMessage::Type::DidSetFullscreen;
  532. response.window_id = window_id;
  533. post_message(response);
  534. }
  535. void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& 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("WSAPISetWindowOpacityRequest: Bad window ID");
  541. return;
  542. }
  543. auto& window = *(*it).value;
  544. window.set_opacity(request.opacity());
  545. }
  546. void WSClientConnection::handle_request(const WSAPISetWallpaperRequest& request)
  547. {
  548. WSCompositor::the().set_wallpaper(request.wallpaper(), [&](bool success) {
  549. WSAPI_ServerMessage response;
  550. response.type = WSAPI_ServerMessage::Type::DidSetWallpaper;
  551. response.value = success;
  552. post_message(response);
  553. });
  554. }
  555. void WSClientConnection::handle_request(const WSAPIGetWallpaperRequest&)
  556. {
  557. auto path = WSCompositor::the().wallpaper_path();
  558. WSAPI_ServerMessage response;
  559. response.type = WSAPI_ServerMessage::Type::DidGetWallpaper;
  560. ASSERT(path.length() < (int)sizeof(response.text));
  561. memcpy(response.text, path.characters(), path.length() + 1);
  562. response.text_length = path.length();
  563. post_message(response);
  564. }
  565. void WSClientConnection::handle_request(const WSAPISetResolutionRequest& request)
  566. {
  567. WSWindowManager::the().set_resolution(request.resolution().width(), request.resolution().height());
  568. WSAPI_ServerMessage response;
  569. response.type = WSAPI_ServerMessage::Type::DidSetResolution;
  570. response.value = true;
  571. post_message(response);
  572. }
  573. void WSClientConnection::handle_request(const WSAPISetWindowTitleRequest& 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("WSAPISetWindowTitleRequest: Bad window ID");
  579. return;
  580. }
  581. auto& window = *(*it).value;
  582. window.set_title(request.title());
  583. }
  584. void WSClientConnection::handle_request(const WSAPIGetWindowTitleRequest& 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("WSAPIGetWindowTitleRequest: Bad window ID");
  590. return;
  591. }
  592. auto& window = *(*it).value;
  593. WSAPI_ServerMessage response;
  594. response.type = WSAPI_ServerMessage::Type::DidGetWindowTitle;
  595. response.window_id = window.window_id();
  596. ASSERT(window.title().length() < (ssize_t)sizeof(response.text));
  597. strcpy(response.text, window.title().characters());
  598. response.text_length = window.title().length();
  599. post_message(response);
  600. }
  601. void WSClientConnection::handle_request(const WSAPISetWindowIconBitmapRequest& request)
  602. {
  603. int window_id = request.window_id();
  604. auto it = m_windows.find(window_id);
  605. if (it == m_windows.end()) {
  606. post_error("WSAPISetWindowIconBitmapRequest: Bad window ID");
  607. return;
  608. }
  609. auto& window = *(*it).value;
  610. auto icon_buffer = SharedBuffer::create_from_shared_buffer_id(request.icon_buffer_id());
  611. if (!icon_buffer) {
  612. window.set_default_icon();
  613. } else {
  614. window.set_icon(GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *icon_buffer, request.icon_size()));
  615. }
  616. window.frame().invalidate_title_bar();
  617. WSWindowManager::the().tell_wm_listeners_window_icon_changed(window);
  618. }
  619. void WSClientConnection::handle_request(const WSAPISetWindowRectRequest& request)
  620. {
  621. int window_id = request.window_id();
  622. auto it = m_windows.find(window_id);
  623. if (it == m_windows.end()) {
  624. post_error("WSAPISetWindowRectRequest: Bad window ID");
  625. return;
  626. }
  627. auto& window = *(*it).value;
  628. if (window.is_fullscreen()) {
  629. dbgprintf("WSClientConnection: Ignoring SetWindowRect request for fullscreen window\n");
  630. return;
  631. }
  632. window.set_rect(request.rect());
  633. window.request_update(request.rect());
  634. }
  635. void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& request)
  636. {
  637. int window_id = request.window_id();
  638. auto it = m_windows.find(window_id);
  639. if (it == m_windows.end()) {
  640. post_error("WSAPIGetWindowRectRequest: Bad window ID");
  641. return;
  642. }
  643. auto& window = *(*it).value;
  644. WSAPI_ServerMessage response;
  645. response.type = WSAPI_ServerMessage::Type::DidGetWindowRect;
  646. response.window_id = window.window_id();
  647. response.window.rect = window.rect();
  648. post_message(response);
  649. }
  650. void WSClientConnection::handle_request(const WSAPISetClipboardContentsRequest& request)
  651. {
  652. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  653. if (!shared_buffer) {
  654. post_error("WSAPISetClipboardContentsRequest: Bad shared buffer ID");
  655. return;
  656. }
  657. WSClipboard::the().set_data(*shared_buffer, request.size(), request.data_type());
  658. WSAPI_ServerMessage response;
  659. response.type = WSAPI_ServerMessage::Type::DidSetClipboardContents;
  660. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  661. post_message(response);
  662. }
  663. void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
  664. {
  665. auto& clipboard = WSClipboard::the();
  666. WSAPI_ServerMessage response;
  667. response.type = WSAPI_ServerMessage::Type::DidGetClipboardContents;
  668. response.clipboard.shared_buffer_id = -1;
  669. response.clipboard.contents_size = 0;
  670. if (clipboard.size()) {
  671. // FIXME: Optimize case where an app is copy/pasting within itself.
  672. // We can just reuse the SharedBuffer then, since it will have the same peer PID.
  673. // It would be even nicer if a SharedBuffer could have an arbitrary number of clients..
  674. RefPtr<SharedBuffer> shared_buffer = SharedBuffer::create_with_size(clipboard.size());
  675. ASSERT(shared_buffer);
  676. memcpy(shared_buffer->data(), clipboard.data(), clipboard.size());
  677. shared_buffer->seal();
  678. shared_buffer->share_with(client_pid());
  679. response.clipboard.shared_buffer_id = shared_buffer->shared_buffer_id();
  680. response.clipboard.contents_size = clipboard.size();
  681. // FIXME: This is a workaround for the fact that SharedBuffers will go away if neither side is retaining them.
  682. // After we respond to GetClipboardContents, we have to wait for the client to ref the buffer on his side.
  683. m_last_sent_clipboard_content = move(shared_buffer);
  684. }
  685. ASSERT(clipboard.data_type().length() < (ssize_t)sizeof(response.text));
  686. if (!clipboard.data_type().is_null())
  687. strcpy(response.text, clipboard.data_type().characters());
  688. response.text_length = clipboard.data_type().length();
  689. post_message(response);
  690. }
  691. void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
  692. {
  693. int window_id = m_next_window_id++;
  694. auto window = WSWindow::construct(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
  695. window->set_background_color(request.background_color());
  696. window->set_has_alpha_channel(request.has_alpha_channel());
  697. window->set_title(request.title());
  698. if (!request.is_fullscreen())
  699. window->set_rect(request.rect());
  700. window->set_show_titlebar(request.show_titlebar());
  701. window->set_opacity(request.opacity());
  702. window->set_size_increment(request.size_increment());
  703. window->set_base_size(request.base_size());
  704. window->invalidate();
  705. m_windows.set(window_id, move(window));
  706. WSAPI_ServerMessage response;
  707. response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
  708. response.window_id = window_id;
  709. post_message(response);
  710. }
  711. void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request)
  712. {
  713. int window_id = request.window_id();
  714. auto it = m_windows.find(window_id);
  715. if (it == m_windows.end()) {
  716. post_error("WSAPIDestroyWindowRequest: Bad window ID");
  717. return;
  718. }
  719. auto& window = *(*it).value;
  720. WSWindowManager::the().invalidate(window);
  721. WSAPI_ServerMessage response;
  722. response.type = WSAPI_ServerMessage::Type::DidDestroyWindow;
  723. response.window_id = window.window_id();
  724. post_message(response);
  725. remove_child(window);
  726. ASSERT(it->value.ptr() == &window);
  727. m_windows.remove(window_id);
  728. }
  729. void WSClientConnection::post_paint_message(WSWindow& window)
  730. {
  731. auto rect_set = window.take_pending_paint_rects();
  732. if (window.is_minimized())
  733. return;
  734. WSAPI_ServerMessage message;
  735. message.type = WSAPI_ServerMessage::Type::Paint;
  736. message.window_id = window.window_id();
  737. auto& rects = rect_set.rects();
  738. message.rect_count = rects.size();
  739. for (int i = 0; i < min(WSAPI_ServerMessage::max_inline_rect_count, rects.size()); ++i)
  740. message.rects[i] = rects[i];
  741. message.paint.window_size = window.size();
  742. ByteBuffer extra_data;
  743. if (rects.size() > WSAPI_ServerMessage::max_inline_rect_count)
  744. extra_data = ByteBuffer::wrap(&rects[WSAPI_ServerMessage::max_inline_rect_count], (rects.size() - WSAPI_ServerMessage::max_inline_rect_count) * sizeof(WSAPI_Rect));
  745. post_message(message, extra_data);
  746. }
  747. void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
  748. {
  749. int window_id = request.window_id();
  750. auto it = m_windows.find(window_id);
  751. if (it == m_windows.end()) {
  752. post_error("WSAPIInvalidateRectRequest: Bad window ID");
  753. return;
  754. }
  755. auto& window = *(*it).value;
  756. for (int i = 0; i < request.rects().size(); ++i)
  757. window.request_update(request.rects()[i].intersected({ {}, window.size() }));
  758. }
  759. void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
  760. {
  761. int window_id = request.window_id();
  762. auto it = m_windows.find(window_id);
  763. if (it == m_windows.end()) {
  764. post_error("WSAPIDidFinishPaintingNotification: Bad window ID");
  765. return;
  766. }
  767. auto& window = *(*it).value;
  768. for (auto& rect : request.rects())
  769. WSWindowManager::the().invalidate(window, rect);
  770. WSWindowSwitcher::the().refresh_if_needed();
  771. }
  772. void WSClientConnection::handle_request(const WSAPIGetWindowBackingStoreRequest& request)
  773. {
  774. int window_id = request.window_id();
  775. auto it = m_windows.find(window_id);
  776. if (it == m_windows.end()) {
  777. post_error("WSAPIGetWindowBackingStoreRequest: Bad window ID");
  778. return;
  779. }
  780. auto& window = *(*it).value;
  781. auto* backing_store = window.backing_store();
  782. WSAPI_ServerMessage response;
  783. response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore;
  784. response.window_id = window_id;
  785. response.backing.bpp = sizeof(RGBA32);
  786. response.backing.pitch = backing_store->pitch();
  787. response.backing.size = backing_store->size();
  788. response.backing.has_alpha_channel = backing_store->has_alpha_channel();
  789. response.backing.shared_buffer_id = backing_store->shared_buffer_id();
  790. post_message(response);
  791. }
  792. void WSClientConnection::handle_request(const WSAPISetWindowBackingStoreRequest& request)
  793. {
  794. int window_id = request.window_id();
  795. auto it = m_windows.find(window_id);
  796. if (it == m_windows.end()) {
  797. post_error("WSAPISetWindowBackingStoreRequest: Bad window ID");
  798. return;
  799. }
  800. auto& window = *(*it).value;
  801. if (window.last_backing_store() && window.last_backing_store()->shared_buffer_id() == request.shared_buffer_id()) {
  802. window.swap_backing_stores();
  803. } else {
  804. auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(request.shared_buffer_id());
  805. if (!shared_buffer)
  806. return;
  807. auto backing_store = GraphicsBitmap::create_with_shared_buffer(
  808. request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
  809. *shared_buffer,
  810. request.size());
  811. window.set_backing_store(move(backing_store));
  812. }
  813. if (request.flush_immediately())
  814. window.invalidate();
  815. WSAPI_ServerMessage response;
  816. response.type = WSAPI_ServerMessage::Type::DidSetWindowBackingStore;
  817. response.window_id = window_id;
  818. response.backing.shared_buffer_id = request.shared_buffer_id();
  819. post_message(response);
  820. }
  821. void WSClientConnection::handle_request(const WSAPISetGlobalCursorTrackingRequest& request)
  822. {
  823. int window_id = request.window_id();
  824. auto it = m_windows.find(window_id);
  825. if (it == m_windows.end()) {
  826. post_error("WSAPISetGlobalCursorTrackingRequest: Bad window ID");
  827. return;
  828. }
  829. auto& window = *(*it).value;
  830. window.set_global_cursor_tracking_enabled(request.value());
  831. }
  832. void WSClientConnection::handle_request(const WSAPISetWindowOverrideCursorRequest& request)
  833. {
  834. int window_id = request.window_id();
  835. auto it = m_windows.find(window_id);
  836. if (it == m_windows.end()) {
  837. post_error("WSAPISetWindowOverrideCursorRequest: Bad window ID");
  838. return;
  839. }
  840. auto& window = *(*it).value;
  841. window.set_override_cursor(WSCursor::create(request.cursor()));
  842. }
  843. void WSClientConnection::handle_request(const WSAPISetWindowHasAlphaChannelRequest& request)
  844. {
  845. int window_id = request.window_id();
  846. auto it = m_windows.find(window_id);
  847. if (it == m_windows.end()) {
  848. post_error("WSAPISetWindowHasAlphaChannelRequest: Bad window ID");
  849. return;
  850. }
  851. auto& window = *(*it).value;
  852. window.set_has_alpha_channel(request.value());
  853. WSAPI_ServerMessage response;
  854. response.type = WSAPI_ServerMessage::Type::DidSetWindowHasAlphaChannel;
  855. response.window_id = window_id;
  856. response.value = request.value();
  857. post_message(response);
  858. }
  859. void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& request)
  860. {
  861. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  862. if (!client) {
  863. post_error("WSWMAPISetActiveWindowRequest: Bad client ID");
  864. return;
  865. }
  866. auto it = client->m_windows.find(request.target_window_id());
  867. if (it == client->m_windows.end()) {
  868. post_error("WSWMAPISetActiveWindowRequest: Bad window ID");
  869. return;
  870. }
  871. auto& window = *(*it).value;
  872. window.set_minimized(false);
  873. WSWindowManager::the().move_to_front_and_make_active(window);
  874. }
  875. void WSClientConnection::handle_request(const WSWMAPIPopupWindowMenuRequest& request)
  876. {
  877. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  878. if (!client) {
  879. post_error("WSWMAPIPopupWindowMenuRequest: Bad client ID");
  880. return;
  881. }
  882. auto it = client->m_windows.find(request.target_window_id());
  883. if (it == client->m_windows.end()) {
  884. post_error("WSWMAPIPopupWindowMenuRequest: Bad window ID");
  885. return;
  886. }
  887. auto& window = *(*it).value;
  888. window.popup_window_menu(request.position());
  889. }
  890. void WSClientConnection::handle_request(const WSWMAPIStartWindowResizeRequest& request)
  891. {
  892. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  893. if (!client) {
  894. post_error("WSWMAPIStartWindowResizeRequest: Bad client ID");
  895. return;
  896. }
  897. auto it = client->m_windows.find(request.target_window_id());
  898. if (it == client->m_windows.end()) {
  899. post_error("WSWMAPIStartWindowResizeRequest: Bad window ID");
  900. return;
  901. }
  902. auto& window = *(*it).value;
  903. // FIXME: We are cheating a bit here by using the current cursor location and hard-coding the left button.
  904. // Maybe the client should be allowed to specify what initiated this request?
  905. WSWindowManager::the().start_window_resize(window, WSScreen::the().cursor_location(), MouseButton::Left);
  906. }
  907. void WSClientConnection::handle_request(const WSWMAPISetWindowMinimizedRequest& request)
  908. {
  909. auto* client = WSClientConnection::from_client_id(request.target_client_id());
  910. if (!client) {
  911. post_error("WSWMAPISetWindowMinimizedRequest: Bad client ID");
  912. return;
  913. }
  914. auto it = client->m_windows.find(request.target_window_id());
  915. if (it == client->m_windows.end()) {
  916. post_error("WSWMAPISetWindowMinimizedRequest: Bad window ID");
  917. return;
  918. }
  919. auto& window = *(*it).value;
  920. window.set_minimized(request.is_minimized());
  921. }
  922. void WSClientConnection::on_request(const WSAPIClientRequest& request)
  923. {
  924. switch (request.type()) {
  925. case WSEvent::APICreateMenubarRequest:
  926. return handle_request(static_cast<const WSAPICreateMenubarRequest&>(request));
  927. case WSEvent::APIDestroyMenubarRequest:
  928. return handle_request(static_cast<const WSAPIDestroyMenubarRequest&>(request));
  929. case WSEvent::APICreateMenuRequest:
  930. return handle_request(static_cast<const WSAPICreateMenuRequest&>(request));
  931. case WSEvent::APIDestroyMenuRequest:
  932. return handle_request(static_cast<const WSAPIDestroyMenuRequest&>(request));
  933. case WSEvent::APISetApplicationMenubarRequest:
  934. return handle_request(static_cast<const WSAPISetApplicationMenubarRequest&>(request));
  935. case WSEvent::APIAddMenuToMenubarRequest:
  936. return handle_request(static_cast<const WSAPIAddMenuToMenubarRequest&>(request));
  937. case WSEvent::APIAddMenuItemRequest:
  938. return handle_request(static_cast<const WSAPIAddMenuItemRequest&>(request));
  939. case WSEvent::APIAddMenuSeparatorRequest:
  940. return handle_request(static_cast<const WSAPIAddMenuSeparatorRequest&>(request));
  941. case WSEvent::APIUpdateMenuItemRequest:
  942. return handle_request(static_cast<const WSAPIUpdateMenuItemRequest&>(request));
  943. case WSEvent::APISetWindowTitleRequest:
  944. return handle_request(static_cast<const WSAPISetWindowTitleRequest&>(request));
  945. case WSEvent::APIGetWindowTitleRequest:
  946. return handle_request(static_cast<const WSAPIGetWindowTitleRequest&>(request));
  947. case WSEvent::APISetWindowRectRequest:
  948. return handle_request(static_cast<const WSAPISetWindowRectRequest&>(request));
  949. case WSEvent::APIGetWindowRectRequest:
  950. return handle_request(static_cast<const WSAPIGetWindowRectRequest&>(request));
  951. case WSEvent::APISetWindowIconBitmapRequest:
  952. return handle_request(static_cast<const WSAPISetWindowIconBitmapRequest&>(request));
  953. case WSEvent::APISetClipboardContentsRequest:
  954. return handle_request(static_cast<const WSAPISetClipboardContentsRequest&>(request));
  955. case WSEvent::APIGetClipboardContentsRequest:
  956. return handle_request(static_cast<const WSAPIGetClipboardContentsRequest&>(request));
  957. case WSEvent::APICreateWindowRequest:
  958. return handle_request(static_cast<const WSAPICreateWindowRequest&>(request));
  959. case WSEvent::APIDestroyWindowRequest:
  960. return handle_request(static_cast<const WSAPIDestroyWindowRequest&>(request));
  961. case WSEvent::APIInvalidateRectRequest:
  962. return handle_request(static_cast<const WSAPIInvalidateRectRequest&>(request));
  963. case WSEvent::APIDidFinishPaintingNotification:
  964. return handle_request(static_cast<const WSAPIDidFinishPaintingNotification&>(request));
  965. case WSEvent::APIGetWindowBackingStoreRequest:
  966. return handle_request(static_cast<const WSAPIGetWindowBackingStoreRequest&>(request));
  967. case WSEvent::APISetGlobalCursorTrackingRequest:
  968. return handle_request(static_cast<const WSAPISetGlobalCursorTrackingRequest&>(request));
  969. case WSEvent::APISetWindowOpacityRequest:
  970. return handle_request(static_cast<const WSAPISetWindowOpacityRequest&>(request));
  971. case WSEvent::APISetWindowBackingStoreRequest:
  972. return handle_request(static_cast<const WSAPISetWindowBackingStoreRequest&>(request));
  973. case WSEvent::APISetWallpaperRequest:
  974. return handle_request(static_cast<const WSAPISetWallpaperRequest&>(request));
  975. case WSEvent::APIGetWallpaperRequest:
  976. return handle_request(static_cast<const WSAPIGetWallpaperRequest&>(request));
  977. case WSEvent::APISetResolutionRequest:
  978. return handle_request(static_cast<const WSAPISetResolutionRequest&>(request));
  979. case WSEvent::APISetWindowOverrideCursorRequest:
  980. return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
  981. case WSEvent::WMAPISetActiveWindowRequest:
  982. return handle_request(static_cast<const WSWMAPISetActiveWindowRequest&>(request));
  983. case WSEvent::WMAPISetWindowMinimizedRequest:
  984. return handle_request(static_cast<const WSWMAPISetWindowMinimizedRequest&>(request));
  985. case WSEvent::WMAPIStartWindowResizeRequest:
  986. return handle_request(static_cast<const WSWMAPIStartWindowResizeRequest&>(request));
  987. case WSEvent::WMAPIPopupWindowMenuRequest:
  988. return handle_request(static_cast<const WSWMAPIPopupWindowMenuRequest&>(request));
  989. case WSEvent::APIPopupMenuRequest:
  990. return handle_request(static_cast<const WSAPIPopupMenuRequest&>(request));
  991. case WSEvent::APIDismissMenuRequest:
  992. return handle_request(static_cast<const WSAPIDismissMenuRequest&>(request));
  993. case WSEvent::APISetWindowHasAlphaChannelRequest:
  994. return handle_request(static_cast<const WSAPISetWindowHasAlphaChannelRequest&>(request));
  995. case WSEvent::APIMoveWindowToFrontRequest:
  996. return handle_request(static_cast<const WSAPIMoveWindowToFrontRequest&>(request));
  997. case WSEvent::APISetFullscreenRequest:
  998. return handle_request(static_cast<const WSAPISetFullscreenRequest&>(request));
  999. default:
  1000. break;
  1001. }
  1002. }
  1003. bool WSClientConnection::is_showing_modal_window() const
  1004. {
  1005. for (auto& it : m_windows) {
  1006. auto& window = *it.value;
  1007. if (window.is_visible() && window.is_modal())
  1008. return true;
  1009. }
  1010. return false;
  1011. }