x11-ozone-fix-X11-screensaver-suspension.patch 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. From 8c1ebea5f601b0b5247535dcdfd01755f3e6e1a6 Mon Sep 17 00:00:00 2001
  2. From: Andrew Wolfers <aswolfers@chromium.org>
  3. Date: Tue, 19 Jul 2022 15:01:25 +0000
  4. Subject: [PATCH] [x11][ozone] Fix X11 screensaver suspension.
  5. X11 screensaver suspension was broken by https://crrev.com/c/3507472,
  6. in which usage patterns were migrated to a non-stacking paradigm.
  7. "Non-stacking" screensaver suspension describes an overriding behavior,
  8. such that the last suspending or un-suspending call defines the current
  9. state. Conversely, a "stacking" screensaver suspension paradigm allows
  10. for parallel suspension, such that suspending calls are expected to be
  11. matched by an equal number of un-suspending calls.
  12. Documentation for `PlatformScreen::SetScreenSaverSuspended` (inherited
  13. by `X11ScreenOzone`) explains that it should be used in a non-stacking
  14. manner [1], which contradicts the child class's underlying
  15. implementation [2].
  16. > If XScreenSaverSuspend is called multiple times with suspend set to
  17. > 'True', it must be called an equal number of times with suspend set
  18. > to 'False' in order for the screensaver timer to be restarted.
  19. This change updates the documentation/API of the `PlatformScreen`
  20. parent class to correctly describe the stacking behavior of child class
  21. `X11ScreenOzone`. This change also updates the implementation of
  22. `WaylandScreen` to a stacking version. Lastly, this change updates the
  23. call sites of `PlatformScreen` according to the API change.
  24. [1] https://crsrc.org/c/ui/ozone/public/platform_screen.h;l=96
  25. [2] https://linux.die.net/man/3/xscreensaverunsetattributes
  26. Bug: b:193670013
  27. Bug: b:196213351
  28. Bug: 1329573
  29. Bug: 1339361
  30. Change-Id: I60975c8da9f86a0f26f3c32cf49c4a7eeeea6a12
  31. Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3759067
  32. Commit-Queue: Andrew Wolfers <aswolfers@chromium.org>
  33. Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
  34. Reviewed-by: Scott Violet <sky@chromium.org>
  35. Cr-Commit-Position: refs/heads/main@{#1025717}
  36. (cherry picked from commit e61f08f8dbf1ec7cead427f3c497934e9d0db35f)
  37. ---
  38. ui/aura/screen_ozone.cc | 14 ++++++--
  39. ui/aura/screen_ozone.h | 29 ++++++++++++----
  40. ui/base/x/x11_util.h | 4 ++-
  41. ui/display/screen.cc | 21 ++----------
  42. ui/display/screen.h | 34 ++++++-------------
  43. .../platform/wayland/host/wayland_screen.cc | 31 +++++++++++++++++
  44. .../platform/wayland/host/wayland_screen.h | 30 +++++++++++++++-
  45. ui/ozone/platform/x11/x11_screen_ozone.cc | 27 +++++++++++++--
  46. ui/ozone/platform/x11/x11_screen_ozone.h | 19 ++++++++++-
  47. ui/ozone/public/platform_screen.cc | 8 +++--
  48. ui/ozone/public/platform_screen.h | 26 +++++++++++---
  49. 11 files changed, 182 insertions(+), 61 deletions(-)
  50. diff --git a/ui/aura/screen_ozone.cc b/ui/aura/screen_ozone.cc
  51. index a78a6a48f1..09f62dc982 100644
  52. --- a/ui/aura/screen_ozone.cc
  53. +++ b/ui/aura/screen_ozone.cc
  54. @@ -4,6 +4,8 @@
  55. #include "ui/aura/screen_ozone.h"
  56. +#include <memory>
  57. +
  58. #include "ui/aura/client/screen_position_client.h"
  59. #include "ui/aura/window.h"
  60. #include "ui/aura/window_tree_host.h"
  61. @@ -108,8 +110,16 @@ display::Display ScreenOzone::GetPrimaryDisplay() const {
  62. }
  63. #if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  64. -bool ScreenOzone::SetScreenSaverSuspended(bool suspend) {
  65. - return platform_screen_->SetScreenSaverSuspended(suspend);
  66. +ScreenOzone::ScreenSaverSuspenderOzone::ScreenSaverSuspenderOzone(
  67. + std::unique_ptr<ui::PlatformScreen::PlatformScreenSaverSuspender> suspender)
  68. + : suspender_(std::move(suspender)) {}
  69. +
  70. +ScreenOzone::ScreenSaverSuspenderOzone::~ScreenSaverSuspenderOzone() = default;
  71. +
  72. +std::unique_ptr<display::Screen::ScreenSaverSuspender>
  73. +ScreenOzone::SuspendScreenSaver() {
  74. + return std::make_unique<ScreenSaverSuspenderOzone>(
  75. + platform_screen_->SuspendScreenSaver());
  76. }
  77. #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  78. diff --git a/ui/aura/screen_ozone.h b/ui/aura/screen_ozone.h
  79. index 2970a0e0e7..d033abf366 100644
  80. --- a/ui/aura/screen_ozone.h
  81. +++ b/ui/aura/screen_ozone.h
  82. @@ -11,10 +11,7 @@
  83. #include "build/chromeos_buildflags.h"
  84. #include "ui/aura/aura_export.h"
  85. #include "ui/display/screen.h"
  86. -
  87. -namespace ui {
  88. -class PlatformScreen;
  89. -}
  90. +#include "ui/ozone/public/platform_screen.h"
  91. namespace aura {
  92. @@ -48,6 +45,10 @@ class AURA_EXPORT ScreenOzone : public display::Screen {
  93. display::Display GetDisplayMatching(
  94. const gfx::Rect& match_rect) const override;
  95. display::Display GetPrimaryDisplay() const override;
  96. +#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  97. + std::unique_ptr<display::Screen::ScreenSaverSuspender> SuspendScreenSaver()
  98. + override;
  99. +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  100. bool IsScreenSaverActive() const override;
  101. base::TimeDelta CalculateIdleTime() const override;
  102. void AddObserver(display::DisplayObserver* observer) override;
  103. @@ -65,11 +66,27 @@ class AURA_EXPORT ScreenOzone : public display::Screen {
  104. protected:
  105. ui::PlatformScreen* platform_screen() { return platform_screen_.get(); }
  106. + private:
  107. #if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  108. - bool SetScreenSaverSuspended(bool suspend) override;
  109. + class ScreenSaverSuspenderOzone
  110. + : public display::Screen::ScreenSaverSuspender {
  111. + public:
  112. + explicit ScreenSaverSuspenderOzone(
  113. + std::unique_ptr<ui::PlatformScreen::PlatformScreenSaverSuspender>
  114. + suspender);
  115. +
  116. + ScreenSaverSuspenderOzone(const ScreenSaverSuspenderOzone&) = delete;
  117. + ScreenSaverSuspenderOzone& operator=(const ScreenSaverSuspenderOzone&) =
  118. + delete;
  119. +
  120. + ~ScreenSaverSuspenderOzone() override;
  121. +
  122. + private:
  123. + std::unique_ptr<ui::PlatformScreen::PlatformScreenSaverSuspender>
  124. + suspender_;
  125. + };
  126. #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  127. - private:
  128. gfx::AcceleratedWidget GetAcceleratedWidgetForWindow(
  129. aura::Window* window) const;
  130. diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
  131. index bf36efe170..0692571582 100644
  132. --- a/ui/base/x/x11_util.h
  133. +++ b/ui/base/x/x11_util.h
  134. @@ -337,7 +337,9 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsCompositingManagerPresent();
  135. COMPONENT_EXPORT(UI_BASE_X) bool IsX11WindowFullScreen(x11::Window window);
  136. // Suspends or resumes the X screen saver, and returns whether the operation was
  137. -// successful. Must be called on the UI thread.
  138. +// successful. Must be called on the UI thread. If called multiple times with
  139. +// |suspend| set to true, the screen saver is not un-suspended until this method
  140. +// is called an equal number of times with |suspend| set to false.
  141. COMPONENT_EXPORT(UI_BASE_X) bool SuspendX11ScreenSaver(bool suspend);
  142. // Returns true if the window manager supports the given hint.
  143. diff --git a/ui/display/screen.cc b/ui/display/screen.cc
  144. index b9723889ce..70dc0a9f5c 100644
  145. --- a/ui/display/screen.cc
  146. +++ b/ui/display/screen.cc
  147. @@ -85,26 +85,11 @@ void Screen::SetDisplayForNewWindows(int64_t display_id) {
  148. }
  149. #if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  150. -std::unique_ptr<Screen::ScreenSaverSuspender> Screen::SuspendScreenSaver() {
  151. - SetScreenSaverSuspended(true);
  152. - screen_saver_suspension_count_++;
  153. - return base::WrapUnique(new Screen::ScreenSaverSuspender(this));
  154. -}
  155. -
  156. -Screen::ScreenSaverSuspender::~ScreenSaverSuspender() {
  157. - // Check that this suspender still refers to the active screen. Particularly
  158. - // in tests, the screen might be destructed before the suspender.
  159. - if (screen_ == GetScreen()) {
  160. - screen_->screen_saver_suspension_count_--;
  161. - if (screen_->screen_saver_suspension_count_ == 0) {
  162. - screen_->SetScreenSaverSuspended(false);
  163. - }
  164. - }
  165. -}
  166. +Screen::ScreenSaverSuspender::~ScreenSaverSuspender() = default;
  167. -bool Screen::SetScreenSaverSuspended(bool suspend) {
  168. +std::unique_ptr<Screen::ScreenSaverSuspender> Screen::SuspendScreenSaver() {
  169. NOTIMPLEMENTED_LOG_ONCE();
  170. - return false;
  171. + return nullptr;
  172. }
  173. #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  174. diff --git a/ui/display/screen.h b/ui/display/screen.h
  175. index a86c5b63cc..d04534006f 100644
  176. --- a/ui/display/screen.h
  177. +++ b/ui/display/screen.h
  178. @@ -133,28 +133,22 @@ class DISPLAY_EXPORT Screen {
  179. // its existence.
  180. class ScreenSaverSuspender {
  181. public:
  182. - ScreenSaverSuspender(const Screen&) = delete;
  183. - ScreenSaverSuspender& operator=(const Screen&) = delete;
  184. + ScreenSaverSuspender() = default;
  185. - // Notifies |screen_| that this instance is being destructed, and causes its
  186. - // platform-specific screensaver to be un-suspended if this is the last such
  187. - // remaining instance.
  188. - ~ScreenSaverSuspender();
  189. + ScreenSaverSuspender(const ScreenSaverSuspender&) = delete;
  190. + ScreenSaverSuspender& operator=(const ScreenSaverSuspender&) = delete;
  191. - private:
  192. - friend class Screen;
  193. -
  194. - explicit ScreenSaverSuspender(Screen* screen) : screen_(screen) {}
  195. -
  196. - Screen* screen_;
  197. + // Causes the platform-specific screensaver to be un-suspended iff this is
  198. + // the last remaining instance.
  199. + virtual ~ScreenSaverSuspender() = 0;
  200. };
  201. // Suspends the platform-specific screensaver until the returned
  202. - // |ScreenSaverSuspender| is destructed. This method allows stacking multiple
  203. - // overlapping calls, such that the platform-specific screensaver will not be
  204. - // un-suspended until all returned |SreenSaverSuspender| instances have been
  205. - // destructed.
  206. - std::unique_ptr<ScreenSaverSuspender> SuspendScreenSaver();
  207. + // |ScreenSaverSuspender| is destructed, or returns nullptr if suspension
  208. + // failed. This method allows stacking multiple overlapping calls, such that
  209. + // the platform-specific screensaver will not be un-suspended until all
  210. + // returned |ScreenSaverSuspender| instances have been destructed.
  211. + virtual std::unique_ptr<ScreenSaverSuspender> SuspendScreenSaver();
  212. #endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  213. // Returns whether the screensaver is currently running.
  214. @@ -200,12 +194,6 @@ class DISPLAY_EXPORT Screen {
  215. const gfx::GpuExtraInfo& gpu_extra_info);
  216. protected:
  217. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  218. - // Suspends or un-suspends the platform-specific screensaver, and returns
  219. - // whether the operation was successful.
  220. - virtual bool SetScreenSaverSuspended(bool suspend);
  221. -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX)
  222. -
  223. void set_shutdown(bool shutdown) { shutdown_ = shutdown; }
  224. private:
  225. diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc
  226. index 0c7dc5c02b..18cd81b472 100644
  227. --- a/ui/ozone/platform/wayland/host/wayland_screen.cc
  228. +++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
  229. @@ -327,6 +327,37 @@ display::Display WaylandScreen::GetDisplayMatching(
  230. return display_matching ? *display_matching : GetPrimaryDisplay();
  231. }
  232. +std::unique_ptr<WaylandScreen::WaylandScreenSaverSuspender>
  233. +WaylandScreen::WaylandScreenSaverSuspender::Create(WaylandScreen& screen) {
  234. + auto suspender = base::WrapUnique(new WaylandScreenSaverSuspender(screen));
  235. + if (suspender->is_suspending_) {
  236. + screen.screen_saver_suspension_count_++;
  237. + return suspender;
  238. + }
  239. +
  240. + return nullptr;
  241. +}
  242. +
  243. +WaylandScreen::WaylandScreenSaverSuspender::WaylandScreenSaverSuspender(
  244. + WaylandScreen& screen)
  245. + : screen_(screen.GetWeakPtr()) {
  246. + is_suspending_ = screen.SetScreenSaverSuspended(true);
  247. +}
  248. +
  249. +WaylandScreen::WaylandScreenSaverSuspender::~WaylandScreenSaverSuspender() {
  250. + if (screen_ && is_suspending_) {
  251. + screen_->screen_saver_suspension_count_--;
  252. + if (screen_->screen_saver_suspension_count_ == 0) {
  253. + screen_->SetScreenSaverSuspended(false);
  254. + }
  255. + }
  256. +}
  257. +
  258. +std::unique_ptr<PlatformScreen::PlatformScreenSaverSuspender>
  259. +WaylandScreen::SuspendScreenSaver() {
  260. + return WaylandScreenSaverSuspender::Create(*this);
  261. +}
  262. +
  263. bool WaylandScreen::SetScreenSaverSuspended(bool suspend) {
  264. if (!connection_->zwp_idle_inhibit_manager())
  265. return false;
  266. diff --git a/ui/ozone/platform/wayland/host/wayland_screen.h b/ui/ozone/platform/wayland/host/wayland_screen.h
  267. index 87358f4f06..8e5515104a 100644
  268. --- a/ui/ozone/platform/wayland/host/wayland_screen.h
  269. +++ b/ui/ozone/platform/wayland/host/wayland_screen.h
  270. @@ -68,7 +68,8 @@ class WaylandScreen : public PlatformScreen {
  271. const gfx::Point& point) const override;
  272. display::Display GetDisplayMatching(
  273. const gfx::Rect& match_rect) const override;
  274. - bool SetScreenSaverSuspended(bool suspend) override;
  275. + std::unique_ptr<PlatformScreen::PlatformScreenSaverSuspender>
  276. + SuspendScreenSaver() override;
  277. bool IsScreenSaverActive() const override;
  278. base::TimeDelta CalculateIdleTime() const override;
  279. void AddObserver(display::DisplayObserver* observer) override;
  280. @@ -76,7 +77,33 @@ class WaylandScreen : public PlatformScreen {
  281. std::vector<base::Value> GetGpuExtraInfo(
  282. const gfx::GpuExtraInfo& gpu_extra_info) override;
  283. + protected:
  284. + // Suspends or un-suspends the platform-specific screensaver, and returns
  285. + // whether the operation was successful. Can be called more than once with the
  286. + // same value for |suspend|, but those states should not stack: the first
  287. + // alternating value should toggle the state of the suspend.
  288. + bool SetScreenSaverSuspended(bool suspend);
  289. +
  290. private:
  291. + class WaylandScreenSaverSuspender
  292. + : public PlatformScreen::PlatformScreenSaverSuspender {
  293. + public:
  294. + WaylandScreenSaverSuspender(const WaylandScreenSaverSuspender&) = delete;
  295. + WaylandScreenSaverSuspender& operator=(const WaylandScreenSaverSuspender&) =
  296. + delete;
  297. +
  298. + ~WaylandScreenSaverSuspender() override;
  299. +
  300. + static std::unique_ptr<WaylandScreenSaverSuspender> Create(
  301. + WaylandScreen& screen);
  302. +
  303. + private:
  304. + explicit WaylandScreenSaverSuspender(WaylandScreen& screen);
  305. +
  306. + base::WeakPtr<WaylandScreen> screen_;
  307. + bool is_suspending_ = false;
  308. + };
  309. +
  310. // All parameters are in DIP screen coordinates/units except |physical_size|,
  311. // which is in physical pixels.
  312. void AddOrUpdateDisplay(uint32_t output_id,
  313. @@ -103,6 +130,7 @@ class WaylandScreen : public PlatformScreen {
  314. #endif
  315. wl::Object<zwp_idle_inhibitor_v1> idle_inhibitor_;
  316. + uint32_t screen_saver_suspension_count_ = 0;
  317. base::WeakPtrFactory<WaylandScreen> weak_factory_;
  318. };
  319. diff --git a/ui/ozone/platform/x11/x11_screen_ozone.cc b/ui/ozone/platform/x11/x11_screen_ozone.cc
  320. index 53265ab58a..b450df9c83 100644
  321. --- a/ui/ozone/platform/x11/x11_screen_ozone.cc
  322. +++ b/ui/ozone/platform/x11/x11_screen_ozone.cc
  323. @@ -4,6 +4,8 @@
  324. #include "ui/ozone/platform/x11/x11_screen_ozone.h"
  325. +#include <memory>
  326. +
  327. #include "base/containers/flat_set.h"
  328. #include "ui/base/linux/linux_desktop.h"
  329. #include "ui/base/x/x11_idle_query.h"
  330. @@ -131,8 +133,29 @@ display::Display X11ScreenOzone::GetDisplayMatching(
  331. return matching_display ? *matching_display : GetPrimaryDisplay();
  332. }
  333. -bool X11ScreenOzone::SetScreenSaverSuspended(bool suspend) {
  334. - return SuspendX11ScreenSaver(suspend);
  335. +X11ScreenOzone::X11ScreenSaverSuspender::X11ScreenSaverSuspender() {
  336. + is_suspending_ = SuspendX11ScreenSaver(true);
  337. +}
  338. +
  339. +std::unique_ptr<X11ScreenOzone::X11ScreenSaverSuspender>
  340. +X11ScreenOzone::X11ScreenSaverSuspender::Create() {
  341. + auto suspender = base::WrapUnique(new X11ScreenSaverSuspender());
  342. + if (suspender->is_suspending_) {
  343. + return suspender;
  344. + }
  345. +
  346. + return nullptr;
  347. +}
  348. +
  349. +X11ScreenOzone::X11ScreenSaverSuspender::~X11ScreenSaverSuspender() {
  350. + if (is_suspending_) {
  351. + SuspendX11ScreenSaver(false);
  352. + }
  353. +}
  354. +
  355. +std::unique_ptr<PlatformScreen::PlatformScreenSaverSuspender>
  356. +X11ScreenOzone::SuspendScreenSaver() {
  357. + return X11ScreenSaverSuspender::Create();
  358. }
  359. bool X11ScreenOzone::IsScreenSaverActive() const {
  360. diff --git a/ui/ozone/platform/x11/x11_screen_ozone.h b/ui/ozone/platform/x11/x11_screen_ozone.h
  361. index d86acae9aa..81e0fd13d8 100644
  362. --- a/ui/ozone/platform/x11/x11_screen_ozone.h
  363. +++ b/ui/ozone/platform/x11/x11_screen_ozone.h
  364. @@ -50,7 +50,8 @@ class X11ScreenOzone : public PlatformScreen,
  365. const gfx::Point& point) const override;
  366. display::Display GetDisplayMatching(
  367. const gfx::Rect& match_rect) const override;
  368. - bool SetScreenSaverSuspended(bool suspend) override;
  369. + std::unique_ptr<PlatformScreen::PlatformScreenSaverSuspender>
  370. + SuspendScreenSaver() override;
  371. bool IsScreenSaverActive() const override;
  372. base::TimeDelta CalculateIdleTime() const override;
  373. void AddObserver(display::DisplayObserver* observer) override;
  374. @@ -66,6 +67,22 @@ class X11ScreenOzone : public PlatformScreen,
  375. private:
  376. friend class X11ScreenOzoneTest;
  377. + class X11ScreenSaverSuspender
  378. + : public PlatformScreen::PlatformScreenSaverSuspender {
  379. + public:
  380. + X11ScreenSaverSuspender(const X11ScreenSaverSuspender&) = delete;
  381. + X11ScreenSaverSuspender& operator=(const X11ScreenSaverSuspender&) = delete;
  382. +
  383. + ~X11ScreenSaverSuspender() override;
  384. +
  385. + static std::unique_ptr<X11ScreenSaverSuspender> Create();
  386. +
  387. + private:
  388. + X11ScreenSaverSuspender();
  389. +
  390. + bool is_suspending_ = false;
  391. + };
  392. +
  393. // Overridden from ui::XDisplayManager::Delegate:
  394. void OnXDisplayListUpdated() override;
  395. float GetXDisplayScaleFactor() const override;
  396. diff --git a/ui/ozone/public/platform_screen.cc b/ui/ozone/public/platform_screen.cc
  397. index 98f599aa41..2353208396 100644
  398. --- a/ui/ozone/public/platform_screen.cc
  399. +++ b/ui/ozone/public/platform_screen.cc
  400. @@ -30,9 +30,13 @@ std::string PlatformScreen::GetCurrentWorkspace() {
  401. return {};
  402. }
  403. -bool PlatformScreen::SetScreenSaverSuspended(bool suspend) {
  404. +PlatformScreen::PlatformScreenSaverSuspender::~PlatformScreenSaverSuspender() =
  405. + default;
  406. +
  407. +std::unique_ptr<PlatformScreen::PlatformScreenSaverSuspender>
  408. +PlatformScreen::SuspendScreenSaver() {
  409. NOTIMPLEMENTED_LOG_ONCE();
  410. - return false;
  411. + return nullptr;
  412. }
  413. bool PlatformScreen::IsScreenSaverActive() const {
  414. diff --git a/ui/ozone/public/platform_screen.h b/ui/ozone/public/platform_screen.h
  415. index 091220a99f..e4adfafce3 100644
  416. --- a/ui/ozone/public/platform_screen.h
  417. +++ b/ui/ozone/public/platform_screen.h
  418. @@ -89,11 +89,27 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformScreen {
  419. virtual display::Display GetDisplayMatching(
  420. const gfx::Rect& match_rect) const = 0;
  421. - // Suspends or un-suspends the platform-specific screensaver, and returns
  422. - // whether the operation was successful. Can be called more than once with the
  423. - // same value for |suspend|, but those states should not stack: the first
  424. - // alternating value should toggle the state of the suspend.
  425. - virtual bool SetScreenSaverSuspended(bool suspend);
  426. + // Object which suspends the platform-specific screensaver for the duration of
  427. + // its existence.
  428. + class PlatformScreenSaverSuspender {
  429. + public:
  430. + PlatformScreenSaverSuspender() = default;
  431. +
  432. + PlatformScreenSaverSuspender(const PlatformScreenSaverSuspender&) = delete;
  433. + PlatformScreenSaverSuspender& operator=(
  434. + const PlatformScreenSaverSuspender&) = delete;
  435. +
  436. + // Causes the platform-specific screensaver to be un-suspended iff this is
  437. + // the last remaining instance.
  438. + virtual ~PlatformScreenSaverSuspender() = 0;
  439. + };
  440. +
  441. + // Suspends the platform-specific screensaver until the returned
  442. + // |PlatformScreenSaverSuspender| is destructed, or returns nullptr if
  443. + // suspension failed. This method allows stacking multiple overlapping calls,
  444. + // such that the platform-specific screensaver will not be un-suspended until
  445. + // all returned |PlatformScreenSaverSuspender| instances have been destructed.
  446. + virtual std::unique_ptr<PlatformScreenSaverSuspender> SuspendScreenSaver();
  447. // Returns whether the screensaver is currently running.
  448. virtual bool IsScreenSaverActive() const;