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. 4 5 #include "content/browser/theme_helper_mac.h" 6 7 #import <Cocoa/Cocoa.h> 8 9 #include "base/command_line.h" 10 #include "base/mac/sdk_forward_declarations.h" 11 #include "content/common/view_messages.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/notification_service.h" 14 #include "content/public/browser/notification_types.h" 15 #include "content/public/browser/render_process_host.h" 16 #include "content/public/common/content_switches.h" 17 18 // Declare notification names from the 10.7 SDK. 19 #if !defined(MAC_OS_X_VERSION_10_7) || \ 20 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 21 22 NSString* NSPreferredScrollerStyleDidChangeNotification = 23 @"NSPreferredScrollerStyleDidChangeNotification"; 24 25 #endif 26 27 @interface ScrollbarPrefsObserver : NSObject 28 29 + (void)registerAsObserver; 30 + (void)appearancePrefsChanged:(NSNotification*)notification; 31 + (void)behaviorPrefsChanged:(NSNotification*)notification; 32 + (void)notifyPrefsChangedWithRedraw:(BOOL)redraw; 33 34 @end 35 36 @implementation ScrollbarPrefsObserver 37 38 + (void)registerAsObserver { 39 [[NSDistributedNotificationCenter defaultCenter] 40 addObserver:self 41 selector:@selector(appearancePrefsChanged:) 42 name:@"AppleAquaScrollBarVariantChanged" 43 object:nil 44 suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; 45 46 [[NSDistributedNotificationCenter defaultCenter] 47 addObserver:self 48 selector:@selector(behaviorPrefsChanged:) 49 name:@"AppleNoRedisplayAppearancePreferenceChanged" 50 object:nil 51 suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce]; 52 53 // In single-process mode, renderers will catch these notifications 54 // themselves and listening for them here may trigger the DCHECK in Observe(). 55 if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] && 56 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { 57 [[NSNotificationCenter defaultCenter] 58 addObserver:self 59 selector:@selector(behaviorPrefsChanged:) 60 name:NSPreferredScrollerStyleDidChangeNotification 61 object:nil]; 62 } 63 } 64 65 + (void)appearancePrefsChanged:(NSNotification*)notification { 66 [self notifyPrefsChangedWithRedraw:YES]; 67 } 68 69 + (void)behaviorPrefsChanged:(NSNotification*)notification { 70 [self notifyPrefsChangedWithRedraw:NO]; 71 } 72 73 + (void)notifyPrefsChangedWithRedraw:(BOOL)redraw { 74 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 75 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 76 [defaults synchronize]; 77 78 content::ThemeHelperMac::SendThemeChangeToAllRenderers( 79 [defaults floatForKey:@"NSScrollerButtonDelay"], 80 [defaults floatForKey:@"NSScrollerButtonPeriod"], 81 [defaults boolForKey:@"AppleScrollerPagingBehavior"], 82 content::ThemeHelperMac::GetPreferredScrollerStyle(), 83 redraw); 84 } 85 86 @end 87 88 namespace content { 89 90 // static 91 ThemeHelperMac* ThemeHelperMac::GetInstance() { 92 return Singleton<ThemeHelperMac, 93 LeakySingletonTraits<ThemeHelperMac> >::get(); 94 } 95 96 // static 97 blink::ScrollerStyle ThemeHelperMac::GetPreferredScrollerStyle() { 98 if (![NSScroller respondsToSelector:@selector(preferredScrollerStyle)]) 99 return blink::ScrollerStyleLegacy; 100 return static_cast<blink::ScrollerStyle>([NSScroller preferredScrollerStyle]); 101 } 102 103 // static 104 void ThemeHelperMac::SendThemeChangeToAllRenderers( 105 float initial_button_delay, 106 float autoscroll_button_delay, 107 bool jump_on_track_click, 108 blink::ScrollerStyle preferred_scroller_style, 109 bool redraw) { 110 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 111 !it.IsAtEnd(); 112 it.Advance()) { 113 it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme( 114 initial_button_delay, 115 autoscroll_button_delay, 116 jump_on_track_click, 117 preferred_scroller_style, 118 redraw)); 119 } 120 } 121 122 ThemeHelperMac::ThemeHelperMac() { 123 [ScrollbarPrefsObserver registerAsObserver]; 124 registrar_.Add(this, 125 NOTIFICATION_RENDERER_PROCESS_CREATED, 126 NotificationService::AllSources()); 127 } 128 129 ThemeHelperMac::~ThemeHelperMac() { 130 } 131 132 void ThemeHelperMac::Observe(int type, 133 const NotificationSource& source, 134 const NotificationDetails& details) { 135 DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type); 136 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 138 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 139 [defaults synchronize]; 140 141 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr(); 142 rph->Send(new ViewMsg_UpdateScrollbarTheme( 143 [defaults floatForKey:@"NSScrollerButtonDelay"], 144 [defaults floatForKey:@"NSScrollerButtonPeriod"], 145 [defaults boolForKey:@"AppleScrollerPagingBehavior"], 146 GetPreferredScrollerStyle(), 147 false)); 148 } 149 150 } // namespace content 151