| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/frame/app_non_client_frame_view_ash.h" | 5 #include "chrome/browser/ui/views/frame/app_non_client_frame_view_ash.h" |
| 6 | 6 |
| 7 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h" | 7 #include "ash/wm/caption_buttons/hideable_caption_button_container.h" |
| 8 #include "base/i18n/rtl.h" | |
| 9 #include "chrome/browser/ui/views/frame/browser_frame.h" | |
| 10 #include "chrome/browser/ui/views/frame/browser_view.h" | |
| 11 #include "grit/ash_resources.h" | 8 #include "grit/ash_resources.h" |
| 12 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
| 13 #include "ui/base/hit_test.h" | 10 #include "ui/base/hit_test.h" |
| 14 #include "ui/base/resource/resource_bundle.h" | |
| 15 #include "ui/gfx/canvas.h" | |
| 16 #include "ui/gfx/image/image.h" | |
| 17 #include "ui/gfx/point.h" | |
| 18 #include "ui/gfx/rect.h" | |
| 19 #include "ui/gfx/size.h" | |
| 20 #include "ui/views/background.h" | |
| 21 #include "ui/views/border.h" | |
| 22 #include "ui/views/widget/widget.h" | 11 #include "ui/views/widget/widget.h" |
| 23 #include "ui/views/window/non_client_view.h" | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 // The size of the shadow around the caption buttons. | |
| 28 const int kShadowSizeX = 16; | |
| 29 const int kShadowSizeBottom = 21; | |
| 30 | |
| 31 // The border for |control_view_|. | |
| 32 class ControlViewBorder : public views::Border { | |
| 33 public: | |
| 34 ControlViewBorder() { | |
| 35 int border_id = base::i18n::IsRTL() ? | |
| 36 IDR_AURA_WINDOW_FULLSCREEN_SHADOW_RTL : | |
| 37 IDR_AURA_WINDOW_FULLSCREEN_SHADOW; | |
| 38 border_ = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 39 border_id).AsImageSkia(); | |
| 40 } | |
| 41 | |
| 42 virtual ~ControlViewBorder() { | |
| 43 } | |
| 44 | |
| 45 private: | |
| 46 // views::Border overrides: | |
| 47 virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE { | |
| 48 canvas->DrawImageInt(border_, 0, view.height() - border_.height()); | |
| 49 } | |
| 50 | |
| 51 virtual gfx::Insets GetInsets() const OVERRIDE { | |
| 52 return gfx::Insets(0, kShadowSizeX, kShadowSizeBottom, 0); | |
| 53 } | |
| 54 | |
| 55 gfx::ImageSkia border_; | |
| 56 | |
| 57 DISALLOW_COPY_AND_ASSIGN(ControlViewBorder); | |
| 58 }; | |
| 59 | |
| 60 // The background for |control_view_|. | |
| 61 class ControlViewBackground : public views::Background { | |
| 62 public: | |
| 63 explicit ControlViewBackground(bool is_incognito) { | |
| 64 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 65 int control_base_resource_id = is_incognito ? | |
| 66 IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE : | |
| 67 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; | |
| 68 background_ = rb.GetImageNamed(control_base_resource_id).AsImageSkia(); | |
| 69 } | |
| 70 | |
| 71 virtual ~ControlViewBackground() { | |
| 72 } | |
| 73 | |
| 74 private: | |
| 75 // views::Background override: | |
| 76 virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { | |
| 77 gfx::Rect paint_bounds(view->GetContentsBounds()); | |
| 78 paint_bounds.set_x(view->GetMirroredXForRect(paint_bounds)); | |
| 79 canvas->TileImageInt(background_, paint_bounds.x(), paint_bounds.y(), | |
| 80 paint_bounds.width(), paint_bounds.height()); | |
| 81 } | |
| 82 | |
| 83 gfx::ImageSkia background_; | |
| 84 | |
| 85 DISALLOW_COPY_AND_ASSIGN(ControlViewBackground); | |
| 86 }; | |
| 87 | |
| 88 } // namespace | |
| 89 | |
| 90 // Observer to detect when the browser frame widget closes so we can clean | |
| 91 // up our ControlView. Because we can be closed via a keyboard shortcut we | |
| 92 // are not guaranteed to run AppNonClientFrameView's Close() or Restore(). | |
| 93 class AppNonClientFrameViewAsh::FrameObserver : public views::WidgetObserver { | |
| 94 public: | |
| 95 explicit FrameObserver(AppNonClientFrameViewAsh* owner) : owner_(owner) {} | |
| 96 virtual ~FrameObserver() {} | |
| 97 | |
| 98 // views::WidgetObserver: | |
| 99 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE { | |
| 100 owner_->CloseControlWidget(); | |
| 101 } | |
| 102 | |
| 103 private: | |
| 104 AppNonClientFrameViewAsh* owner_; | |
| 105 | |
| 106 DISALLOW_COPY_AND_ASSIGN(FrameObserver); | |
| 107 }; | |
| 108 | 12 |
| 109 // static | 13 // static |
| 110 const char AppNonClientFrameViewAsh::kViewClassName[] = | 14 const char AppNonClientFrameViewAsh::kViewClassName[] = |
| 111 "AppNonClientFrameViewAsh"; | 15 "AppNonClientFrameViewAsh"; |
| 112 // static | |
| 113 const char AppNonClientFrameViewAsh::kControlWindowName[] = | |
| 114 "AppNonClientFrameViewAshControls"; | |
| 115 | 16 |
| 116 AppNonClientFrameViewAsh::AppNonClientFrameViewAsh( | 17 AppNonClientFrameViewAsh::AppNonClientFrameViewAsh(views::Widget* frame) { |
| 117 BrowserFrame* frame, BrowserView* browser_view) | |
| 118 : BrowserNonClientFrameView(frame, browser_view), | |
| 119 control_view_(NULL), | |
| 120 control_widget_(NULL), | |
| 121 frame_observer_(new FrameObserver(this)) { | |
| 122 control_view_ = new ash::FrameCaptionButtonContainerView(frame, | |
| 123 ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); | |
| 124 control_view_->set_header_style( | |
| 125 ash::FrameCaptionButtonContainerView::HEADER_STYLE_MAXIMIZED_HOSTED_APP); | |
| 126 control_view_->set_border(new ControlViewBorder()); | |
| 127 control_view_->set_background(new ControlViewBackground( | |
| 128 browser_view->IsOffTheRecord())); | |
| 129 | |
| 130 // This FrameView is always maximized so we don't want the window to have | |
| 131 // resize borders. | |
| 132 frame->GetNativeView()->set_hit_test_bounds_override_inner(gfx::Insets()); | 18 frame->GetNativeView()->set_hit_test_bounds_override_inner(gfx::Insets()); |
| 133 // Watch for frame close so we can clean up the control widget. | 19 container_.reset(new ash::HideableCaptionButtonContainer( |
| 134 frame->AddObserver(frame_observer_.get()); | 20 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE, frame)); |
| 135 set_background(views::Background::CreateSolidBackground(SK_ColorBLACK)); | 21 container_->ShowButtonWidget(); |
| 136 // Create the controls. | |
| 137 control_widget_ = new views::Widget; | |
| 138 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); | |
| 139 params.parent = browser_view->GetNativeWindow(); | |
| 140 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
| 141 control_widget_->Init(params); | |
| 142 control_widget_->SetContentsView(control_view_); | |
| 143 aura::Window* window = control_widget_->GetNativeView(); | |
| 144 window->SetName(kControlWindowName); | |
| 145 | |
| 146 // Need to exclude the shadow from the active control area. | |
| 147 gfx::Insets hit_test_insets(control_view_->GetInsets()); | |
| 148 if (base::i18n::IsRTL()) { | |
| 149 hit_test_insets = gfx::Insets(hit_test_insets.top(), | |
| 150 hit_test_insets.right(), | |
| 151 hit_test_insets.bottom(), | |
| 152 hit_test_insets.left()); | |
| 153 } | |
| 154 window->SetHitTestBoundsOverrideOuter(hit_test_insets, hit_test_insets); | |
| 155 | |
| 156 gfx::Rect control_bounds = GetControlBounds(); | |
| 157 window->SetBounds(control_bounds); | |
| 158 control_widget_->Show(); | |
| 159 } | 22 } |
| 160 | 23 |
| 161 AppNonClientFrameViewAsh::~AppNonClientFrameViewAsh() { | 24 AppNonClientFrameViewAsh::~AppNonClientFrameViewAsh() { |
| 162 frame()->RemoveObserver(frame_observer_.get()); | |
| 163 // This frame view can be replaced (and deleted) if the window is restored | |
| 164 // via a keyboard shortcut like Alt-[. Ensure we close the control widget. | |
| 165 CloseControlWidget(); | |
| 166 } | 25 } |
| 167 | 26 |
| 168 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForClientView() const { | 27 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForClientView() const { |
| 169 return GetLocalBounds(); | 28 return GetLocalBounds(); |
| 170 } | 29 } |
| 171 | 30 |
| 172 gfx::Rect AppNonClientFrameViewAsh::GetWindowBoundsForClientBounds( | 31 gfx::Rect AppNonClientFrameViewAsh::GetWindowBoundsForClientBounds( |
| 173 const gfx::Rect& client_bounds) const { | 32 const gfx::Rect& client_bounds) const { |
| 174 return client_bounds; | 33 return client_bounds; |
| 175 } | 34 } |
| 176 | 35 |
| 177 int AppNonClientFrameViewAsh::NonClientHitTest( | 36 int AppNonClientFrameViewAsh::NonClientHitTest( |
| 178 const gfx::Point& point) { | 37 const gfx::Point& point) { |
| 179 return HTNOWHERE; | 38 return HTNOWHERE; |
| 180 } | 39 } |
| 181 | 40 |
| 182 void AppNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size, | 41 void AppNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size, |
| 183 gfx::Path* window_mask) { | 42 gfx::Path* window_mask) { |
| 184 } | 43 } |
| 185 | 44 |
| 186 void AppNonClientFrameViewAsh::ResetWindowControls() { | 45 void AppNonClientFrameViewAsh::ResetWindowControls() { |
| 187 } | 46 } |
| 188 | 47 |
| 189 void AppNonClientFrameViewAsh::UpdateWindowIcon() { | 48 void AppNonClientFrameViewAsh::UpdateWindowIcon() { |
| 190 } | 49 } |
| 191 | 50 |
| 192 void AppNonClientFrameViewAsh::UpdateWindowTitle() { | 51 void AppNonClientFrameViewAsh::UpdateWindowTitle() { |
| 193 } | 52 } |
| 194 | 53 |
| 195 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForTabStrip( | |
| 196 views::View* tabstrip) const { | |
| 197 return gfx::Rect(); | |
| 198 } | |
| 199 | |
| 200 BrowserNonClientFrameView::TabStripInsets | |
| 201 AppNonClientFrameViewAsh::GetTabStripInsets(bool restored) const { | |
| 202 return TabStripInsets(); | |
| 203 } | |
| 204 | |
| 205 int AppNonClientFrameViewAsh::GetThemeBackgroundXInset() const { | |
| 206 return 0; | |
| 207 } | |
| 208 | |
| 209 void AppNonClientFrameViewAsh::UpdateThrobber(bool running) { | |
| 210 } | |
| 211 | |
| 212 const char* AppNonClientFrameViewAsh::GetClassName() const { | 54 const char* AppNonClientFrameViewAsh::GetClassName() const { |
| 213 return kViewClassName; | 55 return kViewClassName; |
| 214 } | 56 } |
| 215 | |
| 216 void AppNonClientFrameViewAsh::OnBoundsChanged( | |
| 217 const gfx::Rect& previous_bounds) { | |
| 218 if (control_widget_) | |
| 219 control_widget_->GetNativeView()->SetBounds(GetControlBounds()); | |
| 220 } | |
| 221 | |
| 222 gfx::Rect AppNonClientFrameViewAsh::GetControlBounds() const { | |
| 223 if (!control_view_) | |
| 224 return gfx::Rect(); | |
| 225 gfx::Size preferred = control_view_->GetPreferredSize(); | |
| 226 return gfx::Rect( | |
| 227 base::i18n::IsRTL() ? 0 : (width() - preferred.width()), 0, | |
| 228 preferred.width(), preferred.height()); | |
| 229 } | |
| 230 | |
| 231 void AppNonClientFrameViewAsh::CloseControlWidget() { | |
| 232 if (control_widget_) { | |
| 233 control_widget_->Close(); | |
| 234 control_widget_ = NULL; | |
| 235 } | |
| 236 } | |
| OLD | NEW |