1 // Copyright 2013 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.
5 #include "content/browser/theme_helper_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #include "base/command_line.h"
10 #include "base/mac/mac_util.h"
11 #include "base/mac/sdk_forward_declarations.h"
12 #include "content/common/view_messages.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/notification_service.h"
15 #include "content/public/browser/notification_types.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/common/content_switches.h"
20 bool GetScrollAnimationEnabled() {
23 if (base::mac::IsOSMountainLionOrLater()) {
24 value = [[NSUserDefaults standardUserDefaults]
25 objectForKey:@"NSScrollAnimationEnabled"];
27 value = [[NSUserDefaults standardUserDefaults]
28 objectForKey:@"AppleScrollAnimationEnabled"];
31 enabled = [value boolValue];
35 blink::ScrollbarButtonsPlacement GetButtonPlacement() {
36 NSString* scrollbar_variant = [[NSUserDefaults standardUserDefaults]
37 objectForKey:@"AppleScrollBarVariant"];
38 if ([scrollbar_variant isEqualToString:@"Single"])
39 return blink::ScrollbarButtonsPlacementSingle;
40 else if ([scrollbar_variant isEqualToString:@"DoubleMin"])
41 return blink::ScrollbarButtonsPlacementDoubleStart;
42 else if ([scrollbar_variant isEqualToString:@"DoubleBoth"])
43 return blink::ScrollbarButtonsPlacementDoubleBoth;
45 return blink::ScrollbarButtonsPlacementDoubleEnd;
49 @interface ScrollbarPrefsObserver : NSObject
51 + (void)registerAsObserver;
52 + (void)appearancePrefsChanged:(NSNotification*)notification;
53 + (void)behaviorPrefsChanged:(NSNotification*)notification;
54 + (void)notifyPrefsChangedWithRedraw:(BOOL)redraw;
58 @implementation ScrollbarPrefsObserver
60 + (void)registerAsObserver {
61 [[NSDistributedNotificationCenter defaultCenter]
63 selector:@selector(appearancePrefsChanged:)
64 name:@"AppleAquaScrollBarVariantChanged"
66 suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
68 [[NSDistributedNotificationCenter defaultCenter]
70 selector:@selector(behaviorPrefsChanged:)
71 name:@"AppleNoRedisplayAppearancePreferenceChanged"
73 suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
75 if (base::mac::IsOSMountainLionOrLater()) {
76 [[NSDistributedNotificationCenter defaultCenter]
78 selector:@selector(behaviorPrefsChanged:)
79 name:@"NSScrollAnimationEnabled"
81 suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
83 // Register for < 10.8
84 [[NSDistributedNotificationCenter defaultCenter]
86 selector:@selector(behaviorPrefsChanged:)
87 name:@"AppleScrollAnimationEnabled"
89 suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
92 [[NSDistributedNotificationCenter defaultCenter]
94 selector:@selector(appearancePrefsChanged:)
95 name:@"AppleScrollBarVariant"
97 suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
99 // In single-process mode, renderers will catch these notifications
100 // themselves and listening for them here may trigger the DCHECK in Observe().
101 if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] &&
102 !base::CommandLine::ForCurrentProcess()->HasSwitch(
103 switches::kSingleProcess)) {
104 [[NSNotificationCenter defaultCenter]
106 selector:@selector(behaviorPrefsChanged:)
107 name:NSPreferredScrollerStyleDidChangeNotification
112 + (void)appearancePrefsChanged:(NSNotification*)notification {
113 [self notifyPrefsChangedWithRedraw:YES];
116 + (void)behaviorPrefsChanged:(NSNotification*)notification {
117 [self notifyPrefsChangedWithRedraw:NO];
120 + (void)notifyPrefsChangedWithRedraw:(BOOL)redraw {
121 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
122 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
123 [defaults synchronize];
125 content::ThemeHelperMac::SendThemeChangeToAllRenderers(
126 [defaults floatForKey:@"NSScrollerButtonDelay"],
127 [defaults floatForKey:@"NSScrollerButtonPeriod"],
128 [defaults boolForKey:@"AppleScrollerPagingBehavior"],
129 content::ThemeHelperMac::GetPreferredScrollerStyle(), redraw,
130 GetScrollAnimationEnabled(), GetButtonPlacement());
138 ThemeHelperMac* ThemeHelperMac::GetInstance() {
139 return Singleton<ThemeHelperMac,
140 LeakySingletonTraits<ThemeHelperMac> >::get();
144 blink::ScrollerStyle ThemeHelperMac::GetPreferredScrollerStyle() {
145 if (![NSScroller respondsToSelector:@selector(preferredScrollerStyle)])
146 return blink::ScrollerStyleLegacy;
147 return static_cast<blink::ScrollerStyle>([NSScroller preferredScrollerStyle]);
151 void ThemeHelperMac::SendThemeChangeToAllRenderers(
152 float initial_button_delay,
153 float autoscroll_button_delay,
154 bool jump_on_track_click,
155 blink::ScrollerStyle preferred_scroller_style,
157 bool scroll_animation_enabled,
158 blink::ScrollbarButtonsPlacement button_placement) {
159 ViewMsg_UpdateScrollbarTheme_Params params;
160 params.initial_button_delay = initial_button_delay;
161 params.autoscroll_button_delay = autoscroll_button_delay;
162 params.jump_on_track_click = jump_on_track_click;
163 params.preferred_scroller_style = preferred_scroller_style;
164 params.redraw = redraw;
165 params.scroll_animation_enabled = scroll_animation_enabled;
166 params.button_placement = button_placement;
168 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
171 it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme(params));
175 ThemeHelperMac::ThemeHelperMac() {
176 [ScrollbarPrefsObserver registerAsObserver];
178 NOTIFICATION_RENDERER_PROCESS_CREATED,
179 NotificationService::AllSources());
182 ThemeHelperMac::~ThemeHelperMac() {
185 void ThemeHelperMac::Observe(int type,
186 const NotificationSource& source,
187 const NotificationDetails& details) {
188 DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
190 DCHECK_CURRENTLY_ON(BrowserThread::UI);
191 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
192 [defaults synchronize];
194 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
196 ViewMsg_UpdateScrollbarTheme_Params params;
197 params.initial_button_delay = [defaults floatForKey:@"NSScrollerButtonDelay"];
198 params.autoscroll_button_delay =
199 [defaults floatForKey:@"NSScrollerButtonPeriod"];
200 params.jump_on_track_click =
201 [defaults boolForKey:@"AppleScrollerPagingBehavior"];
202 params.preferred_scroller_style = GetPreferredScrollerStyle();
203 params.redraw = false;
204 params.scroll_animation_enabled = GetScrollAnimationEnabled();
205 params.button_placement = GetButtonPlacement();
207 rph->Send(new ViewMsg_UpdateScrollbarTheme(params));
210 } // namespace content