Home | History | Annotate | Download | only in views
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/views/browser_bubble.h"
      6 
      7 #include "chrome/browser/ui/views/bubble/border_contents.h"
      8 #include "chrome/browser/ui/views/bubble/border_widget_win.h"
      9 #include "chrome/browser/ui/views/frame/browser_view.h"
     10 #include "views/widget/root_view.h"
     11 #include "views/widget/widget_win.h"
     12 #include "views/window/window.h"
     13 
     14 class BubbleWidget : public views::WidgetWin {
     15  public:
     16   explicit BubbleWidget(BrowserBubble* bubble)
     17       : bubble_(bubble),
     18         border_widget_(new BorderWidgetWin) {
     19     set_window_style(WS_POPUP | WS_CLIPCHILDREN);
     20     set_window_ex_style(WS_EX_TOOLWINDOW);
     21   }
     22 
     23   void ShowAndActivate(bool activate) {
     24     // Show the border first, then the popup overlaid on top.
     25     border_widget_->Show();
     26     if (activate)
     27       ShowWindow(SW_SHOW);
     28     else
     29       views::WidgetWin::Show();
     30   }
     31 
     32   void Close() {
     33     if (!bubble_)
     34       return;  // We have already been closed.
     35     if (IsActive()) {
     36       BrowserBubble::Delegate* delegate = bubble_->delegate();
     37       if (delegate)
     38         delegate->BubbleLostFocus(bubble_, NULL);
     39     }
     40     border_widget_->Close();
     41     views::WidgetWin::Close();
     42     bubble_ = NULL;
     43   }
     44 
     45   void Hide() {
     46     if (IsActive() && bubble_) {
     47       BrowserBubble::Delegate* delegate = bubble_->delegate();
     48       if (delegate)
     49         delegate->BubbleLostFocus(bubble_, NULL);
     50     }
     51     views::WidgetWin::Hide();
     52     border_widget_->Hide();
     53   }
     54 
     55   void OnActivate(UINT action, BOOL minimized, HWND window) {
     56     WidgetWin::OnActivate(action, minimized, window);
     57     if (!bubble_)
     58       return;
     59 
     60     BrowserBubble::Delegate* delegate = bubble_->delegate();
     61     if (!delegate) {
     62       if (action == WA_INACTIVE) {
     63         bubble_->DetachFromBrowser();
     64         delete bubble_;
     65       }
     66       return;
     67     }
     68 
     69     if (action == WA_INACTIVE) {
     70       bool lost_focus_to_child = false;
     71 
     72       // Are we a parent of this window?
     73       gfx::NativeView parent = window;
     74       while (parent = ::GetParent(parent)) {
     75         if (window == GetNativeView()) {
     76           lost_focus_to_child = true;
     77           break;
     78         }
     79       }
     80 
     81       // Do we own this window?
     82       if (!lost_focus_to_child &&
     83           ::GetWindow(window, GW_OWNER) == GetNativeView()) {
     84         lost_focus_to_child = true;
     85       }
     86 
     87       delegate->BubbleLostFocus(bubble_, lost_focus_to_child);
     88     }
     89   }
     90 
     91   virtual void OnSetFocus(HWND focused_window) {
     92     WidgetWin::OnSetFocus(focused_window);
     93     if (bubble_ && bubble_->delegate())
     94       bubble_->delegate()->BubbleGotFocus(bubble_);
     95   }
     96 
     97   BorderWidgetWin* border_widget() {
     98     return border_widget_;
     99   }
    100 
    101  private:
    102   BrowserBubble* bubble_;
    103   BorderWidgetWin* border_widget_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(BubbleWidget);
    106 };
    107 
    108 void BrowserBubble::InitPopup() {
    109   // popup_ is a Widget, but we need to do some WidgetWin stuff first, then
    110   // we'll assign it into popup_.
    111   BubbleWidget* pop = new BubbleWidget(this);
    112 
    113   BorderWidgetWin* border_widget = pop->border_widget();
    114   border_widget->Init(new BorderContents, frame_->GetNativeView());
    115 
    116   // We make the BorderWidgetWin the owner of the Bubble HWND, so that the
    117   // latter is displayed on top of the former.
    118   pop->Init(border_widget->GetNativeView(), gfx::Rect());
    119   pop->SetContentsView(view_);
    120 
    121   popup_ = pop;
    122 
    123   ResizeToView();
    124   Reposition();
    125   AttachToBrowser();
    126 }
    127 
    128 void BrowserBubble::MovePopup(int x, int y, int w, int h) {
    129   views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
    130   pop->SetBounds(gfx::Rect(x, y, w, h));
    131 }
    132 
    133 void BrowserBubble::Show(bool activate) {
    134   if (visible_)
    135     return;
    136   BubbleWidget* pop = static_cast<BubbleWidget*>(popup_);
    137   pop->ShowAndActivate(activate);
    138   visible_ = true;
    139 }
    140 
    141 void BrowserBubble::Hide() {
    142   if (!visible_)
    143     return;
    144   views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
    145   pop->Hide();
    146   visible_ = false;
    147 }
    148 
    149 void BrowserBubble::ResizeToView() {
    150   BorderWidgetWin* border_widget =
    151       static_cast<BubbleWidget*>(popup_)->border_widget();
    152 
    153   gfx::Rect window_bounds;
    154   window_bounds = border_widget->SizeAndGetBounds(GetAbsoluteRelativeTo(),
    155       arrow_location_, view_->size());
    156 
    157   SetAbsoluteBounds(window_bounds);
    158 }
    159