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