scoped_preferred_scroller_style_mac.mm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2016 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. #import "ui/base/test/scoped_preferred_scroller_style_mac.h"
  5. #import <AppKit/AppKit.h>
  6. #include "base/check.h"
  7. #import "base/mac/scoped_objc_class_swizzler.h"
  8. using base::mac::ScopedObjCClassSwizzler;
  9. namespace {
  10. // Swizzling can be stacked, but not interleaved without creating unexpected
  11. // states. Require that there is only one swizzler rather than tracking a stack.
  12. bool g_swizzling = false;
  13. void NotifyStyleChanged() {
  14. [[NSNotificationCenter defaultCenter]
  15. postNotificationName:NSPreferredScrollerStyleDidChangeNotification
  16. object:nil];
  17. }
  18. NSScrollerStyle GetScrollerStyle(bool overlay) {
  19. return overlay ? NSScrollerStyleOverlay : NSScrollerStyleLegacy;
  20. }
  21. } // namespace
  22. // Donates a testing implementation of +[NSScroller preferredScrollerStyle] by
  23. // returning NSScrollerStyleLegacy.
  24. @interface FakeNSScrollerPreferredStyleLegacyDonor : NSObject
  25. @end
  26. @implementation FakeNSScrollerPreferredStyleLegacyDonor
  27. + (NSInteger)preferredScrollerStyle {
  28. return NSScrollerStyleLegacy;
  29. }
  30. @end
  31. // Donates a testing implementation of +[NSScroller preferredScrollerStyle] by
  32. // returning NSScrollerStyleOverlay.
  33. @interface FakeNSScrollerPreferredStyleOverlayDonor : NSObject
  34. @end
  35. @implementation FakeNSScrollerPreferredStyleOverlayDonor
  36. + (NSInteger)preferredScrollerStyle {
  37. return NSScrollerStyleOverlay;
  38. }
  39. @end
  40. namespace ui {
  41. namespace test {
  42. ScopedPreferredScrollerStyle::ScopedPreferredScrollerStyle(bool overlay)
  43. : overlay_(overlay) {
  44. NSInteger previous_style = [NSScroller preferredScrollerStyle];
  45. Class style_class = overlay_
  46. ? [FakeNSScrollerPreferredStyleOverlayDonor class]
  47. : [FakeNSScrollerPreferredStyleLegacyDonor class];
  48. DCHECK(!g_swizzling);
  49. g_swizzling = true;
  50. swizzler_ = std::make_unique<ScopedObjCClassSwizzler>(
  51. [NSScroller class], style_class, @selector(preferredScrollerStyle));
  52. if (previous_style != GetScrollerStyle(overlay_))
  53. NotifyStyleChanged();
  54. }
  55. ScopedPreferredScrollerStyle::~ScopedPreferredScrollerStyle() {
  56. swizzler_.reset();
  57. DCHECK(g_swizzling);
  58. g_swizzling = false;
  59. if ([NSScroller preferredScrollerStyle] != GetScrollerStyle(overlay_))
  60. NotifyStyleChanged();
  61. }
  62. } // namespace test
  63. } // namespace ui