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 |