| 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/frame/browser_frame_win.h" | |
| 6 | |
| 7 #include <dwmapi.h> | |
| 8 #include <shellapi.h> | |
| 9 #include <set> | |
| 10 | |
| 11 #include "base/command_line.h" | |
| 12 #include "base/strings/utf_string_conversions.h" | |
| 13 #include "base/win/metro.h" | |
| 14 #include "chrome/app/chrome_command_ids.h" | |
| 15 #include "chrome/browser/lifetime/application_lifetime.h" | |
| 16 #include "chrome/browser/profiles/profile.h" | |
| 17 #include "chrome/browser/search_engines/util.h" | |
| 18 #include "chrome/browser/ui/browser_commands.h" | |
| 19 #include "chrome/browser/ui/browser_finder.h" | |
| 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 21 #include "chrome/browser/ui/views/frame/browser_frame_common_win.h" | |
| 22 #include "chrome/browser/ui/views/frame/browser_view.h" | |
| 23 #include "chrome/browser/ui/views/frame/browser_window_property_manager_win.h" | |
| 24 #include "chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h" | |
| 25 #include "chrome/browser/ui/views/tabs/tab_strip.h" | |
| 26 #include "chrome/common/chrome_constants.h" | |
| 27 #include "chrome/common/chrome_switches.h" | |
| 28 #include "content/public/browser/browser_accessibility_state.h" | |
| 29 #include "content/public/browser/page_navigator.h" | |
| 30 #include "content/public/browser/web_contents.h" | |
| 31 #include "content/public/common/page_transition_types.h" | |
| 32 #include "grit/generated_resources.h" | |
| 33 #include "grit/theme_resources.h" | |
| 34 #include "ui/base/l10n/l10n_util.h" | |
| 35 #include "ui/base/layout.h" | |
| 36 #include "ui/base/models/simple_menu_model.h" | |
| 37 #include "ui/base/resource/resource_bundle.h" | |
| 38 #include "ui/base/theme_provider.h" | |
| 39 #include "ui/base/window_open_disposition.h" | |
| 40 #include "ui/gfx/win/dpi.h" | |
| 41 #include "ui/views/controls/menu/native_menu_win.h" | |
| 42 #include "ui/views/views_delegate.h" | |
| 43 #include "ui/views/widget/native_widget_win.h" | |
| 44 #include "ui/views/widget/widget.h" | |
| 45 #include "ui/views/win/hwnd_message_handler.h" | |
| 46 #include "ui/views/window/non_client_view.h" | |
| 47 #include "url/gurl.h" | |
| 48 #include "win8/util/win8_util.h" | |
| 49 | |
| 50 #pragma comment(lib, "dwmapi.lib") | |
| 51 | |
| 52 // static | |
| 53 static const int kClientEdgeThickness = 3; | |
| 54 static const int kTabDragWindowAlpha = 200; | |
| 55 // We need to offset the DWMFrame into the toolbar so that the blackness | |
| 56 // doesn't show up on our rounded corners. | |
| 57 static const int kDWMFrameTopOffset = 3; | |
| 58 // If not -1, windows are shown with this state. | |
| 59 static int explicit_show_state = -1; | |
| 60 | |
| 61 using content::OpenURLParams; | |
| 62 using content::Referrer; | |
| 63 using content::WebContents; | |
| 64 | |
| 65 #if !defined(USE_AURA) | |
| 66 extern "C" { | |
| 67 // Windows metro exported functions from metro_driver. | |
| 68 typedef void (*SetFrameWindow)(HWND window); | |
| 69 typedef void (*CloseFrameWindow)(HWND window); | |
| 70 typedef void (*FlipFrameWindows)(); | |
| 71 typedef void (*MetroSetFullscreen)(bool fullscreen); | |
| 72 } | |
| 73 #endif // USE_AURA | |
| 74 | |
| 75 views::Button* MakeWindowSwitcherButton(views::ButtonListener* listener, | |
| 76 bool is_off_the_record) { | |
| 77 views::ImageButton* switcher_button = new views::ImageButton(listener); | |
| 78 // The button in the incognito window has the hot-cold images inverted | |
| 79 // with respect to the regular browser window. | |
| 80 switcher_button->SetImage( | |
| 81 views::ImageButton::STATE_NORMAL, | |
| 82 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 83 is_off_the_record ? IDR_INCOGNITO_SWITCH_ON : | |
| 84 IDR_INCOGNITO_SWITCH_OFF)); | |
| 85 switcher_button->SetImage( | |
| 86 views::ImageButton::STATE_HOVERED, | |
| 87 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 88 is_off_the_record ? IDR_INCOGNITO_SWITCH_OFF : | |
| 89 IDR_INCOGNITO_SWITCH_ON)); | |
| 90 switcher_button->SetImageAlignment(views::ImageButton::ALIGN_CENTER, | |
| 91 views::ImageButton::ALIGN_MIDDLE); | |
| 92 return switcher_button; | |
| 93 } | |
| 94 | |
| 95 /////////////////////////////////////////////////////////////////////////////// | |
| 96 // BrowserFrameWin, public: | |
| 97 | |
| 98 BrowserFrameWin::BrowserFrameWin(BrowserFrame* browser_frame, | |
| 99 BrowserView* browser_view) | |
| 100 : views::NativeWidgetWin(browser_frame), | |
| 101 browser_view_(browser_view), | |
| 102 browser_frame_(browser_frame) { | |
| 103 if (win8::IsSingleWindowMetroMode()) { | |
| 104 browser_view->SetWindowSwitcherButton( | |
| 105 MakeWindowSwitcherButton(this, browser_view->IsOffTheRecord())); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 BrowserFrameWin::~BrowserFrameWin() { | |
| 110 } | |
| 111 | |
| 112 // static | |
| 113 void BrowserFrameWin::SetShowState(int state) { | |
| 114 explicit_show_state = state; | |
| 115 } | |
| 116 | |
| 117 void BrowserFrameWin::AdjustFrameForImmersiveMode() { | |
| 118 #if defined(USE_AURA) | |
| 119 return; | |
| 120 #endif // USE_AURA | |
| 121 HMODULE metro = base::win::GetMetroModule(); | |
| 122 if (!metro) | |
| 123 return; | |
| 124 // We are in metro mode. | |
| 125 browser_frame_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); | |
| 126 SetFrameWindow set_frame_window = reinterpret_cast<SetFrameWindow>( | |
| 127 ::GetProcAddress(metro, "SetFrameWindow")); | |
| 128 set_frame_window(browser_frame_->GetNativeWindow()); | |
| 129 } | |
| 130 | |
| 131 void BrowserFrameWin::CloseImmersiveFrame() { | |
| 132 #if defined(USE_AURA) | |
| 133 return; | |
| 134 #endif // USE_AURA | |
| 135 HMODULE metro = base::win::GetMetroModule(); | |
| 136 if (!metro) | |
| 137 return; | |
| 138 CloseFrameWindow close_frame_window = reinterpret_cast<CloseFrameWindow>( | |
| 139 ::GetProcAddress(metro, "CloseFrameWindow")); | |
| 140 close_frame_window(browser_frame_->GetNativeWindow()); | |
| 141 } | |
| 142 | |
| 143 | |
| 144 views::NativeMenuWin* BrowserFrameWin::GetSystemMenu() { | |
| 145 if (!system_menu_.get()) { | |
| 146 SystemMenuInsertionDelegateWin insertion_delegate; | |
| 147 system_menu_.reset( | |
| 148 new views::NativeMenuWin(browser_frame_->GetSystemMenuModel(), | |
| 149 GetNativeView())); | |
| 150 system_menu_->Rebuild(&insertion_delegate); | |
| 151 } | |
| 152 return system_menu_.get(); | |
| 153 } | |
| 154 | |
| 155 /////////////////////////////////////////////////////////////////////////////// | |
| 156 // BrowserFrameWin, views::NativeWidgetWin overrides: | |
| 157 | |
| 158 int BrowserFrameWin::GetInitialShowState() const { | |
| 159 if (explicit_show_state != -1) | |
| 160 return explicit_show_state; | |
| 161 | |
| 162 STARTUPINFO si = {0}; | |
| 163 si.cb = sizeof(si); | |
| 164 si.dwFlags = STARTF_USESHOWWINDOW; | |
| 165 GetStartupInfo(&si); | |
| 166 return si.wShowWindow; | |
| 167 } | |
| 168 | |
| 169 bool BrowserFrameWin::GetClientAreaInsets(gfx::Insets* insets) const { | |
| 170 // Use the default client insets for an opaque frame or a glass popup/app | |
| 171 // frame. | |
| 172 if (!GetWidget()->ShouldUseNativeFrame() || | |
| 173 !browser_view_->IsBrowserTypeNormal()) { | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); | |
| 178 // In fullscreen mode, we have no frame. In restored mode, we draw our own | |
| 179 // client edge over part of the default frame. | |
| 180 if (IsFullscreen()) | |
| 181 border_thickness = 0; | |
| 182 else if (!IsMaximized()) | |
| 183 border_thickness -= kClientEdgeThickness; | |
| 184 insets->Set(0, border_thickness, border_thickness, border_thickness); | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 void BrowserFrameWin::HandleCreate() { | |
| 189 NativeWidgetWin::HandleCreate(); | |
| 190 browser_window_property_manager_ = | |
| 191 BrowserWindowPropertyManager::CreateBrowserWindowPropertyManager( | |
| 192 browser_view_); | |
| 193 if (browser_window_property_manager_) { | |
| 194 browser_window_property_manager_->UpdateWindowProperties( | |
| 195 GetMessageHandler()->hwnd()); | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 void BrowserFrameWin::HandleFrameChanged() { | |
| 200 // Handle window frame layout changes, then set the updated glass region. | |
| 201 NativeWidgetWin::HandleFrameChanged(); | |
| 202 UpdateDWMFrame(); | |
| 203 } | |
| 204 | |
| 205 bool BrowserFrameWin::PreHandleMSG(UINT message, | |
| 206 WPARAM w_param, | |
| 207 LPARAM l_param, | |
| 208 LRESULT* result) { | |
| 209 static const UINT metro_navigation_search_message = | |
| 210 RegisterWindowMessage(chrome::kMetroNavigationAndSearchMessage); | |
| 211 | |
| 212 static const UINT metro_get_current_tab_info_message = | |
| 213 RegisterWindowMessage(chrome::kMetroGetCurrentTabInfoMessage); | |
| 214 | |
| 215 if (message == metro_navigation_search_message) { | |
| 216 HandleMetroNavSearchRequest(w_param, l_param); | |
| 217 return false; | |
| 218 } else if (message == metro_get_current_tab_info_message) { | |
| 219 GetMetroCurrentTabInfo(w_param); | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 switch (message) { | |
| 224 case WM_ACTIVATE: | |
| 225 if (LOWORD(w_param) != WA_INACTIVE) | |
| 226 minimize_button_metrics_.OnHWNDActivated(); | |
| 227 return false; | |
| 228 case WM_PRINT: | |
| 229 if (win8::IsSingleWindowMetroMode()) { | |
| 230 // This message is sent by the AnimateWindow API which is used in metro | |
| 231 // mode to flip between active chrome windows. | |
| 232 RECT client_rect = {0}; | |
| 233 ::GetClientRect(GetNativeView(), &client_rect); | |
| 234 HDC dest_dc = reinterpret_cast<HDC>(w_param); | |
| 235 DCHECK(dest_dc); | |
| 236 HDC src_dc = ::GetDC(GetNativeView()); | |
| 237 ::BitBlt(dest_dc, 0, 0, client_rect.right - client_rect.left, | |
| 238 client_rect.bottom - client_rect.top, src_dc, 0, 0, | |
| 239 SRCCOPY); | |
| 240 ::ReleaseDC(GetNativeView(), src_dc); | |
| 241 *result = 0; | |
| 242 return true; | |
| 243 } | |
| 244 return false; | |
| 245 case WM_ENDSESSION: | |
| 246 chrome::SessionEnding(); | |
| 247 return true; | |
| 248 case WM_INITMENUPOPUP: | |
| 249 GetSystemMenu()->UpdateStates(); | |
| 250 return true; | |
| 251 } | |
| 252 return false; | |
| 253 } | |
| 254 | |
| 255 void BrowserFrameWin::PostHandleMSG(UINT message, | |
| 256 WPARAM w_param, | |
| 257 LPARAM l_param) { | |
| 258 switch (message) { | |
| 259 case WM_CREATE: | |
| 260 minimize_button_metrics_.Init(GetNativeView()); | |
| 261 break; | |
| 262 case WM_WINDOWPOSCHANGED: | |
| 263 UpdateDWMFrame(); | |
| 264 | |
| 265 // Windows lies to us about the position of the minimize button before a | |
| 266 // window is visible. We use this position to place the OTR avatar in RTL | |
| 267 // mode, so when the window is shown, we need to re-layout and schedule a | |
| 268 // paint for the non-client frame view so that the icon top has the correct | |
| 269 // position when the window becomes visible. This fixes bugs where the icon | |
| 270 // appears to overlay the minimize button. | |
| 271 // Note that we will call Layout every time SetWindowPos is called with | |
| 272 // SWP_SHOWWINDOW, however callers typically are careful about not | |
| 273 // specifying this flag unless necessary to avoid flicker. | |
| 274 // This may be invoked during creation on XP and before the non_client_view | |
| 275 // has been created. | |
| 276 WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(l_param); | |
| 277 if (window_pos->flags & SWP_SHOWWINDOW && GetWidget()->non_client_view()) { | |
| 278 GetWidget()->non_client_view()->Layout(); | |
| 279 GetWidget()->non_client_view()->SchedulePaint(); | |
| 280 } | |
| 281 break; | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 bool BrowserFrameWin::ShouldUseNativeFrame() const { | |
| 286 if (!NativeWidgetWin::ShouldUseNativeFrame()) | |
| 287 return false; | |
| 288 return chrome::ShouldUseNativeFrame(browser_view_, | |
| 289 GetWidget()->GetThemeProvider()); | |
| 290 } | |
| 291 | |
| 292 void BrowserFrameWin::Show() { | |
| 293 AdjustFrameForImmersiveMode(); | |
| 294 views::NativeWidgetWin::Show(); | |
| 295 } | |
| 296 | |
| 297 void BrowserFrameWin::ShowMaximizedWithBounds( | |
| 298 const gfx::Rect& restored_bounds) { | |
| 299 AdjustFrameForImmersiveMode(); | |
| 300 views::NativeWidgetWin::ShowMaximizedWithBounds(restored_bounds); | |
| 301 } | |
| 302 | |
| 303 void BrowserFrameWin::ShowWithWindowState(ui::WindowShowState show_state) { | |
| 304 AdjustFrameForImmersiveMode(); | |
| 305 views::NativeWidgetWin::ShowWithWindowState(show_state); | |
| 306 } | |
| 307 | |
| 308 void BrowserFrameWin::Close() { | |
| 309 CloseImmersiveFrame(); | |
| 310 views::NativeWidgetWin::Close(); | |
| 311 } | |
| 312 | |
| 313 void BrowserFrameWin::FrameTypeChanged() { | |
| 314 // In Windows 8 metro mode the frame type is set to FRAME_TYPE_FORCE_CUSTOM | |
| 315 // by default. We reset it back to FRAME_TYPE_DEFAULT to ensure that we | |
| 316 // don't end up defaulting to BrowserNonClientFrameView in all cases. | |
| 317 if (win8::IsSingleWindowMetroMode()) | |
| 318 browser_frame_->set_frame_type(views::Widget::FRAME_TYPE_DEFAULT); | |
| 319 | |
| 320 views::NativeWidgetWin::FrameTypeChanged(); | |
| 321 | |
| 322 // In Windows 8 metro mode we call Show on the BrowserFrame instance to | |
| 323 // ensure that the window can be styled appropriately, i.e. no sysmenu, | |
| 324 // etc. | |
| 325 if (win8::IsSingleWindowMetroMode()) | |
| 326 Show(); | |
| 327 } | |
| 328 | |
| 329 void BrowserFrameWin::SetFullscreen(bool fullscreen) { | |
| 330 if (win8::IsSingleWindowMetroMode()) { | |
| 331 HMODULE metro = base::win::GetMetroModule(); | |
| 332 if (metro) { | |
| 333 MetroSetFullscreen set_full_screen = reinterpret_cast<MetroSetFullscreen>( | |
| 334 ::GetProcAddress(metro, "SetFullscreen")); | |
| 335 DCHECK(set_full_screen); | |
| 336 if (set_full_screen) | |
| 337 set_full_screen(fullscreen); | |
| 338 } else { | |
| 339 NOTREACHED() << "Failed to get metro driver module"; | |
| 340 } | |
| 341 } | |
| 342 views::NativeWidgetWin::SetFullscreen(fullscreen); | |
| 343 } | |
| 344 | |
| 345 void BrowserFrameWin::Activate() { | |
| 346 // In Windows 8 metro mode we have only one window visible at any given time. | |
| 347 // The Activate code path is typically called when a new browser window is | |
| 348 // being activated. In metro we need to ensure that the window currently | |
| 349 // being displayed is hidden and the new window being activated becomes | |
| 350 // visible. This is achieved by calling AdjustFrameForImmersiveMode() | |
| 351 // followed by ShowWindow(). | |
| 352 if (win8::IsSingleWindowMetroMode()) { | |
| 353 AdjustFrameForImmersiveMode(); | |
| 354 ::ShowWindow(browser_frame_->GetNativeWindow(), SW_SHOWNORMAL); | |
| 355 } else { | |
| 356 views::NativeWidgetWin::Activate(); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 | |
| 361 //////////////////////////////////////////////////////////////////////////////// | |
| 362 // BrowserFrameWin, NativeBrowserFrame implementation: | |
| 363 | |
| 364 views::NativeWidget* BrowserFrameWin::AsNativeWidget() { | |
| 365 return this; | |
| 366 } | |
| 367 | |
| 368 const views::NativeWidget* BrowserFrameWin::AsNativeWidget() const { | |
| 369 return this; | |
| 370 } | |
| 371 | |
| 372 bool BrowserFrameWin::UsesNativeSystemMenu() const { | |
| 373 return true; | |
| 374 } | |
| 375 | |
| 376 int BrowserFrameWin::GetMinimizeButtonOffset() const { | |
| 377 return minimize_button_metrics_.GetMinimizeButtonOffsetX(); | |
| 378 } | |
| 379 | |
| 380 void BrowserFrameWin::ButtonPressed(views::Button* sender, | |
| 381 const ui::Event& event) { | |
| 382 HMODULE metro = base::win::GetMetroModule(); | |
| 383 if (!metro) | |
| 384 return; | |
| 385 | |
| 386 // Toggle the profile and switch to the corresponding browser window in the | |
| 387 // profile. The GetOffTheRecordProfile function is documented to create an | |
| 388 // incognito profile if one does not exist. That is not a concern as the | |
| 389 // windows 8 window switcher button shows up on the caption only when a | |
| 390 // normal window and an incognito window are open simultaneously. | |
| 391 Profile* profile_to_switch_to = NULL; | |
| 392 Profile* current_profile = browser_view()->browser()->profile(); | |
| 393 if (current_profile->IsOffTheRecord()) | |
| 394 profile_to_switch_to = current_profile->GetOriginalProfile(); | |
| 395 else | |
| 396 profile_to_switch_to = current_profile->GetOffTheRecordProfile(); | |
| 397 | |
| 398 DCHECK(profile_to_switch_to); | |
| 399 | |
| 400 Browser* browser_to_switch_to = chrome::FindTabbedBrowser( | |
| 401 profile_to_switch_to, false, chrome::HOST_DESKTOP_TYPE_NATIVE); | |
| 402 | |
| 403 DCHECK(browser_to_switch_to); | |
| 404 | |
| 405 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser( | |
| 406 browser_to_switch_to); | |
| 407 | |
| 408 // Tell the metro_driver to switch to the Browser we found above. This | |
| 409 // causes the current browser window to be hidden. | |
| 410 SetFrameWindow set_frame_window = reinterpret_cast<SetFrameWindow>( | |
| 411 ::GetProcAddress(metro, "SetFrameWindow")); | |
| 412 set_frame_window(browser_view->frame()->GetNativeWindow()); | |
| 413 ::ShowWindow(browser_view->frame()->GetNativeWindow(), SW_SHOWNORMAL); | |
| 414 } | |
| 415 | |
| 416 /////////////////////////////////////////////////////////////////////////////// | |
| 417 // BrowserFrameWin, private: | |
| 418 | |
| 419 void BrowserFrameWin::UpdateDWMFrame() { | |
| 420 // For "normal" windows on Aero, we always need to reset the glass area | |
| 421 // correctly, even if we're not currently showing the native frame (e.g. | |
| 422 // because a theme is showing), so we explicitly check for that case rather | |
| 423 // than checking browser_frame_->ShouldUseNativeFrame() here. Using that here | |
| 424 // would mean we wouldn't reset the glass area to zero when moving from the | |
| 425 // native frame to an opaque frame, leading to graphical glitches behind the | |
| 426 // opaque frame. Instead, we use that function below to tell us whether the | |
| 427 // frame is currently native or opaque. | |
| 428 if (!GetWidget()->client_view() || !browser_view_->IsBrowserTypeNormal() || | |
| 429 !NativeWidgetWin::ShouldUseNativeFrame()) | |
| 430 return; | |
| 431 | |
| 432 MARGINS margins = { 0 }; | |
| 433 | |
| 434 // If the opaque frame is visible, we use the default (zero) margins. | |
| 435 // Otherwise, we need to figure out how to extend the glass in. | |
| 436 if (browser_frame_->ShouldUseNativeFrame()) { | |
| 437 // In fullscreen mode, we don't extend glass into the client area at all, | |
| 438 // because the GDI-drawn text in the web content composited over it will | |
| 439 // become semi-transparent over any glass area. | |
| 440 if (!IsMaximized() && !IsFullscreen()) { | |
| 441 margins.cxLeftWidth = kClientEdgeThickness + 1; | |
| 442 margins.cxRightWidth = kClientEdgeThickness + 1; | |
| 443 margins.cyBottomHeight = kClientEdgeThickness + 1; | |
| 444 margins.cyTopHeight = kClientEdgeThickness + 1; | |
| 445 } | |
| 446 // In maximized mode, we only have a titlebar strip of glass, no side/bottom | |
| 447 // borders. | |
| 448 if (!IsFullscreen()) { | |
| 449 gfx::Rect tabstrip_bounds( | |
| 450 browser_frame_->GetBoundsForTabStrip(browser_view_->tabstrip())); | |
| 451 tabstrip_bounds = gfx::win::DIPToScreenRect(tabstrip_bounds); | |
| 452 margins.cyTopHeight = tabstrip_bounds.bottom() + kDWMFrameTopOffset; | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 DwmExtendFrameIntoClientArea(GetNativeView(), &margins); | |
| 457 } | |
| 458 | |
| 459 void BrowserFrameWin::HandleMetroNavSearchRequest(WPARAM w_param, | |
| 460 LPARAM l_param) { | |
| 461 if (!base::win::IsMetroProcess()) { | |
| 462 NOTREACHED() << "Received unexpected metro navigation request"; | |
| 463 return; | |
| 464 } | |
| 465 | |
| 466 if (!w_param && !l_param) { | |
| 467 NOTREACHED() << "Invalid metro request parameters"; | |
| 468 return; | |
| 469 } | |
| 470 | |
| 471 Browser* browser = browser_view()->browser(); | |
| 472 DCHECK(browser); | |
| 473 | |
| 474 GURL request_url; | |
| 475 if (w_param) { | |
| 476 request_url = GURL(reinterpret_cast<const wchar_t*>(w_param)); | |
| 477 } else if (l_param) { | |
| 478 request_url = GetDefaultSearchURLForSearchTerms( | |
| 479 browser->profile(), reinterpret_cast<const wchar_t*>(l_param)); | |
| 480 } | |
| 481 if (request_url.is_valid()) { | |
| 482 browser->OpenURL(OpenURLParams(request_url, Referrer(), NEW_FOREGROUND_TAB, | |
| 483 content::PAGE_TRANSITION_TYPED, false)); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 void BrowserFrameWin::GetMetroCurrentTabInfo(WPARAM w_param) { | |
| 488 if (!base::win::IsMetroProcess()) { | |
| 489 NOTREACHED() << "Received unexpected metro request"; | |
| 490 return; | |
| 491 } | |
| 492 | |
| 493 if (!w_param) { | |
| 494 NOTREACHED() << "Invalid metro request parameter"; | |
| 495 return; | |
| 496 } | |
| 497 | |
| 498 base::win::CurrentTabInfo* current_tab_info = | |
| 499 reinterpret_cast<base::win::CurrentTabInfo*>(w_param); | |
| 500 | |
| 501 Browser* browser = browser_view()->browser(); | |
| 502 DCHECK(browser); | |
| 503 | |
| 504 // We allocate memory for the title and url via LocalAlloc. The caller has to | |
| 505 // free the memory via LocalFree. | |
| 506 current_tab_info->title = base::win::LocalAllocAndCopyString( | |
| 507 browser->GetWindowTitleForCurrentTab()); | |
| 508 | |
| 509 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents(); | |
| 510 DCHECK(current_tab); | |
| 511 | |
| 512 current_tab_info->url = base::win::LocalAllocAndCopyString( | |
| 513 base::UTF8ToWide(current_tab->GetURL().spec())); | |
| 514 } | |
| 515 | |
| 516 //////////////////////////////////////////////////////////////////////////////// | |
| 517 // BrowserFrame, public: | |
| 518 | |
| 519 bool BrowserFrame::ShouldLeaveOffsetNearTopBorder() { | |
| 520 if (win8::IsSingleWindowMetroMode()) { | |
| 521 if (ui::GetDisplayLayout() == ui::LAYOUT_DESKTOP) | |
| 522 return false; | |
| 523 } | |
| 524 return !IsMaximized(); | |
| 525 } | |
| OLD | NEW |