| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/frame/browser_frame_win.h" | 5 #include "chrome/browser/ui/views/frame/browser_frame_win.h" |
| 6 | 6 |
| 7 #include <dwmapi.h> | 7 #include <dwmapi.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| 11 | 11 |
| 12 #include "chrome/browser/accessibility/browser_accessibility_state.h" | 12 #include "chrome/browser/accessibility/browser_accessibility_state.h" |
| 13 #include "chrome/browser/profiles/profile.h" | |
| 14 #include "chrome/browser/themes/theme_service.h" | |
| 15 #include "chrome/browser/themes/theme_service_factory.h" | |
| 16 #include "chrome/browser/ui/browser_list.h" | 13 #include "chrome/browser/ui/browser_list.h" |
| 17 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" | |
| 18 #include "chrome/browser/ui/views/frame/browser_view.h" | 14 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 19 #include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" | |
| 20 #include "grit/theme_resources.h" | 15 #include "grit/theme_resources.h" |
| 21 #include "ui/gfx/font.h" | 16 #include "ui/gfx/font.h" |
| 22 #include "views/screen.h" | 17 #include "views/screen.h" |
| 23 #include "views/widget/root_view.h" | 18 #include "views/window/non_client_view.h" |
| 24 #include "views/widget/widget_win.h" | 19 #include "views/window/window.h" |
| 25 #include "views/window/window_win.h" | |
| 26 | 20 |
| 27 // static | 21 // static |
| 28 static const int kClientEdgeThickness = 3; | 22 static const int kClientEdgeThickness = 3; |
| 29 static const int kTabDragWindowAlpha = 200; | 23 static const int kTabDragWindowAlpha = 200; |
| 30 // We need to offset the DWMFrame into the toolbar so that the blackness | 24 // We need to offset the DWMFrame into the toolbar so that the blackness |
| 31 // doesn't show up on our rounded corners. | 25 // doesn't show up on our rounded corners. |
| 32 static const int kDWMFrameTopOffset = 3; | 26 static const int kDWMFrameTopOffset = 3; |
| 33 // If not -1, windows are shown with this state. | 27 // If not -1, windows are shown with this state. |
| 34 static int explicit_show_state = -1; | 28 static int explicit_show_state = -1; |
| 35 | 29 |
| 36 // static (Factory method.) | |
| 37 BrowserFrame* BrowserFrame::Create(BrowserView* browser_view, | |
| 38 Profile* profile) { | |
| 39 BrowserFrame* frame = new BrowserFrameWin(browser_view, profile); | |
| 40 | |
| 41 views::Window::InitParams params(browser_view); | |
| 42 frame->GetWindow()->InitWindow(params); | |
| 43 return frame; | |
| 44 } | |
| 45 | |
| 46 /////////////////////////////////////////////////////////////////////////////// | 30 /////////////////////////////////////////////////////////////////////////////// |
| 47 // BrowserFrameWin, public: | 31 // BrowserFrameWin, public: |
| 48 | 32 |
| 49 BrowserFrameWin::BrowserFrameWin(BrowserView* browser_view, Profile* profile) | 33 BrowserFrameWin::BrowserFrameWin(BrowserFrame* browser_frame, |
| 50 : BrowserFrame(browser_view), | 34 BrowserView* browser_view) |
| 35 : views::WindowWin(browser_frame), |
| 51 browser_view_(browser_view), | 36 browser_view_(browser_view), |
| 52 ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this)) { | 37 browser_frame_(browser_frame) { |
| 53 set_native_browser_frame(this); | |
| 54 browser_view_->set_frame(this); | |
| 55 non_client_view()->SetFrameView(CreateFrameViewForWindow()); | |
| 56 // Don't focus anything on creation, selecting a tab will set the focus. | 38 // Don't focus anything on creation, selecting a tab will set the focus. |
| 57 set_focus_on_creation(false); | 39 set_focus_on_creation(false); |
| 58 } | 40 } |
| 59 | 41 |
| 60 BrowserFrameWin::~BrowserFrameWin() { | 42 BrowserFrameWin::~BrowserFrameWin() { |
| 61 } | 43 } |
| 62 | 44 |
| 63 // static | 45 // static |
| 64 void BrowserFrameWin::SetShowState(int state) { | 46 void BrowserFrameWin::SetShowState(int state) { |
| 65 explicit_show_state = state; | 47 explicit_show_state = state; |
| 66 } | 48 } |
| 67 | 49 |
| 68 /////////////////////////////////////////////////////////////////////////////// | 50 /////////////////////////////////////////////////////////////////////////////// |
| 69 // BrowserFrameWin, views::WindowWin overrides: | 51 // BrowserFrameWin, views::WindowWin overrides: |
| 70 | 52 |
| 71 int BrowserFrameWin::GetShowState() const { | 53 int BrowserFrameWin::GetShowState() const { |
| 72 if (explicit_show_state != -1) | 54 if (explicit_show_state != -1) |
| 73 return explicit_show_state; | 55 return explicit_show_state; |
| 74 | 56 |
| 75 STARTUPINFO si = {0}; | 57 STARTUPINFO si = {0}; |
| 76 si.cb = sizeof(si); | 58 si.cb = sizeof(si); |
| 77 si.dwFlags = STARTF_USESHOWWINDOW; | 59 si.dwFlags = STARTF_USESHOWWINDOW; |
| 78 GetStartupInfo(&si); | 60 GetStartupInfo(&si); |
| 79 return si.wShowWindow; | 61 return si.wShowWindow; |
| 80 } | 62 } |
| 81 | 63 |
| 82 gfx::Insets BrowserFrameWin::GetClientAreaInsets() const { | 64 gfx::Insets BrowserFrameWin::GetClientAreaInsets() const { |
| 83 // Use the default client insets for an opaque frame or a glass popup/app | 65 // Use the default client insets for an opaque frame or a glass popup/app |
| 84 // frame. | 66 // frame. |
| 85 if (!non_client_view()->UseNativeFrame() || | 67 if (!GetWindow()->non_client_view()->UseNativeFrame() || |
| 86 !browser_view_->IsBrowserTypeNormal()) { | 68 !browser_view_->IsBrowserTypeNormal()) { |
| 87 return WindowWin::GetClientAreaInsets(); | 69 return WindowWin::GetClientAreaInsets(); |
| 88 } | 70 } |
| 89 | 71 |
| 90 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); | 72 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); |
| 91 // In fullscreen mode, we have no frame. In restored mode, we draw our own | 73 // In fullscreen mode, we have no frame. In restored mode, we draw our own |
| 92 // client edge over part of the default frame. | 74 // client edge over part of the default frame. |
| 93 if (IsFullscreen()) | 75 if (IsFullscreen()) |
| 94 border_thickness = 0; | 76 border_thickness = 0; |
| 95 else if (!IsMaximized()) | 77 else if (!IsMaximized()) |
| 96 border_thickness -= kClientEdgeThickness; | 78 border_thickness -= kClientEdgeThickness; |
| 97 return gfx::Insets(0, border_thickness, border_thickness, border_thickness); | 79 return gfx::Insets(0, border_thickness, border_thickness, border_thickness); |
| 98 } | 80 } |
| 99 | 81 |
| 100 bool BrowserFrameWin::GetAccelerator(int cmd_id, | 82 void BrowserFrameWin::UpdateFrameAfterFrameChange() { |
| 101 ui::Accelerator* accelerator) { | 83 // We need to update the glass region on or off before the base class adjusts |
| 102 return browser_view_->GetAccelerator(cmd_id, accelerator); | 84 // the window region. |
| 85 UpdateDWMFrame(); |
| 86 WindowWin::UpdateFrameAfterFrameChange(); |
| 103 } | 87 } |
| 104 | 88 |
| 105 void BrowserFrameWin::OnEndSession(BOOL ending, UINT logoff) { | 89 void BrowserFrameWin::OnEndSession(BOOL ending, UINT logoff) { |
| 106 BrowserList::SessionEnding(); | 90 BrowserList::SessionEnding(); |
| 107 } | 91 } |
| 108 | 92 |
| 109 void BrowserFrameWin::OnInitMenuPopup(HMENU menu, UINT position, | 93 void BrowserFrameWin::OnInitMenuPopup(HMENU menu, UINT position, |
| 110 BOOL is_system_menu) { | 94 BOOL is_system_menu) { |
| 111 browser_view_->PrepareToRunSystemMenu(menu); | 95 browser_view_->PrepareToRunSystemMenu(menu); |
| 112 } | 96 } |
| 113 | 97 |
| 114 void BrowserFrameWin::OnWindowPosChanged(WINDOWPOS* window_pos) { | 98 void BrowserFrameWin::OnWindowPosChanged(WINDOWPOS* window_pos) { |
| 115 WindowWin::OnWindowPosChanged(window_pos); | 99 WindowWin::OnWindowPosChanged(window_pos); |
| 116 UpdateDWMFrame(); | 100 UpdateDWMFrame(); |
| 117 | 101 |
| 118 // Windows lies to us about the position of the minimize button before a | 102 // Windows lies to us about the position of the minimize button before a |
| 119 // window is visible. We use this position to place the OTR avatar in RTL | 103 // window is visible. We use this position to place the OTR avatar in RTL |
| 120 // mode, so when the window is shown, we need to re-layout and schedule a | 104 // mode, so when the window is shown, we need to re-layout and schedule a |
| 121 // paint for the non-client frame view so that the icon top has the correct | 105 // paint for the non-client frame view so that the icon top has the correct |
| 122 // position when the window becomes visible. This fixes bugs where the icon | 106 // position when the window becomes visible. This fixes bugs where the icon |
| 123 // appears to overlay the minimize button. | 107 // appears to overlay the minimize button. |
| 124 // Note that we will call Layout every time SetWindowPos is called with | 108 // Note that we will call Layout every time SetWindowPos is called with |
| 125 // SWP_SHOWWINDOW, however callers typically are careful about not specifying | 109 // SWP_SHOWWINDOW, however callers typically are careful about not specifying |
| 126 // this flag unless necessary to avoid flicker. | 110 // this flag unless necessary to avoid flicker. |
| 127 if (window_pos->flags & SWP_SHOWWINDOW) { | 111 if (window_pos->flags & SWP_SHOWWINDOW) { |
| 128 non_client_view()->Layout(); | 112 GetWindow()->non_client_view()->Layout(); |
| 129 non_client_view()->SchedulePaint(); | 113 GetWindow()->non_client_view()->SchedulePaint(); |
| 130 } | 114 } |
| 131 } | 115 } |
| 132 | 116 |
| 133 ThemeProvider* BrowserFrameWin::GetThemeProvider() const { | |
| 134 return ThemeServiceFactory::GetForProfile( | |
| 135 browser_view_->browser()->profile()); | |
| 136 } | |
| 137 | |
| 138 void BrowserFrameWin::OnScreenReaderDetected() { | 117 void BrowserFrameWin::OnScreenReaderDetected() { |
| 139 BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); | 118 BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); |
| 140 WindowWin::OnScreenReaderDetected(); | 119 WindowWin::OnScreenReaderDetected(); |
| 141 } | 120 } |
| 142 | 121 |
| 143 /////////////////////////////////////////////////////////////////////////////// | |
| 144 // BrowserFrameWin, views::Window overrides: | |
| 145 | |
| 146 void BrowserFrameWin::Activate() { | |
| 147 // When running under remote desktop, if the remote desktop client is not | |
| 148 // active on the users desktop, then none of the windows contained in the | |
| 149 // remote desktop will be activated. However, WindowWin::Activate will still | |
| 150 // bring this browser window to the foreground. We explicitly set ourselves | |
| 151 // as the last active browser window to ensure that we get treated as such by | |
| 152 // the rest of Chrome. | |
| 153 BrowserList::SetLastActive(browser_view_->browser()); | |
| 154 | |
| 155 WindowWin::Activate(); | |
| 156 } | |
| 157 | |
| 158 void BrowserFrameWin::UpdateFrameAfterFrameChange() { | |
| 159 // We need to update the glass region on or off before the base class adjusts | |
| 160 // the window region. | |
| 161 UpdateDWMFrame(); | |
| 162 WindowWin::UpdateFrameAfterFrameChange(); | |
| 163 } | |
| 164 | |
| 165 views::RootView* BrowserFrameWin::CreateRootView() { | |
| 166 return delegate_->DelegateCreateRootView(); | |
| 167 } | |
| 168 | |
| 169 views::NonClientFrameView* BrowserFrameWin::CreateFrameViewForWindow() { | |
| 170 return delegate_->DelegateCreateFrameViewForWindow(); | |
| 171 } | |
| 172 | |
| 173 //////////////////////////////////////////////////////////////////////////////// | 122 //////////////////////////////////////////////////////////////////////////////// |
| 174 // BrowserFrameWin, NativeBrowserFrame implementation: | 123 // BrowserFrameWin, NativeBrowserFrame implementation: |
| 175 | 124 |
| 176 views::NativeWindow* BrowserFrameWin::AsNativeWindow() { | 125 views::NativeWindow* BrowserFrameWin::AsNativeWindow() { |
| 177 return this; | 126 return this; |
| 178 } | 127 } |
| 179 | 128 |
| 180 const views::NativeWindow* BrowserFrameWin::AsNativeWindow() const { | 129 const views::NativeWindow* BrowserFrameWin::AsNativeWindow() const { |
| 181 return this; | 130 return this; |
| 182 } | 131 } |
| 183 | 132 |
| 184 BrowserNonClientFrameView* BrowserFrameWin::CreateBrowserNonClientFrameView() { | |
| 185 if (AlwaysUseNativeFrame()) | |
| 186 return new GlassBrowserFrameView(this, browser_view_); | |
| 187 return browser::CreateBrowserNonClientFrameView(this, browser_view_); | |
| 188 } | |
| 189 | |
| 190 int BrowserFrameWin::GetMinimizeButtonOffset() const { | 133 int BrowserFrameWin::GetMinimizeButtonOffset() const { |
| 191 TITLEBARINFOEX titlebar_info; | 134 TITLEBARINFOEX titlebar_info; |
| 192 titlebar_info.cbSize = sizeof(TITLEBARINFOEX); | 135 titlebar_info.cbSize = sizeof(TITLEBARINFOEX); |
| 193 SendMessage(GetNativeView(), WM_GETTITLEBARINFOEX, 0, (WPARAM)&titlebar_info); | 136 SendMessage(GetNativeView(), WM_GETTITLEBARINFOEX, 0, (WPARAM)&titlebar_info); |
| 194 | 137 |
| 195 CPoint minimize_button_corner(titlebar_info.rgrect[2].left, | 138 CPoint minimize_button_corner(titlebar_info.rgrect[2].left, |
| 196 titlebar_info.rgrect[2].top); | 139 titlebar_info.rgrect[2].top); |
| 197 MapWindowPoints(HWND_DESKTOP, GetNativeView(), &minimize_button_corner, 1); | 140 MapWindowPoints(HWND_DESKTOP, GetNativeView(), &minimize_button_corner, 1); |
| 198 | 141 |
| 199 return minimize_button_corner.x; | 142 return minimize_button_corner.x; |
| 200 } | 143 } |
| 201 | 144 |
| 202 ui::ThemeProvider* BrowserFrameWin::GetThemeProviderForFrame() const { | |
| 203 // This is implemented for a different interface than GetThemeProvider is, | |
| 204 // but they mean the same things. | |
| 205 return GetThemeProvider(); | |
| 206 } | |
| 207 | |
| 208 bool BrowserFrameWin::AlwaysUseNativeFrame() const { | |
| 209 // App panel windows draw their own frame. | |
| 210 if (browser_view_->IsBrowserTypePanel() && browser_view_->IsBrowserTypeApp()) | |
| 211 return false; | |
| 212 | |
| 213 // We don't theme popup or app windows, so regardless of whether or not a | |
| 214 // theme is active for normal browser windows, we don't want to use the custom | |
| 215 // frame for popups/apps. | |
| 216 if (!browser_view_->IsBrowserTypeNormal() && | |
| 217 views::WidgetWin::IsAeroGlassEnabled()) | |
| 218 return true; | |
| 219 | |
| 220 // Otherwise, we use the native frame when we're told we should by the theme | |
| 221 // provider (e.g. no custom theme is active). | |
| 222 return GetThemeProvider()->ShouldUseNativeFrame(); | |
| 223 } | |
| 224 | |
| 225 void BrowserFrameWin::TabStripDisplayModeChanged() { | 145 void BrowserFrameWin::TabStripDisplayModeChanged() { |
| 226 if (GetRootView()->has_children()) { | |
| 227 // Make sure the child of the root view gets Layout again. | |
| 228 GetRootView()->GetChildViewAt(0)->InvalidateLayout(); | |
| 229 } | |
| 230 GetRootView()->Layout(); | |
| 231 | |
| 232 UpdateDWMFrame(); | 146 UpdateDWMFrame(); |
| 233 } | 147 } |
| 234 | 148 |
| 235 /////////////////////////////////////////////////////////////////////////////// | 149 /////////////////////////////////////////////////////////////////////////////// |
| 236 // BrowserFrameWin, private: | 150 // BrowserFrameWin, private: |
| 237 | 151 |
| 238 void BrowserFrameWin::UpdateDWMFrame() { | 152 void BrowserFrameWin::UpdateDWMFrame() { |
| 239 // Nothing to do yet, or we're not showing a DWM frame. | 153 // Nothing to do yet, or we're not showing a DWM frame. |
| 240 if (!client_view() || !AlwaysUseNativeFrame()) | 154 if (!GetWindow()->client_view() || !browser_frame_->AlwaysUseNativeFrame()) |
| 241 return; | 155 return; |
| 242 | 156 |
| 243 MARGINS margins = { 0 }; | 157 MARGINS margins = { 0 }; |
| 244 if (browser_view_->IsBrowserTypeNormal()) { | 158 if (browser_view_->IsBrowserTypeNormal()) { |
| 245 // In fullscreen mode, we don't extend glass into the client area at all, | 159 // In fullscreen mode, we don't extend glass into the client area at all, |
| 246 // because the GDI-drawn text in the web content composited over it will | 160 // because the GDI-drawn text in the web content composited over it will |
| 247 // become semi-transparent over any glass area. | 161 // become semi-transparent over any glass area. |
| 248 if (!IsMaximized() && !IsFullscreen()) { | 162 if (!IsMaximized() && !IsFullscreen()) { |
| 249 margins.cxLeftWidth = kClientEdgeThickness + 1; | 163 margins.cxLeftWidth = kClientEdgeThickness + 1; |
| 250 margins.cxRightWidth = kClientEdgeThickness + 1; | 164 margins.cxRightWidth = kClientEdgeThickness + 1; |
| 251 margins.cyBottomHeight = kClientEdgeThickness + 1; | 165 margins.cyBottomHeight = kClientEdgeThickness + 1; |
| 252 margins.cyTopHeight = kClientEdgeThickness + 1; | 166 margins.cyTopHeight = kClientEdgeThickness + 1; |
| 253 } | 167 } |
| 254 // In maximized mode, we only have a titlebar strip of glass, no side/bottom | 168 // In maximized mode, we only have a titlebar strip of glass, no side/bottom |
| 255 // borders. | 169 // borders. |
| 256 if (!browser_view_->IsFullscreen()) { | 170 if (!browser_view_->IsFullscreen()) { |
| 257 gfx::Rect tabstrip_bounds( | 171 gfx::Rect tabstrip_bounds( |
| 258 GetBoundsForTabStrip(browser_view_->tabstrip())); | 172 browser_frame_->GetBoundsForTabStrip(browser_view_->tabstrip())); |
| 259 margins.cyTopHeight = (browser_view_->UseVerticalTabs() ? | 173 margins.cyTopHeight = (browser_view_->UseVerticalTabs() ? |
| 260 tabstrip_bounds.y() : tabstrip_bounds.bottom()) + kDWMFrameTopOffset; | 174 tabstrip_bounds.y() : tabstrip_bounds.bottom()) + kDWMFrameTopOffset; |
| 261 } | 175 } |
| 262 } else { | 176 } else { |
| 263 // For popup and app windows we want to use the default margins. | 177 // For popup and app windows we want to use the default margins. |
| 264 } | 178 } |
| 265 DwmExtendFrameIntoClientArea(GetNativeView(), &margins); | 179 DwmExtendFrameIntoClientArea(GetNativeView(), &margins); |
| 266 } | 180 } |
| 267 | 181 |
| 268 //////////////////////////////////////////////////////////////////////////////// | 182 //////////////////////////////////////////////////////////////////////////////// |
| 269 // BrowserFrame, public: | 183 // BrowserFrame, public: |
| 270 | 184 |
| 271 // static | 185 // static |
| 272 const gfx::Font& BrowserFrame::GetTitleFont() { | 186 const gfx::Font& BrowserFrame::GetTitleFont() { |
| 273 static gfx::Font* title_font = | 187 static gfx::Font* title_font = |
| 274 new gfx::Font(views::WindowWin::GetWindowTitleFont()); | 188 new gfx::Font(views::WindowWin::GetWindowTitleFont()); |
| 275 return *title_font; | 189 return *title_font; |
| 276 } | 190 } |
| 277 | 191 |
| 192 //////////////////////////////////////////////////////////////////////////////// |
| 193 // NativeBrowserFrame, public: |
| 194 |
| 195 // static |
| 196 NativeBrowserFrame* NativeBrowserFrame::CreateNativeBrowserFrame( |
| 197 BrowserFrame* browser_frame, |
| 198 BrowserView* browser_view) { |
| 199 return new BrowserFrameWin(browser_frame, browser_view); |
| 200 } |
| 201 |
| OLD | NEW |