| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/views/status_bubble_views.h" | 5 #include "chrome/browser/views/status_bubble_views.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "app/gfx/canvas.h" | 9 #include "app/gfx/canvas.h" |
| 10 #include "app/gfx/text_elider.h" | 10 #include "app/gfx/text_elider.h" |
| 11 #include "app/l10n_util.h" | 11 #include "app/l10n_util.h" |
| 12 #if defined(OS_WIN) | |
| 13 #include "app/l10n_util_win.h" | |
| 14 #endif | |
| 15 #include "app/animation.h" | 12 #include "app/animation.h" |
| 16 #include "app/resource_bundle.h" | 13 #include "app/resource_bundle.h" |
| 17 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 18 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 19 #include "chrome/browser/browser_theme_provider.h" | 16 #include "chrome/browser/browser_theme_provider.h" |
| 20 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
| 21 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 22 #include "grit/theme_resources.h" | 19 #include "grit/theme_resources.h" |
| 23 #include "net/base/net_util.h" | 20 #include "net/base/net_util.h" |
| 24 #include "third_party/skia/include/core/SkPaint.h" | 21 #include "third_party/skia/include/core/SkPaint.h" |
| 25 #include "third_party/skia/include/core/SkPath.h" | 22 #include "third_party/skia/include/core/SkPath.h" |
| 26 #include "third_party/skia/include/core/SkRect.h" | 23 #include "third_party/skia/include/core/SkRect.h" |
| 27 #include "views/controls/label.h" | 24 #include "views/controls/label.h" |
| 25 #include "views/screen.h" |
| 28 #include "views/widget/root_view.h" | 26 #include "views/widget/root_view.h" |
| 29 #include "views/widget/widget.h" | 27 #include "views/widget/widget.h" |
| 30 #if defined(OS_WIN) | 28 #include "views/window/window.h" |
| 31 #include "views/widget/widget_win.h" | |
| 32 #endif | |
| 33 | 29 |
| 34 // The alpha and color of the bubble's shadow. | 30 // The alpha and color of the bubble's shadow. |
| 35 static const SkColor kShadowColor = SkColorSetARGB(30, 0, 0, 0); | 31 static const SkColor kShadowColor = SkColorSetARGB(30, 0, 0, 0); |
| 36 | 32 |
| 37 // The roundedness of the edges of our bubble. | 33 // The roundedness of the edges of our bubble. |
| 38 static const int kBubbleCornerRadius = 4; | 34 static const int kBubbleCornerRadius = 4; |
| 39 | 35 |
| 40 // How close the mouse can get to the infobubble before it starts sliding | 36 // How close the mouse can get to the infobubble before it starts sliding |
| 41 // off-screen. | 37 // off-screen. |
| 42 static const int kMousePadding = 20; | 38 static const int kMousePadding = 20; |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 download_shelf_is_visible_(false) { | 455 download_shelf_is_visible_(false) { |
| 460 } | 456 } |
| 461 | 457 |
| 462 StatusBubbleViews::~StatusBubbleViews() { | 458 StatusBubbleViews::~StatusBubbleViews() { |
| 463 if (popup_.get()) | 459 if (popup_.get()) |
| 464 popup_->CloseNow(); | 460 popup_->CloseNow(); |
| 465 } | 461 } |
| 466 | 462 |
| 467 void StatusBubbleViews::Init() { | 463 void StatusBubbleViews::Init() { |
| 468 if (!popup_.get()) { | 464 if (!popup_.get()) { |
| 469 #if defined(OS_WIN) | 465 popup_.reset(views::Widget::CreateTransparentPopupWidget(false)); |
| 470 views::WidgetWin* popup = new views::WidgetWin; | |
| 471 popup->set_delete_on_destroy(false); | |
| 472 | |
| 473 if (!view_) | 466 if (!view_) |
| 474 view_ = new StatusView(this, popup, frame_->GetThemeProvider()); | 467 view_ = new StatusView(this, popup_.get(), frame_->GetThemeProvider()); |
| 475 | 468 popup_->SetOpacity(0x00); |
| 476 popup->set_window_style(WS_POPUP); | 469 popup_->Init(frame_->GetNativeView(), gfx::Rect()); |
| 477 popup->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | | 470 popup_->SetContentsView(view_); |
| 478 WS_EX_TRANSPARENT | | |
| 479 l10n_util::GetExtendedTooltipStyles()); | |
| 480 popup->SetOpacity(0x00); | |
| 481 popup->Init(frame_->GetNativeView(), gfx::Rect()); | |
| 482 popup->SetContentsView(view_); | |
| 483 Reposition(); | 471 Reposition(); |
| 484 popup->Show(); | 472 popup_->Show(); |
| 485 popup_.reset(popup); | |
| 486 #else | |
| 487 NOTIMPLEMENTED(); | |
| 488 #endif | |
| 489 } | 473 } |
| 490 } | 474 } |
| 491 | 475 |
| 492 void StatusBubbleViews::Reposition() { | 476 void StatusBubbleViews::Reposition() { |
| 493 if (popup_.get()) { | 477 if (popup_.get()) { |
| 494 gfx::Point top_left; | 478 gfx::Point top_left; |
| 495 views::View::ConvertPointToScreen(frame_->GetRootView(), &top_left); | 479 views::View::ConvertPointToScreen(frame_->GetRootView(), &top_left); |
| 496 | 480 |
| 497 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), | 481 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), |
| 498 top_left.y() + position_.y(), | 482 top_left.y() + position_.y(), |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 AvoidMouse(); | 566 AvoidMouse(); |
| 583 } | 567 } |
| 584 } | 568 } |
| 585 } | 569 } |
| 586 | 570 |
| 587 void StatusBubbleViews::UpdateDownloadShelfVisibility(bool visible) { | 571 void StatusBubbleViews::UpdateDownloadShelfVisibility(bool visible) { |
| 588 download_shelf_is_visible_ = visible; | 572 download_shelf_is_visible_ = visible; |
| 589 } | 573 } |
| 590 | 574 |
| 591 void StatusBubbleViews::AvoidMouse() { | 575 void StatusBubbleViews::AvoidMouse() { |
| 592 // Our status bubble is located in screen coordinates, so we should get | |
| 593 // those rather than attempting to reverse decode the web contents | |
| 594 // coordinates. | |
| 595 gfx::Point cursor_location; | |
| 596 #if defined(OS_WIN) | |
| 597 POINT tmp = { 0, 0 }; | |
| 598 GetCursorPos(&tmp); | |
| 599 cursor_location = tmp; | |
| 600 #else | |
| 601 NOTIMPLEMENTED(); | |
| 602 #endif | |
| 603 | |
| 604 // Get the position of the frame. | 576 // Get the position of the frame. |
| 605 gfx::Point top_left; | 577 gfx::Point top_left; |
| 606 views::RootView* root = frame_->GetRootView(); | 578 views::RootView* root = frame_->GetRootView(); |
| 607 views::View::ConvertPointToScreen(root, &top_left); | 579 views::View::ConvertPointToScreen(root, &top_left); |
| 608 int window_width = root->GetLocalBounds(true).width(); // border included. | 580 int window_width = root->GetLocalBounds(true).width(); // border included. |
| 609 | 581 |
| 582 // Our status bubble is located in screen coordinates, so we should get |
| 583 // those rather than attempting to reverse decode the web contents |
| 584 // coordinates. |
| 585 gfx::Point cursor_location = views::Screen::GetCursorScreenPoint(); |
| 586 |
| 610 // Get the cursor position relative to the popup. | 587 // Get the cursor position relative to the popup. |
| 611 if (view_->UILayoutIsRightToLeft()) { | 588 if (view_->UILayoutIsRightToLeft()) { |
| 612 int top_right_x = top_left.x() + window_width; | 589 int top_right_x = top_left.x() + window_width; |
| 613 cursor_location.set_x(top_right_x - cursor_location.x()); | 590 cursor_location.set_x(top_right_x - cursor_location.x()); |
| 614 } else { | 591 } else { |
| 615 cursor_location.set_x(cursor_location.x() - (top_left.x() + position_.x())); | 592 cursor_location.set_x(cursor_location.x() - (top_left.x() + position_.x())); |
| 616 } | 593 } |
| 617 cursor_location.set_y(cursor_location.y() - (top_left.y() + position_.y())); | 594 cursor_location.set_y(cursor_location.y() - (top_left.y() + position_.y())); |
| 618 | 595 |
| 619 // If the mouse is in a position where we think it would move the | 596 // If the mouse is in a position where we think it would move the |
| (...skipping 21 matching lines...) Expand all Loading... |
| 641 offset = size_.height() - kShadowThickness * 2; | 618 offset = size_.height() - kShadowThickness * 2; |
| 642 view_->SetStyle(StatusView::STYLE_BOTTOM); | 619 view_->SetStyle(StatusView::STYLE_BOTTOM); |
| 643 } else if (offset > kBubbleCornerRadius / 2 - kShadowThickness) { | 620 } else if (offset > kBubbleCornerRadius / 2 - kShadowThickness) { |
| 644 view_->SetStyle(StatusView::STYLE_FLOATING); | 621 view_->SetStyle(StatusView::STYLE_FLOATING); |
| 645 } else { | 622 } else { |
| 646 view_->SetStyle(StatusView::STYLE_STANDARD); | 623 view_->SetStyle(StatusView::STYLE_STANDARD); |
| 647 } | 624 } |
| 648 | 625 |
| 649 // Check if the bubble sticks out from the monitor or will obscure | 626 // Check if the bubble sticks out from the monitor or will obscure |
| 650 // download shelf. | 627 // download shelf. |
| 651 #if defined(OS_WIN) | 628 gfx::NativeWindow window = frame_->GetWindow()->GetNativeWindow(); |
| 652 MONITORINFO monitor_info; | 629 gfx::Rect monitor_rect = |
| 653 monitor_info.cbSize = sizeof(monitor_info); | 630 views::Screen::GetMonitorWorkAreaNearestWindow(window); |
| 654 GetMonitorInfo(MonitorFromWindow(frame_->GetNativeView(), | |
| 655 MONITOR_DEFAULTTONEAREST), &monitor_info); | |
| 656 gfx::Rect monitor_rect(monitor_info.rcWork); | |
| 657 #else | |
| 658 gfx::Rect monitor_rect; | |
| 659 NOTIMPLEMENTED(); | |
| 660 #endif | |
| 661 const int bubble_bottom_y = top_left.y() + position_.y() + size_.height(); | 631 const int bubble_bottom_y = top_left.y() + position_.y() + size_.height(); |
| 662 | 632 |
| 663 if (bubble_bottom_y + offset > monitor_rect.height() || | 633 if (bubble_bottom_y + offset > monitor_rect.height() || |
| 664 (download_shelf_is_visible_ && | 634 (download_shelf_is_visible_ && |
| 665 view_->GetStyle() == StatusView::STYLE_FLOATING)) { | 635 view_->GetStyle() == StatusView::STYLE_FLOATING)) { |
| 666 // The offset is still too large. Move the bubble to the right and reset | 636 // The offset is still too large. Move the bubble to the right and reset |
| 667 // Y offset_ to zero. | 637 // Y offset_ to zero. |
| 668 view_->SetStyle(StatusView::STYLE_STANDARD_RIGHT); | 638 view_->SetStyle(StatusView::STYLE_STANDARD_RIGHT); |
| 669 offset_ = 0; | 639 offset_ = 0; |
| 670 | 640 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 681 } | 651 } |
| 682 } else if (offset_ != 0 || | 652 } else if (offset_ != 0 || |
| 683 view_->GetStyle() == StatusView::STYLE_STANDARD_RIGHT) { | 653 view_->GetStyle() == StatusView::STYLE_STANDARD_RIGHT) { |
| 684 offset_ = 0; | 654 offset_ = 0; |
| 685 view_->SetStyle(StatusView::STYLE_STANDARD); | 655 view_->SetStyle(StatusView::STYLE_STANDARD); |
| 686 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), | 656 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), |
| 687 top_left.y() + position_.y(), | 657 top_left.y() + position_.y(), |
| 688 size_.width(), size_.height())); | 658 size_.width(), size_.height())); |
| 689 } | 659 } |
| 690 } | 660 } |
| OLD | NEW |