native_app_window_views.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2014 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 "components/native_app_window/native_app_window_views.h" 6 7#include "base/threading/sequenced_worker_pool.h" 8#include "content/public/browser/render_view_host.h" 9#include "content/public/browser/render_widget_host_view.h" 10#include "content/public/browser/web_contents.h" 11#include "extensions/browser/app_window/app_window.h" 12#include "extensions/common/draggable_region.h" 13#include "third_party/skia/include/core/SkRegion.h" 14#include "ui/gfx/path.h" 15#include "ui/views/controls/webview/webview.h" 16#include "ui/views/widget/widget.h" 17#include "ui/views/window/non_client_view.h" 18 19#if defined(USE_AURA) 20#include "ui/aura/window.h" 21#endif 22 23using extensions::AppWindow; 24 25namespace native_app_window { 26 27NativeAppWindowViews::NativeAppWindowViews() 28 : app_window_(NULL), 29 web_view_(NULL), 30 widget_(NULL), 31 frameless_(false), 32 resizable_(false) { 33} 34 35void NativeAppWindowViews::Init(AppWindow* app_window, 36 const AppWindow::CreateParams& create_params) { 37 app_window_ = app_window; 38 frameless_ = create_params.frame == AppWindow::FRAME_NONE; 39 resizable_ = create_params.resizable; 40 size_constraints_.set_minimum_size( 41 create_params.GetContentMinimumSize(gfx::Insets())); 42 size_constraints_.set_maximum_size( 43 create_params.GetContentMaximumSize(gfx::Insets())); 44 Observe(app_window_->web_contents()); 45 46 widget_ = new views::Widget; 47 InitializeWindow(app_window, create_params); 48 49 OnViewWasResized(); 50 widget_->AddObserver(this); 51} 52 53NativeAppWindowViews::~NativeAppWindowViews() { 54 web_view_->SetWebContents(NULL); 55} 56 57void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() { 58 app_window_->OnNativeWindowChanged(); 59} 60 61void NativeAppWindowViews::InitializeWindow( 62 AppWindow* app_window, 63 const AppWindow::CreateParams& create_params) { 64 // Stub implementation. See also ChromeNativeAppWindowViews. 65 views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW); 66 init_params.delegate = this; 67 init_params.keep_on_top = create_params.always_on_top; 68 widget_->Init(init_params); 69 widget_->CenterWindow( 70 create_params.GetInitialWindowBounds(gfx::Insets()).size()); 71} 72 73// ui::BaseWindow implementation. 74 75bool NativeAppWindowViews::IsActive() const { 76 return widget_->IsActive(); 77} 78 79bool NativeAppWindowViews::IsMaximized() const { 80 return widget_->IsMaximized(); 81} 82 83bool NativeAppWindowViews::IsMinimized() const { 84 return widget_->IsMinimized(); 85} 86 87bool NativeAppWindowViews::IsFullscreen() const { 88 return widget_->IsFullscreen(); 89} 90 91gfx::NativeWindow NativeAppWindowViews::GetNativeWindow() { 92 return widget_->GetNativeWindow(); 93} 94 95gfx::Rect NativeAppWindowViews::GetRestoredBounds() const { 96 return widget_->GetRestoredBounds(); 97} 98 99ui::WindowShowState NativeAppWindowViews::GetRestoredState() const { 100 // Stub implementation. See also ChromeNativeAppWindowViews. 101 if (IsMaximized()) 102 return ui::SHOW_STATE_MAXIMIZED; 103 if (IsFullscreen()) 104 return ui::SHOW_STATE_FULLSCREEN; 105 return ui::SHOW_STATE_NORMAL; 106} 107 108gfx::Rect NativeAppWindowViews::GetBounds() const { 109 return widget_->GetWindowBoundsInScreen(); 110} 111 112void NativeAppWindowViews::Show() { 113 if (widget_->IsVisible()) { 114 widget_->Activate(); 115 return; 116 } 117 widget_->Show(); 118} 119 120void NativeAppWindowViews::ShowInactive() { 121 if (widget_->IsVisible()) 122 return; 123 124 widget_->ShowInactive(); 125} 126 127void NativeAppWindowViews::Hide() { 128 widget_->Hide(); 129} 130 131void NativeAppWindowViews::Close() { 132 widget_->Close(); 133} 134 135void NativeAppWindowViews::Activate() { 136 widget_->Activate(); 137} 138 139void NativeAppWindowViews::Deactivate() { 140 widget_->Deactivate(); 141} 142 143void NativeAppWindowViews::Maximize() { 144 widget_->Maximize(); 145} 146 147void NativeAppWindowViews::Minimize() { 148 widget_->Minimize(); 149} 150 151void NativeAppWindowViews::Restore() { 152 widget_->Restore(); 153} 154 155void NativeAppWindowViews::SetBounds(const gfx::Rect& bounds) { 156 widget_->SetBounds(bounds); 157} 158 159void NativeAppWindowViews::FlashFrame(bool flash) { 160 widget_->FlashFrame(flash); 161} 162 163bool NativeAppWindowViews::IsAlwaysOnTop() const { 164 // Stub implementation. See also ChromeNativeAppWindowViews. 165 return widget_->IsAlwaysOnTop(); 166} 167 168void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) { 169 widget_->SetAlwaysOnTop(always_on_top); 170} 171 172gfx::NativeView NativeAppWindowViews::GetHostView() const { 173 return widget_->GetNativeView(); 174} 175 176gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) { 177 gfx::Size app_window_size = widget_->GetWindowBoundsInScreen().size(); 178 return gfx::Point(app_window_size.width() / 2 - size.width() / 2, 179 app_window_size.height() / 2 - size.height() / 2); 180} 181 182gfx::Size NativeAppWindowViews::GetMaximumDialogSize() { 183 return widget_->GetWindowBoundsInScreen().size(); 184} 185 186void NativeAppWindowViews::AddObserver( 187 web_modal::ModalDialogHostObserver* observer) { 188 observer_list_.AddObserver(observer); 189} 190void NativeAppWindowViews::RemoveObserver( 191 web_modal::ModalDialogHostObserver* observer) { 192 observer_list_.RemoveObserver(observer); 193} 194 195void NativeAppWindowViews::OnViewWasResized() { 196 FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, 197 observer_list_, 198 OnPositionRequiresUpdate()); 199} 200 201// WidgetDelegate implementation. 202 203void NativeAppWindowViews::OnWidgetMove() { 204 app_window_->OnNativeWindowChanged(); 205} 206 207views::View* NativeAppWindowViews::GetInitiallyFocusedView() { 208 return web_view_; 209} 210 211bool NativeAppWindowViews::CanResize() const { 212 return resizable_ && !size_constraints_.HasFixedSize() && 213 !WidgetHasHitTestMask(); 214} 215 216bool NativeAppWindowViews::CanMaximize() const { 217 return resizable_ && !size_constraints_.HasMaximumSize() && 218 !app_window_->window_type_is_panel() && !WidgetHasHitTestMask(); 219} 220 221bool NativeAppWindowViews::CanMinimize() const { 222 return true; 223} 224 225base::string16 NativeAppWindowViews::GetWindowTitle() const { 226 return app_window_->GetTitle(); 227} 228 229bool NativeAppWindowViews::ShouldShowWindowTitle() const { 230 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; 231} 232 233bool NativeAppWindowViews::ShouldShowWindowIcon() const { 234 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; 235} 236 237void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds, 238 ui::WindowShowState show_state) { 239 views::WidgetDelegate::SaveWindowPlacement(bounds, show_state); 240 app_window_->OnNativeWindowChanged(); 241} 242 243void NativeAppWindowViews::DeleteDelegate() { 244 widget_->RemoveObserver(this); 245 app_window_->OnNativeClose(); 246} 247 248views::Widget* NativeAppWindowViews::GetWidget() { 249 return widget_; 250} 251 252const views::Widget* NativeAppWindowViews::GetWidget() const { 253 return widget_; 254} 255 256views::View* NativeAppWindowViews::GetContentsView() { 257 return this; 258} 259 260bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling( 261 gfx::NativeView child, 262 const gfx::Point& location) { 263#if defined(USE_AURA) 264 if (child->Contains(web_view_->web_contents()->GetNativeView())) { 265 // App window should claim mouse events that fall within the draggable 266 // region. 267 return !draggable_region_.get() || 268 !draggable_region_->contains(location.x(), location.y()); 269 } 270#endif 271 272 return true; 273} 274 275// WidgetObserver implementation. 276 277void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget, 278 bool visible) { 279 app_window_->OnNativeWindowChanged(); 280} 281 282void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget* widget, 283 bool active) { 284 app_window_->OnNativeWindowChanged(); 285 if (active) 286 app_window_->OnNativeWindowActivated(); 287} 288 289// WebContentsObserver implementation. 290 291void NativeAppWindowViews::RenderViewCreated( 292 content::RenderViewHost* render_view_host) { 293 if (app_window_->requested_alpha_enabled() && CanHaveAlphaEnabled()) { 294 content::RenderWidgetHostView* view = render_view_host->GetView(); 295 DCHECK(view); 296 view->SetBackgroundOpaque(false); 297 } 298} 299 300void NativeAppWindowViews::RenderViewHostChanged( 301 content::RenderViewHost* old_host, 302 content::RenderViewHost* new_host) { 303 OnViewWasResized(); 304} 305 306// views::View implementation. 307 308void NativeAppWindowViews::Layout() { 309 DCHECK(web_view_); 310 web_view_->SetBounds(0, 0, width(), height()); 311 OnViewWasResized(); 312} 313 314void NativeAppWindowViews::ViewHierarchyChanged( 315 const ViewHierarchyChangedDetails& details) { 316 if (details.is_add && details.child == this) { 317 web_view_ = new views::WebView(NULL); 318 AddChildView(web_view_); 319 web_view_->SetWebContents(app_window_->web_contents()); 320 } 321} 322 323gfx::Size NativeAppWindowViews::GetMinimumSize() const { 324 return size_constraints_.GetMinimumSize(); 325} 326 327gfx::Size NativeAppWindowViews::GetMaximumSize() const { 328 return size_constraints_.GetMaximumSize(); 329} 330 331void NativeAppWindowViews::OnFocus() { 332 web_view_->RequestFocus(); 333} 334 335// NativeAppWindow implementation. 336 337void NativeAppWindowViews::SetFullscreen(int fullscreen_types) { 338 // Stub implementation. See also ChromeNativeAppWindowViews. 339 widget_->SetFullscreen(fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); 340} 341 342bool NativeAppWindowViews::IsFullscreenOrPending() const { 343 // Stub implementation. See also ChromeNativeAppWindowViews. 344 return widget_->IsFullscreen(); 345} 346 347void NativeAppWindowViews::UpdateWindowIcon() { 348 widget_->UpdateWindowIcon(); 349} 350 351void NativeAppWindowViews::UpdateWindowTitle() { 352 widget_->UpdateWindowTitle(); 353} 354 355void NativeAppWindowViews::UpdateBadgeIcon() { 356 // Stub implementation. See also ChromeNativeAppWindowViews. 357} 358 359void NativeAppWindowViews::UpdateDraggableRegions( 360 const std::vector<extensions::DraggableRegion>& regions) { 361 // Draggable region is not supported for non-frameless window. 362 if (!frameless_) 363 return; 364 365 draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions)); 366 OnViewWasResized(); 367} 368 369SkRegion* NativeAppWindowViews::GetDraggableRegion() { 370 return draggable_region_.get(); 371} 372 373void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) { 374 // Stub implementation. See also ChromeNativeAppWindowViews. 375} 376 377void NativeAppWindowViews::HandleKeyboardEvent( 378 const content::NativeWebKeyboardEvent& event) { 379 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, 380 GetFocusManager()); 381} 382 383bool NativeAppWindowViews::IsFrameless() const { 384 return frameless_; 385} 386 387bool NativeAppWindowViews::HasFrameColor() const { 388 return false; 389} 390 391SkColor NativeAppWindowViews::ActiveFrameColor() const { 392 return SK_ColorBLACK; 393} 394 395SkColor NativeAppWindowViews::InactiveFrameColor() const { 396 return SK_ColorBLACK; 397} 398 399gfx::Insets NativeAppWindowViews::GetFrameInsets() const { 400 if (frameless_) 401 return gfx::Insets(); 402 403 // The pretend client_bounds passed in need to be large enough to ensure that 404 // GetWindowBoundsForClientBounds() doesn't decide that it needs more than 405 // the specified amount of space to fit the window controls in, and return a 406 // number larger than the real frame insets. Most window controls are smaller 407 // than 1000x1000px, so this should be big enough. 408 gfx::Rect client_bounds = gfx::Rect(1000, 1000); 409 gfx::Rect window_bounds = 410 widget_->non_client_view()->GetWindowBoundsForClientBounds(client_bounds); 411 return window_bounds.InsetsFrom(client_bounds); 412} 413 414void NativeAppWindowViews::HideWithApp() { 415} 416 417void NativeAppWindowViews::ShowWithApp() { 418} 419 420void NativeAppWindowViews::UpdateShelfMenu() { 421} 422 423gfx::Size NativeAppWindowViews::GetContentMinimumSize() const { 424 return size_constraints_.GetMinimumSize(); 425} 426 427gfx::Size NativeAppWindowViews::GetContentMaximumSize() const { 428 return size_constraints_.GetMaximumSize(); 429} 430 431void NativeAppWindowViews::SetContentSizeConstraints( 432 const gfx::Size& min_size, 433 const gfx::Size& max_size) { 434 size_constraints_.set_minimum_size(min_size); 435 size_constraints_.set_maximum_size(max_size); 436 widget_->OnSizeConstraintsChanged(); 437} 438 439bool NativeAppWindowViews::CanHaveAlphaEnabled() const { 440 return widget_->IsTranslucentWindowOpacitySupported(); 441} 442 443void NativeAppWindowViews::SetVisibleOnAllWorkspaces(bool always_visible) { 444 widget_->SetVisibleOnAllWorkspaces(always_visible); 445} 446 447} // namespace native_app_window 448