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
31namespace remoting {
32
33// A bridge between C++ and ObjC implementations of ContinueWindow.
34// Everything important occurs in ContinueWindowMacController.
35class 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
51ContinueWindowMac::ContinueWindowMac() {
52}
53
54ContinueWindowMac::~ContinueWindowMac() {
55  DCHECK(CalledOnValidThread());
56}
57
58void ContinueWindowMac::ShowUi() {
59  DCHECK(CalledOnValidThread());
60
61  base::mac::ScopedNSAutoreleasePool pool;
62  controller_.reset(
63      [[ContinueWindowMacController alloc] initWithWindow:this]);
64  [controller_ show];
65}
66
67void ContinueWindowMac::HideUi() {
68  DCHECK(CalledOnValidThread());
69
70  base::mac::ScopedNSAutoreleasePool pool;
71  [controller_ hide];
72}
73
74// static
75scoped_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(IDR_CONTINUE_PROMPT)];
116
117  NSButton* continue_button =
118      [continue_alert_ addButtonWithTitle:l10n_util::GetNSString(
119          IDR_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          IDR_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