OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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 "chrome/browser/ui/views/panels/panel_stack_view.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/browser/profiles/profile.h" |
| 10 #include "chrome/browser/ui/panels/panel.h" |
| 11 #include "chrome/browser/ui/panels/stacked_panel_collection.h" |
| 12 #include "chrome/common/extensions/extension.h" |
| 13 #include "ui/gfx/rect.h" |
| 14 #include "ui/views/widget/widget.h" |
| 15 |
| 16 #if defined(OS_WIN) |
| 17 #include "chrome/browser/shell_integration.h" |
| 18 #include "ui/base/win/shell.h" |
| 19 #endif |
| 20 |
| 21 // static |
| 22 NativePanelStack* NativePanelStack::Create( |
| 23 scoped_ptr<StackedPanelCollection> stacked_collection) { |
| 24 #if defined(OS_WIN) |
| 25 return new PanelStackView(stacked_collection.Pass()); |
| 26 #else |
| 27 NOTIMPLEMENTED(); |
| 28 return NULL; |
| 29 #endif |
| 30 } |
| 31 |
| 32 PanelStackView::PanelStackView( |
| 33 scoped_ptr<StackedPanelCollection> stacked_collection) |
| 34 : stacked_collection_(stacked_collection.Pass()), |
| 35 delay_initialized_(false), |
| 36 window_(NULL) { |
| 37 window_ = new views::Widget; |
| 38 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); |
| 39 params.delegate = this; |
| 40 params.remove_standard_frame = true; |
| 41 params.transparent = true; |
| 42 // Empty size is not allowed so a temporary small size is passed. SetBounds |
| 43 // will be called later to update the bounds. |
| 44 params.bounds = gfx::Rect(0, 0, 1, 1); |
| 45 window_->Init(params); |
| 46 window_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); |
| 47 window_->set_focus_on_creation(false); |
| 48 window_->AddObserver(this); |
| 49 window_->ShowInactive(); |
| 50 } |
| 51 |
| 52 PanelStackView::~PanelStackView() { |
| 53 } |
| 54 |
| 55 void PanelStackView::EnsureInitialized() { |
| 56 // The stack view cannot be fully initialized until the first panel has been |
| 57 // added to the stack because we need the information from that panel. |
| 58 if (delay_initialized_) |
| 59 return; |
| 60 Panel* panel = stacked_collection_->top_panel(); |
| 61 if (!panel) |
| 62 return; |
| 63 delay_initialized_ = true; |
| 64 |
| 65 #if defined(OS_WIN) && !defined(USE_AURA) |
| 66 ui::win::SetAppIdForWindow( |
| 67 ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(panel->app_name()), |
| 68 panel->profile()->GetPath()), |
| 69 window_->GetNativeWindow()); |
| 70 #endif |
| 71 } |
| 72 |
| 73 void PanelStackView::Close() { |
| 74 window_->Close(); |
| 75 } |
| 76 |
| 77 void PanelStackView::OnPanelAddedOrRemoved(Panel* panel) { |
| 78 EnsureInitialized(); |
| 79 |
| 80 UpdateWindowOwnerForTaskbarIconAppearance(panel); |
| 81 |
| 82 window_->UpdateWindowTitle(); |
| 83 window_->UpdateWindowIcon(); |
| 84 } |
| 85 |
| 86 void PanelStackView::SetBounds(const gfx::Rect& bounds) { |
| 87 window_->SetBounds(bounds); |
| 88 } |
| 89 |
| 90 string16 PanelStackView::GetWindowTitle() const { |
| 91 Panel* panel = stacked_collection_->top_panel(); |
| 92 if (!panel) |
| 93 return string16(); |
| 94 |
| 95 const extensions::Extension* extension = panel->GetExtension(); |
| 96 return UTF8ToUTF16(extension && !extension->name().empty() ? |
| 97 extension->name() : panel->app_name()); |
| 98 } |
| 99 |
| 100 gfx::ImageSkia PanelStackView::GetWindowAppIcon() { |
| 101 Panel* panel = stacked_collection_->top_panel(); |
| 102 if (panel) { |
| 103 gfx::Image app_icon = panel->app_icon(); |
| 104 if (!app_icon.IsEmpty()) |
| 105 return *app_icon.ToImageSkia(); |
| 106 } |
| 107 return gfx::ImageSkia(); |
| 108 } |
| 109 |
| 110 gfx::ImageSkia PanelStackView::GetWindowIcon() { |
| 111 return GetWindowAppIcon(); |
| 112 } |
| 113 |
| 114 views::Widget* PanelStackView::GetWidget() { |
| 115 return window_; |
| 116 } |
| 117 |
| 118 const views::Widget* PanelStackView::GetWidget() const { |
| 119 return window_; |
| 120 } |
| 121 |
| 122 void PanelStackView::DeleteDelegate() { |
| 123 delete this; |
| 124 } |
| 125 |
| 126 void PanelStackView::OnWidgetClosing(views::Widget* widget) { |
| 127 window_ = NULL; |
| 128 } |
| 129 |
| 130 void PanelStackView::UpdateWindowOwnerForTaskbarIconAppearance(Panel* panel) { |
| 131 #if defined(OS_WIN) && !defined(USE_AURA) |
| 132 HWND panel_window = panel->GetNativeWindow(); |
| 133 |
| 134 HWND stack_window = NULL; |
| 135 StackedPanelCollection* stack = panel->stack(); |
| 136 if (stack) { |
| 137 stack_window = static_cast<PanelStackView*>(stack->native_stack())-> |
| 138 window_->GetNativeWindow(); |
| 139 } |
| 140 |
| 141 // The extended style WS_EX_APPWINDOW is used to force a top-level window onto |
| 142 // the taskbar. In order for multiple stacked panels to appear as one, this |
| 143 // bit needs to be cleared. |
| 144 int value = ::GetWindowLong(panel_window, GWL_EXSTYLE); |
| 145 ::SetWindowLong( |
| 146 panel_window, |
| 147 GWL_EXSTYLE, |
| 148 stack_window ? (value & ~WS_EX_APPWINDOW) : (value | WS_EX_APPWINDOW)); |
| 149 |
| 150 // All the windows that share the same owner window will appear as a single |
| 151 // window on the taskbar. |
| 152 ::SetWindowLong(panel_window, |
| 153 GWL_HWNDPARENT, |
| 154 reinterpret_cast<LONG>(stack_window)); |
| 155 |
| 156 #else |
| 157 NOTIMPLEMENTED(); |
| 158 #endif |
| 159 } |
OLD | NEW |