15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dwmapi.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_service.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_service_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_frame.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_frame_common_win.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h"
150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_window_property_manager_win.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab_strip.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/theme_image_mapper.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/theme_resources.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/theme_provider.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/dpi.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/menu/native_menu_win.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "dwmapi.lib")
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kClientEdgeThickness = 3;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to offset the DWMFrame into the toolbar so that the blackness
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't show up on our rounded corners.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDWMFrameTopOffset = 3;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DesktopThemeProvider maps resource ids using MapThemeImage(). This is
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// necessary for BrowserDesktopRootWindowHostWin so that it uses the windows
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// theme images rather than the ash theme images.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DesktopThemeProvider : public ui::ThemeProvider {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DesktopThemeProvider(ui::ThemeProvider* delegate)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : delegate_(delegate) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetImageSkiaNamed(
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id));
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SkColor GetColor(int id) const OVERRIDE {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetColor(id);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual int GetDisplayProperty(int id) const OVERRIDE {
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return delegate_->GetDisplayProperty(id);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ShouldUseNativeFrame() const OVERRIDE {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->ShouldUseNativeFrame();
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasCustomImage(int id) const OVERRIDE {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->HasCustomImage(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id));
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::RefCountedMemory* GetRawData(
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int id,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::ScaleFactor scale_factor) const OVERRIDE {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetRawData(id, scale_factor);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ThemeProvider* delegate_;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DesktopThemeProvider);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserDesktopRootWindowHostWin, public:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserDesktopRootWindowHostWin::BrowserDesktopRootWindowHostWin(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::internal::NativeWidgetDelegate* native_widget_delegate,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::DesktopNativeWidgetAura* desktop_native_widget_aura,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserView* browser_view,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserFrame* browser_frame)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : DesktopRootWindowHostWin(native_widget_delegate,
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                               desktop_native_widget_aura),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_view_(browser_view),
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      browser_frame_(browser_frame),
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      did_gdi_clear_(false) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::ThemeProvider> theme_provider(
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DesktopThemeProvider(ThemeServiceFactory::GetForProfile(
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   browser_view->browser()->profile())));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser_frame->SetThemeProvider(theme_provider.Pass());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserDesktopRootWindowHostWin::~BrowserDesktopRootWindowHostWin() {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)views::NativeMenuWin* BrowserDesktopRootWindowHostWin::GetSystemMenu() {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!system_menu_.get()) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SystemMenuInsertionDelegateWin insertion_delegate;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_menu_.reset(
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new views::NativeMenuWin(browser_frame_->GetSystemMenuModel(),
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GetHWND()));
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_menu_->Rebuild(&insertion_delegate);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return system_menu_.get();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserDesktopRootWindowHostWin, BrowserDesktopRootWindowHost implementation:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::DesktopRootWindowHost*
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDesktopRootWindowHostWin::AsDesktopRootWindowHost() {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserDesktopRootWindowHostWin::GetMinimizeButtonOffset() const {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return minimize_button_metrics_.GetMinimizeButtonOffsetX();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BrowserDesktopRootWindowHostWin::UsesNativeSystemMenu() const {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserDesktopRootWindowHostWin, views::DesktopRootWindowHostWin overrides:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserDesktopRootWindowHostWin::GetInitialShowState() const {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STARTUPINFO si = {0};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  si.cb = sizeof(si);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  si.dwFlags = STARTF_USESHOWWINDOW;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetStartupInfo(&si);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return si.wShowWindow;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserDesktopRootWindowHostWin::GetClientAreaInsets(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Insets* insets) const {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the default client insets for an opaque frame or a glass popup/app
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetWidget()->ShouldUseNativeFrame() ||
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !browser_view_->IsBrowserTypeNormal()) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In fullscreen mode, we have no frame. In restored mode, we draw our own
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // client edge over part of the default frame.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetWidget()->IsFullscreen())
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border_thickness = 0;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (!IsMaximized())
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border_thickness -= kClientEdgeThickness;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insets->Set(0, border_thickness, border_thickness, border_thickness);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void BrowserDesktopRootWindowHostWin::HandleCreate() {
1550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DesktopRootWindowHostWin::HandleCreate();
1560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  browser_window_property_manager_ =
1570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      BrowserWindowPropertyManager::CreateBrowserWindowPropertyManager(
1580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          browser_view_);
1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (browser_window_property_manager_)
1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    browser_window_property_manager_->UpdateWindowProperties(GetHWND());
1610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserDesktopRootWindowHostWin::HandleFrameChanged() {
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Reinitialize the status bubble, since it needs to be initialized
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // differently depending on whether or not DWM composition is enabled
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  browser_view_->InitStatusBubble();
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to update the glass region on or off before the base class adjusts
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the window region.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDWMFrame();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DesktopRootWindowHostWin::HandleFrameChanged();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserDesktopRootWindowHostWin::PreHandleMSG(UINT message,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   WPARAM w_param,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   LPARAM l_param,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   LRESULT* result) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_ACTIVATE:
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (LOWORD(w_param) != WA_INACTIVE)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        minimize_button_metrics_.OnHWNDActivated();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_ENDSESSION:
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::SessionEnding();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_INITMENUPOPUP:
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetSystemMenu()->UpdateStates();
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DesktopRootWindowHostWin::PreHandleMSG(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message, w_param, l_param, result);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserDesktopRootWindowHostWin::PostHandleMSG(UINT message,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    WPARAM w_param,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    LPARAM l_param) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case WM_CREATE:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    minimize_button_metrics_.Init(GetHWND());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case WM_WINDOWPOSCHANGED: {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDWMFrame();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Windows lies to us about the position of the minimize button before a
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // window is visible.  We use this position to place the OTR avatar in RTL
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // mode, so when the window is shown, we need to re-layout and schedule a
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // paint for the non-client frame view so that the icon top has the correct
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // position when the window becomes visible.  This fixes bugs where the icon
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // appears to overlay the minimize button.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that we will call Layout every time SetWindowPos is called with
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SWP_SHOWWINDOW, however callers typically are careful about not
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // specifying this flag unless necessary to avoid flicker.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This may be invoked during creation on XP and before the non_client_view
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has been created.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(l_param);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window_pos->flags & SWP_SHOWWINDOW && GetWidget()->non_client_view()) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetWidget()->non_client_view()->Layout();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetWidget()->non_client_view()->SchedulePaint();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case WM_ERASEBKGND:
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!did_gdi_clear_ && DesktopRootWindowHostWin::ShouldUseNativeFrame()) {
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // This is necessary to avoid white flashing in the titlebar area around
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // the minimize/maximize/close buttons.
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      HDC dc = GetDC(GetHWND());
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      MARGINS margins = GetDWMFrameMargins();
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      RECT client_rect;
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      GetClientRect(GetHWND(), &client_rect);
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      HBRUSH brush = CreateSolidBrush(0);
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      RECT rect = { 0, 0, client_rect.right, margins.cyTopHeight };
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      FillRect(dc, &rect, brush);
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DeleteObject(brush);
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ReleaseDC(GetHWND(), dc);
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      did_gdi_clear_ = true;
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    break;
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserDesktopRootWindowHostWin::IsUsingCustomFrame() const {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't theme popup or app windows, so regardless of whether or not a
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // theme is active for normal browser windows, we don't want to use the custom
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame for popups/apps.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser_view_->IsBrowserTypeNormal() &&
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !DesktopRootWindowHostWin::IsUsingCustomFrame()) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we use the native frame when we're told we should by the theme
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provider (e.g. no custom theme is active).
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !GetWidget()->GetThemeProvider()->ShouldUseNativeFrame();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BrowserDesktopRootWindowHostWin::ShouldUseNativeFrame() {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!views::DesktopRootWindowHostWin::ShouldUseNativeFrame())
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function can get called when the Browser window is closed i.e. in the
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // context of the BrowserView destructor.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!browser_view_->browser())
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return chrome::ShouldUseNativeFrame(browser_view_,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      GetWidget()->GetThemeProvider());
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BrowserDesktopRootWindowHostWin::FrameTypeChanged() {
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  views::DesktopRootWindowHostWin::FrameTypeChanged();
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  did_gdi_clear_ = false;
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserDesktopRootWindowHostWin, private:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserDesktopRootWindowHostWin::UpdateDWMFrame() {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For "normal" windows on Aero, we always need to reset the glass area
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // correctly, even if we're not currently showing the native frame (e.g.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because a theme is showing), so we explicitly check for that case rather
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than checking browser_frame_->ShouldUseNativeFrame() here.  Using that here
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would mean we wouldn't reset the glass area to zero when moving from the
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // native frame to an opaque frame, leading to graphical glitches behind the
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // opaque frame.  Instead, we use that function below to tell us whether the
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame is currently native or opaque.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetWidget()->client_view() || !browser_view_->IsBrowserTypeNormal() ||
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !DesktopRootWindowHostWin::ShouldUseNativeFrame())
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  MARGINS margins = GetDWMFrameMargins();
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DwmExtendFrameIntoClientArea(GetHWND(), &margins);
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)MARGINS BrowserDesktopRootWindowHostWin::GetDWMFrameMargins() const {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MARGINS margins = { 0 };
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the opaque frame is visible, we use the default (zero) margins.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we need to figure out how to extend the glass in.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetWidget()->ShouldUseNativeFrame()) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In fullscreen mode, we don't extend glass into the client area at all,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because the GDI-drawn text in the web content composited over it will
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // become semi-transparent over any glass area.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsMaximized() && !GetWidget()->IsFullscreen()) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cxLeftWidth = kClientEdgeThickness + 1;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cxRightWidth = kClientEdgeThickness + 1;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyBottomHeight = kClientEdgeThickness + 1;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyTopHeight = kClientEdgeThickness + 1;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In maximized mode, we only have a titlebar strip of glass, no side/bottom
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // borders.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!browser_view_->IsFullscreen()) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect tabstrip_bounds(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser_frame_->GetBoundsForTabStrip(browser_view_->tabstrip()));
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      tabstrip_bounds = gfx::win::DIPToScreenRect(tabstrip_bounds);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyTopHeight = tabstrip_bounds.bottom() + kDWMFrameTopOffset;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return margins;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserDesktopRootWindowHost, public:
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserDesktopRootWindowHost*
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserDesktopRootWindowHost::CreateBrowserDesktopRootWindowHost(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        views::internal::NativeWidgetDelegate* native_widget_delegate,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        views::DesktopNativeWidgetAura* desktop_native_widget_aura,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserView* browser_view,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserFrame* browser_frame) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new BrowserDesktopRootWindowHostWin(native_widget_delegate,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             desktop_native_widget_aura,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             browser_view,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             browser_frame);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335