OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 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 "apps/ui/views/native_app_window_views.h" |
| 6 |
| 7 #include "apps/app_window.h" |
| 8 //#include "apps/ui/views/app_window_frame_view.h" |
| 9 //#include "base/command_line.h" |
| 10 #include "base/threading/sequenced_worker_pool.h" |
| 11 //#include "chrome/browser/app_mode/app_mode_utils.h" |
| 12 //#include "chrome/browser/chrome_page_zoom.h" |
| 13 #include "chrome/browser/extensions/extension_host.h" |
| 14 //#include "chrome/browser/favicon/favicon_tab_helper.h" |
| 15 //#include "chrome/browser/profiles/profile.h" |
| 16 //#include "chrome/browser/ui/ash/multi_user/multi_user_context_menu.h" |
| 17 //#include "chrome/browser/ui/host_desktop.h" |
| 18 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" |
| 19 //#include "chrome/browser/ui/views/extensions/extension_keybinding_registry_vie
ws.h" |
| 20 //#include "chrome/browser/ui/views/frame/taskbar_decorator.h" |
| 21 //#include "chrome/browser/web_applications/web_app.h" |
| 22 //#include "chrome/common/chrome_switches.h" |
| 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/render_view_host.h" |
| 25 #include "content/public/browser/render_widget_host_view.h" |
| 26 #include "content/public/browser/web_contents.h" |
| 27 #include "content/public/browser/web_contents_view.h" |
| 28 #include "extensions/common/draggable_region.h" |
| 29 //#include "extensions/common/extension.h" |
| 30 #include "ui/base/hit_test.h" |
| 31 //#include "ui/base/models/simple_menu_model.h" |
| 32 #include "ui/gfx/path.h" |
| 33 //#include "ui/views/controls/menu/menu_runner.h" |
| 34 #include "ui/views/controls/webview/webview.h" |
| 35 #include "ui/views/widget/widget.h" |
| 36 #include "ui/views/window/non_client_view.h" |
| 37 |
| 38 //#if defined(OS_LINUX) |
| 39 //#include "chrome/browser/shell_integration_linux.h" |
| 40 //#endif |
| 41 |
| 42 //#if defined(USE_ASH) |
| 43 //#include "ash/ash_constants.h" |
| 44 //#include "ash/ash_switches.h" |
| 45 //#include "ash/screen_util.h" |
| 46 //#include "ash/shell.h" |
| 47 //#include "ash/wm/custom_frame_view_ash.h" |
| 48 //#include "ash/wm/immersive_fullscreen_controller.h" |
| 49 //#include "ash/wm/panels/panel_frame_view.h" |
| 50 //#include "ash/wm/window_state.h" |
| 51 //#include "ash/wm/window_state_delegate.h" |
| 52 //#include "ash/wm/window_state_observer.h" |
| 53 //#include "chrome/browser/ui/ash/ash_util.h" |
| 54 //#include "ui/aura/client/aura_constants.h" |
| 55 //#include "ui/aura/client/window_tree_client.h" |
| 56 //#include "ui/aura/window.h" |
| 57 //#include "ui/aura/window_observer.h" |
| 58 //#endif |
| 59 |
| 60 #if defined(USE_AURA) |
| 61 #include "ui/aura/window.h" |
| 62 #endif |
| 63 |
| 64 using apps::AppWindow; |
| 65 |
| 66 namespace { |
| 67 |
| 68 //const int kResizeInsideBoundsSize = 5; |
| 69 //const int kResizeAreaCornerSize = 16; |
| 70 |
| 71 |
| 72 |
| 73 //#if defined(USE_ASH) |
| 74 //// This class handles a user's fullscreen request (Shift+F4/F4). |
| 75 //class NativeAppWindowStateDelegate : public ash::wm::WindowStateDelegate, |
| 76 // public ash::wm::WindowStateObserver, |
| 77 // public aura::WindowObserver { |
| 78 // public: |
| 79 // NativeAppWindowStateDelegate(AppWindow* app_window, |
| 80 // apps::NativeAppWindow* native_app_window) |
| 81 // : app_window_(app_window), |
| 82 // window_state_( |
| 83 // ash::wm::GetWindowState(native_app_window->GetNativeWindow())) { |
| 84 // // Add a window state observer to exit fullscreen properly in case |
| 85 // // fullscreen is exited without going through AppWindow::Restore(). This |
| 86 // // is the case when exiting immersive fullscreen via the "Restore" window |
| 87 // // control. |
| 88 // // TODO(pkotwicz): This is a hack. Remove ASAP. http://crbug.com/319048 |
| 89 // window_state_->AddObserver(this); |
| 90 // window_state_->window()->AddObserver(this); |
| 91 // } |
| 92 // virtual ~NativeAppWindowStateDelegate(){ |
| 93 // if (window_state_) { |
| 94 // window_state_->RemoveObserver(this); |
| 95 // window_state_->window()->RemoveObserver(this); |
| 96 // } |
| 97 // } |
| 98 // |
| 99 // private: |
| 100 // // Overridden from ash::wm::WindowStateDelegate. |
| 101 // virtual bool ToggleFullscreen(ash::wm::WindowState* window_state) OVERRIDE { |
| 102 // // Windows which cannot be maximized should not be fullscreened. |
| 103 // DCHECK(window_state->IsFullscreen() || window_state->CanMaximize()); |
| 104 // if (window_state->IsFullscreen()) |
| 105 // app_window_->Restore(); |
| 106 // else if (window_state->CanMaximize()) |
| 107 // app_window_->OSFullscreen(); |
| 108 // return true; |
| 109 // } |
| 110 // |
| 111 // // Overridden from ash::wm::WindowStateObserver: |
| 112 // virtual void OnPostWindowShowTypeChange( |
| 113 // ash::wm::WindowState* window_state, |
| 114 // ash::wm::WindowShowType old_type) OVERRIDE { |
| 115 // if (!window_state->IsFullscreen() && !window_state->IsMinimized() && |
| 116 // app_window_->GetBaseWindow()->IsFullscreenOrPending()) { |
| 117 // app_window_->Restore(); |
| 118 // // Usually OnNativeWindowChanged() is called when the window bounds are |
| 119 // // changed as a result of a show type change. Because the change in show |
| 120 // // type has already occurred, we need to call OnNativeWindowChanged() |
| 121 // // explicitly. |
| 122 // app_window_->OnNativeWindowChanged(); |
| 123 // } |
| 124 // } |
| 125 // |
| 126 // // Overridden from aura::WindowObserver: |
| 127 // virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { |
| 128 // window_state_->RemoveObserver(this); |
| 129 // window_state_->window()->RemoveObserver(this); |
| 130 // window_state_ = NULL; |
| 131 // } |
| 132 // |
| 133 // // Not owned. |
| 134 // AppWindow* app_window_; |
| 135 // ash::wm::WindowState* window_state_; |
| 136 // |
| 137 // DISALLOW_COPY_AND_ASSIGN(NativeAppWindowStateDelegate); |
| 138 //}; |
| 139 //#endif // USE_ASH |
| 140 |
| 141 } // namespace |
| 142 |
| 143 NativeAppWindowViews::NativeAppWindowViews() |
| 144 : app_window_(NULL), |
| 145 web_view_(NULL), |
| 146 window_(NULL), |
| 147 frameless_(false), |
| 148 transparent_background_(false), |
| 149 resizable_(false) {} |
| 150 // is_fullscreen_(false), |
| 151 // weak_ptr_factory_(this) { |
| 152 |
| 153 void NativeAppWindowViews::Init(apps::AppWindow* app_window, |
| 154 const AppWindow::CreateParams& create_params) { |
| 155 app_window_ = app_window; |
| 156 frameless_ = create_params.frame == AppWindow::FRAME_NONE; |
| 157 transparent_background_ = create_params.transparent_background; |
| 158 resizable_ = create_params.resizable; |
| 159 Observe(app_window_->web_contents()); |
| 160 |
| 161 window_ = new views::Widget; |
| 162 InitializeWindow(app_window, create_params); |
| 163 |
| 164 OnViewWasResized(); |
| 165 window_->AddObserver(this); |
| 166 } |
| 167 |
| 168 NativeAppWindowViews::~NativeAppWindowViews() { |
| 169 web_view_->SetWebContents(NULL); |
| 170 } |
| 171 |
| 172 //void NativeAppWindowViews::OnBeforeWidgetInit( |
| 173 // views::Widget::InitParams* init_params, |
| 174 // views::Widget* widget) {} |
| 175 // |
| 176 //void NativeAppWindowViews::InitializeDefaultWindow( |
| 177 // const AppWindow::CreateParams& create_params) { |
| 178 // std::string app_name = |
| 179 // web_app::GenerateApplicationNameFromExtensionId(extension()->id()); |
| 180 // |
| 181 // views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW
); |
| 182 // init_params.delegate = this; |
| 183 // init_params.remove_standard_frame = ShouldUseChromeStyleFrame(); |
| 184 //#if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 185 // // On Linux, remove the standard frame. Instead, we will use CustomFrameView |
| 186 // // to draw a native-like frame. |
| 187 // // TODO(mgiuca): Remove this during fix for http://crbug.com/322256. |
| 188 // init_params.remove_standard_frame = true; |
| 189 //#endif |
| 190 // init_params.use_system_default_icon = true; |
| 191 // // TODO(erg): Conceptually, these are toplevel windows, but we theoretically |
| 192 // // could plumb context through to here in some cases. |
| 193 // init_params.top_level = true; |
| 194 // if (create_params.transparent_background) |
| 195 // init_params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| 196 // init_params.keep_on_top = create_params.always_on_top; |
| 197 // gfx::Rect window_bounds = create_params.bounds; |
| 198 // bool position_specified = |
| 199 // window_bounds.x() != INT_MIN && window_bounds.y() != INT_MIN; |
| 200 // if (position_specified && !window_bounds.IsEmpty()) |
| 201 // init_params.bounds = window_bounds; |
| 202 // |
| 203 //#if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 204 // // Set up a custom WM_CLASS for app windows. This allows task switchers in |
| 205 // // X11 environments to distinguish them from main browser windows. |
| 206 // init_params.wm_class_name = web_app::GetWMClassFromAppName(app_name); |
| 207 // init_params.wm_class_class = ShellIntegrationLinux::GetProgramClassName(); |
| 208 // const char kX11WindowRoleApp[] = "app"; |
| 209 // init_params.wm_role_name = std::string(kX11WindowRoleApp); |
| 210 //#endif |
| 211 // |
| 212 // OnBeforeWidgetInit(&init_params, window_); |
| 213 // window_->Init(init_params); |
| 214 // |
| 215 // gfx::Rect adjusted_bounds = window_bounds; |
| 216 // adjusted_bounds.Inset(-GetFrameInsets()); |
| 217 // // Center window if no position was specified. |
| 218 // if (!position_specified) |
| 219 // window_->CenterWindow(adjusted_bounds.size()); |
| 220 // else if (!adjusted_bounds.IsEmpty() && adjusted_bounds != window_bounds) |
| 221 // window_->SetBounds(adjusted_bounds); |
| 222 // |
| 223 // // Register accelarators supported by app windows. |
| 224 // // TODO(jeremya/stevenjb): should these be registered for panels too? |
| 225 // views::FocusManager* focus_manager = GetFocusManager(); |
| 226 // const std::map<ui::Accelerator, int>& accelerator_table = |
| 227 // GetAcceleratorTable(); |
| 228 // const bool is_kiosk_app_mode = chrome::IsRunningInForcedAppMode(); |
| 229 // |
| 230 // // Ensures that kiosk mode accelerators are enabled when in kiosk mode (to b
e |
| 231 // // future proof). This is needed because GetAcceleratorTable() uses a static |
| 232 // // to store data and only checks kiosk mode once. If a platform app is |
| 233 // // launched before kiosk mode starts, the kiosk accelerators will not be |
| 234 // // registered. This DCHECK catches the case. |
| 235 // DCHECK(!is_kiosk_app_mode || |
| 236 // accelerator_table.size() == |
| 237 // arraysize(kAppWindowAcceleratorMap) + |
| 238 // arraysize(kAppWindowKioskAppModeAcceleratorMap)); |
| 239 // |
| 240 // for (std::map<ui::Accelerator, int>::const_iterator iter = |
| 241 // accelerator_table.begin(); |
| 242 // iter != accelerator_table.end(); ++iter) { |
| 243 // if (is_kiosk_app_mode && !chrome::IsCommandAllowedInAppMode(iter->second)) |
| 244 // continue; |
| 245 // |
| 246 // focus_manager->RegisterAccelerator( |
| 247 // iter->first, ui::AcceleratorManager::kNormalPriority, this); |
| 248 // } |
| 249 //} |
| 250 // |
| 251 //void NativeAppWindowViews::InitializePanelWindow( |
| 252 // const AppWindow::CreateParams& create_params) { |
| 253 // views::Widget::InitParams params(views::Widget::InitParams::TYPE_PANEL); |
| 254 // params.delegate = this; |
| 255 // |
| 256 // preferred_size_ = gfx::Size(create_params.bounds.width(), |
| 257 // create_params.bounds.height()); |
| 258 // if (preferred_size_.width() == 0) |
| 259 // preferred_size_.set_width(kDefaultPanelWidth); |
| 260 // else if (preferred_size_.width() < kMinPanelWidth) |
| 261 // preferred_size_.set_width(kMinPanelWidth); |
| 262 // |
| 263 // if (preferred_size_.height() == 0) |
| 264 // preferred_size_.set_height(kDefaultPanelHeight); |
| 265 // else if (preferred_size_.height() < kMinPanelHeight) |
| 266 // preferred_size_.set_height(kMinPanelHeight); |
| 267 //#if defined(USE_ASH) |
| 268 // if (ash::Shell::HasInstance()) { |
| 269 // // Open a new panel on the target root. |
| 270 // aura::Window* target = ash::Shell::GetTargetRootWindow(); |
| 271 // params.bounds = ash::ScreenUtil::ConvertRectToScreen( |
| 272 // target, gfx::Rect(preferred_size_)); |
| 273 // } else { |
| 274 // params.bounds = gfx::Rect(preferred_size_); |
| 275 // } |
| 276 //#else |
| 277 // params.bounds = gfx::Rect(preferred_size_); |
| 278 //#endif |
| 279 // // TODO(erg): Conceptually, these are toplevel windows, but we theoretically |
| 280 // // could plumb context through to here in some cases. |
| 281 // params.top_level = true; |
| 282 // window_->Init(params); |
| 283 // window_->set_focus_on_creation(create_params.focused); |
| 284 // |
| 285 //#if defined(USE_ASH) |
| 286 // if (create_params.state == ui::SHOW_STATE_DETACHED) { |
| 287 // gfx::Rect window_bounds(create_params.bounds.x(), |
| 288 // create_params.bounds.y(), |
| 289 // preferred_size_.width(), |
| 290 // preferred_size_.height()); |
| 291 // aura::Window* native_window = GetNativeWindow(); |
| 292 // ash::wm::GetWindowState(native_window)->set_panel_attached(false); |
| 293 // aura::client::ParentWindowWithContext(native_window, |
| 294 // native_window->GetRootWindow(), |
| 295 // native_window->GetBoundsInScreen()); |
| 296 // window_->SetBounds(window_bounds); |
| 297 // } |
| 298 //#else |
| 299 // // TODO(stevenjb): NativeAppWindow panels need to be implemented for other |
| 300 // // platforms. |
| 301 //#endif |
| 302 //} |
| 303 |
| 304 //bool NativeAppWindowViews::ShouldUseChromeStyleFrame() const { |
| 305 // if (frameless_) |
| 306 // return true; |
| 307 // |
| 308 //#if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 309 // // Linux always uses native style frames. |
| 310 // return false; |
| 311 //#endif |
| 312 // |
| 313 // return !CommandLine::ForCurrentProcess()->HasSwitch( |
| 314 // switches::kAppsUseNativeFrame); |
| 315 //} |
| 316 |
| 317 //apps::AppWindowFrameView* NativeAppWindowViews::CreateAppWindowFrameView() { |
| 318 // // By default the user can resize the window from slightly inside the bounds
. |
| 319 // int resize_inside_bounds_size = kResizeInsideBoundsSize; |
| 320 // int resize_outside_bounds_size = 0; |
| 321 // int resize_outside_scale_for_touch = 1; |
| 322 // int resize_area_corner_size = kResizeAreaCornerSize; |
| 323 //#if defined(USE_ASH) |
| 324 // // For Aura windows on the Ash desktop the sizes are different and the user |
| 325 // // can resize the window from slightly outside the bounds as well. |
| 326 // if (chrome::IsNativeWindowInAsh(window_->GetNativeWindow())) { |
| 327 // resize_inside_bounds_size = ash::kResizeInsideBoundsSize; |
| 328 // resize_outside_bounds_size = ash::kResizeOutsideBoundsSize; |
| 329 // resize_outside_scale_for_touch = ash::kResizeOutsideBoundsScaleForTouch; |
| 330 // resize_area_corner_size = ash::kResizeAreaCornerSize; |
| 331 // } |
| 332 //#endif |
| 333 // apps::AppWindowFrameView* frame_view = new apps::AppWindowFrameView(this); |
| 334 // frame_view->Init(window_, |
| 335 // resize_inside_bounds_size, |
| 336 // resize_outside_bounds_size, |
| 337 // resize_outside_scale_for_touch, |
| 338 // resize_area_corner_size); |
| 339 // return frame_view; |
| 340 //} |
| 341 |
| 342 // ui::BaseWindow implementation. |
| 343 |
| 344 bool NativeAppWindowViews::IsActive() const { |
| 345 return window_->IsActive(); |
| 346 } |
| 347 |
| 348 bool NativeAppWindowViews::IsMaximized() const { |
| 349 return window_->IsMaximized(); |
| 350 } |
| 351 |
| 352 bool NativeAppWindowViews::IsMinimized() const { |
| 353 return window_->IsMinimized(); |
| 354 } |
| 355 |
| 356 bool NativeAppWindowViews::IsFullscreen() const { |
| 357 return window_->IsFullscreen(); |
| 358 } |
| 359 |
| 360 gfx::NativeWindow NativeAppWindowViews::GetNativeWindow() { |
| 361 return window_->GetNativeWindow(); |
| 362 } |
| 363 |
| 364 gfx::Rect NativeAppWindowViews::GetRestoredBounds() const { |
| 365 return window_->GetRestoredBounds(); |
| 366 } |
| 367 |
| 368 ui::WindowShowState NativeAppWindowViews::GetRestoredState() const { |
| 369 //james delegate this? |
| 370 if (IsMaximized()) |
| 371 return ui::SHOW_STATE_MAXIMIZED; |
| 372 if (IsFullscreen()) |
| 373 return ui::SHOW_STATE_FULLSCREEN; |
| 374 return ui::SHOW_STATE_NORMAL; |
| 375 } |
| 376 |
| 377 gfx::Rect NativeAppWindowViews::GetBounds() const { |
| 378 return window_->GetWindowBoundsInScreen(); |
| 379 } |
| 380 |
| 381 void NativeAppWindowViews::Show() { |
| 382 if (window_->IsVisible()) { |
| 383 window_->Activate(); |
| 384 return; |
| 385 } |
| 386 |
| 387 window_->Show(); |
| 388 } |
| 389 |
| 390 void NativeAppWindowViews::ShowInactive() { |
| 391 if (window_->IsVisible()) |
| 392 return; |
| 393 window_->ShowInactive(); |
| 394 } |
| 395 |
| 396 void NativeAppWindowViews::Hide() { |
| 397 window_->Hide(); |
| 398 } |
| 399 |
| 400 void NativeAppWindowViews::Close() { |
| 401 window_->Close(); |
| 402 } |
| 403 |
| 404 void NativeAppWindowViews::Activate() { |
| 405 window_->Activate(); |
| 406 } |
| 407 |
| 408 void NativeAppWindowViews::Deactivate() { |
| 409 window_->Deactivate(); |
| 410 } |
| 411 |
| 412 void NativeAppWindowViews::Maximize() { |
| 413 window_->Maximize(); |
| 414 } |
| 415 |
| 416 void NativeAppWindowViews::Minimize() { |
| 417 window_->Minimize(); |
| 418 } |
| 419 |
| 420 void NativeAppWindowViews::Restore() { |
| 421 window_->Restore(); |
| 422 } |
| 423 |
| 424 void NativeAppWindowViews::SetBounds(const gfx::Rect& bounds) { |
| 425 window_->SetBounds(bounds); |
| 426 } |
| 427 |
| 428 void NativeAppWindowViews::FlashFrame(bool flash) { |
| 429 window_->FlashFrame(flash); |
| 430 } |
| 431 |
| 432 //bool NativeAppWindowViews::IsAlwaysOnTop() const { |
| 433 // if (app_window_->window_type_is_panel()) { |
| 434 //#if defined(USE_ASH) |
| 435 // return ash::wm::GetWindowState(window_->GetNativeWindow())-> |
| 436 // panel_attached(); |
| 437 //#else |
| 438 // return true; |
| 439 //#endif |
| 440 // } else { |
| 441 // return window_->IsAlwaysOnTop(); |
| 442 // } |
| 443 //} |
| 444 |
| 445 void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) { |
| 446 window_->SetAlwaysOnTop(always_on_top); |
| 447 } |
| 448 |
| 449 //void NativeAppWindowViews::ShowContextMenuForView( |
| 450 // views::View* source, |
| 451 // const gfx::Point& p, |
| 452 // ui::MenuSourceType source_type) { |
| 453 //#if defined(USE_ASH) & defined(OS_CHROMEOS) |
| 454 // scoped_ptr<ui::MenuModel> model = |
| 455 // CreateMultiUserContextMenu(app_window_->GetNativeWindow()); |
| 456 // if (!model.get()) |
| 457 // return; |
| 458 // |
| 459 // // Only show context menu if point is in caption. |
| 460 // gfx::Point point_in_view_coords(p); |
| 461 // views::View::ConvertPointFromScreen(window_->non_client_view(), |
| 462 // &point_in_view_coords); |
| 463 // int hit_test = window_->non_client_view()->NonClientHitTest( |
| 464 // point_in_view_coords); |
| 465 // if (hit_test == HTCAPTION) { |
| 466 // menu_runner_.reset(new views::MenuRunner(model.get())); |
| 467 // if (menu_runner_->RunMenuAt(source->GetWidget(), NULL, |
| 468 // gfx::Rect(p, gfx::Size(0,0)), views::MenuItemView::TOPLEFT, |
| 469 // source_type, |
| 470 // views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU)
== |
| 471 // views::MenuRunner::MENU_DELETED) |
| 472 // return; |
| 473 // } |
| 474 //#endif |
| 475 //} |
| 476 |
| 477 gfx::NativeView NativeAppWindowViews::GetHostView() const { |
| 478 return window_->GetNativeView(); |
| 479 } |
| 480 |
| 481 gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) { |
| 482 gfx::Size app_window_size = window_->GetWindowBoundsInScreen().size(); |
| 483 return gfx::Point(app_window_size.width() / 2 - size.width() / 2, |
| 484 app_window_size.height() / 2 - size.height() / 2); |
| 485 } |
| 486 |
| 487 gfx::Size NativeAppWindowViews::GetMaximumDialogSize() { |
| 488 return window_->GetWindowBoundsInScreen().size(); |
| 489 } |
| 490 |
| 491 void NativeAppWindowViews::AddObserver( |
| 492 web_modal::ModalDialogHostObserver* observer) { |
| 493 observer_list_.AddObserver(observer); |
| 494 } |
| 495 void NativeAppWindowViews::RemoveObserver( |
| 496 web_modal::ModalDialogHostObserver* observer) { |
| 497 observer_list_.RemoveObserver(observer); |
| 498 } |
| 499 |
| 500 void NativeAppWindowViews::OnViewWasResized() { |
| 501 FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, |
| 502 observer_list_, |
| 503 OnPositionRequiresUpdate()); |
| 504 } |
| 505 |
| 506 // WidgetDelegate implementation. |
| 507 |
| 508 void NativeAppWindowViews::OnWidgetMove() { |
| 509 app_window_->OnNativeWindowChanged(); |
| 510 } |
| 511 |
| 512 views::View* NativeAppWindowViews::GetInitiallyFocusedView() { |
| 513 return web_view_; |
| 514 } |
| 515 |
| 516 bool NativeAppWindowViews::CanResize() const { |
| 517 return resizable_ && !app_window_->size_constraints().HasFixedSize(); |
| 518 } |
| 519 |
| 520 bool NativeAppWindowViews::CanMaximize() const { |
| 521 return resizable_ && !app_window_->size_constraints().HasMaximumSize() && |
| 522 !app_window_->window_type_is_panel(); |
| 523 } |
| 524 |
| 525 base::string16 NativeAppWindowViews::GetWindowTitle() const { |
| 526 return app_window_->GetTitle(); |
| 527 } |
| 528 |
| 529 bool NativeAppWindowViews::ShouldShowWindowTitle() const { |
| 530 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; |
| 531 } |
| 532 |
| 533 gfx::ImageSkia NativeAppWindowViews::GetWindowAppIcon() { |
| 534 gfx::Image app_icon = app_window_->app_icon(); |
| 535 if (app_icon.IsEmpty()) |
| 536 return GetWindowIcon(); |
| 537 else |
| 538 return *app_icon.ToImageSkia(); |
| 539 } |
| 540 |
| 541 //gfx::ImageSkia NativeAppWindowViews::GetWindowIcon() { |
| 542 // content::WebContents* web_contents = app_window_->web_contents(); |
| 543 // if (web_contents) { |
| 544 // FaviconTabHelper* favicon_tab_helper = |
| 545 // FaviconTabHelper::FromWebContents(web_contents); |
| 546 // gfx::Image app_icon = favicon_tab_helper->GetFavicon(); |
| 547 // if (!app_icon.IsEmpty()) |
| 548 // return *app_icon.ToImageSkia(); |
| 549 // } |
| 550 // return gfx::ImageSkia(); |
| 551 //} |
| 552 |
| 553 bool NativeAppWindowViews::ShouldShowWindowIcon() const { |
| 554 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; |
| 555 } |
| 556 |
| 557 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds, |
| 558 ui::WindowShowState show_state) { |
| 559 views::WidgetDelegate::SaveWindowPlacement(bounds, show_state); |
| 560 app_window_->OnNativeWindowChanged(); |
| 561 } |
| 562 |
| 563 void NativeAppWindowViews::DeleteDelegate() { |
| 564 window_->RemoveObserver(this); |
| 565 app_window_->OnNativeClose(); |
| 566 } |
| 567 |
| 568 views::Widget* NativeAppWindowViews::GetWidget() { |
| 569 return window_; |
| 570 } |
| 571 |
| 572 const views::Widget* NativeAppWindowViews::GetWidget() const { |
| 573 return window_; |
| 574 } |
| 575 |
| 576 views::View* NativeAppWindowViews::GetContentsView() { |
| 577 return this; |
| 578 } |
| 579 |
| 580 //views::NonClientFrameView* NativeAppWindowViews::CreateNonClientFrameView( |
| 581 // views::Widget* widget) { |
| 582 //#if defined(USE_ASH) |
| 583 // if (chrome::IsNativeViewInAsh(widget->GetNativeView())) { |
| 584 // // Set the delegate now because CustomFrameViewAsh sets the |
| 585 // // WindowStateDelegate if one is not already set. |
| 586 // ash::wm::GetWindowState(GetNativeWindow())->SetDelegate( |
| 587 // scoped_ptr<ash::wm::WindowStateDelegate>( |
| 588 // new NativeAppWindowStateDelegate(app_window_, this)).Pass()); |
| 589 // |
| 590 // if (app_window_->window_type_is_panel()) { |
| 591 // ash::PanelFrameView::FrameType frame_type = frameless_ ? |
| 592 // ash::PanelFrameView::FRAME_NONE : ash::PanelFrameView::FRAME_ASH; |
| 593 // views::NonClientFrameView* frame_view = |
| 594 // new ash::PanelFrameView(widget, frame_type); |
| 595 // frame_view->set_context_menu_controller(this); |
| 596 // return frame_view; |
| 597 // } |
| 598 // |
| 599 // if (!frameless_) { |
| 600 // ash::CustomFrameViewAsh* custom_frame_view = |
| 601 // new ash::CustomFrameViewAsh(widget); |
| 602 //#if defined(OS_CHROMEOS) |
| 603 // // Non-frameless app windows can be put into immersive fullscreen. |
| 604 // // TODO(pkotwicz): Investigate if immersive fullscreen can be enabled fo
r |
| 605 // // Windows Ash. |
| 606 // if (ash::switches::UseImmersiveFullscreenForAllWindows()) { |
| 607 // immersive_fullscreen_controller_.reset( |
| 608 // new ash::ImmersiveFullscreenController()); |
| 609 // custom_frame_view->InitImmersiveFullscreenControllerForView( |
| 610 // immersive_fullscreen_controller_.get()); |
| 611 // } |
| 612 //#endif |
| 613 // custom_frame_view->GetHeaderView()->set_context_menu_controller(this); |
| 614 // return custom_frame_view; |
| 615 // } |
| 616 // } |
| 617 //#endif |
| 618 // if (ShouldUseChromeStyleFrame()) |
| 619 // return CreateAppWindowFrameView(); |
| 620 // return views::WidgetDelegateView::CreateNonClientFrameView(widget); |
| 621 //} |
| 622 |
| 623 bool NativeAppWindowViews::WidgetHasHitTestMask() const { |
| 624 return shape_ != NULL; |
| 625 } |
| 626 |
| 627 void NativeAppWindowViews::GetWidgetHitTestMask(gfx::Path* mask) const { |
| 628 shape_->getBoundaryPath(mask); |
| 629 } |
| 630 |
| 631 bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling( |
| 632 gfx::NativeView child, |
| 633 const gfx::Point& location) { |
| 634 #if defined(USE_AURA) |
| 635 if (child->Contains(web_view_->web_contents()->GetView()->GetNativeView())) { |
| 636 // App window should claim mouse events that fall within the draggable |
| 637 // region. |
| 638 return !draggable_region_.get() || |
| 639 !draggable_region_->contains(location.x(), location.y()); |
| 640 } |
| 641 #endif |
| 642 |
| 643 return true; |
| 644 } |
| 645 |
| 646 // WidgetObserver implementation. |
| 647 |
| 648 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget, |
| 649 bool visible) { |
| 650 app_window_->OnNativeWindowChanged(); |
| 651 } |
| 652 |
| 653 void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget* widget, |
| 654 bool active) { |
| 655 app_window_->OnNativeWindowChanged(); |
| 656 if (active) |
| 657 app_window_->OnNativeWindowActivated(); |
| 658 } |
| 659 |
| 660 // WebContentsObserver implementation. |
| 661 |
| 662 void NativeAppWindowViews::RenderViewCreated( |
| 663 content::RenderViewHost* render_view_host) { |
| 664 if (transparent_background_) { |
| 665 // Use a background with transparency to trigger transparency in Webkit. |
| 666 SkBitmap background; |
| 667 background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); |
| 668 background.allocPixels(); |
| 669 background.eraseARGB(0x00, 0x00, 0x00, 0x00); |
| 670 |
| 671 content::RenderWidgetHostView* view = render_view_host->GetView(); |
| 672 DCHECK(view); |
| 673 view->SetBackground(background); |
| 674 } |
| 675 } |
| 676 |
| 677 void NativeAppWindowViews::RenderViewHostChanged( |
| 678 content::RenderViewHost* old_host, |
| 679 content::RenderViewHost* new_host) { |
| 680 OnViewWasResized(); |
| 681 } |
| 682 |
| 683 // views::View implementation. |
| 684 |
| 685 void NativeAppWindowViews::Layout() { |
| 686 DCHECK(web_view_); |
| 687 web_view_->SetBounds(0, 0, width(), height()); |
| 688 OnViewWasResized(); |
| 689 } |
| 690 |
| 691 void NativeAppWindowViews::ViewHierarchyChanged( |
| 692 const ViewHierarchyChangedDetails& details) { |
| 693 if (details.is_add && details.child == this) { |
| 694 web_view_ = new views::WebView(NULL); |
| 695 AddChildView(web_view_); |
| 696 web_view_->SetWebContents(app_window_->web_contents()); |
| 697 } |
| 698 } |
| 699 |
| 700 //gfx::Size NativeAppWindowViews::GetPreferredSize() { |
| 701 // if (!preferred_size_.IsEmpty()) |
| 702 // return preferred_size_; |
| 703 // return views::View::GetPreferredSize(); |
| 704 //} |
| 705 |
| 706 gfx::Size NativeAppWindowViews::GetMinimumSize() { |
| 707 return app_window_->size_constraints().GetMinimumSize(); |
| 708 } |
| 709 |
| 710 gfx::Size NativeAppWindowViews::GetMaximumSize() { |
| 711 return app_window_->size_constraints().GetMaximumSize(); |
| 712 } |
| 713 |
| 714 void NativeAppWindowViews::OnFocus() { |
| 715 web_view_->RequestFocus(); |
| 716 } |
| 717 |
| 718 //bool NativeAppWindowViews::AcceleratorPressed( |
| 719 // const ui::Accelerator& accelerator) { |
| 720 // const std::map<ui::Accelerator, int>& accelerator_table = |
| 721 // GetAcceleratorTable(); |
| 722 // std::map<ui::Accelerator, int>::const_iterator iter = |
| 723 // accelerator_table.find(accelerator); |
| 724 // DCHECK(iter != accelerator_table.end()); |
| 725 // int command_id = iter->second; |
| 726 // switch (command_id) { |
| 727 // case IDC_CLOSE_WINDOW: |
| 728 // Close(); |
| 729 // return true; |
| 730 // case IDC_ZOOM_MINUS: |
| 731 // chrome_page_zoom::Zoom(web_view_->GetWebContents(), |
| 732 // content::PAGE_ZOOM_OUT); |
| 733 // return true; |
| 734 // case IDC_ZOOM_NORMAL: |
| 735 // chrome_page_zoom::Zoom(web_view_->GetWebContents(), |
| 736 // content::PAGE_ZOOM_RESET); |
| 737 // return true; |
| 738 // case IDC_ZOOM_PLUS: |
| 739 // chrome_page_zoom::Zoom(web_view_->GetWebContents(), |
| 740 // content::PAGE_ZOOM_IN); |
| 741 // return true; |
| 742 // default: |
| 743 // NOTREACHED() << "Unknown accelerator sent to app window."; |
| 744 // } |
| 745 // return false; |
| 746 //} |
| 747 |
| 748 // NativeAppWindow implementation. |
| 749 |
| 750 //void NativeAppWindowViews::SetFullscreen(int fullscreen_types) { |
| 751 // // Fullscreen not supported by panels. |
| 752 // if (app_window_->window_type_is_panel()) |
| 753 // return; |
| 754 // is_fullscreen_ = (fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); |
| 755 // window_->SetFullscreen(is_fullscreen_); |
| 756 // |
| 757 //#if defined(USE_ASH) |
| 758 // if (immersive_fullscreen_controller_.get()) { |
| 759 // // |immersive_fullscreen_controller_| should only be set if immersive |
| 760 // // fullscreen is the fullscreen type used by the OS. |
| 761 // immersive_fullscreen_controller_->SetEnabled( |
| 762 // ash::ImmersiveFullscreenController::WINDOW_TYPE_PACKAGED_APP, |
| 763 // (fullscreen_types & AppWindow::FULLSCREEN_TYPE_OS) != 0); |
| 764 // // Autohide the shelf instead of hiding the shelf completely when only in |
| 765 // // OS fullscreen. |
| 766 // ash::wm::WindowState* window_state = |
| 767 // ash::wm::GetWindowState(window_->GetNativeWindow()); |
| 768 // window_state->set_hide_shelf_when_fullscreen(fullscreen_types != |
| 769 // AppWindow::FULLSCREEN_TYPE_OS
); |
| 770 // DCHECK(ash::Shell::HasInstance()); |
| 771 // ash::Shell::GetInstance()->UpdateShelfVisibility(); |
| 772 // } |
| 773 //#endif |
| 774 // |
| 775 // // TODO(jeremya) we need to call RenderViewHost::ExitFullscreen() if we |
| 776 // // ever drop the window out of fullscreen in response to something that |
| 777 // // wasn't the app calling webkitCancelFullScreen(). |
| 778 //} |
| 779 // |
| 780 //bool NativeAppWindowViews::IsFullscreenOrPending() const { |
| 781 // return is_fullscreen_; |
| 782 //} |
| 783 |
| 784 //bool NativeAppWindowViews::IsDetached() const { |
| 785 // if (!app_window_->window_type_is_panel()) |
| 786 // return false; |
| 787 //#if defined(USE_ASH) |
| 788 // return !ash::wm::GetWindowState(window_->GetNativeWindow())->panel_attached(
); |
| 789 //#else |
| 790 // return false; |
| 791 //#endif |
| 792 //} |
| 793 |
| 794 void NativeAppWindowViews::UpdateWindowIcon() { |
| 795 window_->UpdateWindowIcon(); |
| 796 } |
| 797 |
| 798 void NativeAppWindowViews::UpdateWindowTitle() { |
| 799 window_->UpdateWindowTitle(); |
| 800 } |
| 801 |
| 802 //void NativeAppWindowViews::UpdateBadgeIcon() { |
| 803 // const gfx::Image* icon = NULL; |
| 804 // if (!app_window_->badge_icon().IsEmpty()) { |
| 805 // icon = &app_window_->badge_icon(); |
| 806 // // chrome::DrawTaskbarDecoration can do interesting things with non-square |
| 807 // // bitmaps. |
| 808 // // TODO(benwells): Refactor chrome::DrawTaskbarDecoration to not be avatar |
| 809 // // specific, and lift this restriction. |
| 810 // if (icon->Width() != icon->Height()) { |
| 811 // LOG(ERROR) << "Attempt to set a non-square badge; request ignored."; |
| 812 // return; |
| 813 // } |
| 814 // } |
| 815 // chrome::DrawTaskbarDecoration(GetNativeWindow(), icon); |
| 816 //} |
| 817 |
| 818 void NativeAppWindowViews::UpdateDraggableRegions( |
| 819 const std::vector<extensions::DraggableRegion>& regions) { |
| 820 // Draggable region is not supported for non-frameless window. |
| 821 if (!frameless_) |
| 822 return; |
| 823 |
| 824 draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions)); |
| 825 OnViewWasResized(); |
| 826 } |
| 827 |
| 828 SkRegion* NativeAppWindowViews::GetDraggableRegion() { |
| 829 return draggable_region_.get(); |
| 830 } |
| 831 |
| 832 void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) { |
| 833 bool had_shape = shape_; |
| 834 shape_ = region.Pass(); |
| 835 |
| 836 aura::Window* native_window = window_->GetNativeWindow(); |
| 837 if (shape_) { |
| 838 window_->SetShape(new SkRegion(*shape_)); |
| 839 if (!had_shape) { |
| 840 native_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( |
| 841 new ShapedAppWindowTargeter(native_window, this))); |
| 842 } |
| 843 } else { |
| 844 window_->SetShape(NULL); |
| 845 if (had_shape) |
| 846 native_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>()); |
| 847 } |
| 848 } |
| 849 |
| 850 void NativeAppWindowViews::HandleKeyboardEvent( |
| 851 const content::NativeWebKeyboardEvent& event) { |
| 852 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, |
| 853 GetFocusManager()); |
| 854 } |
| 855 |
| 856 bool NativeAppWindowViews::IsFrameless() const { |
| 857 return frameless_; |
| 858 } |
| 859 |
| 860 gfx::Insets NativeAppWindowViews::GetFrameInsets() const { |
| 861 if (frameless_) |
| 862 return gfx::Insets(); |
| 863 |
| 864 // The pretend client_bounds passed in need to be large enough to ensure that |
| 865 // GetWindowBoundsForClientBounds() doesn't decide that it needs more than |
| 866 // the specified amount of space to fit the window controls in, and return a |
| 867 // number larger than the real frame insets. Most window controls are smaller |
| 868 // than 1000x1000px, so this should be big enough. |
| 869 gfx::Rect client_bounds = gfx::Rect(1000, 1000); |
| 870 gfx::Rect window_bounds = |
| 871 window_->non_client_view()->GetWindowBoundsForClientBounds( |
| 872 client_bounds); |
| 873 return window_bounds.InsetsFrom(client_bounds); |
| 874 } |
| 875 |
| 876 void NativeAppWindowViews::HideWithApp() {} |
| 877 void NativeAppWindowViews::ShowWithApp() {} |
| 878 void NativeAppWindowViews::UpdateWindowMinMaxSize() {} |
OLD | NEW |