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