zaura_shell.cc 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/exo/wayland/zaura_shell.h"
  5. #include <aura-shell-server-protocol.h>
  6. #include <wayland-server-core.h>
  7. #include <wayland-server-protocol-core.h>
  8. #include <xdg-shell-server-protocol.h>
  9. #include <algorithm>
  10. #include <limits>
  11. #include <memory>
  12. #include <utility>
  13. #include <vector>
  14. #include "ash/public/cpp/window_properties.h"
  15. #include "ash/wm/window_state.h"
  16. #include "base/logging.h"
  17. #include "base/strings/string_number_conversions.h"
  18. #include "build/chromeos_buildflags.h"
  19. #include "chromeos/ui/base/window_properties.h"
  20. #include "chromeos/ui/base/window_state_type.h"
  21. #include "components/exo/display.h"
  22. #include "components/exo/seat.h"
  23. #include "components/exo/seat_observer.h"
  24. #include "components/exo/shell_surface.h"
  25. #include "components/exo/shell_surface_base.h"
  26. #include "components/exo/wayland/serial_tracker.h"
  27. #include "components/exo/wayland/server_util.h"
  28. #include "components/exo/wayland/wayland_display_observer.h"
  29. #include "components/exo/wayland/wayland_display_util.h"
  30. #include "components/exo/wayland/wl_output.h"
  31. #include "components/exo/wm_helper.h"
  32. #include "ui/aura/env.h"
  33. #include "ui/aura/window_occlusion_tracker.h"
  34. #include "ui/compositor/layer.h"
  35. #include "ui/display/display_observer.h"
  36. #include "ui/display/manager/display_manager.h"
  37. #include "ui/display/manager/display_manager_util.h"
  38. #include "ui/display/screen.h"
  39. #include "ui/views/widget/widget.h"
  40. #include "ui/wm/core/coordinate_conversion.h"
  41. #include "ui/wm/public/activation_client.h"
  42. #if BUILDFLAG(IS_CHROMEOS_ASH)
  43. #include "ash/display/display_util.h"
  44. #include "ash/display/screen_orientation_controller.h"
  45. #include "ash/public/cpp/tablet_mode_observer.h"
  46. #include "ash/session/session_controller_impl.h"
  47. #include "ash/shell.h"
  48. #include "ash/wm/desks/desk.h"
  49. #include "ash/wm/desks/desks_controller.h"
  50. #include "base/strings/utf_string_conversions.h"
  51. #include "components/exo/wayland/xdg_shell.h"
  52. #include "components/exo/wm_helper_chromeos.h"
  53. #include "ui/aura/client/aura_constants.h"
  54. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  55. namespace exo {
  56. namespace wayland {
  57. namespace {
  58. constexpr int kAuraShellSeatObserverPriority = 1;
  59. static_assert(Seat::IsValidObserverPriority(kAuraShellSeatObserverPriority),
  60. "kAuraShellSeatObserverPriority is not in the valid range.");
  61. // A property key containing a boolean set to true if na aura surface object is
  62. // associated with surface object.
  63. DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasAuraSurfaceKey, false)
  64. bool TransformRelativeToScreenIsAxisAligned(aura::Window* window) {
  65. gfx::Transform transform_relative_to_screen;
  66. DCHECK(window->layer()->GetTargetTransformRelativeTo(
  67. window->GetRootWindow()->layer(), &transform_relative_to_screen));
  68. transform_relative_to_screen.ConcatTransform(
  69. window->GetRootWindow()->layer()->GetTargetTransform());
  70. return transform_relative_to_screen.Preserves2dAxisAlignment();
  71. }
  72. // This does not handle non-axis aligned rotations, but we don't have any
  73. // slightly (e.g. 45 degree) windows so it is okay.
  74. gfx::Rect GetTransformedBoundsInScreen(aura::Window* window) {
  75. DCHECK(TransformRelativeToScreenIsAxisAligned(window));
  76. // This assumes that opposite points on the window bounds rectangle will
  77. // be mapped to opposite points on the output rectangle.
  78. gfx::Point a = window->bounds().origin();
  79. gfx::Point b = window->bounds().bottom_right();
  80. ::wm::ConvertPointToScreen(window->parent(), &a);
  81. ::wm::ConvertPointToScreen(window->parent(), &b);
  82. return gfx::Rect(std::min(a.x(), b.x()), std::min(a.y(), b.y()),
  83. std::abs(a.x() - b.x()), std::abs(a.y() - b.y()));
  84. }
  85. SurfaceFrameType AuraSurfaceFrameType(uint32_t frame_type) {
  86. switch (frame_type) {
  87. case ZAURA_SURFACE_FRAME_TYPE_NONE:
  88. return SurfaceFrameType::NONE;
  89. case ZAURA_SURFACE_FRAME_TYPE_NORMAL:
  90. return SurfaceFrameType::NORMAL;
  91. case ZAURA_SURFACE_FRAME_TYPE_SHADOW:
  92. return SurfaceFrameType::SHADOW;
  93. default:
  94. VLOG(2) << "Unkonwn aura-shell frame type: " << frame_type;
  95. return SurfaceFrameType::NONE;
  96. }
  97. }
  98. zaura_surface_occlusion_state WaylandOcclusionState(
  99. const aura::Window::OcclusionState occlusion_state) {
  100. switch (occlusion_state) {
  101. case aura::Window::OcclusionState::UNKNOWN:
  102. return ZAURA_SURFACE_OCCLUSION_STATE_UNKNOWN;
  103. case aura::Window::OcclusionState::VISIBLE:
  104. return ZAURA_SURFACE_OCCLUSION_STATE_VISIBLE;
  105. case aura::Window::OcclusionState::OCCLUDED:
  106. return ZAURA_SURFACE_OCCLUSION_STATE_OCCLUDED;
  107. case aura::Window::OcclusionState::HIDDEN:
  108. return ZAURA_SURFACE_OCCLUSION_STATE_HIDDEN;
  109. }
  110. return ZAURA_SURFACE_OCCLUSION_STATE_UNKNOWN;
  111. }
  112. void aura_surface_set_frame(wl_client* client,
  113. wl_resource* resource,
  114. uint32_t type) {
  115. GetUserDataAs<AuraSurface>(resource)->SetFrame(AuraSurfaceFrameType(type));
  116. }
  117. void aura_surface_set_parent(wl_client* client,
  118. wl_resource* resource,
  119. wl_resource* parent_resource,
  120. int32_t x,
  121. int32_t y) {
  122. GetUserDataAs<AuraSurface>(resource)->SetParent(
  123. parent_resource ? GetUserDataAs<AuraSurface>(parent_resource) : nullptr,
  124. gfx::Point(x, y));
  125. }
  126. void aura_surface_set_frame_colors(wl_client* client,
  127. wl_resource* resource,
  128. uint32_t active_color,
  129. uint32_t inactive_color) {
  130. GetUserDataAs<AuraSurface>(resource)->SetFrameColors(active_color,
  131. inactive_color);
  132. }
  133. void aura_surface_set_startup_id(wl_client* client,
  134. wl_resource* resource,
  135. const char* startup_id) {
  136. GetUserDataAs<AuraSurface>(resource)->SetStartupId(startup_id);
  137. }
  138. void aura_surface_set_application_id(wl_client* client,
  139. wl_resource* resource,
  140. const char* application_id) {
  141. GetUserDataAs<AuraSurface>(resource)->SetApplicationId(application_id);
  142. }
  143. void aura_surface_set_client_surface_id_DEPRECATED(wl_client* client,
  144. wl_resource* resource,
  145. int client_surface_id) {
  146. // DEPRECATED. Use aura_surface_set_client_surface_str_id
  147. std::string client_surface_str_id = base::NumberToString(client_surface_id);
  148. GetUserDataAs<AuraSurface>(resource)->SetClientSurfaceId(
  149. client_surface_str_id.c_str());
  150. }
  151. void aura_surface_set_occlusion_tracking(wl_client* client,
  152. wl_resource* resource) {
  153. GetUserDataAs<AuraSurface>(resource)->SetOcclusionTracking(true);
  154. }
  155. void aura_surface_unset_occlusion_tracking(wl_client* client,
  156. wl_resource* resource) {
  157. GetUserDataAs<AuraSurface>(resource)->SetOcclusionTracking(false);
  158. }
  159. void aura_surface_activate(wl_client* client, wl_resource* resource) {
  160. GetUserDataAs<AuraSurface>(resource)->Activate();
  161. }
  162. void aura_surface_draw_attention(wl_client* client, wl_resource* resource) {
  163. GetUserDataAs<AuraSurface>(resource)->DrawAttention();
  164. }
  165. void aura_surface_set_fullscreen_mode(wl_client* client,
  166. wl_resource* resource,
  167. uint32_t mode) {
  168. GetUserDataAs<AuraSurface>(resource)->SetFullscreenMode(mode);
  169. }
  170. void aura_surface_set_client_surface_str_id(wl_client* client,
  171. wl_resource* resource,
  172. const char* client_surface_id) {
  173. GetUserDataAs<AuraSurface>(resource)->SetClientSurfaceId(client_surface_id);
  174. }
  175. void aura_surface_set_server_start_resize(wl_client* client,
  176. wl_resource* resource) {
  177. GetUserDataAs<AuraSurface>(resource)->SetServerStartResize();
  178. }
  179. void aura_surface_intent_to_snap(wl_client* client,
  180. wl_resource* resource,
  181. uint32_t snap_direction) {
  182. GetUserDataAs<AuraSurface>(resource)->IntentToSnap(snap_direction);
  183. }
  184. void aura_surface_set_snap_left(wl_client* client, wl_resource* resource) {
  185. GetUserDataAs<AuraSurface>(resource)->SetSnapPrimary();
  186. }
  187. void aura_surface_set_snap_right(wl_client* client, wl_resource* resource) {
  188. GetUserDataAs<AuraSurface>(resource)->SetSnapSecondary();
  189. }
  190. void aura_surface_unset_snap(wl_client* client, wl_resource* resource) {
  191. GetUserDataAs<AuraSurface>(resource)->UnsetSnap();
  192. }
  193. void aura_surface_set_window_session_id(wl_client* client,
  194. wl_resource* resource,
  195. int32_t id) {
  196. GetUserDataAs<AuraSurface>(resource)->SetWindowSessionId(id);
  197. }
  198. void aura_surface_set_can_go_back(wl_client* client, wl_resource* resource) {
  199. GetUserDataAs<AuraSurface>(resource)->SetCanGoBack();
  200. }
  201. void aura_surface_unset_can_go_back(wl_client* client, wl_resource* resource) {
  202. GetUserDataAs<AuraSurface>(resource)->UnsetCanGoBack();
  203. }
  204. void aura_surface_set_pip(wl_client* client, wl_resource* resource) {
  205. GetUserDataAs<AuraSurface>(resource)->SetPip();
  206. }
  207. void aura_surface_unset_pip(wl_client* client, wl_resource* resource) {
  208. GetUserDataAs<AuraSurface>(resource)->UnsetPip();
  209. }
  210. void aura_surface_set_aspect_ratio(wl_client* client,
  211. wl_resource* resource,
  212. int32_t width,
  213. int32_t height) {
  214. GetUserDataAs<AuraSurface>(resource)->SetAspectRatio(
  215. gfx::SizeF(width, height));
  216. }
  217. void aura_surface_move_to_desk(wl_client* client,
  218. wl_resource* resource,
  219. int index) {
  220. GetUserDataAs<AuraSurface>(resource)->MoveToDesk(index);
  221. }
  222. void aura_surface_set_initial_workspace(wl_client* client,
  223. wl_resource* resource,
  224. const char* initial_workspace) {
  225. GetUserDataAs<AuraSurface>(resource)->SetInitialWorkspace(initial_workspace);
  226. }
  227. void aura_surface_set_pin(wl_client* client,
  228. wl_resource* resource,
  229. int32_t trusted) {
  230. GetUserDataAs<AuraSurface>(resource)->Pin(trusted);
  231. }
  232. void aura_surface_unset_pin(wl_client* client, wl_resource* resource) {
  233. GetUserDataAs<AuraSurface>(resource)->Unpin();
  234. }
  235. void aura_surface_release(wl_client* client, wl_resource* resource) {
  236. wl_resource_destroy(resource);
  237. }
  238. const struct zaura_surface_interface aura_surface_implementation = {
  239. aura_surface_set_frame,
  240. aura_surface_set_parent,
  241. aura_surface_set_frame_colors,
  242. aura_surface_set_startup_id,
  243. aura_surface_set_application_id,
  244. aura_surface_set_client_surface_id_DEPRECATED,
  245. aura_surface_set_occlusion_tracking,
  246. aura_surface_unset_occlusion_tracking,
  247. aura_surface_activate,
  248. aura_surface_draw_attention,
  249. aura_surface_set_fullscreen_mode,
  250. aura_surface_set_client_surface_str_id,
  251. aura_surface_set_server_start_resize,
  252. aura_surface_intent_to_snap,
  253. aura_surface_set_snap_left,
  254. aura_surface_set_snap_right,
  255. aura_surface_unset_snap,
  256. aura_surface_set_window_session_id,
  257. aura_surface_set_can_go_back,
  258. aura_surface_unset_can_go_back,
  259. aura_surface_set_pip,
  260. aura_surface_unset_pip,
  261. aura_surface_set_aspect_ratio,
  262. aura_surface_move_to_desk,
  263. aura_surface_set_initial_workspace,
  264. aura_surface_set_pin,
  265. aura_surface_unset_pin,
  266. aura_surface_release,
  267. };
  268. } // namespace
  269. ////////////////////////////////////////////////////////////////////////////////
  270. // aura_surface_interface:
  271. AuraSurface::AuraSurface(Surface* surface, wl_resource* resource)
  272. : surface_(surface), resource_(resource) {
  273. surface_->AddSurfaceObserver(this);
  274. surface_->SetProperty(kSurfaceHasAuraSurfaceKey, true);
  275. WMHelper::GetInstance()->AddActivationObserver(this);
  276. }
  277. AuraSurface::~AuraSurface() {
  278. WMHelper::GetInstance()->RemoveActivationObserver(this);
  279. if (surface_) {
  280. surface_->RemoveSurfaceObserver(this);
  281. surface_->SetProperty(kSurfaceHasAuraSurfaceKey, false);
  282. }
  283. }
  284. void AuraSurface::SetFrame(SurfaceFrameType type) {
  285. if (surface_)
  286. surface_->SetFrame(type);
  287. }
  288. void AuraSurface::SetServerStartResize() {
  289. if (surface_)
  290. surface_->SetServerStartResize();
  291. }
  292. void AuraSurface::SetFrameColors(SkColor active_frame_color,
  293. SkColor inactive_frame_color) {
  294. if (surface_)
  295. surface_->SetFrameColors(active_frame_color, inactive_frame_color);
  296. }
  297. void AuraSurface::SetParent(AuraSurface* parent, const gfx::Point& position) {
  298. if (surface_)
  299. surface_->SetParent(parent ? parent->surface_ : nullptr, position);
  300. }
  301. void AuraSurface::SetStartupId(const char* startup_id) {
  302. if (surface_)
  303. surface_->SetStartupId(startup_id);
  304. }
  305. void AuraSurface::SetApplicationId(const char* application_id) {
  306. if (surface_)
  307. surface_->SetApplicationId(application_id);
  308. }
  309. void AuraSurface::SetClientSurfaceId(const char* client_surface_id) {
  310. if (surface_)
  311. surface_->SetClientSurfaceId(client_surface_id);
  312. }
  313. void AuraSurface::SetOcclusionTracking(bool tracking) {
  314. if (surface_)
  315. surface_->SetOcclusionTracking(tracking);
  316. }
  317. void AuraSurface::Activate() {
  318. if (surface_)
  319. surface_->RequestActivation();
  320. }
  321. void AuraSurface::DrawAttention() {
  322. if (!surface_)
  323. return;
  324. // TODO(hollingum): implement me.
  325. LOG(WARNING) << "Surface requested attention, but that is not implemented";
  326. }
  327. void AuraSurface::SetFullscreenMode(uint32_t mode) {
  328. if (!surface_)
  329. return;
  330. switch (mode) {
  331. case ZAURA_SURFACE_FULLSCREEN_MODE_PLAIN:
  332. surface_->SetUseImmersiveForFullscreen(false);
  333. break;
  334. case ZAURA_SURFACE_FULLSCREEN_MODE_IMMERSIVE:
  335. surface_->SetUseImmersiveForFullscreen(true);
  336. break;
  337. default:
  338. VLOG(2) << "aura_surface_set_fullscreen_mode(): unknown fullscreen_mode: "
  339. << mode;
  340. break;
  341. }
  342. }
  343. void AuraSurface::IntentToSnap(uint32_t snap_direction) {
  344. switch (snap_direction) {
  345. case ZAURA_SURFACE_SNAP_DIRECTION_NONE:
  346. surface_->HideSnapPreview();
  347. break;
  348. case ZAURA_SURFACE_SNAP_DIRECTION_LEFT:
  349. surface_->ShowSnapPreviewToPrimary();
  350. break;
  351. case ZAURA_SURFACE_SNAP_DIRECTION_RIGHT:
  352. surface_->ShowSnapPreviewToSecondary();
  353. break;
  354. }
  355. }
  356. void AuraSurface::SetSnapPrimary() {
  357. surface_->SetSnappedToPrimary();
  358. }
  359. void AuraSurface::SetSnapSecondary() {
  360. surface_->SetSnappedToSecondary();
  361. }
  362. void AuraSurface::UnsetSnap() {
  363. surface_->UnsetSnap();
  364. }
  365. void AuraSurface::SetWindowSessionId(int32_t window_session_id) {
  366. surface_->SetWindowSessionId(window_session_id);
  367. }
  368. void AuraSurface::SetCanGoBack() {
  369. surface_->SetCanGoBack();
  370. }
  371. void AuraSurface::UnsetCanGoBack() {
  372. surface_->UnsetCanGoBack();
  373. }
  374. void AuraSurface::SetPip() {
  375. surface_->SetPip();
  376. }
  377. void AuraSurface::UnsetPip() {
  378. surface_->UnsetPip();
  379. }
  380. void AuraSurface::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
  381. surface_->SetAspectRatio(aspect_ratio);
  382. }
  383. // Overridden from SurfaceObserver:
  384. void AuraSurface::OnSurfaceDestroying(Surface* surface) {
  385. surface->RemoveSurfaceObserver(this);
  386. surface_ = nullptr;
  387. }
  388. void AuraSurface::OnWindowOcclusionChanged(Surface* surface) {
  389. if (!surface_ || !surface_->IsTrackingOcclusion())
  390. return;
  391. auto* window = surface_->window();
  392. ComputeAndSendOcclusion(window->GetOcclusionState(),
  393. window->occluded_region_in_root());
  394. }
  395. void AuraSurface::OnFrameLockingChanged(Surface* surface, bool lock) {
  396. if (wl_resource_get_version(resource_) <
  397. ZAURA_SURFACE_LOCK_FRAME_NORMAL_SINCE_VERSION)
  398. return;
  399. if (lock)
  400. zaura_surface_send_lock_frame_normal(resource_);
  401. else
  402. zaura_surface_send_unlock_frame_normal(resource_);
  403. }
  404. void AuraSurface::OnWindowActivating(ActivationReason reason,
  405. aura::Window* gaining_active,
  406. aura::Window* losing_active) {
  407. if (!surface_ || !losing_active)
  408. return;
  409. auto* window = surface_->window();
  410. // Check if this surface is a child of a window that is losing focus.
  411. auto* widget = views::Widget::GetTopLevelWidgetForNativeView(window);
  412. if (!widget || losing_active != widget->GetNativeWindow() ||
  413. !surface_->IsTrackingOcclusion())
  414. return;
  415. // Result may be changed by animated windows, so compute it explicitly.
  416. // We need to send occlusion updates before activation changes because
  417. // we can only trigger onUserLeaveHint (which triggers Android PIP) upon
  418. // losing activation. Windows that have animations applied to them are
  419. // normally ignored by the occlusion tracker, but in this case we want
  420. // to send the occlusion state after animations finish before activation
  421. // changes. This lets us support showing a new window triggering PIP,
  422. // which normally would not work due to the window show animation delaying
  423. // any occlusion update.
  424. // This happens before any window stacking changes occur, which means that
  425. // calling the occlusion tracker here for activation changes which change
  426. // the window stacking order may not produce correct results. But,
  427. // showing a new window will have it stacked on top already, so this will not
  428. // be a problem.
  429. // TODO(edcourtney): Currently, this does not work for activating via the
  430. // overview, because starting the overview activates some overview specific
  431. // window. To support overview, we would need to have it keep the original
  432. // window activated and also do this inside OnWindowStackingChanged.
  433. // See crbug.com/948492.
  434. auto* occlusion_tracker =
  435. aura::Env::GetInstance()->GetWindowOcclusionTracker();
  436. if (occlusion_tracker->HasIgnoredAnimatingWindows()) {
  437. const auto& occlusion_data =
  438. occlusion_tracker->ComputeTargetOcclusionForWindow(window);
  439. ComputeAndSendOcclusion(occlusion_data.occlusion_state,
  440. occlusion_data.occluded_region);
  441. }
  442. }
  443. void AuraSurface::SendOcclusionFraction(float occlusion_fraction) {
  444. if (wl_resource_get_version(resource_) < 8)
  445. return;
  446. // TODO(edcourtney): For now, we are treating every occlusion change as
  447. // from a user action.
  448. zaura_surface_send_occlusion_changed(
  449. resource_, wl_fixed_from_double(occlusion_fraction),
  450. ZAURA_SURFACE_OCCLUSION_CHANGE_REASON_USER_ACTION);
  451. wl_client_flush(wl_resource_get_client(resource_));
  452. }
  453. void AuraSurface::SendOcclusionState(
  454. const aura::Window::OcclusionState occlusion_state) {
  455. if (wl_resource_get_version(resource_) < 21)
  456. return;
  457. zaura_surface_send_occlusion_state_changed(
  458. resource_, WaylandOcclusionState(occlusion_state));
  459. wl_client_flush(wl_resource_get_client(resource_));
  460. }
  461. void AuraSurface::ComputeAndSendOcclusion(
  462. const aura::Window::OcclusionState occlusion_state,
  463. const SkRegion& occluded_region) {
  464. SendOcclusionState(occlusion_state);
  465. #if BUILDFLAG(IS_CHROMEOS_ASH)
  466. // Should re-write in locked case - we don't want to trigger PIP upon
  467. // locking the screen.
  468. if (ash::Shell::Get()->session_controller()->IsScreenLocked()) {
  469. SendOcclusionFraction(0.0f);
  470. return;
  471. }
  472. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  473. // Send the occlusion fraction.
  474. auto* window = surface_->window();
  475. float fraction_occluded = 0.0f;
  476. switch (occlusion_state) {
  477. case aura::Window::OcclusionState::VISIBLE: {
  478. const gfx::Rect display_bounds_in_screen =
  479. display::Screen::GetScreen()
  480. ->GetDisplayNearestWindow(window)
  481. .bounds();
  482. const gfx::Rect bounds_in_screen = GetTransformedBoundsInScreen(window);
  483. const int tracked_area =
  484. bounds_in_screen.width() * bounds_in_screen.height();
  485. SkRegion tracked_and_occluded_region = occluded_region;
  486. tracked_and_occluded_region.op(gfx::RectToSkIRect(bounds_in_screen),
  487. SkRegion::Op::kIntersect_Op);
  488. // Clip the area outside of the display.
  489. gfx::Rect area_inside_display = bounds_in_screen;
  490. area_inside_display.Intersect(display_bounds_in_screen);
  491. int occluded_area = tracked_area - area_inside_display.width() *
  492. area_inside_display.height();
  493. for (SkRegion::Iterator i(tracked_and_occluded_region); !i.done();
  494. i.next()) {
  495. occluded_area += i.rect().width() * i.rect().height();
  496. }
  497. if (tracked_area) {
  498. fraction_occluded = static_cast<float>(occluded_area) /
  499. static_cast<float>(tracked_area);
  500. }
  501. break;
  502. }
  503. case aura::Window::OcclusionState::OCCLUDED:
  504. case aura::Window::OcclusionState::HIDDEN:
  505. // Consider the OCCLUDED and HIDDEN cases as 100% occlusion.
  506. fraction_occluded = 1.0f;
  507. break;
  508. case aura::Window::OcclusionState::UNKNOWN:
  509. return; // Window is not tracked.
  510. }
  511. SendOcclusionFraction(fraction_occluded);
  512. }
  513. void AuraSurface::OnDeskChanged(Surface* surface, int state) {
  514. if (wl_resource_get_version(resource_) <
  515. ZAURA_SURFACE_DESK_CHANGED_SINCE_VERSION) {
  516. return;
  517. }
  518. zaura_surface_send_desk_changed(resource_, state);
  519. }
  520. void AuraSurface::ThrottleFrameRate(bool on) {
  521. if (wl_resource_get_version(resource_) <
  522. ZAURA_SURFACE_START_THROTTLE_SINCE_VERSION) {
  523. return;
  524. }
  525. if (on)
  526. zaura_surface_send_start_throttle(resource_);
  527. else
  528. zaura_surface_send_end_throttle(resource_);
  529. wl_client_flush(wl_resource_get_client(resource_));
  530. }
  531. void AuraSurface::MoveToDesk(int desk_index) {
  532. constexpr int kToggleVisibleOnAllWorkspacesValue = -1;
  533. if (desk_index == kToggleVisibleOnAllWorkspacesValue) {
  534. surface_->SetVisibleOnAllWorkspaces();
  535. } else {
  536. surface_->MoveToDesk(desk_index);
  537. }
  538. }
  539. void AuraSurface::SetInitialWorkspace(const char* initial_workspace) {
  540. surface_->SetInitialWorkspace(initial_workspace);
  541. }
  542. void AuraSurface::Pin(bool trusted) {
  543. surface_->Pin(trusted);
  544. }
  545. void AuraSurface::Unpin() {
  546. surface_->Unpin();
  547. }
  548. #if BUILDFLAG(IS_CHROMEOS_ASH)
  549. chromeos::OrientationType OrientationLock(uint32_t orientation_lock) {
  550. switch (orientation_lock) {
  551. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_NONE:
  552. return chromeos::OrientationType::kAny;
  553. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_CURRENT:
  554. return chromeos::OrientationType::kCurrent;
  555. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_PORTRAIT:
  556. return chromeos::OrientationType::kPortrait;
  557. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_LANDSCAPE:
  558. return chromeos::OrientationType::kLandscape;
  559. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_PORTRAIT_PRIMARY:
  560. return chromeos::OrientationType::kPortraitPrimary;
  561. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_LANDSCAPE_PRIMARY:
  562. return chromeos::OrientationType::kLandscapePrimary;
  563. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_PORTRAIT_SECONDARY:
  564. return chromeos::OrientationType::kPortraitSecondary;
  565. case ZAURA_TOPLEVEL_ORIENTATION_LOCK_LANDSCAPE_SECONDARY:
  566. return chromeos::OrientationType::kLandscapeSecondary;
  567. }
  568. VLOG(2) << "Unexpected value of orientation_lock: " << orientation_lock;
  569. return chromeos::OrientationType::kAny;
  570. }
  571. using AuraSurfaceConfigureCallback =
  572. base::RepeatingCallback<void(const gfx::Rect& bounds,
  573. chromeos::WindowStateType state_type,
  574. bool resizing,
  575. bool activated)>;
  576. uint32_t HandleAuraSurfaceConfigureCallback(
  577. wl_resource* resource,
  578. SerialTracker* serial_tracker,
  579. const AuraSurfaceConfigureCallback& callback,
  580. const gfx::Rect& bounds,
  581. chromeos::WindowStateType state_type,
  582. bool resizing,
  583. bool activated,
  584. const gfx::Vector2d& origin_offset) {
  585. uint32_t serial =
  586. serial_tracker->GetNextSerial(SerialTracker::EventType::OTHER_EVENT);
  587. callback.Run(bounds, state_type, resizing, activated);
  588. xdg_surface_send_configure(resource, serial);
  589. wl_client_flush(wl_resource_get_client(resource));
  590. return serial;
  591. }
  592. AuraToplevel::AuraToplevel(ShellSurface* shell_surface,
  593. SerialTracker* const serial_tracker,
  594. wl_resource* xdg_toplevel_resource,
  595. wl_resource* aura_toplevel_resource)
  596. : shell_surface_(shell_surface),
  597. serial_tracker_(serial_tracker),
  598. xdg_toplevel_resource_(xdg_toplevel_resource),
  599. aura_toplevel_resource_(aura_toplevel_resource) {
  600. DCHECK(shell_surface);
  601. }
  602. AuraToplevel::~AuraToplevel() = default;
  603. void AuraToplevel::SetOrientationLock(uint32_t lock_type) {
  604. shell_surface_->SetOrientationLock(OrientationLock(lock_type));
  605. }
  606. void AuraToplevel::SetClientSubmitsSurfacesInPixelCoordinates(bool enable) {
  607. shell_surface_->set_client_submits_surfaces_in_pixel_coordinates(enable);
  608. }
  609. void AuraToplevel::SetWindowBounds(int32_t x,
  610. int32_t y,
  611. int32_t width,
  612. int32_t height) {
  613. if (!shell_surface_->IsDragged())
  614. shell_surface_->SetWindowBounds(gfx::Rect(x, y, width, height));
  615. }
  616. void AuraToplevel::SetRestoreInfo(int32_t restore_session_id,
  617. int32_t restore_window_id) {
  618. shell_surface_->SetRestoreInfo(restore_session_id, restore_window_id);
  619. }
  620. void AuraToplevel::SetRestoreInfoWithWindowIdSource(
  621. int32_t restore_session_id,
  622. const std::string& restore_window_id_source) {
  623. shell_surface_->SetRestoreInfoWithWindowIdSource(restore_session_id,
  624. restore_window_id_source);
  625. }
  626. void AuraToplevel::OnOriginChange(const gfx::Point& origin) {
  627. zaura_toplevel_send_origin_change(aura_toplevel_resource_, origin.x(),
  628. origin.y());
  629. wl_client_flush(wl_resource_get_client(aura_toplevel_resource_));
  630. }
  631. void AuraToplevel::SetDecoration(SurfaceFrameType type) {
  632. shell_surface_->OnSetFrame(type);
  633. }
  634. void AuraToplevel::SetZOrder(ui::ZOrderLevel z_order) {
  635. shell_surface_->SetZOrder(z_order);
  636. }
  637. void AuraToplevel::SetClientUsesScreenCoordinates() {
  638. supports_window_bounds_ = true;
  639. shell_surface_->set_client_supports_window_bounds(true);
  640. shell_surface_->set_configure_callback(
  641. base::BindRepeating(&HandleAuraSurfaceConfigureCallback,
  642. xdg_toplevel_resource_, serial_tracker_,
  643. base::BindRepeating(&AuraToplevel::OnConfigure,
  644. weak_ptr_factory_.GetWeakPtr())));
  645. shell_surface_->set_origin_change_callback(base::BindRepeating(
  646. &AuraToplevel::OnOriginChange, weak_ptr_factory_.GetWeakPtr()));
  647. }
  648. void AuraToplevel::SetSystemModal(bool modal) {
  649. shell_surface_->SetSystemModal(modal);
  650. }
  651. void AuraToplevel::SetFloat() {
  652. shell_surface_->SetFloat();
  653. }
  654. void AuraToplevel::UnsetFloat() {
  655. shell_surface_->UnsetFloat();
  656. }
  657. template <class T>
  658. void AddState(wl_array* states, T state) {
  659. T* value = static_cast<T*>(wl_array_add(states, sizeof(T)));
  660. DCHECK(value);
  661. *value = state;
  662. }
  663. void AuraToplevel::OnConfigure(const gfx::Rect& bounds,
  664. chromeos::WindowStateType state_type,
  665. bool resizing,
  666. bool activated) {
  667. wl_array states;
  668. wl_array_init(&states);
  669. if (state_type == chromeos::WindowStateType::kMaximized)
  670. AddState(&states, XDG_TOPLEVEL_STATE_MAXIMIZED);
  671. // TODO(crbug/1250129): Pinned states need to be handled properly.
  672. // TODO(crbug/1250129): Support snapped state.
  673. if (IsFullscreenOrPinnedWindowStateType(state_type)) {
  674. AddState(&states, XDG_TOPLEVEL_STATE_FULLSCREEN);
  675. if (shell_surface_->GetWidget()->GetNativeWindow()->GetProperty(
  676. chromeos::kImmersiveImpliedByFullscreen))
  677. AddState(&states, ZAURA_TOPLEVEL_STATE_IMMERSIVE);
  678. }
  679. if (resizing)
  680. AddState(&states, XDG_TOPLEVEL_STATE_RESIZING);
  681. if (activated)
  682. AddState(&states, XDG_TOPLEVEL_STATE_ACTIVATED);
  683. if (state_type == chromeos::WindowStateType::kPrimarySnapped)
  684. AddState(&states, ZAURA_TOPLEVEL_STATE_SNAPPED_PRIMARY);
  685. if (state_type == chromeos::WindowStateType::kSecondarySnapped)
  686. AddState(&states, ZAURA_TOPLEVEL_STATE_SNAPPED_SECONDARY);
  687. if (state_type == chromeos::WindowStateType::kMinimized)
  688. AddState(&states, ZAURA_TOPLEVEL_STATE_MINIMIZED);
  689. zaura_toplevel_send_configure(aura_toplevel_resource_, bounds.x(), bounds.y(),
  690. bounds.width(), bounds.height(), &states);
  691. wl_array_release(&states);
  692. }
  693. AuraPopup::AuraPopup(ShellSurfaceBase* shell_surface)
  694. : shell_surface_(shell_surface) {
  695. DCHECK(shell_surface);
  696. }
  697. AuraPopup::~AuraPopup() = default;
  698. void AuraPopup::SetClientSubmitsSurfacesInPixelCoordinates(bool enable) {
  699. shell_surface_->set_client_submits_surfaces_in_pixel_coordinates(enable);
  700. }
  701. void AuraPopup::SetDecoration(SurfaceFrameType type) {
  702. shell_surface_->OnSetFrame(type);
  703. }
  704. void AuraPopup::SetMenu() {
  705. shell_surface_->SetMenu();
  706. }
  707. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  708. namespace {
  709. void aura_output_release(wl_client* client, wl_resource* resource) {
  710. wl_resource_destroy(resource);
  711. }
  712. const struct zaura_output_interface aura_output_implementation = {
  713. aura_output_release,
  714. };
  715. } // namespace
  716. ////////////////////////////////////////////////////////////////////////////////
  717. // aura_output_interface:
  718. AuraOutput::AuraOutput(wl_resource* resource,
  719. WaylandDisplayHandler* display_handler)
  720. : resource_(resource), display_handler_(display_handler) {
  721. display_handler_->AddObserver(this);
  722. }
  723. AuraOutput::~AuraOutput() {
  724. if (display_handler_)
  725. display_handler_->RemoveObserver(this);
  726. }
  727. bool AuraOutput::SendDisplayMetrics(const display::Display& display,
  728. uint32_t changed_metrics) {
  729. if (!(changed_metrics &
  730. (display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
  731. display::DisplayObserver::DISPLAY_METRIC_WORK_AREA |
  732. display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
  733. display::DisplayObserver::DISPLAY_METRIC_ROTATION))) {
  734. return false;
  735. }
  736. const WMHelper* wm_helper = WMHelper::GetInstance();
  737. const display::ManagedDisplayInfo& display_info =
  738. wm_helper->GetDisplayInfo(display.id());
  739. if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_SCALE_SINCE_VERSION) {
  740. display::ManagedDisplayMode active_mode;
  741. bool rv = wm_helper->GetActiveModeForDisplayId(display.id(), &active_mode);
  742. DCHECK(rv);
  743. const int32_t current_output_scale =
  744. std::round(display_info.zoom_factor() * 1000.f);
  745. std::vector<float> zoom_factors =
  746. display::GetDisplayZoomFactors(active_mode);
  747. // Ensure that the current zoom factor is a part of the list.
  748. auto it = std::find_if(
  749. zoom_factors.begin(), zoom_factors.end(),
  750. [&display_info](float zoom_factor) -> bool {
  751. return std::abs(display_info.zoom_factor() - zoom_factor) <=
  752. std::numeric_limits<float>::epsilon();
  753. });
  754. if (it == zoom_factors.end())
  755. zoom_factors.push_back(display_info.zoom_factor());
  756. for (float zoom_factor : zoom_factors) {
  757. int32_t output_scale = std::round(zoom_factor * 1000.f);
  758. uint32_t flags = 0;
  759. if (output_scale == 1000)
  760. flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED;
  761. if (current_output_scale == output_scale)
  762. flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT;
  763. // TODO(malaykeshav): This can be removed in the future when client
  764. // has been updated.
  765. if (wl_resource_get_version(resource_) < 6)
  766. output_scale = std::round(1000.f / zoom_factor);
  767. zaura_output_send_scale(resource_, flags, output_scale);
  768. }
  769. }
  770. if (wl_resource_get_version(resource_) >=
  771. ZAURA_OUTPUT_CONNECTION_SINCE_VERSION) {
  772. zaura_output_send_connection(
  773. resource_, display.IsInternal() ? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL
  774. : ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN);
  775. }
  776. if (wl_resource_get_version(resource_) >=
  777. ZAURA_OUTPUT_DEVICE_SCALE_FACTOR_SINCE_VERSION) {
  778. zaura_output_send_device_scale_factor(
  779. resource_, display_info.device_scale_factor() * 1000);
  780. }
  781. if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_INSETS_SINCE_VERSION)
  782. SendInsets(display.bounds().InsetsFrom(display.work_area()));
  783. if (wl_resource_get_version(resource_) >=
  784. ZAURA_OUTPUT_LOGICAL_TRANSFORM_SINCE_VERSION) {
  785. SendLogicalTransform(OutputTransform(display.rotation()));
  786. }
  787. return true;
  788. }
  789. void AuraOutput::OnOutputDestroyed() {
  790. display_handler_->RemoveObserver(this);
  791. display_handler_ = nullptr;
  792. }
  793. bool AuraOutput::HasDisplayHandlerForTesting() const {
  794. return !!display_handler_;
  795. }
  796. void AuraOutput::SendInsets(const gfx::Insets& insets) {
  797. zaura_output_send_insets(resource_, insets.top(), insets.left(),
  798. insets.bottom(), insets.right());
  799. }
  800. void AuraOutput::SendLogicalTransform(int32_t transform) {
  801. zaura_output_send_logical_transform(resource_, transform);
  802. }
  803. namespace {
  804. ////////////////////////////////////////////////////////////////////////////////
  805. // aura_shell_interface:
  806. #if BUILDFLAG(IS_CHROMEOS_ASH)
  807. // IDs of bugs that have been fixed in the exo implementation. These are
  808. // propagated to clients on aura_shell bind and can be used to gate client
  809. // logic on the presence of certain fixes.
  810. const uint32_t kFixedBugIds[] = {
  811. 1151508, // Do not remove, used for sanity checks by
  812. // |wayland_simple_client|
  813. };
  814. // Implements aura shell interface and monitors workspace state needed
  815. // for the aura shell interface.
  816. class WaylandAuraShell : public ash::DesksController::Observer,
  817. public ash::TabletModeObserver,
  818. public SeatObserver {
  819. public:
  820. WaylandAuraShell(wl_resource* aura_shell_resource, Display* display)
  821. : aura_shell_resource_(aura_shell_resource), seat_(display->seat()) {
  822. WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
  823. helper->AddTabletModeObserver(this);
  824. ash::DesksController::Get()->AddObserver(this);
  825. if (wl_resource_get_version(aura_shell_resource_) >=
  826. ZAURA_SHELL_LAYOUT_MODE_SINCE_VERSION) {
  827. auto layout_mode = helper->InTabletMode()
  828. ? ZAURA_SHELL_LAYOUT_MODE_TABLET
  829. : ZAURA_SHELL_LAYOUT_MODE_WINDOWED;
  830. zaura_shell_send_layout_mode(aura_shell_resource_, layout_mode);
  831. }
  832. if (wl_resource_get_version(aura_shell_resource_) >=
  833. ZAURA_SHELL_BUG_FIX_SINCE_VERSION) {
  834. for (uint32_t bug_id : kFixedBugIds) {
  835. zaura_shell_send_bug_fix(aura_shell_resource_, bug_id);
  836. }
  837. }
  838. display->seat()->AddObserver(this, kAuraShellSeatObserverPriority);
  839. OnDesksChanged();
  840. OnDeskActivationChanged();
  841. }
  842. WaylandAuraShell(const WaylandAuraShell&) = delete;
  843. WaylandAuraShell& operator=(const WaylandAuraShell&) = delete;
  844. ~WaylandAuraShell() override {
  845. WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
  846. helper->RemoveTabletModeObserver(this);
  847. ash::DesksController::Get()->RemoveObserver(this);
  848. if (seat_)
  849. seat_->RemoveObserver(this);
  850. }
  851. // Overridden from ash::TabletModeObserver:
  852. void OnTabletModeStarted() override {
  853. if (wl_resource_get_version(aura_shell_resource_) >=
  854. ZAURA_SHELL_LAYOUT_MODE_SINCE_VERSION)
  855. zaura_shell_send_layout_mode(aura_shell_resource_,
  856. ZAURA_SHELL_LAYOUT_MODE_TABLET);
  857. }
  858. void OnTabletModeEnding() override {
  859. if (wl_resource_get_version(aura_shell_resource_) >=
  860. ZAURA_SHELL_LAYOUT_MODE_SINCE_VERSION)
  861. zaura_shell_send_layout_mode(aura_shell_resource_,
  862. ZAURA_SHELL_LAYOUT_MODE_WINDOWED);
  863. }
  864. void OnTabletModeEnded() override {}
  865. // Overridden from SeatObserver:
  866. void OnSurfaceFocused(Surface* gained_focus,
  867. Surface* lost_focus,
  868. bool has_focused_surface) override {
  869. FocusedSurfaceChanged(gained_focus, lost_focus, has_focused_surface);
  870. }
  871. // ash::DesksController::Observer:
  872. void OnDeskAdded(const ash::Desk* desk) override { OnDesksChanged(); }
  873. void OnDeskRemoved(const ash::Desk* desk) override { OnDesksChanged(); }
  874. void OnDeskReordered(int old_index, int new_index) override {
  875. OnDesksChanged();
  876. }
  877. void OnDeskActivationChanged(const ash::Desk* activated,
  878. const ash::Desk* deactivated) override {
  879. OnDeskActivationChanged();
  880. }
  881. void OnDeskSwitchAnimationLaunching() override {}
  882. void OnDeskSwitchAnimationFinished() override {}
  883. void OnDeskNameChanged(const ash::Desk* desk,
  884. const std::u16string& new_name) override {
  885. OnDesksChanged();
  886. }
  887. private:
  888. void OnDesksChanged() {
  889. if (wl_resource_get_version(aura_shell_resource_) <
  890. ZAURA_SHELL_DESKS_CHANGED_SINCE_VERSION) {
  891. return;
  892. }
  893. wl_array desk_names;
  894. wl_array_init(&desk_names);
  895. for (const auto& desk : ash::DesksController::Get()->desks()) {
  896. std::string name = base::UTF16ToUTF8(desk->name());
  897. char* desk_name =
  898. static_cast<char*>(wl_array_add(&desk_names, name.size() + 1));
  899. strcpy(desk_name, name.c_str());
  900. }
  901. zaura_shell_send_desks_changed(aura_shell_resource_, &desk_names);
  902. wl_array_release(&desk_names);
  903. }
  904. void OnDeskActivationChanged() {
  905. if (wl_resource_get_version(aura_shell_resource_) <
  906. ZAURA_SHELL_DESK_ACTIVATION_CHANGED_SINCE_VERSION) {
  907. return;
  908. }
  909. zaura_shell_send_desk_activation_changed(
  910. aura_shell_resource_,
  911. ash::DesksController::Get()->GetActiveDeskIndex());
  912. }
  913. void FocusedSurfaceChanged(Surface* gained_active_surface,
  914. Surface* lost_active_surface,
  915. bool has_focused_client) {
  916. if (wl_resource_get_version(aura_shell_resource_) <
  917. ZAURA_SHELL_ACTIVATED_SINCE_VERSION)
  918. return;
  919. if (gained_active_surface == lost_active_surface &&
  920. last_has_focused_client_ == has_focused_client)
  921. return;
  922. last_has_focused_client_ = has_focused_client;
  923. wl_resource* gained_active_surface_resource =
  924. gained_active_surface ? GetSurfaceResource(gained_active_surface)
  925. : nullptr;
  926. wl_resource* lost_active_surface_resource =
  927. lost_active_surface ? GetSurfaceResource(lost_active_surface) : nullptr;
  928. wl_client* client = wl_resource_get_client(aura_shell_resource_);
  929. // If surface that gained active is not owned by the aura shell then
  930. // set to null.
  931. if (gained_active_surface_resource &&
  932. wl_resource_get_client(gained_active_surface_resource) != client) {
  933. gained_active_surface_resource = nullptr;
  934. }
  935. // If surface that lost active is not owned by the aura shell then set
  936. // to null.
  937. if (lost_active_surface_resource &&
  938. wl_resource_get_client(lost_active_surface_resource) != client) {
  939. lost_active_surface_resource = nullptr;
  940. }
  941. zaura_shell_send_activated(aura_shell_resource_,
  942. gained_active_surface_resource,
  943. lost_active_surface_resource);
  944. wl_client_flush(client);
  945. }
  946. // The aura shell resource associated with observer.
  947. wl_resource* const aura_shell_resource_;
  948. Seat* const seat_;
  949. bool last_has_focused_client_ = false;
  950. base::WeakPtrFactory<WaylandAuraShell> weak_ptr_factory_{this};
  951. };
  952. ////////////////////////////////////////////////////////////////////////////////
  953. // aura_toplevel_interface:
  954. void aura_toplevel_set_orientation_lock(wl_client* client,
  955. wl_resource* resource,
  956. uint32_t orientation_lock) {
  957. GetUserDataAs<AuraToplevel>(resource)->SetOrientationLock(orientation_lock);
  958. }
  959. void aura_toplevel_set_client_supports_window_bounds(wl_client* client,
  960. wl_resource* resource) {
  961. GetUserDataAs<AuraToplevel>(resource)->SetClientUsesScreenCoordinates();
  962. }
  963. void aura_toplevel_surface_submission_in_pixel_coordinates(
  964. wl_client* client,
  965. wl_resource* resource) {
  966. GetUserDataAs<AuraToplevel>(resource)
  967. ->SetClientSubmitsSurfacesInPixelCoordinates(true);
  968. }
  969. void aura_toplevel_set_window_bounds(wl_client* client,
  970. wl_resource* resource,
  971. int32_t x,
  972. int32_t y,
  973. int32_t width,
  974. int32_t height,
  975. wl_resource* output) {
  976. // TODO(crbug.com/1261321): Use output hint.
  977. GetUserDataAs<AuraToplevel>(resource)->SetWindowBounds(x, y, width, height);
  978. }
  979. void aura_toplevel_set_restore_info(wl_client* client,
  980. wl_resource* resource,
  981. int32_t restore_session_id,
  982. int32_t restore_window_id) {
  983. GetUserDataAs<AuraToplevel>(resource)->SetRestoreInfo(restore_session_id,
  984. restore_window_id);
  985. }
  986. void aura_toplevel_set_system_modal(wl_client* client, wl_resource* resource) {
  987. GetUserDataAs<AuraToplevel>(resource)->SetSystemModal(true);
  988. }
  989. void aura_toplevel_unset_system_modal(wl_client* client,
  990. wl_resource* resource) {
  991. GetUserDataAs<AuraToplevel>(resource)->SetSystemModal(false);
  992. }
  993. void aura_toplevel_set_float(wl_client* client, wl_resource* resource) {
  994. GetUserDataAs<AuraToplevel>(resource)->SetFloat();
  995. }
  996. void aura_toplevel_unset_float(wl_client* client, wl_resource* resource) {
  997. GetUserDataAs<AuraToplevel>(resource)->UnsetFloat();
  998. }
  999. void aura_toplevel_set_restore_info_with_window_id_source(
  1000. wl_client* client,
  1001. wl_resource* resource,
  1002. int32_t restore_session_id,
  1003. const char* restore_window_id_source) {
  1004. GetUserDataAs<AuraToplevel>(resource)->SetRestoreInfoWithWindowIdSource(
  1005. restore_session_id, restore_window_id_source);
  1006. }
  1007. SurfaceFrameType AuraTopLevelDecorationType(uint32_t decoration_type) {
  1008. switch (decoration_type) {
  1009. case ZAURA_TOPLEVEL_DECORATION_TYPE_NONE:
  1010. return SurfaceFrameType::NONE;
  1011. case ZAURA_TOPLEVEL_DECORATION_TYPE_NORMAL:
  1012. return SurfaceFrameType::NORMAL;
  1013. case ZAURA_TOPLEVEL_DECORATION_TYPE_SHADOW:
  1014. return SurfaceFrameType::SHADOW;
  1015. default:
  1016. VLOG(2) << "Unknown aura-toplevel decoration type: " << decoration_type;
  1017. return SurfaceFrameType::NONE;
  1018. }
  1019. }
  1020. void aura_toplevel_set_decoration(wl_client* client,
  1021. wl_resource* resource,
  1022. uint32_t type) {
  1023. GetUserDataAs<AuraToplevel>(resource)->SetDecoration(
  1024. AuraTopLevelDecorationType(type));
  1025. }
  1026. void aura_toplevel_release(wl_client* client, wl_resource* resource) {
  1027. wl_resource_destroy(resource);
  1028. }
  1029. ui::ZOrderLevel AuraTopLevelZOrderLevel(uint32_t z_order_level) {
  1030. switch (z_order_level) {
  1031. case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_NORMAL:
  1032. return ui::ZOrderLevel::kNormal;
  1033. case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_FLOATING_WINDOW:
  1034. return ui::ZOrderLevel::kFloatingWindow;
  1035. case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_FLOATING_UI_ELEMENT:
  1036. return ui::ZOrderLevel::kFloatingUIElement;
  1037. case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_SECURITY_SURFACE:
  1038. return ui::ZOrderLevel::kSecuritySurface;
  1039. }
  1040. NOTREACHED();
  1041. return ui::ZOrderLevel::kNormal;
  1042. }
  1043. void aura_toplevel_set_z_order(wl_client* client,
  1044. wl_resource* resource,
  1045. uint32_t z_order) {
  1046. GetUserDataAs<AuraToplevel>(resource)->SetZOrder(
  1047. AuraTopLevelZOrderLevel(z_order));
  1048. }
  1049. const struct zaura_toplevel_interface aura_toplevel_implementation = {
  1050. aura_toplevel_set_orientation_lock,
  1051. aura_toplevel_surface_submission_in_pixel_coordinates,
  1052. aura_toplevel_set_client_supports_window_bounds,
  1053. aura_toplevel_set_window_bounds,
  1054. aura_toplevel_set_restore_info,
  1055. aura_toplevel_set_system_modal,
  1056. aura_toplevel_unset_system_modal,
  1057. aura_toplevel_set_restore_info_with_window_id_source,
  1058. aura_toplevel_set_decoration,
  1059. aura_toplevel_release,
  1060. aura_toplevel_set_float,
  1061. aura_toplevel_unset_float,
  1062. aura_toplevel_set_z_order,
  1063. };
  1064. void aura_popup_surface_submission_in_pixel_coordinates(wl_client* client,
  1065. wl_resource* resource) {
  1066. GetUserDataAs<AuraPopup>(resource)
  1067. ->SetClientSubmitsSurfacesInPixelCoordinates(true);
  1068. }
  1069. SurfaceFrameType AuraPopupDecorationType(uint32_t decoration_type) {
  1070. switch (decoration_type) {
  1071. case ZAURA_POPUP_DECORATION_TYPE_NONE:
  1072. return SurfaceFrameType::NONE;
  1073. case ZAURA_POPUP_DECORATION_TYPE_NORMAL:
  1074. return SurfaceFrameType::NORMAL;
  1075. case ZAURA_POPUP_DECORATION_TYPE_SHADOW:
  1076. return SurfaceFrameType::SHADOW;
  1077. default:
  1078. VLOG(2) << "Unknown aura-popup decoration type: " << decoration_type;
  1079. return SurfaceFrameType::NONE;
  1080. }
  1081. }
  1082. void aura_popup_set_decoration(wl_client* client,
  1083. wl_resource* resource,
  1084. uint32_t type) {
  1085. GetUserDataAs<AuraPopup>(resource)->SetDecoration(
  1086. AuraPopupDecorationType(type));
  1087. }
  1088. void aura_popup_set_menu(wl_client* client, wl_resource* resource) {
  1089. GetUserDataAs<AuraPopup>(resource)->SetMenu();
  1090. }
  1091. void aura_popup_release(wl_client* client, wl_resource* resource) {
  1092. wl_resource_destroy(resource);
  1093. }
  1094. const struct zaura_popup_interface aura_popup_implementation = {
  1095. aura_popup_surface_submission_in_pixel_coordinates,
  1096. aura_popup_set_decoration,
  1097. aura_popup_set_menu,
  1098. aura_popup_release,
  1099. };
  1100. void aura_shell_get_aura_toplevel(wl_client* client,
  1101. wl_resource* resource,
  1102. uint32_t id,
  1103. wl_resource* xdg_toplevel_resource) {
  1104. ShellSurfaceData shell_surface_data =
  1105. GetShellSurfaceFromToplevelResource(xdg_toplevel_resource);
  1106. wl_resource* aura_toplevel_resource = wl_resource_create(
  1107. client, &zaura_toplevel_interface, wl_resource_get_version(resource), id);
  1108. SetImplementation(
  1109. aura_toplevel_resource, &aura_toplevel_implementation,
  1110. std::make_unique<AuraToplevel>(
  1111. shell_surface_data.shell_surface, shell_surface_data.serial_tracker,
  1112. shell_surface_data.surface_resource, aura_toplevel_resource));
  1113. }
  1114. void aura_shell_get_aura_popup(wl_client* client,
  1115. wl_resource* resource,
  1116. uint32_t id,
  1117. wl_resource* surface_resource) {
  1118. wl_resource* aura_popup_resource = wl_resource_create(
  1119. client, &zaura_popup_interface, wl_resource_get_version(resource), id);
  1120. ShellSurfaceBase* shell_surface =
  1121. GetShellSurfaceFromPopupResource(surface_resource);
  1122. SetImplementation(aura_popup_resource, &aura_popup_implementation,
  1123. std::make_unique<AuraPopup>(shell_surface));
  1124. }
  1125. #else
  1126. void aura_shell_get_aura_toplevel(wl_client* client,
  1127. wl_resource* resource,
  1128. uint32_t id,
  1129. wl_resource* surface_resource) {
  1130. NOTREACHED();
  1131. }
  1132. void aura_shell_get_aura_popup(wl_client* client,
  1133. wl_resource* resource,
  1134. uint32_t id,
  1135. wl_resource* surface_resource) {
  1136. NOTREACHED();
  1137. }
  1138. #endif // BUILDFLAG(IS_CHROMEOS_ASH))
  1139. void aura_shell_get_aura_surface(wl_client* client,
  1140. wl_resource* resource,
  1141. uint32_t id,
  1142. wl_resource* surface_resource) {
  1143. Surface* surface = GetUserDataAs<Surface>(surface_resource);
  1144. if (surface->GetProperty(kSurfaceHasAuraSurfaceKey)) {
  1145. wl_resource_post_error(
  1146. resource, ZAURA_SHELL_ERROR_AURA_SURFACE_EXISTS,
  1147. "an aura surface object for that surface already exists");
  1148. return;
  1149. }
  1150. wl_resource* aura_surface_resource = wl_resource_create(
  1151. client, &zaura_surface_interface, wl_resource_get_version(resource), id);
  1152. SetImplementation(
  1153. aura_surface_resource, &aura_surface_implementation,
  1154. std::make_unique<AuraSurface>(surface, aura_surface_resource));
  1155. }
  1156. void aura_shell_get_aura_output(wl_client* client,
  1157. wl_resource* resource,
  1158. uint32_t id,
  1159. wl_resource* output_resource) {
  1160. WaylandDisplayHandler* display_handler =
  1161. GetUserDataAs<WaylandDisplayHandler>(output_resource);
  1162. wl_resource* aura_output_resource = wl_resource_create(
  1163. client, &zaura_output_interface, wl_resource_get_version(resource), id);
  1164. auto aura_output =
  1165. std::make_unique<AuraOutput>(aura_output_resource, display_handler);
  1166. SetImplementation(aura_output_resource, &aura_output_implementation,
  1167. std::move(aura_output));
  1168. }
  1169. void aura_shell_surface_submission_in_pixel_coordinates(wl_client* client,
  1170. wl_resource* resource) {
  1171. LOG(WARNING) << "Deprecated. The server doesn't support this request.";
  1172. }
  1173. void aura_shell_release(wl_client* client, wl_resource* resource) {
  1174. // Nothing to do here.
  1175. }
  1176. const struct zaura_shell_interface aura_shell_implementation = {
  1177. aura_shell_get_aura_surface,
  1178. aura_shell_get_aura_output,
  1179. aura_shell_surface_submission_in_pixel_coordinates,
  1180. aura_shell_get_aura_toplevel,
  1181. aura_shell_get_aura_popup,
  1182. aura_shell_release,
  1183. };
  1184. } // namespace
  1185. void bind_aura_shell(wl_client* client,
  1186. void* data,
  1187. uint32_t version,
  1188. uint32_t id) {
  1189. wl_resource* resource =
  1190. wl_resource_create(client, &zaura_shell_interface,
  1191. std::min(version, kZAuraShellVersion), id);
  1192. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1193. Display* display = static_cast<Display*>(data);
  1194. SetImplementation(resource, &aura_shell_implementation,
  1195. std::make_unique<WaylandAuraShell>(resource, display));
  1196. #else
  1197. wl_resource_set_implementation(resource, &aura_shell_implementation, nullptr,
  1198. nullptr);
  1199. #endif
  1200. }
  1201. } // namespace wayland
  1202. } // namespace exo