| OLD | NEW |
| (Empty) |
| 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 | |
| 23 using extensions::AppWindow; | |
| 24 | |
| 25 namespace native_app_window { | |
| 26 | |
| 27 NativeAppWindowViews::NativeAppWindowViews() | |
| 28 : app_window_(NULL), | |
| 29 web_view_(NULL), | |
| 30 widget_(NULL), | |
| 31 frameless_(false), | |
| 32 resizable_(false) { | |
| 33 } | |
| 34 | |
| 35 void 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 | |
| 53 NativeAppWindowViews::~NativeAppWindowViews() { | |
| 54 web_view_->SetWebContents(NULL); | |
| 55 } | |
| 56 | |
| 57 void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() { | |
| 58 app_window_->OnNativeWindowChanged(); | |
| 59 } | |
| 60 | |
| 61 void 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 | |
| 75 bool NativeAppWindowViews::IsActive() const { | |
| 76 return widget_->IsActive(); | |
| 77 } | |
| 78 | |
| 79 bool NativeAppWindowViews::IsMaximized() const { | |
| 80 return widget_->IsMaximized(); | |
| 81 } | |
| 82 | |
| 83 bool NativeAppWindowViews::IsMinimized() const { | |
| 84 return widget_->IsMinimized(); | |
| 85 } | |
| 86 | |
| 87 bool NativeAppWindowViews::IsFullscreen() const { | |
| 88 return widget_->IsFullscreen(); | |
| 89 } | |
| 90 | |
| 91 gfx::NativeWindow NativeAppWindowViews::GetNativeWindow() { | |
| 92 return widget_->GetNativeWindow(); | |
| 93 } | |
| 94 | |
| 95 gfx::Rect NativeAppWindowViews::GetRestoredBounds() const { | |
| 96 return widget_->GetRestoredBounds(); | |
| 97 } | |
| 98 | |
| 99 ui::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 | |
| 108 gfx::Rect NativeAppWindowViews::GetBounds() const { | |
| 109 return widget_->GetWindowBoundsInScreen(); | |
| 110 } | |
| 111 | |
| 112 void NativeAppWindowViews::Show() { | |
| 113 if (widget_->IsVisible()) { | |
| 114 widget_->Activate(); | |
| 115 return; | |
| 116 } | |
| 117 widget_->Show(); | |
| 118 } | |
| 119 | |
| 120 void NativeAppWindowViews::ShowInactive() { | |
| 121 if (widget_->IsVisible()) | |
| 122 return; | |
| 123 | |
| 124 widget_->ShowInactive(); | |
| 125 } | |
| 126 | |
| 127 void NativeAppWindowViews::Hide() { | |
| 128 widget_->Hide(); | |
| 129 } | |
| 130 | |
| 131 void NativeAppWindowViews::Close() { | |
| 132 widget_->Close(); | |
| 133 } | |
| 134 | |
| 135 void NativeAppWindowViews::Activate() { | |
| 136 widget_->Activate(); | |
| 137 } | |
| 138 | |
| 139 void NativeAppWindowViews::Deactivate() { | |
| 140 widget_->Deactivate(); | |
| 141 } | |
| 142 | |
| 143 void NativeAppWindowViews::Maximize() { | |
| 144 widget_->Maximize(); | |
| 145 } | |
| 146 | |
| 147 void NativeAppWindowViews::Minimize() { | |
| 148 widget_->Minimize(); | |
| 149 } | |
| 150 | |
| 151 void NativeAppWindowViews::Restore() { | |
| 152 widget_->Restore(); | |
| 153 } | |
| 154 | |
| 155 void NativeAppWindowViews::SetBounds(const gfx::Rect& bounds) { | |
| 156 widget_->SetBounds(bounds); | |
| 157 } | |
| 158 | |
| 159 void NativeAppWindowViews::FlashFrame(bool flash) { | |
| 160 widget_->FlashFrame(flash); | |
| 161 } | |
| 162 | |
| 163 bool NativeAppWindowViews::IsAlwaysOnTop() const { | |
| 164 // Stub implementation. See also ChromeNativeAppWindowViews. | |
| 165 return widget_->IsAlwaysOnTop(); | |
| 166 } | |
| 167 | |
| 168 void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) { | |
| 169 widget_->SetAlwaysOnTop(always_on_top); | |
| 170 } | |
| 171 | |
| 172 gfx::NativeView NativeAppWindowViews::GetHostView() const { | |
| 173 return widget_->GetNativeView(); | |
| 174 } | |
| 175 | |
| 176 gfx::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 | |
| 182 gfx::Size NativeAppWindowViews::GetMaximumDialogSize() { | |
| 183 return widget_->GetWindowBoundsInScreen().size(); | |
| 184 } | |
| 185 | |
| 186 void NativeAppWindowViews::AddObserver( | |
| 187 web_modal::ModalDialogHostObserver* observer) { | |
| 188 observer_list_.AddObserver(observer); | |
| 189 } | |
| 190 void NativeAppWindowViews::RemoveObserver( | |
| 191 web_modal::ModalDialogHostObserver* observer) { | |
| 192 observer_list_.RemoveObserver(observer); | |
| 193 } | |
| 194 | |
| 195 void NativeAppWindowViews::OnViewWasResized() { | |
| 196 FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, | |
| 197 observer_list_, | |
| 198 OnPositionRequiresUpdate()); | |
| 199 } | |
| 200 | |
| 201 // WidgetDelegate implementation. | |
| 202 | |
| 203 void NativeAppWindowViews::OnWidgetMove() { | |
| 204 app_window_->OnNativeWindowChanged(); | |
| 205 } | |
| 206 | |
| 207 views::View* NativeAppWindowViews::GetInitiallyFocusedView() { | |
| 208 return web_view_; | |
| 209 } | |
| 210 | |
| 211 bool NativeAppWindowViews::CanResize() const { | |
| 212 return resizable_ && !size_constraints_.HasFixedSize() && | |
| 213 !WidgetHasHitTestMask(); | |
| 214 } | |
| 215 | |
| 216 bool NativeAppWindowViews::CanMaximize() const { | |
| 217 return resizable_ && !size_constraints_.HasMaximumSize() && | |
| 218 !app_window_->window_type_is_panel() && !WidgetHasHitTestMask(); | |
| 219 } | |
| 220 | |
| 221 bool NativeAppWindowViews::CanMinimize() const { | |
| 222 return true; | |
| 223 } | |
| 224 | |
| 225 base::string16 NativeAppWindowViews::GetWindowTitle() const { | |
| 226 return app_window_->GetTitle(); | |
| 227 } | |
| 228 | |
| 229 bool NativeAppWindowViews::ShouldShowWindowTitle() const { | |
| 230 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; | |
| 231 } | |
| 232 | |
| 233 bool NativeAppWindowViews::ShouldShowWindowIcon() const { | |
| 234 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; | |
| 235 } | |
| 236 | |
| 237 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds, | |
| 238 ui::WindowShowState show_state) { | |
| 239 views::WidgetDelegate::SaveWindowPlacement(bounds, show_state); | |
| 240 app_window_->OnNativeWindowChanged(); | |
| 241 } | |
| 242 | |
| 243 void NativeAppWindowViews::DeleteDelegate() { | |
| 244 widget_->RemoveObserver(this); | |
| 245 app_window_->OnNativeClose(); | |
| 246 } | |
| 247 | |
| 248 views::Widget* NativeAppWindowViews::GetWidget() { | |
| 249 return widget_; | |
| 250 } | |
| 251 | |
| 252 const views::Widget* NativeAppWindowViews::GetWidget() const { | |
| 253 return widget_; | |
| 254 } | |
| 255 | |
| 256 views::View* NativeAppWindowViews::GetContentsView() { | |
| 257 return this; | |
| 258 } | |
| 259 | |
| 260 bool 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 | |
| 277 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget, | |
| 278 bool visible) { | |
| 279 app_window_->OnNativeWindowChanged(); | |
| 280 } | |
| 281 | |
| 282 void 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 | |
| 291 void 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 | |
| 300 void NativeAppWindowViews::RenderViewHostChanged( | |
| 301 content::RenderViewHost* old_host, | |
| 302 content::RenderViewHost* new_host) { | |
| 303 OnViewWasResized(); | |
| 304 } | |
| 305 | |
| 306 // views::View implementation. | |
| 307 | |
| 308 void NativeAppWindowViews::Layout() { | |
| 309 DCHECK(web_view_); | |
| 310 web_view_->SetBounds(0, 0, width(), height()); | |
| 311 OnViewWasResized(); | |
| 312 } | |
| 313 | |
| 314 void 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 | |
| 323 gfx::Size NativeAppWindowViews::GetMinimumSize() const { | |
| 324 return size_constraints_.GetMinimumSize(); | |
| 325 } | |
| 326 | |
| 327 gfx::Size NativeAppWindowViews::GetMaximumSize() const { | |
| 328 return size_constraints_.GetMaximumSize(); | |
| 329 } | |
| 330 | |
| 331 void NativeAppWindowViews::OnFocus() { | |
| 332 web_view_->RequestFocus(); | |
| 333 } | |
| 334 | |
| 335 // NativeAppWindow implementation. | |
| 336 | |
| 337 void NativeAppWindowViews::SetFullscreen(int fullscreen_types) { | |
| 338 // Stub implementation. See also ChromeNativeAppWindowViews. | |
| 339 widget_->SetFullscreen(fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); | |
| 340 } | |
| 341 | |
| 342 bool NativeAppWindowViews::IsFullscreenOrPending() const { | |
| 343 // Stub implementation. See also ChromeNativeAppWindowViews. | |
| 344 return widget_->IsFullscreen(); | |
| 345 } | |
| 346 | |
| 347 void NativeAppWindowViews::UpdateWindowIcon() { | |
| 348 widget_->UpdateWindowIcon(); | |
| 349 } | |
| 350 | |
| 351 void NativeAppWindowViews::UpdateWindowTitle() { | |
| 352 widget_->UpdateWindowTitle(); | |
| 353 } | |
| 354 | |
| 355 void NativeAppWindowViews::UpdateBadgeIcon() { | |
| 356 // Stub implementation. See also ChromeNativeAppWindowViews. | |
| 357 } | |
| 358 | |
| 359 void 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 | |
| 369 SkRegion* NativeAppWindowViews::GetDraggableRegion() { | |
| 370 return draggable_region_.get(); | |
| 371 } | |
| 372 | |
| 373 void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) { | |
| 374 // Stub implementation. See also ChromeNativeAppWindowViews. | |
| 375 } | |
| 376 | |
| 377 void NativeAppWindowViews::HandleKeyboardEvent( | |
| 378 const content::NativeWebKeyboardEvent& event) { | |
| 379 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, | |
| 380 GetFocusManager()); | |
| 381 } | |
| 382 | |
| 383 bool NativeAppWindowViews::IsFrameless() const { | |
| 384 return frameless_; | |
| 385 } | |
| 386 | |
| 387 bool NativeAppWindowViews::HasFrameColor() const { | |
| 388 return false; | |
| 389 } | |
| 390 | |
| 391 SkColor NativeAppWindowViews::ActiveFrameColor() const { | |
| 392 return SK_ColorBLACK; | |
| 393 } | |
| 394 | |
| 395 SkColor NativeAppWindowViews::InactiveFrameColor() const { | |
| 396 return SK_ColorBLACK; | |
| 397 } | |
| 398 | |
| 399 gfx::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 | |
| 414 void NativeAppWindowViews::HideWithApp() { | |
| 415 } | |
| 416 | |
| 417 void NativeAppWindowViews::ShowWithApp() { | |
| 418 } | |
| 419 | |
| 420 void NativeAppWindowViews::UpdateShelfMenu() { | |
| 421 } | |
| 422 | |
| 423 gfx::Size NativeAppWindowViews::GetContentMinimumSize() const { | |
| 424 return size_constraints_.GetMinimumSize(); | |
| 425 } | |
| 426 | |
| 427 gfx::Size NativeAppWindowViews::GetContentMaximumSize() const { | |
| 428 return size_constraints_.GetMaximumSize(); | |
| 429 } | |
| 430 | |
| 431 void 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 | |
| 439 bool NativeAppWindowViews::CanHaveAlphaEnabled() const { | |
| 440 return widget_->IsTranslucentWindowOpacitySupported(); | |
| 441 } | |
| 442 | |
| 443 void NativeAppWindowViews::SetVisibleOnAllWorkspaces(bool always_visible) { | |
| 444 widget_->SetVisibleOnAllWorkspaces(always_visible); | |
| 445 } | |
| 446 | |
| 447 } // namespace native_app_window | |
| OLD | NEW |