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)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_desktop_window_tree_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"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/theme_provider.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/dpi.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/menu/native_menu_win.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "dwmapi.lib")
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kClientEdgeThickness = 3;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to offset the DWMFrame into the toolbar so that the blackness
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't show up on our rounded corners.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDWMFrameTopOffset = 3;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DesktopThemeProvider maps resource ids using MapThemeImage(). This is
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// necessary for BrowserDesktopWindowTreeHostWin so that it uses the windows
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// theme images rather than the ash theme images.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DesktopThemeProvider : public ui::ThemeProvider {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DesktopThemeProvider(ui::ThemeProvider* delegate)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : delegate_(delegate) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual bool UsingSystemTheme() const OVERRIDE {
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return delegate_->UsingSystemTheme();
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetImageSkiaNamed(
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id));
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SkColor GetColor(int id) const OVERRIDE {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetColor(id);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual int GetDisplayProperty(int id) const OVERRIDE {
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return delegate_->GetDisplayProperty(id);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ShouldUseNativeFrame() const OVERRIDE {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->ShouldUseNativeFrame();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasCustomImage(int id) const OVERRIDE {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->HasCustomImage(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id));
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::RefCountedMemory* GetRawData(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int id,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::ScaleFactor scale_factor) const OVERRIDE {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return delegate_->GetRawData(id, scale_factor);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ThemeProvider* delegate_;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DesktopThemeProvider);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BrowserDesktopWindowTreeHostWin, public:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserDesktopWindowTreeHostWin::BrowserDesktopWindowTreeHostWin(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::internal::NativeWidgetDelegate* native_widget_delegate,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::DesktopNativeWidgetAura* desktop_native_widget_aura,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserView* browser_view,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserFrame* browser_frame)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : DesktopWindowTreeHostWin(native_widget_delegate,
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                               desktop_native_widget_aura),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_view_(browser_view),
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      browser_frame_(browser_frame),
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      did_gdi_clear_(false) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::ThemeProvider> theme_provider(
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new DesktopThemeProvider(ThemeServiceFactory::GetForProfile(
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   browser_view->browser()->profile())));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser_frame->SetThemeProvider(theme_provider.Pass());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserDesktopWindowTreeHostWin::~BrowserDesktopWindowTreeHostWin() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)views::NativeMenuWin* BrowserDesktopWindowTreeHostWin::GetSystemMenu() {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!system_menu_.get()) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SystemMenuInsertionDelegateWin insertion_delegate;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_menu_.reset(
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new views::NativeMenuWin(browser_frame_->GetSystemMenuModel(),
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GetHWND()));
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_menu_->Rebuild(&insertion_delegate);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return system_menu_.get();
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BrowserDesktopWindowTreeHostWin, BrowserDesktopWindowTreeHost implementation:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)views::DesktopWindowTreeHost*
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserDesktopWindowTreeHostWin::AsDesktopWindowTreeHost() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int BrowserDesktopWindowTreeHostWin::GetMinimizeButtonOffset() const {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return minimize_button_metrics_.GetMinimizeButtonOffsetX();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserDesktopWindowTreeHostWin::UsesNativeSystemMenu() const {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BrowserDesktopWindowTreeHostWin, views::DesktopWindowTreeHostWin overrides:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int BrowserDesktopWindowTreeHostWin::GetInitialShowState() const {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STARTUPINFO si = {0};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  si.cb = sizeof(si);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  si.dwFlags = STARTF_USESHOWWINDOW;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetStartupInfo(&si);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return si.wShowWindow;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserDesktopWindowTreeHostWin::GetClientAreaInsets(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Insets* insets) const {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the default client insets for an opaque frame or a glass popup/app
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetWidget()->ShouldUseNativeFrame() ||
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !browser_view_->IsBrowserTypeNormal()) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In fullscreen mode, we have no frame. In restored mode, we draw our own
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // client edge over part of the default frame.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetWidget()->IsFullscreen())
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border_thickness = 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (!IsMaximized())
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    border_thickness -= kClientEdgeThickness;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insets->Set(0, border_thickness, border_thickness, border_thickness);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserDesktopWindowTreeHostWin::HandleCreate() {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DesktopWindowTreeHostWin::HandleCreate();
1570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  browser_window_property_manager_ =
1580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      BrowserWindowPropertyManager::CreateBrowserWindowPropertyManager(
1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          browser_view_);
1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (browser_window_property_manager_)
1610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    browser_window_property_manager_->UpdateWindowProperties(GetHWND());
1620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserDesktopWindowTreeHostWin::HandleFrameChanged() {
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Reinitialize the status bubble, since it needs to be initialized
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // differently depending on whether or not DWM composition is enabled
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  browser_view_->InitStatusBubble();
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to update the glass region on or off before the base class adjusts
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the window region.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDWMFrame();
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DesktopWindowTreeHostWin::HandleFrameChanged();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserDesktopWindowTreeHostWin::PreHandleMSG(UINT message,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   WPARAM w_param,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   LPARAM l_param,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   LRESULT* result) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_ACTIVATE:
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (LOWORD(w_param) != WA_INACTIVE)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        minimize_button_metrics_.OnHWNDActivated();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_ENDSESSION:
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::SessionEnding();
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_INITMENUPOPUP:
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetSystemMenu()->UpdateStates();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return DesktopWindowTreeHostWin::PreHandleMSG(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message, w_param, l_param, result);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserDesktopWindowTreeHostWin::PostHandleMSG(UINT message,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    WPARAM w_param,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    LPARAM l_param) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case WM_CREATE:
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    minimize_button_metrics_.Init(GetHWND());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case WM_WINDOWPOSCHANGED: {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDWMFrame();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Windows lies to us about the position of the minimize button before a
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // window is visible.  We use this position to place the OTR avatar in RTL
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // mode, so when the window is shown, we need to re-layout and schedule a
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // paint for the non-client frame view so that the icon top has the correct
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // position when the window becomes visible.  This fixes bugs where the icon
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // appears to overlay the minimize button.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that we will call Layout every time SetWindowPos is called with
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SWP_SHOWWINDOW, however callers typically are careful about not
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // specifying this flag unless necessary to avoid flicker.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This may be invoked during creation on XP and before the non_client_view
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has been created.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(l_param);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window_pos->flags & SWP_SHOWWINDOW && GetWidget()->non_client_view()) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetWidget()->non_client_view()->Layout();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetWidget()->non_client_view()->SchedulePaint();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  case WM_ERASEBKGND:
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!did_gdi_clear_ && DesktopWindowTreeHostWin::ShouldUseNativeFrame()) {
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // This is necessary to avoid white flashing in the titlebar area around
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // the minimize/maximize/close buttons.
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      HDC dc = GetDC(GetHWND());
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      MARGINS margins = GetDWMFrameMargins();
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      RECT client_rect;
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      GetClientRect(GetHWND(), &client_rect);
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      HBRUSH brush = CreateSolidBrush(0);
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      RECT rect = { 0, 0, client_rect.right, margins.cyTopHeight };
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      FillRect(dc, &rect, brush);
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DeleteObject(brush);
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ReleaseDC(GetHWND(), dc);
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      did_gdi_clear_ = true;
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    break;
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserDesktopWindowTreeHostWin::IsUsingCustomFrame() const {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't theme popup or app windows, so regardless of whether or not a
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // theme is active for normal browser windows, we don't want to use the custom
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame for popups/apps.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser_view_->IsBrowserTypeNormal() &&
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !DesktopWindowTreeHostWin::IsUsingCustomFrame()) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we use the native frame when we're told we should by the theme
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provider (e.g. no custom theme is active).
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !GetWidget()->GetThemeProvider()->ShouldUseNativeFrame();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserDesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!views::DesktopWindowTreeHostWin::ShouldUseNativeFrame())
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function can get called when the Browser window is closed i.e. in the
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // context of the BrowserView destructor.
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!browser_view_->browser())
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return chrome::ShouldUseNativeFrame(browser_view_,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      GetWidget()->GetThemeProvider());
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserDesktopWindowTreeHostWin::FrameTypeChanged() {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  views::DesktopWindowTreeHostWin::FrameTypeChanged();
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  did_gdi_clear_ = false;
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BrowserDesktopWindowTreeHostWin, private:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserDesktopWindowTreeHostWin::UpdateDWMFrame() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For "normal" windows on Aero, we always need to reset the glass area
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // correctly, even if we're not currently showing the native frame (e.g.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because a theme is showing), so we explicitly check for that case rather
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // than checking browser_frame_->ShouldUseNativeFrame() here.  Using that here
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would mean we wouldn't reset the glass area to zero when moving from the
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // native frame to an opaque frame, leading to graphical glitches behind the
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // opaque frame.  Instead, we use that function below to tell us whether the
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame is currently native or opaque.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetWidget()->client_view() || !browser_view_->IsBrowserTypeNormal() ||
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !DesktopWindowTreeHostWin::ShouldUseNativeFrame())
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  MARGINS margins = GetDWMFrameMargins();
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DwmExtendFrameIntoClientArea(GetHWND(), &margins);
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MARGINS BrowserDesktopWindowTreeHostWin::GetDWMFrameMargins() const {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MARGINS margins = { 0 };
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the opaque frame is visible, we use the default (zero) margins.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we need to figure out how to extend the glass in.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetWidget()->ShouldUseNativeFrame()) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In fullscreen mode, we don't extend glass into the client area at all,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because the GDI-drawn text in the web content composited over it will
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // become semi-transparent over any glass area.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsMaximized() && !GetWidget()->IsFullscreen()) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cxLeftWidth = kClientEdgeThickness + 1;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cxRightWidth = kClientEdgeThickness + 1;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyBottomHeight = kClientEdgeThickness + 1;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyTopHeight = kClientEdgeThickness + 1;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In maximized mode, we only have a titlebar strip of glass, no side/bottom
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // borders.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!browser_view_->IsFullscreen()) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect tabstrip_bounds(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser_frame_->GetBoundsForTabStrip(browser_view_->tabstrip()));
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      tabstrip_bounds = gfx::win::DIPToScreenRect(tabstrip_bounds);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margins.cyTopHeight = tabstrip_bounds.bottom() + kDWMFrameTopOffset;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return margins;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BrowserDesktopWindowTreeHost, public:
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserDesktopWindowTreeHost*
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserDesktopWindowTreeHost::CreateBrowserDesktopWindowTreeHost(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        views::internal::NativeWidgetDelegate* native_widget_delegate,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        views::DesktopNativeWidgetAura* desktop_native_widget_aura,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserView* browser_view,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserFrame* browser_frame) {
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new BrowserDesktopWindowTreeHostWin(native_widget_delegate,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             desktop_native_widget_aura,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             browser_view,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             browser_frame);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
336