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 <vector>
      8 
      9 #include "chrome/browser/ui/views/bubble/border_contents.h"
     10 #include "chrome/browser/ui/views/frame/browser_view.h"
     11 #include "views/widget/root_view.h"
     12 #include "views/widget/widget_gtk.h"
     13 
     14 #if defined(OS_CHROMEOS)
     15 #include "chrome/browser/chromeos/wm_ipc.h"
     16 #include "third_party/cros/chromeos_wm_ipc_enums.h"
     17 #endif
     18 
     19 using std::vector;
     20 
     21 namespace {
     22 
     23 class BubbleWidget : public views::WidgetGtk {
     24  public:
     25   explicit BubbleWidget(BrowserBubble* bubble)
     26       : views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW),
     27         bubble_(bubble),
     28         border_contents_(new BorderContents) {
     29     border_contents_->Init();
     30   }
     31 
     32   void ShowAndActivate(bool activate) {
     33     // TODO: honor activate.
     34     views::WidgetGtk::Show();
     35   }
     36 
     37   virtual void Close() {
     38     if (!bubble_)
     39       return;  // We have already been closed.
     40     if (IsActive()) {
     41       BrowserBubble::Delegate* delegate = bubble_->delegate();
     42       if (delegate)
     43         delegate->BubbleLostFocus(bubble_, false);
     44     }
     45     views::WidgetGtk::Close();
     46     bubble_ = NULL;
     47   }
     48 
     49   virtual void Hide() {
     50     if (IsActive()&& bubble_) {
     51       BrowserBubble::Delegate* delegate = bubble_->delegate();
     52       if (delegate)
     53         delegate->BubbleLostFocus(bubble_, false);
     54     }
     55     views::WidgetGtk::Hide();
     56   }
     57 
     58   virtual void IsActiveChanged() {
     59     if (IsActive() || !bubble_)
     60       return;
     61     BrowserBubble::Delegate* delegate = bubble_->delegate();
     62     if (!delegate) {
     63       bubble_->DetachFromBrowser();
     64       delete bubble_;
     65       return;
     66     }
     67 
     68     // TODO(jcampan): http://crbugs.com/29131 Check if the window we are losing
     69     //                focus to is a child window and pass that to the call
     70     //                below.
     71     delegate->BubbleLostFocus(bubble_, false);
     72   }
     73 
     74   virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
     75     if (bubble_ && bubble_->delegate())
     76       bubble_->delegate()->BubbleGotFocus(bubble_);
     77     return views::WidgetGtk::OnFocusIn(widget, event);
     78   }
     79 
     80   BorderContents* border_contents() {
     81     return border_contents_;
     82   }
     83 
     84  private:
     85   BrowserBubble* bubble_;
     86   BorderContents* border_contents_;  // Owned by root view of this widget.
     87 
     88   DISALLOW_COPY_AND_ASSIGN(BubbleWidget);
     89 };
     90 
     91 }  // namespace
     92 
     93 void BrowserBubble::InitPopup() {
     94   // TODO(port)
     95   BubbleWidget* pop = new BubbleWidget(this);
     96   pop->MakeTransparent();
     97   pop->make_transient_to_parent();
     98   pop->Init(frame_->GetNativeView(), gfx::Rect());
     99 #if defined(OS_CHROMEOS)
    100   {
    101     vector<int> params;
    102     params.push_back(0);  // don't show while screen is locked
    103     chromeos::WmIpc::instance()->SetWindowType(
    104         pop->GetNativeView(),
    105         chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
    106         &params);
    107   }
    108 #endif
    109 
    110   views::View* contents_view = new views::View;
    111 
    112   // We add |contents_view| to ourselves before the AddChildView() call below so
    113   // that when |contents| gets added, it will already have a widget, and thus
    114   // any NativeButtons it creates in ViewHierarchyChanged() will be functional
    115   // (e.g. calling SetChecked() on checkboxes is safe).
    116   pop->SetContentsView(contents_view);
    117 
    118   // Added border_contents before |view_| so it will paint under it.
    119   contents_view->AddChildView(pop->border_contents());
    120   contents_view->AddChildView(view_);
    121 
    122   popup_ = pop;
    123 
    124   ResizeToView();
    125   Reposition();
    126   AttachToBrowser();
    127 }
    128 
    129 void BrowserBubble::MovePopup(int x, int y, int w, int h) {
    130   views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_);
    131   pop->SetBounds(gfx::Rect(x, y, w, h));
    132 }
    133 
    134 void BrowserBubble::Show(bool activate) {
    135   if (visible_)
    136     return;
    137   static_cast<BubbleWidget*>(popup_)->ShowAndActivate(activate);
    138   visible_ = true;
    139 }
    140 
    141 void BrowserBubble::Hide() {
    142   if (!visible_)
    143     return;
    144   views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_);
    145   pop->Hide();
    146   visible_ = false;
    147 }
    148 
    149 void BrowserBubble::ResizeToView() {
    150   BorderContents* border_contents =
    151       static_cast<BubbleWidget*>(popup_)->border_contents();
    152 
    153   // Calculate and set the bounds for all windows and views.
    154   gfx::Rect window_bounds;
    155   gfx::Rect contents_bounds;
    156   border_contents->SizeAndGetBounds(GetAbsoluteRelativeTo(),
    157       arrow_location_, false, view_->size(),
    158       &contents_bounds, &window_bounds);
    159 
    160   border_contents->SetBoundsRect(gfx::Rect(gfx::Point(), window_bounds.size()));
    161   view_->SetBoundsRect(contents_bounds);
    162 
    163   SetAbsoluteBounds(window_bounds);
    164 }
    165