| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 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/views/frame/aero_glass_frame.h" | |
| 6 | |
| 7 #include <dwmapi.h> | |
| 8 | |
| 9 #include "chrome/browser/browser_list.h" | |
| 10 #include "chrome/browser/views/frame/browser_view.h" | |
| 11 #include "chrome/browser/views/frame/aero_glass_non_client_view.h" | |
| 12 #include "chrome/common/resource_bundle.h" | |
| 13 #include "chrome/views/window_delegate.h" | |
| 14 #include "grit/theme_resources.h" | |
| 15 | |
| 16 // static | |
| 17 | |
| 18 static const int kClientEdgeThickness = 3; | |
| 19 | |
| 20 HICON AeroGlassFrame::throbber_icons_[AeroGlassFrame::kThrobberIconCount]; | |
| 21 | |
| 22 /////////////////////////////////////////////////////////////////////////////// | |
| 23 // AeroGlassFrame, public: | |
| 24 | |
| 25 AeroGlassFrame::AeroGlassFrame(BrowserView* browser_view) | |
| 26 : Window(browser_view), | |
| 27 browser_view_(browser_view), | |
| 28 frame_initialized_(false), | |
| 29 throbber_running_(false), | |
| 30 throbber_frame_(0) { | |
| 31 non_client_view_ = new AeroGlassNonClientView(this, browser_view); | |
| 32 browser_view_->set_frame(this); | |
| 33 | |
| 34 if (window_delegate()->ShouldShowWindowIcon()) | |
| 35 InitThrobberIcons(); | |
| 36 } | |
| 37 | |
| 38 AeroGlassFrame::~AeroGlassFrame() { | |
| 39 } | |
| 40 | |
| 41 void AeroGlassFrame::Init() { | |
| 42 Window::Init(NULL, gfx::Rect()); | |
| 43 } | |
| 44 | |
| 45 int AeroGlassFrame::GetMinimizeButtonOffset() const { | |
| 46 TITLEBARINFOEX titlebar_info; | |
| 47 titlebar_info.cbSize = sizeof(TITLEBARINFOEX); | |
| 48 SendMessage(GetHWND(), WM_GETTITLEBARINFOEX, 0, (WPARAM)&titlebar_info); | |
| 49 | |
| 50 CPoint minimize_button_corner(titlebar_info.rgrect[2].left, | |
| 51 titlebar_info.rgrect[2].top); | |
| 52 MapWindowPoints(HWND_DESKTOP, GetHWND(), &minimize_button_corner, 1); | |
| 53 | |
| 54 return minimize_button_corner.x; | |
| 55 } | |
| 56 | |
| 57 /////////////////////////////////////////////////////////////////////////////// | |
| 58 // AeroGlassFrame, BrowserFrame implementation: | |
| 59 | |
| 60 gfx::Rect AeroGlassFrame::GetWindowBoundsForClientBounds( | |
| 61 const gfx::Rect& client_bounds) { | |
| 62 RECT rect = client_bounds.ToRECT(); | |
| 63 AdjustWindowRectEx(&rect, window_style(), FALSE, window_ex_style()); | |
| 64 return gfx::Rect(rect); | |
| 65 } | |
| 66 | |
| 67 gfx::Rect AeroGlassFrame::GetBoundsForTabStrip(TabStrip* tabstrip) const { | |
| 68 return GetAeroGlassNonClientView()->GetBoundsForTabStrip(tabstrip); | |
| 69 } | |
| 70 | |
| 71 void AeroGlassFrame::UpdateThrobber(bool running) { | |
| 72 if (throbber_running_) { | |
| 73 if (running) { | |
| 74 DisplayNextThrobberFrame(); | |
| 75 } else { | |
| 76 StopThrobber(); | |
| 77 } | |
| 78 } else if (running) { | |
| 79 StartThrobber(); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 views::Window* AeroGlassFrame::GetWindow() { | |
| 84 return this; | |
| 85 } | |
| 86 | |
| 87 const views::Window* AeroGlassFrame::GetWindow() const { | |
| 88 return this; | |
| 89 } | |
| 90 | |
| 91 /////////////////////////////////////////////////////////////////////////////// | |
| 92 // AeroGlassFrame, views::WidgetWin overrides: | |
| 93 | |
| 94 bool AeroGlassFrame::AcceleratorPressed(views::Accelerator* accelerator) { | |
| 95 return browser_view_->AcceleratorPressed(*accelerator); | |
| 96 } | |
| 97 | |
| 98 bool AeroGlassFrame::GetAccelerator(int cmd_id, | |
| 99 views::Accelerator* accelerator) { | |
| 100 return browser_view_->GetAccelerator(cmd_id, accelerator); | |
| 101 } | |
| 102 | |
| 103 void AeroGlassFrame::OnInitMenuPopup(HMENU menu, UINT position, | |
| 104 BOOL is_system_menu) { | |
| 105 browser_view_->PrepareToRunSystemMenu(menu); | |
| 106 } | |
| 107 | |
| 108 void AeroGlassFrame::OnEnterSizeMove() { | |
| 109 browser_view_->WindowMoveOrResizeStarted(); | |
| 110 } | |
| 111 | |
| 112 void AeroGlassFrame::OnEndSession(BOOL ending, UINT logoff) { | |
| 113 BrowserList::WindowsSessionEnding(); | |
| 114 } | |
| 115 | |
| 116 LRESULT AeroGlassFrame::OnMouseActivate(HWND window, UINT hittest_code, | |
| 117 UINT message) { | |
| 118 return browser_view_->ActivateAppModalDialog() ? MA_NOACTIVATEANDEAT | |
| 119 : MA_ACTIVATE; | |
| 120 } | |
| 121 | |
| 122 void AeroGlassFrame::OnMove(const CPoint& point) { | |
| 123 browser_view_->WindowMoved(); | |
| 124 } | |
| 125 | |
| 126 void AeroGlassFrame::OnMoving(UINT param, const RECT* new_bounds) { | |
| 127 browser_view_->WindowMoved(); | |
| 128 } | |
| 129 | |
| 130 LRESULT AeroGlassFrame::OnNCActivate(BOOL active) { | |
| 131 if (browser_view_->ActivateAppModalDialog()) | |
| 132 return TRUE; | |
| 133 | |
| 134 if (!frame_initialized_) { | |
| 135 if (browser_view_->IsBrowserTypeNormal()) { | |
| 136 ::SetWindowPos(GetHWND(), NULL, 0, 0, 0, 0, | |
| 137 SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED); | |
| 138 UpdateDWMFrame(); | |
| 139 } | |
| 140 frame_initialized_ = true; | |
| 141 } | |
| 142 browser_view_->ActivationChanged(!!active); | |
| 143 SetMsgHandled(false); | |
| 144 return TRUE; | |
| 145 } | |
| 146 | |
| 147 LRESULT AeroGlassFrame::OnNCCalcSize(BOOL mode, LPARAM l_param) { | |
| 148 if (!browser_view_->IsBrowserTypeNormal() || !mode) { | |
| 149 SetMsgHandled(FALSE); | |
| 150 return 0; | |
| 151 } | |
| 152 | |
| 153 // In fullscreen mode, we make the whole window client area. | |
| 154 if (!browser_view_->IsFullscreen()) { | |
| 155 NCCALCSIZE_PARAMS* params = reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param); | |
| 156 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); | |
| 157 params->rgrc[0].left += (border_thickness - kClientEdgeThickness); | |
| 158 params->rgrc[0].right -= (border_thickness - kClientEdgeThickness); | |
| 159 params->rgrc[0].bottom -= (border_thickness - kClientEdgeThickness); | |
| 160 } | |
| 161 | |
| 162 UpdateDWMFrame(); | |
| 163 | |
| 164 SetMsgHandled(TRUE); | |
| 165 return 0; | |
| 166 } | |
| 167 | |
| 168 LRESULT AeroGlassFrame::OnNCHitTest(const CPoint& pt) { | |
| 169 LRESULT result; | |
| 170 if (DwmDefWindowProc(GetHWND(), WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y), | |
| 171 &result)) { | |
| 172 return result; | |
| 173 } | |
| 174 return Window::OnNCHitTest(pt); | |
| 175 } | |
| 176 | |
| 177 /////////////////////////////////////////////////////////////////////////////// | |
| 178 // AeroGlassFrame, views::CustomFrameWindow overrides: | |
| 179 | |
| 180 int AeroGlassFrame::GetShowState() const { | |
| 181 return browser_view_->GetShowState(); | |
| 182 } | |
| 183 | |
| 184 /////////////////////////////////////////////////////////////////////////////// | |
| 185 // AeroGlassFrame, private: | |
| 186 | |
| 187 void AeroGlassFrame::UpdateDWMFrame() { | |
| 188 // Nothing to do yet. | |
| 189 if (!client_view()) | |
| 190 return; | |
| 191 | |
| 192 // In fullscreen mode, we don't extend glass into the client area at all, | |
| 193 // because the GDI-drawn text in the web content composited over it will | |
| 194 // become semi-transparent over any glass area. | |
| 195 MARGINS margins = { 0 }; | |
| 196 if (!browser_view_->IsFullscreen()) { | |
| 197 margins.cxLeftWidth = kClientEdgeThickness + 1; | |
| 198 margins.cxRightWidth = kClientEdgeThickness + 1; | |
| 199 margins.cyTopHeight = | |
| 200 GetBoundsForTabStrip(browser_view_->tabstrip()).bottom(); | |
| 201 margins.cyBottomHeight = kClientEdgeThickness + 1; | |
| 202 } | |
| 203 DwmExtendFrameIntoClientArea(GetHWND(), &margins); | |
| 204 } | |
| 205 | |
| 206 AeroGlassNonClientView* AeroGlassFrame::GetAeroGlassNonClientView() const { | |
| 207 // We can safely assume that this conversion is true. | |
| 208 return static_cast<AeroGlassNonClientView*>(non_client_view_); | |
| 209 } | |
| 210 | |
| 211 void AeroGlassFrame::StartThrobber() { | |
| 212 if (!throbber_running_) { | |
| 213 throbber_running_ = true; | |
| 214 throbber_frame_ = 0; | |
| 215 InitThrobberIcons(); | |
| 216 ::SendMessage(GetHWND(), WM_SETICON, static_cast<WPARAM>(ICON_SMALL), | |
| 217 reinterpret_cast<LPARAM>(throbber_icons_[throbber_frame_])); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 void AeroGlassFrame::StopThrobber() { | |
| 222 if (throbber_running_) | |
| 223 throbber_running_ = false; | |
| 224 } | |
| 225 | |
| 226 void AeroGlassFrame::DisplayNextThrobberFrame() { | |
| 227 throbber_frame_ = (throbber_frame_ + 1) % kThrobberIconCount; | |
| 228 ::SendMessage(GetHWND(), WM_SETICON, static_cast<WPARAM>(ICON_SMALL), | |
| 229 reinterpret_cast<LPARAM>(throbber_icons_[throbber_frame_])); | |
| 230 } | |
| 231 | |
| 232 // static | |
| 233 void AeroGlassFrame::InitThrobberIcons() { | |
| 234 static bool initialized = false; | |
| 235 if (!initialized) { | |
| 236 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); | |
| 237 for (int i = 0; i < kThrobberIconCount; ++i) { | |
| 238 throbber_icons_[i] = rb.LoadThemeIcon(IDR_THROBBER_01 + i); | |
| 239 DCHECK(throbber_icons_[i]); | |
| 240 } | |
| 241 initialized = true; | |
| 242 } | |
| 243 } | |
| OLD | NEW |