summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd12
-rw-r--r--chrome/browser/views/browser_views.vcproj8
-rw-r--r--chrome/browser/views/frame/browser_view.cc9
-rw-r--r--chrome/browser/views/frame/browser_view.h3
-rw-r--r--chrome/browser/views/fullscreen_exit_bubble.cc219
-rw-r--r--chrome/browser/views/fullscreen_exit_bubble.h85
-rw-r--r--chrome/browser/views/toolbar_view.cc2
-rw-r--r--chrome/views/accelerator.cc3
8 files changed, 340 insertions, 1 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index b61864d..463736a 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -559,6 +559,9 @@ each locale. -->
<message name="IDS_SHOW_BOOKMARK_BAR" desc="The toggle to show the bookmark bar">
&amp;Always show bookmarks bar
</message>
+ <message name="IDS_FULLSCREEN" desc="Switches into fullscreen mode">
+ &amp;Full screen
+ </message>
<message name="IDS_CLEAR_BROWSING_DATA" desc="The text label for the menu item for clearing of browsing data">
&amp;Clear browsing data...
</message>
@@ -1487,6 +1490,12 @@ each locale. -->
Close find bar
</message>
+
+ <!-- Fullscreen mode -->
+ <message name="IDS_EXIT_FULLSCREEN_MODE" desc="Clickable message displayed on entering fullscreen mode to tell users how to return to normal mode">
+ Exit full screen (<ph name="ACCELERATOR">$1<ex>F11</ex></ph>)
+ </message>
+
<!-- Task Manager Window -->
<message name="IDS_TASK_MANAGER_KILL" desc="The caption of the Task Manager kill button">
@@ -3189,6 +3198,9 @@ each locale. -->
<message name="IDS_F1_KEY" desc="F1 key">
F1
</message>
+ <message name="IDS_F11_KEY" desc="F11 key">
+ F11
+ </message>
<!-- Strings used in local directory listings -->
<message name="IDS_DIRECTORY_LISTING_HEADER" desc="When viewing a local directory, this is the title of the page.">
diff --git a/chrome/browser/views/browser_views.vcproj b/chrome/browser/views/browser_views.vcproj
index 870ab14..92d345d 100644
--- a/chrome/browser/views/browser_views.vcproj
+++ b/chrome/browser/views/browser_views.vcproj
@@ -554,6 +554,14 @@
>
</File>
<File
+ RelativePath=".\fullscreen_exit_bubble.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\fullscreen_exit_bubble.h"
+ >
+ </File>
+ <File
RelativePath=".\go_button.cc"
>
</File>
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index b2fbe13a..c0476d5 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/views/clear_browsing_data.h"
#include "chrome/browser/views/download_shelf_view.h"
#include "chrome/browser/views/frame/browser_frame.h"
+#include "chrome/browser/views/fullscreen_exit_bubble.h"
#include "chrome/browser/views/html_dialog_view.h"
#include "chrome/browser/views/importer_view.h"
#include "chrome/browser/views/infobars/infobar_container.h"
@@ -577,7 +578,9 @@ void BrowserView::SetFullscreen(bool fullscreen) {
if (bookmark_bar_view_.get())
bookmark_bar_view_->OnFullscreenToggled(fullscreen_);
- HWND hwnd = GetWidget()->GetHWND();
+ // Size/position/style window appropriately.
+ views::Widget* widget = GetWidget();
+ HWND hwnd = widget->GetHWND();
gfx::Rect new_rect;
if (fullscreen_) {
// Save current window information.
@@ -605,6 +608,10 @@ void BrowserView::SetFullscreen(bool fullscreen) {
// This will cause the window to re-layout.
SetWindowPos(hwnd, NULL, new_rect.x(), new_rect.y(), new_rect.width(),
new_rect.height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
+
+ // Turn fullscreen bubble on or off.
+ fullscreen_bubble_.reset(fullscreen_ ?
+ new FullscreenExitBubble(widget, browser_.get()) : NULL);
}
bool BrowserView::IsFullscreen() const {
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index dccd54d..c91af8e 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -24,6 +24,7 @@ class BookmarkBarView;
class Browser;
class BrowserToolbarView;
class EncodingMenuControllerDelegate;
+class FullscreenExitBubble;
class InfoBarContainer;
class Menu;
class StatusBubbleViews;
@@ -389,6 +390,8 @@ class BrowserView : public BrowserWindow,
// Saved window information from before entering fullscreen mode.
SavedWindowInfo saved_window_info_;
+ scoped_ptr<FullscreenExitBubble> fullscreen_bubble_;
+
// Lazily created representation of the system menu.
scoped_ptr<Menu> system_menu_;
diff --git a/chrome/browser/views/fullscreen_exit_bubble.cc b/chrome/browser/views/fullscreen_exit_bubble.cc
new file mode 100644
index 0000000..667088a
--- /dev/null
+++ b/chrome/browser/views/fullscreen_exit_bubble.cc
@@ -0,0 +1,219 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/fullscreen_exit_bubble.h"
+
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/views/root_view.h"
+#include "grit/generated_resources.h"
+
+
+// FullscreenExitView ----------------------------------------------------------
+
+class FullscreenExitBubble::FullscreenExitView : public views::View {
+ public:
+ FullscreenExitView(FullscreenExitBubble* bubble,
+ views::WidgetWin* popup,
+ const std::wstring& accelerator);
+ virtual ~FullscreenExitView();
+
+ // views::View
+ virtual gfx::Size GetPreferredSize();
+
+ private:
+ static const int kPaddingPixels; // Number of pixels around all sides of link
+
+ // views::View
+ virtual void Layout();
+ virtual void Paint(ChromeCanvas* canvas);
+
+ // Handle to the HWND that contains us.
+ views::WidgetWin* popup_;
+
+ // Clickable hint text to show in the bubble.
+ views::Link link_;
+};
+
+const int FullscreenExitBubble::FullscreenExitView::kPaddingPixels = 8;
+
+FullscreenExitBubble::FullscreenExitView::FullscreenExitView(
+ FullscreenExitBubble* bubble,
+ views::WidgetWin* popup,
+ const std::wstring& accelerator)
+ : popup_(popup) {
+ link_.SetParentOwned(false);
+ link_.SetText(l10n_util::GetStringF(IDS_EXIT_FULLSCREEN_MODE, accelerator));
+ link_.SetController(bubble);
+ link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
+ ResourceBundle::LargeFont));
+ link_.SetNormalColor(SK_ColorWHITE);
+ link_.SetHighlightedColor(SK_ColorWHITE);
+ AddChildView(&link_);
+}
+
+FullscreenExitBubble::FullscreenExitView::~FullscreenExitView() {
+}
+
+gfx::Size FullscreenExitBubble::FullscreenExitView::GetPreferredSize() {
+ gfx::Size preferred_size(link_.GetPreferredSize());
+ preferred_size.Enlarge(kPaddingPixels * 2, kPaddingPixels * 2);
+ return preferred_size;
+}
+
+void FullscreenExitBubble::FullscreenExitView::Layout() {
+ gfx::Size link_preferred_size(link_.GetPreferredSize());
+ link_.SetBounds(kPaddingPixels,
+ height() - kPaddingPixels - link_preferred_size.height(),
+ link_preferred_size.width(), link_preferred_size.height());
+}
+
+void FullscreenExitBubble::FullscreenExitView::Paint(ChromeCanvas* canvas) {
+ // Create a round-bottomed rect to fill the whole View.
+ CRect parent_rect;
+ SkRect rect;
+ SkScalar padding = SkIntToScalar(kPaddingPixels);
+ // The "-padding" top coordinate ensures that the rect is always tall enough
+ // to contain the complete rounded corner radius. If we set this to 0, as the
+ // popup slides offscreen (in reality, squishes to 0 height), the corners will
+ // flatten out as the height becomes less than the corner radius.
+ rect.set(0, -padding, SkIntToScalar(width()), SkIntToScalar(height()));
+ SkScalar rad[8] = { 0, 0, 0, 0, padding, padding, padding, padding };
+ SkPath path;
+ path.addRoundRect(rect, rad, SkPath::kCW_Direction);
+
+ // Fill it black.
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawPath(path, paint);
+}
+
+
+// FullscreenExitBubble --------------------------------------------------------
+
+const double FullscreenExitBubble::kOpacity = 0.7;
+const int FullscreenExitBubble::kInitialDelayMs = 2300;
+const int FullscreenExitBubble::kPositionCheckHz = 10;
+const int FullscreenExitBubble::kSlideInRegionHeightPx = 4;
+const int FullscreenExitBubble::kSlideInDurationMs = 350;
+const int FullscreenExitBubble::kSlideOutDurationMs = 700;
+
+FullscreenExitBubble::FullscreenExitBubble(
+ views::Widget* frame,
+ CommandUpdater::CommandUpdaterDelegate* delegate)
+ : root_view_(frame->GetRootView()),
+ delegate_(delegate),
+ popup_(new views::WidgetWin()),
+ size_animation_(new SlideAnimation(this)) {
+ size_animation_->Reset(1);
+
+ // Create the contents view.
+ views::Accelerator accelerator(0, false, false, false);
+ bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
+ DCHECK(got_accelerator);
+ view_ = new FullscreenExitView(this, popup_, accelerator.GetShortcutText());
+
+ // Initialize the popup.
+ popup_->set_delete_on_destroy(false);
+ popup_->set_window_style(WS_POPUP);
+ popup_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW |
+ l10n_util::GetExtendedTooltipStyles());
+ popup_->SetLayeredAlpha(static_cast<int>(0xff * kOpacity));
+ popup_->Init(frame->GetHWND(), GetPopupRect(false), false);
+ popup_->SetContentsView(view_);
+ popup_->Show();
+
+ // Start the initial delay timer.
+ initial_delay_.Start(base::TimeDelta::FromMilliseconds(kInitialDelayMs), this,
+ &FullscreenExitBubble::AfterInitialDelay);
+}
+
+FullscreenExitBubble::~FullscreenExitBubble() {
+ // This is tricky. We may be in an ATL message handler stack, in which case
+ // the popup cannot be deleted yet. We also can't blindly use
+ // set_delete_on_destroy(true) on the popup to delete it when it closes,
+ // because if the user closed the last tab while in fullscreen mode, Windows
+ // has already destroyed the popup HWND by the time we get here, and thus
+ // either the popup will already have been deleted (if we set this in our
+ // constructor) or the popup will never get another OnFinalMessage() call (if
+ // not, as currently). So instead, we tell the popup to synchronously hide,
+ // and then asynchronously close and delete itself.
+ popup_->Close();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
+}
+
+void FullscreenExitBubble::LinkActivated(views::Link* source, int event_flags) {
+ delegate_->ExecuteCommand(IDC_FULLSCREEN);
+}
+
+void FullscreenExitBubble::AnimationProgressed(
+ const Animation* animation) {
+ gfx::Rect popup_rect(GetPopupRect(false));
+ if (popup_rect.IsEmpty()) {
+ popup_->Hide();
+ } else {
+ popup_->MoveWindow(popup_rect.x(), popup_rect.y(), popup_rect.width(),
+ popup_rect.height());
+ popup_->Show();
+ }
+}
+void FullscreenExitBubble::AnimationEnded(
+ const Animation* animation) {
+ AnimationProgressed(animation);
+}
+
+void FullscreenExitBubble::AfterInitialDelay() {
+ // Check the mouse position immediately and every 50 ms afterwards.
+ CheckMousePosition();
+ mouse_position_checker_.Start(
+ base::TimeDelta::FromMilliseconds(1000 / kPositionCheckHz), this,
+ &FullscreenExitBubble::CheckMousePosition);
+}
+
+void FullscreenExitBubble::CheckMousePosition() {
+ // Desired behavior:
+ //
+ // +------------+-----------------------------+------------+
+ // | _ _ _ _ | Exit full screen mode (F11) | _ _ _ _ | Slide-in region
+ // | _ _ _ _ \_____________________________/ _ _ _ _ | Neutral region
+ // | | Slide-out region
+ // : :
+ //
+ // * If the mouse is in the slide-in region, we show the popup.
+ // * If the mouse is in the slide-out region, we hide the popup.
+ // * If the mouse is in the neutral region, we do nothing, except if the popup
+ // is currently sliding out, in which case we show it again. This
+ // facilitates users correcting us if they try to mouse horizontally towards
+ // the popup and unintentionally drop too low.
+
+ POINT cursor_pos;
+ GetCursorPos(&cursor_pos);
+ gfx::Point transformed_pos(cursor_pos);
+ views::View::ConvertPointToView(NULL, root_view_, &transformed_pos);
+ gfx::Rect trigger_rect(GetPopupRect(true));
+ if (!root_view_->HitTest(transformed_pos) ||
+ (cursor_pos.y >= trigger_rect.bottom())) {
+ size_animation_->SetSlideDuration(kSlideOutDurationMs);
+ size_animation_->Hide();
+ } else if ((cursor_pos.y < kSlideInRegionHeightPx) ||
+ (size_animation_->GetCurrentValue() != 0)) {
+ size_animation_->SetSlideDuration(kSlideInDurationMs);
+ size_animation_->Show();
+ }
+}
+
+gfx::Rect FullscreenExitBubble::GetPopupRect(
+ bool ignore_animation_state) const {
+ gfx::Size size(view_->GetPreferredSize());
+ if (!ignore_animation_state) {
+ size.set_height(static_cast<int>(static_cast<double>(size.height()) *
+ size_animation_->GetCurrentValue()));
+ }
+ gfx::Point origin((root_view_->width() - size.width()) / 2, 0);
+ views::View::ConvertPointToScreen(root_view_, &origin);
+ return gfx::Rect(origin, size);
+}
diff --git a/chrome/browser/views/fullscreen_exit_bubble.h b/chrome/browser/views/fullscreen_exit_bubble.h
new file mode 100644
index 0000000..ff855be
--- /dev/null
+++ b/chrome/browser/views/fullscreen_exit_bubble.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H__
+#define CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H__
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/command_updater.h"
+#include "chrome/common/slide_animation.h"
+#include "chrome/views/link.h"
+#include "chrome/views/widget_win.h"
+
+// FullscreenExitBubble is responsible for showing a bubble atop the screen in
+// fullscreen mode, telling users how to exit and providing a click target.
+// The bubble auto-hides, and re-shows when the user moves to the screen top.
+
+class FullscreenExitBubble : public views::LinkController,
+ public AnimationDelegate {
+ public:
+ explicit FullscreenExitBubble(
+ views::Widget* frame,
+ CommandUpdater::CommandUpdaterDelegate* delegate);
+ virtual ~FullscreenExitBubble();
+
+ private:
+ class FullscreenExitView;
+
+ static const double kOpacity; // Opacity of the bubble, 0.0 - 1.0
+ static const int kInitialDelayMs; // Initial time bubble remains onscreen
+ static const int kPositionCheckHz; // How fast to check the mouse position
+ static const int kSlideInRegionHeightPx;
+ // Height of region triggering slide-in
+ static const int kSlideInDurationMs; // Duration of slide-in animation
+ static const int kSlideOutDurationMs; // Duration of slide-out animation
+
+ // views::LinkController
+ virtual void LinkActivated(views::Link* source, int event_flags);
+
+ // AnimationDelegate
+ virtual void AnimationProgressed(const Animation* animation);
+ virtual void AnimationEnded(const Animation* animation);
+
+ // Called after the initial delay to start checking the mouse position.
+ void AfterInitialDelay();
+
+ // Called repeatedly to get the current mouse position and animate the bubble
+ // on or off the screen as appropriate.
+ void CheckMousePosition();
+
+ // Returns the current desirable rect for the popup window. If
+ // |ignore_animation_state| is true this returns the rect assuming the popup
+ // is fully onscreen.
+ gfx::Rect GetPopupRect(bool ignore_animation_state) const;
+
+ // The root view containing us.
+ views::View* root_view_;
+
+ // Someone who can toggle fullscreen mode on and off when the user requests
+ // it.
+ CommandUpdater::CommandUpdaterDelegate* delegate_;
+
+ // We use an HWND for the popup so that it may float above any plugins in the
+ // page.
+ views::WidgetWin* popup_;
+
+ // The contents of the popup.
+ FullscreenExitView* view_;
+
+ // Animation controlling sliding into/out of the top of the screen.
+ scoped_ptr<SlideAnimation> size_animation_;
+
+ // Timer to delay before starting the mouse checking/bubble hiding code.
+ base::OneShotTimer<FullscreenExitBubble> initial_delay_;
+
+ // Timer to poll the current mouse position. We can't just listen for mouse
+ // events without putting a non-empty HWND onscreen (or hooking Windows, which
+ // has other problems), so instead we run a low-frequency poller to see if the
+ // user has moved in or out of our show/hide regions.
+ base::RepeatingTimer<FullscreenExitBubble> mouse_position_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenExitBubble);
+};
+
+#endif // CHROME_BROWSER_VIEWS_FULLSCREEN_EXIT_BUBBLE_H__
diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc
index 16f6a69..bc2d778 100644
--- a/chrome/browser/views/toolbar_view.cc
+++ b/chrome/browser/views/toolbar_view.cc
@@ -563,6 +563,8 @@ void BrowserToolbarView::RunAppMenu(const CPoint& pt, HWND hwnd) {
menu.AppendSeparator();
menu.AppendMenuItemWithLabel(IDC_SHOW_BOOKMARK_BAR,
l10n_util::GetString(IDS_SHOW_BOOKMARK_BAR));
+ menu.AppendMenuItemWithLabel(IDC_FULLSCREEN,
+ l10n_util::GetString(IDS_FULLSCREEN));
menu.AppendSeparator();
menu.AppendMenuItemWithLabel(IDC_SHOW_HISTORY,
l10n_util::GetString(IDS_SHOW_HISTORY));
diff --git a/chrome/views/accelerator.cc b/chrome/views/accelerator.cc
index 8619394..e2a5f18 100644
--- a/chrome/views/accelerator.cc
+++ b/chrome/views/accelerator.cc
@@ -44,6 +44,9 @@ std::wstring Accelerator::GetShortcutText() const {
case VK_F1:
string_id = IDS_F1_KEY;
break;
+ case VK_F11:
+ string_id = IDS_F11_KEY;
+ break;
}
std::wstring shortcut;