1 // Copyright (c) 2012 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 #import <Cocoa/Cocoa.h> 6 7 #include "base/compiler_specific.h" 8 #include "base/logging.h" 9 #include "base/mac/scoped_nsautorelease_pool.h" 10 #include "base/mac/scoped_nsobject.h" 11 #include "base/strings/sys_string_conversions.h" 12 #include "remoting/base/string_resources.h" 13 #include "remoting/host/continue_window.h" 14 #include "ui/base/l10n/l10n_util_mac.h" 15 16 // Handles the ContinueWindow. 17 @interface ContinueWindowMacController : NSObject { 18 @private 19 base::scoped_nsobject<NSMutableArray> shades_; 20 base::scoped_nsobject<NSAlert> continue_alert_; 21 remoting::ContinueWindow* continue_window_; 22 } 23 24 - (id)initWithWindow:(remoting::ContinueWindow*)continue_window; 25 - (void)show; 26 - (void)hide; 27 - (void)onCancel:(id)sender; 28 - (void)onContinue:(id)sender; 29 @end 30 31 namespace remoting { 32 33 // A bridge between C++ and ObjC implementations of ContinueWindow. 34 // Everything important occurs in ContinueWindowMacController. 35 class ContinueWindowMac : public ContinueWindow { 36 public: 37 ContinueWindowMac(); 38 virtual ~ContinueWindowMac(); 39 40 protected: 41 // ContinueWindow overrides. 42 virtual void ShowUi() OVERRIDE; 43 virtual void HideUi() OVERRIDE; 44 45 private: 46 base::scoped_nsobject<ContinueWindowMacController> controller_; 47 48 DISALLOW_COPY_AND_ASSIGN(ContinueWindowMac); 49 }; 50 51 ContinueWindowMac::ContinueWindowMac() { 52 } 53 54 ContinueWindowMac::~ContinueWindowMac() { 55 DCHECK(CalledOnValidThread()); 56 } 57 58 void ContinueWindowMac::ShowUi() { 59 DCHECK(CalledOnValidThread()); 60 61 base::mac::ScopedNSAutoreleasePool pool; 62 controller_.reset( 63 [[ContinueWindowMacController alloc] initWithWindow:this]); 64 [controller_ show]; 65 } 66 67 void ContinueWindowMac::HideUi() { 68 DCHECK(CalledOnValidThread()); 69 70 base::mac::ScopedNSAutoreleasePool pool; 71 [controller_ hide]; 72 } 73 74 // static 75 scoped_ptr<HostWindow> HostWindow::CreateContinueWindow() { 76 return scoped_ptr<HostWindow>(new ContinueWindowMac()); 77 } 78 79 } // namespace remoting 80 81 @implementation ContinueWindowMacController 82 83 - (id)initWithWindow:(remoting::ContinueWindow*)continue_window { 84 if ((self = [super init])) { 85 continue_window_ = continue_window; 86 } 87 return self; 88 } 89 90 - (void)show { 91 // Generate window shade 92 NSArray* screens = [NSScreen screens]; 93 shades_.reset([[NSMutableArray alloc] initWithCapacity:[screens count]]); 94 for (NSScreen *screen in screens) { 95 NSWindow* shade = 96 [[[NSWindow alloc] initWithContentRect:[screen frame] 97 styleMask:NSBorderlessWindowMask 98 backing:NSBackingStoreBuffered 99 defer:NO 100 screen:screen] autorelease]; 101 [shade setReleasedWhenClosed:NO]; 102 [shade setAlphaValue:0.8]; 103 [shade setOpaque:NO]; 104 [shade setBackgroundColor:[NSColor blackColor]]; 105 // Raise the window shade above just about everything else. 106 // Leave the dock and menu bar exposed so the user has some basic level 107 // of control (like they can quit Chromium). 108 [shade setLevel:NSModalPanelWindowLevel - 1]; 109 [shade orderFront:nil]; 110 [shades_ addObject:shade]; 111 } 112 113 // Create alert. 114 continue_alert_.reset([[NSAlert alloc] init]); 115 [continue_alert_ setMessageText:l10n_util::GetNSString(IDS_CONTINUE_PROMPT)]; 116 117 NSButton* continue_button = 118 [continue_alert_ addButtonWithTitle:l10n_util::GetNSString( 119 IDS_CONTINUE_BUTTON)]; 120 [continue_button setAction:@selector(onContinue:)]; 121 [continue_button setTarget:self]; 122 123 NSButton* cancel_button = 124 [continue_alert_ addButtonWithTitle:l10n_util::GetNSString( 125 IDS_STOP_SHARING_BUTTON)]; 126 [cancel_button setAction:@selector(onCancel:)]; 127 [cancel_button setTarget:self]; 128 129 NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 130 NSString *imagePath = [bundle pathForResource:@"chromoting128" ofType:@"png"]; 131 base::scoped_nsobject<NSImage> image( 132 [[NSImage alloc] initByReferencingFile:imagePath]); 133 [continue_alert_ setIcon:image]; 134 [continue_alert_ layout]; 135 136 // Force alert to be at the proper level and location. 137 NSWindow* continue_window = [continue_alert_ window]; 138 [continue_window center]; 139 [continue_window setLevel:NSModalPanelWindowLevel]; 140 [continue_window orderWindow:NSWindowAbove 141 relativeTo:[[shades_ lastObject] windowNumber]]; 142 [continue_window makeKeyWindow]; 143 } 144 145 - (void)hide { 146 // Remove window shade. 147 for (NSWindow* window in shades_.get()) { 148 [window close]; 149 } 150 shades_.reset(); 151 continue_alert_.reset(); 152 } 153 154 - (void)onCancel:(id)sender { 155 [self hide]; 156 continue_window_->DisconnectSession(); 157 } 158 159 - (void)onContinue:(id)sender { 160 [self hide]; 161 continue_window_->ContinueSession(); 162 } 163 164 @end 165