1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/screen_capture_notification_ui.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/shell.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/app/chrome_dll_resource.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/views/chrome_views_export.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "grit/theme_resources.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/hit_test.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/l10n/l10n_util.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/resource/resource_bundle.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/bubble/bubble_border.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/bubble/bubble_frame_view.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/controls/button/blue_button.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/controls/image_view.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/views/controls/link.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/views/controls/link_listener.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/view.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/widget/widget.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/widget/widget_delegate.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/shadow_types.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_WIN)
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/views/win/hwnd_util.h"
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kMinimumWidth = 460;
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kMaximumWidth = 1000;
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kHorizontalMargin = 10;
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst float kWindowAlphaValue = 0.85f;
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst int kPaddingVertical = 5;
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst int kPaddingHorizontal = 10;
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A ClientView that overrides NonClientHitTest() so that the whole window area
43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// acts as a window caption, except a rect specified using set_client_rect().
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ScreenCaptureNotificationUIViews uses this class to make the notification bar
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// draggable.
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass NotificationBarClientView : public views::ClientView {
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotificationBarClientView(views::Widget* widget, views::View* view)
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : views::ClientView(widget, view) {
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~NotificationBarClientView() {}
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void set_client_rect(const gfx::Rect& rect) { rect_ = rect; }
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // views::ClientView overrides.
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE  {
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!bounds().Contains(point))
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return HTNOWHERE;
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // The whole window is HTCAPTION, except the |rect_|.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (rect_.Contains(gfx::PointAtOffsetFromOrigin(point - bounds().origin())))
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return HTCLIENT;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return HTCAPTION;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect rect_;
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(NotificationBarClientView);
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ScreenCaptureNotificationUI implementation using Views.
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass ScreenCaptureNotificationUIViews
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : public ScreenCaptureNotificationUI,
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      public views::WidgetDelegateView,
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      public views::ButtonListener,
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      public views::LinkListener {
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit ScreenCaptureNotificationUIViews(const base::string16& text);
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~ScreenCaptureNotificationUIViews();
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // ScreenCaptureNotificationUI interface.
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      OVERRIDE;
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // views::View overrides.
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE;
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void Layout() OVERRIDE;
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // views::WidgetDelegateView overrides.
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void DeleteDelegate() OVERRIDE;
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual views::View* GetContentsView() OVERRIDE;
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual views::NonClientFrameView* CreateNonClientFrameView(
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      views::Widget* widget) OVERRIDE;
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetWindowTitle() const OVERRIDE;
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual bool ShouldShowWindowTitle() const OVERRIDE;
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual bool ShouldShowCloseButton() const OVERRIDE;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool CanActivate() const OVERRIDE;
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // views::ButtonListener interface.
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void ButtonPressed(views::Button* sender,
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             const ui::Event& event) OVERRIDE;
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // views::LinkListener interface.
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Helper to call |stop_callback_|.
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void NotifyStopped();
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const base::string16 text_;
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::Closure stop_callback_;
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotificationBarClientView* client_view_;
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::ImageView* gripper_;
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::Label* label_;
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::BlueButton* stop_button_;
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  views::Link* hide_link_;
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ScreenCaptureNotificationUIViews);
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochScreenCaptureNotificationUIViews::ScreenCaptureNotificationUIViews(
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& text)
1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : text_(text),
1283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      client_view_(NULL),
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      gripper_(NULL),
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_(NULL),
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stop_button_(NULL),
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      hide_link_(NULL) {
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  set_owned_by_client();
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gripper_ = new views::ImageView();
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gripper_->SetImage(
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP));
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddChildView(gripper_);
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_ = new views::Label();
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddChildView(label_);
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 stop_text =
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      l10n_util::GetStringUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP);
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stop_button_ = new views::BlueButton(this, stop_text);
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddChildView(stop_button_);
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(jiayl): IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON is used for the need to
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // merge to M34. Change it to a new IDS_ after the merge.
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  hide_link_ = new views::Link(
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  hide_link_->set_listener(this);
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  hide_link_->SetUnderline(false);
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddChildView(hide_link_);
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochScreenCaptureNotificationUIViews::~ScreenCaptureNotificationUIViews() {
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stop_callback_.Reset();
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete GetWidget();
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochgfx::NativeViewId ScreenCaptureNotificationUIViews::OnStarted(
1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const base::Closure& stop_callback) {
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stop_callback_ = stop_callback;
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  label_->SetElideBehavior(gfx::ELIDE_MIDDLE);
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  label_->SetText(text_);
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::Widget* widget = new views::Widget;
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.delegate = this;
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.remove_standard_frame = true;
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.keep_on_top = true;
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(sergeyu): The notification bar must be shown on the monitor that's
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // being captured. Make sure it's always the case. Currently we always capture
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the primary monitor.
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (ash::Shell::HasInstance())
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    params.context = ash::Shell::GetPrimaryRootWindow();
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  widget->Init(params);
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  widget->SetAlwaysOnTop(true);
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Screen* screen = gfx::Screen::GetNativeScreen();
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(sergeyu): Move the notification to the display being captured when
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // per-display screen capture is supported.
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Place the bar in the center of the bottom of the display.
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Size size = widget->non_client_view()->GetPreferredSize();
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect bounds(
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      work_area.x() + work_area.width() / 2 - size.width() / 2,
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      work_area.y() + work_area.height() - size.height(),
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size.width(), size.height());
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  widget->SetBounds(bounds);
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  widget->Show();
2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // This has to be called after Show() to have effect.
2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  widget->SetOpacity(0xFF * kWindowAlphaValue);
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(OS_WIN)
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return gfx::NativeViewId(views::HWNDForWidget(widget));
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#else
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return 0;
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ScreenCaptureNotificationUIViews::GetPreferredSize() const {
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Size grip_size = gripper_->GetPreferredSize();
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size label_size = label_->GetPreferredSize();
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size stop_button_size = stop_button_->GetPreferredSize();
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size hide_link_size = hide_link_->GetPreferredSize();
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int width = kHorizontalMargin * 3 + grip_size.width() + label_size.width() +
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stop_button_size.width() + hide_link_size.width();
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  width = std::max(width, kMinimumWidth);
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  width = std::min(width, kMaximumWidth);
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return gfx::Size(width, std::max(label_size.height(),
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   std::max(hide_link_size.height(),
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                            stop_button_size.height())));
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ScreenCaptureNotificationUIViews::Layout() {
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect grip_rect(gripper_->GetPreferredSize());
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  grip_rect.set_y((bounds().height() - grip_rect.height()) / 2);
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gripper_->SetBoundsRect(grip_rect);
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect stop_button_rect(stop_button_->GetPreferredSize());
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect hide_link_rect(hide_link_->GetPreferredSize());
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  hide_link_rect.set_x(bounds().width() - hide_link_rect.width());
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  hide_link_rect.set_y((bounds().height() - hide_link_rect.height()) / 2);
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  hide_link_->SetBoundsRect(hide_link_rect);
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  stop_button_rect.set_x(
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      hide_link_rect.x() - kHorizontalMargin - stop_button_rect.width());
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  stop_button_->SetBoundsRect(stop_button_rect);
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect label_rect;
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_rect.set_x(grip_rect.right() + kHorizontalMargin);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  label_rect.set_width(
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stop_button_rect.x() - kHorizontalMargin - label_rect.x());
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_rect.set_height(bounds().height());
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_->SetBoundsRect(label_rect);
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  client_view_->set_client_rect(gfx::Rect(
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stop_button_rect.x(), stop_button_rect.y(),
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stop_button_rect.width() + kHorizontalMargin + hide_link_rect.width(),
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      std::max(stop_button_rect.height(), hide_link_rect.height())));
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ScreenCaptureNotificationUIViews::DeleteDelegate() {
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotifyStopped();
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochviews::View* ScreenCaptureNotificationUIViews::GetContentsView() {
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return this;
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochviews::ClientView* ScreenCaptureNotificationUIViews::CreateClientView(
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    views::Widget* widget) {
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!client_view_);
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  client_view_ = new NotificationBarClientView(widget, this);
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return client_view_;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochviews::NonClientFrameView*
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochScreenCaptureNotificationUIViews::CreateNonClientFrameView(
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    views::Widget* widget) {
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::BubbleFrameView* frame = new views::BubbleFrameView(
278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      gfx::Insets(kPaddingVertical,
279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                  kPaddingHorizontal,
280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                  kPaddingVertical,
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                  kPaddingHorizontal));
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkColor color = widget->GetNativeTheme()->GetSystemColor(
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ui::NativeTheme::kColorId_DialogBackground);
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new views::BubbleBorder(views::BubbleBorder::NONE,
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              views::BubbleBorder::SMALL_SHADOW,
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              color)));
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return frame;
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 ScreenCaptureNotificationUIViews::GetWindowTitle() const {
2923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return text_;
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ScreenCaptureNotificationUIViews::ShouldShowWindowTitle() const {
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ScreenCaptureNotificationUIViews::ShouldShowCloseButton() const {
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ScreenCaptureNotificationUIViews::CanActivate() const {
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // When the window is visible, it can be activated so the mouse clicks
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // can be sent to the window; when the window is minimized, we don't want it
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to activate, otherwise it sometimes does not show properly on Windows.
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetWidget() && GetWidget()->IsVisible();
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ScreenCaptureNotificationUIViews::ButtonPressed(views::Button* sender,
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                     const ui::Event& event) {
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotifyStopped();
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ScreenCaptureNotificationUIViews::LinkClicked(views::Link* source,
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   int event_flags) {
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetWidget()->Minimize();
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ScreenCaptureNotificationUIViews::NotifyStopped() {
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!stop_callback_.is_null()) {
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::Closure callback = stop_callback_;
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    stop_callback_.Reset();
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callback.Run();
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochscoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create(
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& text) {
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return scoped_ptr<ScreenCaptureNotificationUI>(
3333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      new ScreenCaptureNotificationUIViews(text));
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
335