summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-23 20:01:00 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-23 20:01:00 +0000
commit69c579e522c4493c15c93ebf33b28a35b1e7213b (patch)
tree5dde3cc78e0de04bb87613c09be12b47b80d8307 /chrome/browser
parent12f144239468f206dc82c3f3481fef477f636798 (diff)
downloadchromium_src-69c579e522c4493c15c93ebf33b28a35b1e7213b.zip
chromium_src-69c579e522c4493c15c93ebf33b28a35b1e7213b.tar.gz
chromium_src-69c579e522c4493c15c93ebf33b28a35b1e7213b.tar.bz2
Re-instate the temporary revert from r45267. That reverted certain
Omnibox, toolbar, tab animations, and other UI changes for purposes of testing and merging into mstone-5. Additionally reverts these CLs to fix the earlier revert: r45271: [Mac] Image references missing from Omnibox revert. r45268: GTK fix merge failure in uber-revert. Additional revert which fixed a bug for the branch: r45381: [Mac] Omnibox popup icons and text lined up under toolbar. Slight merge conflict which should be good: r45322: GTK: Implement OnDragCanceled() for autocomplete... Also ++kThemePackVersion and regenerate the cached theme pak. Re-instated changes: r45213: GTK: Override cursor colors in chrome-theme mode. r45103: Support drawing nano tabs in the tabstrip. r45084: GTK: Position the EV certificate stuff inside a green bubble. r44979: Subclassing the InfoBubble to handle anchoring bubbles basedon... r44957: GTK: Tint the geolocation icons in gtk mode. r44943: Changes FormatURL to not strip http if the host starts with ft... r44930: Remove an icon that is no longer used. r44929: SSL UI changes, Windows, code side (images are separate). r44859: SSL UI changes (icons). TBRed since trybots hate binary patches. r44822: GTK: Select better greens in the native omnibox popup. r44814: GTK: navigate to URL on PRIMARY when middle-clicking the locat... r44789: [Mac] Bookmark star missing on NTP and BMM. r44775: [Mac] Centralize hack to make tests work with AutocompleteClas... r44678: Display the SECURITY_WARNING status in the location bar for the r44648: [Mac] Add an arrow cursor rect for the location image. r44615: Revert r44611 because it may have broken "unit_tests" on "Vist... r44611: Display the SECURITY_WARNING status in the location bar for the r44577: Revert 44572 - [Mac] Update locationbar icon as user types. r44572: [Mac] Update location-bar icon as user types. r44555: GTK: Use correct button mask on reload button. r44545: [Mac] Omnibox text drag drag URL when select-all. r44523: GTK: Prevent inappropriate drag of location bar location icon. r44519: GTK: make the primary selection include the url's scheme when ... r44492: [Mac] Fix search icon in keyword search to be right-side-up. r44415: GTK: Update top padding on icons in the autocomplete popup. r44401: GTK: Tint omnibox icons in GTK mode differently. r44380: GTK: Move reload in gtk mode and fix omnibox popup location. r44282: Fixes crash in autocomplete when typing some URLs. The problem r44273: [Mac] PDF icons for omnibox nits. r44269: Fix build break due to bad merge resolve r44268: Shift omnibox dropdown in and up on Windows, and square off th... r44178: GTK: fix TTS padding. r44177: Round the top left and right edges of the toolbar. r44171: Images only checkin for try server goodness. r44163: GTK: fix padding of autocomplete popup. r44152: [Mac] PDF icons for omnibox. r44145: GTK: Theme the icons in the location bar and use GTK colors fo... r44140: Strips http from the omnibox r44131: Fixes bugs in new tab strip animations where they weren't doin... r44116: Change the default theme colors. r44117: Add newline to EOF to fix CrOS builder. r44115: Make the bottom edges of the opaque frame rounded. r44091: [Mac] No star icon or page actions in omnibox on popups. r44087: Don't allow drag or click on location icon when editing in omn... r44021: [GTK] Add TTS lens graphic to linux TTS box. r44008: [Mac] Tweak location icon spacing in omnibox. r43977: GTK: don't show the star or page actions in ShouldOnlyShowLoca... r43972: Make the firstrun bubble point at a better spot now that the l... r43971: [Mac] Location icon in omnibox as drag source. r43970: Make the star and page action icons not appear on popup windows. r43954: Fixes bug in TabStrip where dragging tab out then back in rapidly r43864: Tweaks to BoundsAnimator/SlideAnimation and TabStrip: r43787: Allow location icon to be dragged & dropped. This also fixes ... r43759: Changes end cap of tab-to-search images. r43740: Change bookmark bar toggle to ctrl-shift-b. r43723: Show Page Info dialog on mouse up, not mouse down. r43677: Fix Mac build failure. r43676: Replace omnibox icons with new set that are all the same size ... r43596: Fix browser test TestStarButtonAccObj. r43593: Disables TestStarButtonAccObj. r43582: Changes tab strip to use BoundsAnimator for tab strip animatio... r43563: GTK: don't show reload button for popup/app windows. r43562: Star/reload shuffle, Windows version. r43540: [Mac] Magnifying glass in keyword-search bubble. r43482: Adds images needed for new tab animation. I'm separating this ... r43422: Add reload mask resource. r43392: GTK: make the location icon a drag source. r43376: [Mac] Move star button into page-actions area of omnibox. r43357: [Mac] Line up omnibox popup under field. r43290: gtk: fix display of icons in omnibox popup r43269: GTK: fix reload button. r43249: [Mac] Rearrange SSL status icon/label in omnibox. r43248: BrowserThemePack: Adds persistant ids for the reload endcaps. r43241: GTK: more location bar updates. r43191: Fix memory leak in BrowserThemePack. r43154: GTK: set the new star button's ID r43151: Fix bad conflict resolution for r43146. r43146: GTK: toolbar reload/star shuffle. r43025: Show the location bar icon (almost) all the time, and have its... r43023: Add new images for new reload button. No code change. r42782: Remove this icon, now that it's no longer used (due to my secu... r42502: Omnibox M5 work, part 1: Security changes r42245: Check in new icons for omnibox security changes alone, so that... BUG=none TEST=People go back to complaining about missing http://. R=pkasting@chromium.org,beng@chromium.org git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45474 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/autocomplete/autocomplete.cc72
-rw-r--r--chrome/browser/autocomplete/autocomplete.h39
-rw-r--r--chrome/browser/autocomplete/autocomplete_classifier.cc34
-rw-r--r--chrome/browser/autocomplete/autocomplete_classifier.h43
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit.cc134
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit.h55
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view.h7
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc199
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.h47
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_mac.h10
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_mac.mm101
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_win.cc82
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_win.h7
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_model.cc56
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_model.h20
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view.h19
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc306
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_gtk.h35
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.h4
-rw-r--r--chrome/browser/autocomplete/autocomplete_popup_view_mac.mm89
-rw-r--r--chrome/browser/autocomplete/history_contents_provider.cc6
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc35
-rw-r--r--chrome/browser/autocomplete/search_provider.cc11
-rw-r--r--chrome/browser/bookmarks/bookmark_table_model.cc6
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.cc3
-rw-r--r--chrome/browser/browser_theme_pack.cc79
-rw-r--r--chrome/browser/browser_theme_provider.cc40
-rw-r--r--chrome/browser/bubble_positioner.h24
-rw-r--r--chrome/browser/cert_store.cc5
-rw-r--r--chrome/browser/cert_store.h8
-rw-r--r--chrome/browser/chromeos/compact_location_bar_host.cc5
-rw-r--r--chrome/browser/chromeos/compact_location_bar_host.h4
-rw-r--r--chrome/browser/chromeos/compact_location_bar_view.cc88
-rw-r--r--chrome/browser/chromeos/compact_location_bar_view.h24
-rw-r--r--chrome/browser/chromeos/frame/browser_view.cc16
-rw-r--r--chrome/browser/chromeos/frame/browser_view.h2
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field.h7
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field.mm31
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_cell.h85
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_cell.mm563
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm139
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_editor.mm29
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_unittest.mm96
-rw-r--r--chrome/browser/cocoa/bookmark_bubble_controller.mm2
-rw-r--r--chrome/browser/cocoa/browser_test_helper.h9
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm2
-rw-r--r--chrome/browser/cocoa/browser_window_controller_unittest.mm4
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.h108
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.mm243
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac_unittest.mm37
-rw-r--r--chrome/browser/cocoa/status_bubble_mac_unittest.mm8
-rw-r--r--chrome/browser/cocoa/tab_strip_controller_unittest.mm2
-rw-r--r--chrome/browser/cocoa/toolbar_controller.h12
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm104
-rw-r--r--chrome/browser/cocoa/toolbar_controller_unittest.mm34
-rw-r--r--chrome/browser/gtk/accelerators_gtk.cc3
-rw-r--r--chrome/browser/gtk/bookmark_bubble_gtk.cc2
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc142
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.h20
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc6
-rw-r--r--chrome/browser/gtk/find_bar_gtk.cc2
-rw-r--r--chrome/browser/gtk/gtk_theme_provider.cc78
-rw-r--r--chrome/browser/gtk/gtk_theme_provider.h7
-rw-r--r--chrome/browser/gtk/gtk_util.cc30
-rw-r--r--chrome/browser/gtk/gtk_util.h7
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc448
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h131
-rw-r--r--chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc2
-rw-r--r--chrome/browser/gtk/options/passwords_page_gtk.cc4
-rw-r--r--chrome/browser/gtk/options/url_picker_dialog_gtk.cc3
-rw-r--r--chrome/browser/gtk/rounded_window.cc4
-rw-r--r--chrome/browser/gtk/rounded_window.h3
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.cc24
-rw-r--r--chrome/browser/gtk/toolbar_star_toggle_gtk.cc141
-rw-r--r--chrome/browser/gtk/toolbar_star_toggle_gtk.h76
-rw-r--r--chrome/browser/location_bar.h1
-rw-r--r--chrome/browser/net/browser_url_util.cc6
-rw-r--r--chrome/browser/net/url_fixer_upper.cc8
-rw-r--r--chrome/browser/profile.cc17
-rw-r--r--chrome/browser/profile.h15
-rw-r--r--chrome/browser/search_versus_navigate_classifier.cc56
-rw-r--r--chrome/browser/search_versus_navigate_classifier.h52
-rw-r--r--chrome/browser/ssl/ssl_browser_tests.cc5
-rw-r--r--chrome/browser/ssl/ssl_manager.cc27
-rw-r--r--chrome/browser/ssl/ssl_manager.h10
-rw-r--r--chrome/browser/ssl/ssl_policy.cc15
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc26
-rw-r--r--chrome/browser/theme_resources_util_unittest.cc4
-rw-r--r--chrome/browser/toolbar_model.cc188
-rw-r--r--chrome/browser/toolbar_model.h58
-rw-r--r--chrome/browser/views/accelerator_table_gtk.cc3
-rw-r--r--chrome/browser/views/app_launcher.cc76
-rw-r--r--chrome/browser/views/app_launcher.h16
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc149
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h6
-rw-r--r--chrome/browser/views/bookmark_editor_view.cc5
-rw-r--r--chrome/browser/views/browser_views_accessibility_browsertest.cc5
-rw-r--r--chrome/browser/views/bubble_border.cc107
-rw-r--r--chrome/browser/views/bubble_border.h33
-rw-r--r--chrome/browser/views/constrained_window_win.cc20
-rw-r--r--chrome/browser/views/frame/browser_frame_win.cc6
-rw-r--r--chrome/browser/views/frame/browser_root_view.cc15
-rw-r--r--chrome/browser/views/frame/browser_view.cc32
-rw-r--r--chrome/browser/views/frame/glass_browser_frame_view.cc47
-rw-r--r--chrome/browser/views/frame/opaque_browser_frame_view.cc88
-rw-r--r--chrome/browser/views/info_bubble.cc74
-rw-r--r--chrome/browser/views/info_bubble.h77
-rw-r--r--chrome/browser/views/location_bar_view.cc1254
-rw-r--r--chrome/browser/views/location_bar_view.h327
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.cc74
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.h89
-rw-r--r--chrome/browser/views/tabs/dragged_tab_controller.cc9
-rw-r--r--chrome/browser/views/tabs/tab_renderer.cc204
-rw-r--r--chrome/browser/views/tabs/tab_renderer.h52
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc1369
-rw-r--r--chrome/browser/views/tabs/tab_strip.h248
-rw-r--r--chrome/browser/views/toolbar_star_toggle.cc133
-rw-r--r--chrome/browser/views/toolbar_star_toggle.h85
-rw-r--r--chrome/browser/views/toolbar_view.cc182
-rw-r--r--chrome/browser/views/toolbar_view.h24
-rw-r--r--chrome/browser/views/url_picker.cc6
121 files changed, 4748 insertions, 4918 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc
index 9c7e942..ba37681 100644
--- a/chrome/browser/autocomplete/autocomplete.cc
+++ b/chrome/browser/autocomplete/autocomplete.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -27,6 +27,7 @@
#include "googleurl/src/url_canon_ip.h"
#include "googleurl/src/url_util.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "net/base/net_util.h"
#include "net/base/registry_controlled_domain.h"
#include "net/url_request/url_request.h"
@@ -367,6 +368,18 @@ void AutocompleteInput::Clear() {
// AutocompleteMatch ----------------------------------------------------------
+AutocompleteMatch::AutocompleteMatch()
+ : provider(NULL),
+ relevance(0),
+ deletable(false),
+ inline_autocomplete_offset(std::wstring::npos),
+ transition(PageTransition::GENERATED),
+ is_history_what_you_typed_match(false),
+ type(SEARCH_WHAT_YOU_TYPED),
+ template_url(NULL),
+ starred(false) {
+}
+
AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
int relevance,
bool deletable,
@@ -384,23 +397,40 @@ AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
// static
std::string AutocompleteMatch::TypeToString(Type type) {
- switch (type) {
- case URL_WHAT_YOU_TYPED: return "url-what-you-typed";
- case HISTORY_URL: return "history-url";
- case HISTORY_TITLE: return "history-title";
- case HISTORY_BODY: return "history-body";
- case HISTORY_KEYWORD: return "history-keyword";
- case NAVSUGGEST: return "navsuggest";
- case SEARCH_WHAT_YOU_TYPED: return "search-what-you-typed";
- case SEARCH_HISTORY: return "search-history";
- case SEARCH_SUGGEST: return "search-suggest";
- case SEARCH_OTHER_ENGINE: return "search-other-engine";
- case OPEN_HISTORY_PAGE: return "open-history-page";
+ const char* strings[NUM_TYPES] = {
+ "url-what-you-typed",
+ "history-url",
+ "history-title",
+ "history-body",
+ "history-keyword",
+ "navsuggest",
+ "search-what-you-typed",
+ "search-history",
+ "search-suggest",
+ "search-other-engine",
+ "open-history-page",
+ };
+ DCHECK(arraysize(strings) == NUM_TYPES);
+ return strings[type];
+}
- default:
- NOTREACHED();
- return std::string();
- }
+// static
+int AutocompleteMatch::TypeToIcon(Type type) {
+ int icons[NUM_TYPES] = {
+ IDR_OMNIBOX_HTTP,
+ IDR_OMNIBOX_HTTP,
+ IDR_OMNIBOX_HISTORY,
+ IDR_OMNIBOX_HISTORY,
+ IDR_OMNIBOX_HISTORY,
+ IDR_OMNIBOX_HTTP,
+ IDR_OMNIBOX_SEARCH,
+ IDR_OMNIBOX_SEARCH,
+ IDR_OMNIBOX_SEARCH,
+ IDR_OMNIBOX_SEARCH,
+ IDR_OMNIBOX_MORE,
+ };
+ DCHECK(arraysize(icons) == NUM_TYPES);
+ return icons[type];
}
// static
@@ -565,10 +595,14 @@ void AutocompleteProvider::UpdateStarredStateOfMatches() {
std::wstring AutocompleteProvider::StringForURLDisplay(
const GURL& url,
- bool check_accept_lang) const {
+ bool check_accept_lang,
+ bool trim_http) const {
std::wstring languages = (check_accept_lang && profile_) ?
profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::wstring();
- return net::FormatUrl(url, languages);
+ const net::FormatUrlTypes format_types = trim_http ?
+ net::kFormatUrlOmitAll : net::kFormatUrlOmitUsernamePassword;
+ return net::FormatUrl(url, languages, format_types, UnescapeRule::SPACES,
+ NULL, NULL, NULL);
}
// AutocompleteResult ---------------------------------------------------------
diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h
index d64fd6c..54bd9ff 100644
--- a/chrome/browser/autocomplete/autocomplete.h
+++ b/chrome/browser/autocomplete/autocomplete.h
@@ -314,22 +314,24 @@ struct AutocompleteMatch {
// The type of this match.
enum Type {
- URL_WHAT_YOU_TYPED, // The input as a URL.
- HISTORY_URL, // A past page whose URL contains the input.
- HISTORY_TITLE, // A past page whose title contains the input.
- HISTORY_BODY, // A past page whose body contains the input.
- HISTORY_KEYWORD, // A past page whose keyword contains the input.
- NAVSUGGEST, // A suggested URL.
- SEARCH_WHAT_YOU_TYPED, // The input as a search query (with the default
- // engine).
- SEARCH_HISTORY, // A past search (with the default engine)
- // containing the input.
- SEARCH_SUGGEST, // A suggested search (with the default engine).
- SEARCH_OTHER_ENGINE, // A search with a non-default engine.
- OPEN_HISTORY_PAGE, // A synthetic result that opens the history page to
- // search for the input.
+ URL_WHAT_YOU_TYPED = 0, // The input as a URL.
+ HISTORY_URL, // A past page whose URL contains the input.
+ HISTORY_TITLE, // A past page whose title contains the input.
+ HISTORY_BODY, // A past page whose body contains the input.
+ HISTORY_KEYWORD, // A past page whose keyword contains the input.
+ NAVSUGGEST, // A suggested URL.
+ SEARCH_WHAT_YOU_TYPED, // The input as a search query (with the default
+ // engine).
+ SEARCH_HISTORY, // A past search (with the default engine)
+ // containing the input.
+ SEARCH_SUGGEST, // A suggested search (with the default engine).
+ SEARCH_OTHER_ENGINE, // A search with a non-default engine.
+ OPEN_HISTORY_PAGE, // A synthetic result that opens the history page
+ // to search for the input.
+ NUM_TYPES,
};
+ AutocompleteMatch();
AutocompleteMatch(AutocompleteProvider* provider,
int relevance,
bool deletable,
@@ -338,6 +340,10 @@ struct AutocompleteMatch {
// Converts |type| to a string representation. Used in logging.
static std::string TypeToString(Type type);
+ // Converts |type| to a resource identifier for the appropriate icon for this
+ // type.
+ static int TypeToIcon(Type type);
+
// Comparison function for determining when one match is better than another.
static bool MoreRelevant(const AutocompleteMatch& elem1,
const AutocompleteMatch& elem2);
@@ -555,7 +561,8 @@ class AutocompleteProvider
// "Accept Languages" when check_accept_lang is true. Otherwise, it's called
// with an empty list.
std::wstring StringForURLDisplay(const GURL& url,
- bool check_accept_lang) const;
+ bool check_accept_lang,
+ bool trim_http) const;
// The profile associated with the AutocompleteProvider. Reference is not
// owned by us.
@@ -776,7 +783,7 @@ class AutocompleteController : public ACProviderListener {
const AutocompleteInput& input() const { return input_; }
const AutocompleteResult& result() const { return result_; }
// This next is temporary and should go away when
- // AutocompletePopup::URLsForCurrentSelection() moves to the controller.
+ // AutocompletePopup::InfoForCurrentSelection() moves to the controller.
const AutocompleteResult& latest_result() const { return latest_result_; }
bool done() const { return done_ && !update_delay_timer_.IsRunning(); }
diff --git a/chrome/browser/autocomplete/autocomplete_classifier.cc b/chrome/browser/autocomplete/autocomplete_classifier.cc
new file mode 100644
index 0000000..3e96ff5
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_classifier.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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/autocomplete/autocomplete_classifier.h"
+
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "googleurl/src/gurl.h"
+
+AutocompleteClassifier::AutocompleteClassifier(Profile* profile)
+ : controller_(new AutocompleteController(profile)) {
+}
+
+AutocompleteClassifier::~AutocompleteClassifier() {
+}
+
+void AutocompleteClassifier::Classify(const std::wstring& text,
+ const std::wstring& desired_tld,
+ AutocompleteMatch* match,
+ GURL* alternate_nav_url) {
+ controller_->Start(text, desired_tld, true, false, true);
+ DCHECK(controller_->done());
+ const AutocompleteResult& result = controller_->result();
+ if (result.empty()) {
+ if (alternate_nav_url)
+ *alternate_nav_url = GURL();
+ return;
+ }
+
+ DCHECK(result.default_match() != result.end());
+ *match = *result.default_match();
+ if (alternate_nav_url)
+ *alternate_nav_url = result.alternate_nav_url();
+}
diff --git a/chrome/browser/autocomplete/autocomplete_classifier.h b/chrome/browser/autocomplete/autocomplete_classifier.h
new file mode 100644
index 0000000..3588c27
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete_classifier.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 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_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_
+#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+
+class AutocompleteController;
+struct AutocompleteMatch;
+class GURL;
+class Profile;
+
+class AutocompleteClassifier {
+ public:
+ explicit AutocompleteClassifier(Profile* profile);
+ virtual ~AutocompleteClassifier();
+
+ // Given some string |text| that the user wants to use for navigation,
+ // determines how it should be interpreted. |desired_tld| is the user's
+ // desired TLD, if any; see AutocompleteInput::desired_tld(). |match| should
+ // be a non-NULL outparam that will be set to the default match for this
+ // input, if any (for invalid input, there will be no default match, and
+ // |match| will be left unchanged). |alternate_nav_url| is a possibly-NULL
+ // outparam that, if non-NULL, will be set to the navigational URL (if any) in
+ // case of an accidental search; see comments on
+ // AutocompleteResult::alternate_nav_url_ in autocomplete.h.
+ void Classify(const std::wstring& text,
+ const std::wstring& desired_tld,
+ AutocompleteMatch* match,
+ GURL* alternate_nav_url);
+
+ private:
+ scoped_ptr<AutocompleteController> controller_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AutocompleteClassifier);
+};
+
+#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc
index f4c2583..9b0aefb 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
@@ -19,7 +20,6 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/search_versus_navigate_classifier.h"
#include "chrome/common/notification_service.h"
#include "googleurl/src/gurl.h"
#include "googleurl/src/url_util.h"
@@ -44,7 +44,6 @@ AutocompleteEditModel::AutocompleteEditModel(
control_key_state_(UP),
is_keyword_hint_(false),
keyword_ui_state_(NORMAL),
- show_search_hint_(true),
paste_and_go_transition_(PageTransition::TYPED),
profile_(profile) {
}
@@ -81,7 +80,7 @@ const AutocompleteEditModel::State
}
return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_,
- keyword_ui_state_, show_search_hint_);
+ keyword_ui_state_);
}
void AutocompleteEditModel::RestoreState(const State& state) {
@@ -92,7 +91,6 @@ void AutocompleteEditModel::RestoreState(const State& state) {
keyword_ = state.keyword;
is_keyword_hint_ = state.is_keyword_hint;
keyword_ui_state_ = state.keyword_ui_state;
- show_search_hint_ = state.show_search_hint;
view_->SetUserText(state.user_text,
DisplayTextFromUserText(state.user_text), false);
}
@@ -122,7 +120,9 @@ void AutocompleteEditModel::SetUserText(const std::wstring& text) {
void AutocompleteEditModel::GetDataForURLExport(GURL* url,
std::wstring* title,
SkBitmap* favicon) {
- *url = GetURLForCurrentText(NULL, NULL, NULL);
+ AutocompleteMatch match;
+ GetInfoForCurrentText(&match, NULL);
+ *url = match.destination_url;
if (UTF8ToWide(url->possibly_invalid_spec()) == permanent_text_) {
*title = controller_->GetTitle();
*favicon = controller_->GetFavIcon();
@@ -134,7 +134,7 @@ std::wstring AutocompleteEditModel::GetDesiredTLD() const {
std::wstring(L"com") : std::wstring();
}
-bool AutocompleteEditModel::CurrentTextIsURL() {
+bool AutocompleteEditModel::CurrentTextIsURL() const {
// If !user_input_in_progress_, the permanent text is showing, which should
// always be a URL, so no further checking is needed. By avoiding checking in
// this case, we avoid calling into the autocomplete providers, and thus
@@ -142,9 +142,15 @@ bool AutocompleteEditModel::CurrentTextIsURL() {
if (!user_input_in_progress_)
return true;
- PageTransition::Type transition = PageTransition::LINK;
- GetURLForCurrentText(&transition, NULL, NULL);
- return transition == PageTransition::TYPED;
+ AutocompleteMatch match;
+ GetInfoForCurrentText(&match, NULL);
+ return match.transition == PageTransition::TYPED;
+}
+
+AutocompleteMatch::Type AutocompleteEditModel::CurrentTextType() const {
+ AutocompleteMatch match;
+ GetInfoForCurrentText(&match, NULL);
+ return match.type;
}
bool AutocompleteEditModel::GetURLForText(const std::wstring& text,
@@ -174,7 +180,6 @@ void AutocompleteEditModel::Revert() {
keyword_.clear();
is_keyword_hint_ = false;
keyword_ui_state_ = NORMAL;
- show_search_hint_ = permanent_text_.empty();
has_temporary_text_ = false;
view_->SetWindowTextAndCaretPos(permanent_text_,
has_focus_ ? permanent_text_.length() : 0);
@@ -191,14 +196,11 @@ bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const {
if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL))
return false;
- paste_and_go_url_ = GURL();
- paste_and_go_transition_ = PageTransition::TYPED;
- paste_and_go_alternate_nav_url_ = GURL();
-
- profile_->GetSearchVersusNavigateClassifier()->Classify(text, std::wstring(),
- NULL, &paste_and_go_url_, &paste_and_go_transition_, NULL,
- &paste_and_go_alternate_nav_url_);
-
+ AutocompleteMatch match;
+ profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(),
+ &match, &paste_and_go_alternate_nav_url_);
+ paste_and_go_url_ = match.destination_url;
+ paste_and_go_transition_ = match.transition;
return paste_and_go_url_.is_valid();
}
@@ -215,33 +217,30 @@ void AutocompleteEditModel::PasteAndGo() {
void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition,
bool for_drop) {
// Get the URL and transition type for the selected entry.
- PageTransition::Type transition;
- bool is_history_what_you_typed_match;
+ AutocompleteMatch match;
GURL alternate_nav_url;
- const GURL url(GetURLForCurrentText(&transition,
- &is_history_what_you_typed_match,
- &alternate_nav_url));
- if (!url.is_valid())
+ GetInfoForCurrentText(&match, &alternate_nav_url);
+ if (!match.destination_url.is_valid())
return;
- if (UTF8ToWide(url.spec()) == permanent_text_) {
+ if (UTF8ToWide(match.destination_url.spec()) == permanent_text_) {
// When the user hit enter on the existing permanent URL, treat it like a
// reload for scoring purposes. We could detect this by just checking
// user_input_in_progress_, but it seems better to treat "edits" that end
// up leaving the URL unchanged (e.g. deleting the last character and then
// retyping it) as reloads too.
- transition = PageTransition::RELOAD;
+ match.transition = PageTransition::RELOAD;
} else if (for_drop || ((paste_state_ != NONE) &&
- is_history_what_you_typed_match)) {
+ match.is_history_what_you_typed_match)) {
// When the user pasted in a URL and hit enter, score it like a link click
// rather than a normal typed URL, so it doesn't get inline autocompleted
// as aggressively later.
- transition = PageTransition::LINK;
+ match.transition = PageTransition::LINK;
}
- view_->OpenURL(url, disposition, transition, alternate_nav_url,
- AutocompletePopupModel::kNoMatch,
- is_keyword_hint_ ? std::wstring() : keyword_);
+ view_->OpenURL(match.destination_url, disposition, match.transition,
+ alternate_nav_url, AutocompletePopupModel::kNoMatch,
+ is_keyword_hint_ ? std::wstring() : keyword_);
}
void AutocompleteEditModel::SendOpenNotification(size_t selected_line,
@@ -325,17 +324,20 @@ void AutocompleteEditModel::OnKillFocus() {
}
bool AutocompleteEditModel::OnEscapeKeyPressed() {
- if (has_temporary_text_ &&
- (popup_->URLsForCurrentSelection(NULL, NULL, NULL) != original_url_)) {
- // The user typed something, then selected a different item. Restore the
- // text they typed and change back to the default item.
- // NOTE: This purposefully does not reset paste_state_.
- just_deleted_text_ = false;
- has_temporary_text_ = false;
- keyword_ui_state_ = original_keyword_ui_state_;
- popup_->ResetToDefaultMatch();
- view_->OnRevertTemporaryText();
- return true;
+ if (has_temporary_text_) {
+ AutocompleteMatch match;
+ popup_->InfoForCurrentSelection(&match, NULL);
+ if (match.destination_url != original_url_) {
+ // The user typed something, then selected a different item. Restore the
+ // text they typed and change back to the default item.
+ // NOTE: This purposefully does not reset paste_state_.
+ just_deleted_text_ = false;
+ has_temporary_text_ = false;
+ keyword_ui_state_ = original_keyword_ui_state_;
+ popup_->ResetToDefaultMatch();
+ view_->OnRevertTemporaryText();
+ return true;
+ }
}
// If the user wasn't editing, but merely had focus in the edit, allow <esc>
@@ -405,35 +407,24 @@ void AutocompleteEditModel::OnUpOrDownKeyPressed(int count) {
void AutocompleteEditModel::OnPopupDataChanged(
const std::wstring& text,
- bool is_temporary_text,
+ GURL* destination_for_temporary_text_change,
const std::wstring& keyword,
- bool is_keyword_hint,
- AutocompleteMatch::Type type) {
- // We don't want to show the search hint if we're showing a keyword hint or
- // selected keyword, or (subtle!) if we would be showing a selected keyword
- // but for keyword_ui_state_ == NO_KEYWORD.
- const bool show_search_hint = keyword.empty() &&
- ((type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED) ||
- (type == AutocompleteMatch::SEARCH_HISTORY) ||
- (type == AutocompleteMatch::SEARCH_SUGGEST));
-
+ bool is_keyword_hint) {
// Update keyword/hint-related local state.
bool keyword_state_changed = (keyword_ != keyword) ||
- ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()) ||
- (show_search_hint_ != show_search_hint);
+ ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty());
if (keyword_state_changed) {
keyword_ = keyword;
is_keyword_hint_ = is_keyword_hint;
- show_search_hint_ = show_search_hint;
}
// Handle changes to temporary text.
- if (is_temporary_text) {
+ if (destination_for_temporary_text_change != NULL) {
const bool save_original_selection = !has_temporary_text_;
if (save_original_selection) {
// Save the original selection and URL so it can be reverted later.
has_temporary_text_ = true;
- original_url_ = popup_->URLsForCurrentSelection(NULL, NULL, NULL);
+ original_url_ = *destination_for_temporary_text_change;
original_keyword_ui_state_ = keyword_ui_state_;
}
if (control_key_state_ == DOWN_WITHOUT_CHANGE) {
@@ -542,7 +533,6 @@ void AutocompleteEditModel::Observe(NotificationType type,
std::wstring inline_autocomplete_text;
std::wstring keyword;
bool is_keyword_hint = false;
- AutocompleteMatch::Type match_type = AutocompleteMatch::SEARCH_WHAT_YOU_TYPED;
const AutocompleteResult* result =
Details<const AutocompleteResult>(details).ptr();
const AutocompleteResult::const_iterator match(result->default_match());
@@ -559,11 +549,9 @@ void AutocompleteEditModel::Observe(NotificationType type,
// the OS DNS cache could suffer eviction problems for minimal gain.
is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword);
- match_type = match->type;
}
- OnPopupDataChanged(inline_autocomplete_text, false, keyword, is_keyword_hint,
- match_type);
+ OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint);
}
void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) {
@@ -586,20 +574,14 @@ std::wstring AutocompleteEditModel::UserTextFromDisplayText(
text : (keyword_ + L" " + text);
}
-GURL AutocompleteEditModel::GetURLForCurrentText(
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
+void AutocompleteEditModel::GetInfoForCurrentText(
+ AutocompleteMatch* match,
GURL* alternate_nav_url) const {
if (popup_->IsOpen() || query_in_progress()) {
- return popup_->URLsForCurrentSelection(transition,
- is_history_what_you_typed_match,
- alternate_nav_url);
+ popup_->InfoForCurrentSelection(match, alternate_nav_url);
+ } else {
+ profile_->GetAutocompleteClassifier()->Classify(
+ UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), match,
+ alternate_nav_url);
}
-
- GURL destination_url;
- profile_->GetSearchVersusNavigateClassifier()->Classify(
- UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), NULL,
- &destination_url, transition, is_history_what_you_typed_match,
- alternate_nav_url);
- return destination_url;
}
diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h
index 1a0386c..9f4e973 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.h
+++ b/chrome/browser/autocomplete/autocomplete_edit.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -83,14 +83,12 @@ class AutocompleteEditModel : public NotificationObserver {
const std::wstring& user_text,
const std::wstring& keyword,
bool is_keyword_hint,
- KeywordUIState keyword_ui_state,
- bool show_search_hint)
+ KeywordUIState keyword_ui_state)
: user_input_in_progress(user_input_in_progress),
user_text(user_text),
keyword(keyword),
is_keyword_hint(is_keyword_hint),
- keyword_ui_state(keyword_ui_state),
- show_search_hint(show_search_hint) {
+ keyword_ui_state(keyword_ui_state) {
}
bool user_input_in_progress;
@@ -98,7 +96,6 @@ class AutocompleteEditModel : public NotificationObserver {
const std::wstring keyword;
const bool is_keyword_hint;
const KeywordUIState keyword_ui_state;
- const bool show_search_hint;
};
AutocompleteEditModel(AutocompleteEditView* view,
@@ -137,7 +134,10 @@ class AutocompleteEditModel : public NotificationObserver {
// Returns true if the current edit contents will be treated as a
// URL/navigation, as opposed to a search.
- bool CurrentTextIsURL();
+ bool CurrentTextIsURL() const;
+
+ // Returns the match type for the current edit contents.
+ AutocompleteMatch::Type CurrentTextType() const;
// Returns true if |text| (which is display text in the current context)
// parses as a URL, and in that case sets |url| to the calculated URL.
@@ -208,7 +208,7 @@ class AutocompleteEditModel : public NotificationObserver {
// Accessors for keyword-related state (see comments on keyword_ and
// is_keyword_hint_).
std::wstring keyword() const {
- return (is_keyword_hint_ ? has_focus_ : (keyword_ui_state_ != NO_KEYWORD)) ?
+ return (is_keyword_hint_ || (keyword_ui_state_ != NO_KEYWORD)) ?
keyword_ : std::wstring();
}
bool is_keyword_hint() const { return is_keyword_hint_; }
@@ -220,10 +220,6 @@ class AutocompleteEditModel : public NotificationObserver {
// currently visible in the edit.
void ClearKeyword(const std::wstring& visible_text);
- // True if we should show the "Type to search" hint (see comments on
- // show_search_hint_).
- bool show_search_hint() const { return has_focus_ && show_search_hint_; }
-
// Returns true if a query to an autocomplete provider is currently
// in progress. This logic should in the future live in
// AutocompleteController but resides here for now. This method is used by
@@ -260,21 +256,20 @@ class AutocompleteEditModel : public NotificationObserver {
// Called when any relevant data changes. This rolls together several
// separate pieces of data into one call so we can update all the UI
// efficiently:
- // |text| is either the new temporary text (if |is_temporary_text| is true)
- // from the user manually selecting a different match, or the inline
- // autocomplete text (if |is_temporary_text| is false).
+ // |text| is either the new temporary text from the user manually selecting
+ // a different match, or the inline autocomplete text. We distinguish by
+ // checking if |destination_for_temporary_text_change| is NULL.
+ // |destination_for_temporary_text_change| is NULL (if temporary text should
+ // not change) or the pre-change desitnation URL (if temporary text should
+ // change) so we can save it off to restore later.
// |keyword| is the keyword to show a hint for if |is_keyword_hint| is true,
// or the currently selected keyword if |is_keyword_hint| is false (see
// comments on keyword_ and is_keyword_hint_).
- // |type| is the type of match selected; this is used to determine whether
- // we can show the "Type to search" hint (see comments on
- // show_search_hint_).
void OnPopupDataChanged(
const std::wstring& text,
- bool is_temporary_text,
+ GURL* destination_for_temporary_text_change,
const std::wstring& keyword,
- bool is_keyword_hint,
- AutocompleteMatch::Type type);
+ bool is_keyword_hint);
// Called by the AutocompleteEditView after something changes, with details
// about what state changes occured. Updates internal state, updates the
@@ -326,16 +321,10 @@ class AutocompleteEditModel : public NotificationObserver {
std::wstring DisplayTextFromUserText(const std::wstring& text) const;
std::wstring UserTextFromDisplayText(const std::wstring& text) const;
- // Returns the URL. If the user has not edited the text, this returns the
- // permanent text. If the user has edited the text, this returns the default
- // match based on the current text, which may be a search URL, or keyword
- // generated URL.
- //
- // See AutocompleteEdit for a description of the args (they may be null if
- // not needed).
- GURL GetURLForCurrentText(PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
- GURL* alternate_nav_url) const;
+ // Returns the default match for the current text, as well as the alternate
+ // nav URL, if |alternate_nav_url| is non-NULL and there is such a URL.
+ void GetInfoForCurrentText(AutocompleteMatch* match,
+ GURL* alternate_nav_url) const;
AutocompleteEditView* view_;
@@ -432,10 +421,6 @@ class AutocompleteEditModel : public NotificationObserver {
// See KeywordUIState enum.
KeywordUIState keyword_ui_state_;
- // True when it's safe to show a "Type to search" hint to the user (when the
- // edit is empty, or the user is in the process of searching).
- bool show_search_hint_;
-
// Paste And Go-related state. See CanPasteAndGo().
mutable GURL paste_and_go_url_;
mutable PageTransition::Type paste_and_go_transition_;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h
index 63c2524..0d4c230 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view.h
@@ -59,6 +59,13 @@ class AutocompleteEditView {
// browser, or just whatever the user has currently typed.
virtual std::wstring GetText() const = 0;
+ // |true| if the user is in the process of editing the field, or if
+ // the field is empty.
+ virtual bool IsEditingOrEmpty() const = 0;
+
+ // Returns the resource ID of the icon to show for the current text.
+ virtual int GetIcon() const = 0;
+
// The user text is the text the user has manually keyed in. When present,
// this is shown in preference to the permanent text; hitting escape will
// revert to the permanent text.
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index 86d886d..006395f 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -17,7 +17,6 @@
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/defaults.h"
@@ -34,9 +33,11 @@
#include "net/base/escape.h"
#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
#include "chrome/browser/views/location_bar_view.h"
#include "gfx/skia_utils_gtk.h"
#else
+#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/location_bar_view_gtk.h"
#endif
@@ -45,11 +46,13 @@ using gfx::SkColorToGdkColor;
namespace {
+const gchar* kAutocompleteEditViewGtkKey = "__ACE_VIEW_GTK__";
+
const char kTextBaseColor[] = "#808080";
-const char kSecureSchemeColor[] = "#009614";
-const char kInsecureSchemeColor[] = "#c80000";
+const char kSecureSchemeColor[] = "#079500";
+const char kSecurityErrorSchemeColor[] = "#a20000";
-const double kStrikethroughStrokeRed = 210.0 / 256.0;
+const double kStrikethroughStrokeRed = 162.0 / 256.0;
const double kStrikethroughStrokeWidth = 2.0;
size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) {
@@ -108,6 +111,26 @@ void SetEntryStyle() {
"style \"chrome-location-bar-entry\"");
}
+// Copied from GTK+. Called when we lose the primary selection. This will clear
+// the selection in the text buffer.
+void ClipboardSelectionCleared(GtkClipboard* clipboard,
+ gpointer data) {
+ GtkTextIter insert;
+ GtkTextIter selection_bound;
+ GtkTextBuffer* buffer = GTK_TEXT_BUFFER(data);
+
+ gtk_text_buffer_get_iter_at_mark(buffer, &insert,
+ gtk_text_buffer_get_insert(buffer));
+ gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
+ gtk_text_buffer_get_selection_bound(buffer));
+
+ if (!gtk_text_iter_equal(&insert, &selection_bound)) {
+ gtk_text_buffer_move_mark(buffer,
+ gtk_text_buffer_get_selection_bound(buffer),
+ &insert);
+ }
+}
+
} // namespace
AutocompleteEditViewGtk::AutocompleteEditViewGtk(
@@ -116,23 +139,30 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk(
Profile* profile,
CommandUpdater* command_updater,
bool popup_window_mode,
- const BubblePositioner* bubble_positioner)
+#if defined(TOOLKIT_VIEWS)
+ const views::View* location_bar)
+#else
+ GtkWidget* location_bar)
+#endif
: text_view_(NULL),
tag_table_(NULL),
text_buffer_(NULL),
faded_text_tag_(NULL),
secure_scheme_tag_(NULL),
- insecure_scheme_tag_(NULL),
+ security_error_scheme_tag_(NULL),
model_(new AutocompleteEditModel(this, controller, profile)),
- popup_view_(AutocompletePopupView::CreatePopupView(gfx::Font(), this,
- model_.get(),
- profile,
- bubble_positioner)),
+#if defined(TOOLKIT_VIEWS)
+ popup_view_(new AutocompletePopupContentsView(
+ gfx::Font(), this, model_.get(), profile, location_bar)),
+#else
+ popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile,
+ location_bar)),
+#endif
controller_(controller),
toolbar_model_(toolbar_model),
command_updater_(command_updater),
popup_window_mode_(popup_window_mode),
- scheme_security_level_(ToolbarModel::NORMAL),
+ security_level_(ToolbarModel::NONE),
mark_set_handler_id_(0),
#if defined(OS_CHROMEOS)
button_1_pressed_(false),
@@ -185,6 +215,7 @@ void AutocompleteEditViewGtk::Init() {
// the other objects adds a reference; it doesn't adopt them.
tag_table_ = gtk_text_tag_table_new();
text_buffer_ = gtk_text_buffer_new(tag_table_);
+ g_object_set_data(G_OBJECT(text_buffer_), kAutocompleteEditViewGtkKey, this);
text_view_ = gtk_text_view_new_with_buffer(text_buffer_);
if (popup_window_mode_)
gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view_), false);
@@ -215,8 +246,8 @@ void AutocompleteEditViewGtk::Init() {
NULL, "foreground", kTextBaseColor, NULL);
secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
NULL, "foreground", kSecureSchemeColor, NULL);
- insecure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
- NULL, "foreground", kInsecureSchemeColor, NULL);
+ security_error_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
+ NULL, "foreground", kSecurityErrorSchemeColor, NULL);
normal_text_tag_ = gtk_text_buffer_create_tag(text_buffer_,
NULL, "foreground", "#000000", NULL);
@@ -258,6 +289,8 @@ void AutocompleteEditViewGtk::Init() {
G_CALLBACK(&HandlePopulatePopupThunk), this);
mark_set_handler_id_ = g_signal_connect(
text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this);
+ mark_set_handler_id2_ = g_signal_connect_after(
+ text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetAfterThunk), this);
g_signal_connect(text_view_, "drag-data-received",
G_CALLBACK(&HandleDragDataReceivedThunk), this);
g_signal_connect(text_view_, "backspace",
@@ -284,7 +317,7 @@ void AutocompleteEditViewGtk::Init() {
SetBaseColor();
#endif
- ViewIDUtil::SetID(widget(), VIEW_ID_AUTOCOMPLETE);
+ ViewIDUtil::SetID(GetNativeView(), VIEW_ID_AUTOCOMPLETE);
}
void AutocompleteEditViewGtk::SetFocus() {
@@ -318,9 +351,8 @@ void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) {
DCHECK(tab);
// If any text has been selected, register it as the PRIMARY selection so it
// can still be pasted via middle-click after the text view is cleared.
- if (!selected_text_.empty()) {
+ if (!selected_text_.empty())
SavePrimarySelection(selected_text_);
- }
// NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch();
GetStateAccessor()->SetProperty(
@@ -334,15 +366,9 @@ void AutocompleteEditViewGtk::Update(const TabContents* contents) {
model_->UpdatePermanentText(toolbar_model_->GetText());
ToolbarModel::SecurityLevel security_level =
- toolbar_model_->GetSchemeSecurityLevel();
- bool changed_security_level = (security_level != scheme_security_level_);
- scheme_security_level_ = security_level;
-
- // TODO(deanm): This doesn't exactly match Windows. There there is a member
- // background_color_. I think we can get away with just the level though.
- if (changed_security_level) {
- SetBaseColor();
- }
+ toolbar_model_->GetSecurityLevel();
+ bool changed_security_level = (security_level != security_level_);
+ security_level_ = security_level;
if (contents) {
selected_text_.clear();
@@ -392,6 +418,17 @@ std::wstring AutocompleteEditViewGtk::GetText() const {
return out;
}
+bool AutocompleteEditViewGtk::IsEditingOrEmpty() const {
+ return model_->user_input_in_progress() ||
+ (gtk_text_buffer_get_char_count(text_buffer_) == 0);
+}
+
+int AutocompleteEditViewGtk::GetIcon() const {
+ return IsEditingOrEmpty() ?
+ AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
+ toolbar_model_->GetIcon();
+}
+
void AutocompleteEditViewGtk::SetUserText(const std::wstring& text,
const std::wstring& display_text,
bool update_popup) {
@@ -582,10 +619,8 @@ void AutocompleteEditViewGtk::SetBaseColor() {
bool use_gtk = theme_provider_->UseGtkTheme();
#endif
- // If we're on a secure connection, ignore what the theme wants us to do
- // and use a yellow background.
- bool is_secure = (scheme_security_level_ == ToolbarModel::SECURE);
- if (use_gtk && !is_secure) {
+ if (use_gtk) {
+ gtk_widget_modify_cursor(text_view_, NULL, NULL);
gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL);
gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, NULL);
gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, NULL);
@@ -600,20 +635,21 @@ void AutocompleteEditViewGtk::SetBaseColor() {
GdkColor average_color = gtk_util::AverageColors(
style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
- g_object_set(faded_text_tag_, "foreground-gdk",
- &average_color, NULL);
+ g_object_set(faded_text_tag_, "foreground-gdk", &average_color, NULL);
g_object_set(normal_text_tag_, "foreground-gdk",
&style->text[GTK_STATE_NORMAL], NULL);
} else {
+ const GdkColor* background_color_ptr;
#if defined(TOOLKIT_VIEWS)
const GdkColor background_color = gfx::SkColorToGdkColor(
- LocationBarView::GetColor(is_secure, LocationBarView::BACKGROUND));
- gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL,
- &background_color);
+ LocationBarView::GetColor(ToolbarModel::NONE,
+ LocationBarView::BACKGROUND));
+ background_color_ptr = &background_color;
#else
- gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL,
- &LocationBarViewGtk::kBackgroundColorByLevel[scheme_security_level_]);
+ background_color_ptr = &LocationBarViewGtk::kBackgroundColor;
#endif
+ gtk_widget_modify_cursor(text_view_, &gfx::kGdkBlack, &gfx::kGdkGray);
+ gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background_color_ptr);
#if !defined(TOOLKIT_VIEWS)
// Override the selected colors so we don't leak colors from the current
@@ -1037,11 +1073,32 @@ void AutocompleteEditViewGtk::HandleMarkSet(GtkTextBuffer* buffer,
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_))
SavePrimarySelection(selected_text_);
+ } else if (IsSelectAll() && !model_->user_input_in_progress()) {
+ // Copy the whole URL to the clipboard (including the scheme, which is
+ // hidden in the case of http://).
+ GURL url;
+ if (model_->GetURLForText(GetText(), &url))
+ OwnPrimarySelection(url.spec());
}
selected_text_ = new_selected_text;
}
+// Override the primary selection the text buffer has set. This has to happen
+// after the default handler for the "mark-set" signal.
+void AutocompleteEditViewGtk::HandleMarkSetAfter(GtkTextBuffer* buffer,
+ GtkTextIter* location,
+ GtkTextMark* mark) {
+ std::wstring text = GetText();
+ if (IsSelectAll() && !model_->user_input_in_progress() && !text.empty()) {
+ // Copy the whole URL to the clipboard (including the scheme, which is
+ // hidden in the case of http://).
+ GURL url;
+ if (model_->GetURLForText(GetText(), &url))
+ OwnPrimarySelection(url.spec());
+ }
+}
+
// Just use the default behavior for DnD, except if the drop can be a PasteAndGo
// then override.
void AutocompleteEditViewGtk::HandleDragDataReceived(
@@ -1178,18 +1235,14 @@ void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(GtkWidget* sender) {
// string to avoid encoding and escaping issues when pasting this text
// elsewhere.
scw.WriteText(url_spec16);
+ OwnPrimarySelection(url.spec());
} else {
scw.WriteText(text16);
+ OwnPrimarySelection(UTF16ToUTF8(text16));
}
scw.WriteHyperlink(UTF16ToUTF8(EscapeForHTML(text16)), url.spec());
- // Update PRIMARY selection if it is not owned by the text_buffer.
- if (gtk_clipboard_get_owner(clipboard) != G_OBJECT(text_buffer_)) {
- std::string utf8_text(UTF16ToUTF8(text16));
- gtk_clipboard_set_text(clipboard, utf8_text.c_str(), utf8_text.length());
- }
-
// Stop propagating the signal.
static guint signal_id =
g_signal_lookup("copy-clipboard", GTK_TYPE_TEXT_VIEW);
@@ -1197,16 +1250,27 @@ void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(GtkWidget* sender) {
return;
}
- // Passing gtk_text_buffer_copy_clipboard() a text buffer that already owns
- // the clipboard that's being updated clears the highlighted text, which we
- // don't want to do (and it also appears to at least sometimes trigger a
- // failed G_IS_OBJECT() assertion).
- if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_))
- return;
+ OwnPrimarySelection(selected_text_);
+}
- // We can't just call SavePrimarySelection(); that makes the text view lose
- // the selection and unhighlight its text.
- gtk_text_buffer_copy_clipboard(text_buffer_, clipboard);
+void AutocompleteEditViewGtk::OwnPrimarySelection(const std::string& text) {
+ primary_selection_text_ = text;
+
+ GtkTargetList* list = gtk_target_list_new(NULL, 0);
+ gtk_target_list_add_text_targets(list, 0);
+ gint len;
+ GtkTargetEntry* entries = gtk_target_table_new_from_list(list, &len);
+
+ // When |text_buffer_| is destroyed, it will clear the clipboard, hence
+ // we needn't worry about calling gtk_clipboard_clear().
+ gtk_clipboard_set_with_owner(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
+ entries, len,
+ ClipboardGetSelectionThunk,
+ ClipboardSelectionCleared,
+ G_OBJECT(text_buffer_));
+
+ gtk_target_list_unref(list);
+ gtk_target_table_free(entries, len);
}
void AutocompleteEditViewGtk::HandlePasteClipboard(GtkWidget* sender) {
@@ -1294,6 +1358,7 @@ void AutocompleteEditViewGtk::StartUpdatingHighlightedText() {
gtk_text_buffer_remove_selection_clipboard(text_buffer_, clipboard);
}
g_signal_handler_block(text_buffer_, mark_set_handler_id_);
+ g_signal_handler_block(text_buffer_, mark_set_handler_id2_);
}
void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() {
@@ -1305,6 +1370,7 @@ void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() {
gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard);
}
g_signal_handler_unblock(text_buffer_, mark_set_handler_id_);
+ g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_);
}
AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() {
@@ -1374,22 +1440,21 @@ void AutocompleteEditViewGtk::EmphasizeURLComponents() {
strikethrough_ = CharRange();
// Emphasize the scheme for security UI display purposes (if necessary).
if (!model_->user_input_in_progress() && scheme.is_nonempty() &&
- (scheme_security_level_ != ToolbarModel::NORMAL)) {
+ (security_level_ != ToolbarModel::NONE)) {
CharRange scheme_range = CharRange(GetUTF8Offset(text, scheme.begin),
GetUTF8Offset(text, scheme.end()));
ItersFromCharRange(scheme_range, &start, &end);
- if (scheme_security_level_ == ToolbarModel::SECURE) {
- gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_,
- &start, &end);
- } else {
+ if (security_level_ == ToolbarModel::SECURITY_ERROR) {
strikethrough_ = scheme_range;
// When we draw the strikethrough, we don't want to include the ':' at the
// end of the scheme.
strikethrough_.cp_max--;
- gtk_text_buffer_apply_tag(text_buffer_, insecure_scheme_tag_,
+ gtk_text_buffer_apply_tag(text_buffer_, security_error_scheme_tag_,
&start, &end);
+ } else {
+ gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, &start, &end);
}
}
}
@@ -1469,3 +1534,23 @@ void AutocompleteEditViewGtk::HandleWidgetDirectionChanged(
void AutocompleteEditViewGtk::HandleKeymapDirectionChanged(GdkKeymap* sender) {
AdjustTextJustification();
}
+
+// static
+void AutocompleteEditViewGtk::ClipboardGetSelectionThunk(
+ GtkClipboard* clipboard,
+ GtkSelectionData* selection_data,
+ guint info,
+ gpointer object) {
+ AutocompleteEditViewGtk* edit_view =
+ reinterpret_cast<AutocompleteEditViewGtk*>(
+ g_object_get_data(G_OBJECT(object), kAutocompleteEditViewGtkKey));
+ edit_view->ClipboardGetSelection(clipboard, selection_data, info);
+}
+
+void AutocompleteEditViewGtk::ClipboardGetSelection(
+ GtkClipboard* clipboard,
+ GtkSelectionData* selection_data,
+ guint info) {
+ gtk_selection_data_set_text(selection_data, primary_selection_text_.c_str(),
+ primary_selection_text_.size());
+}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
index 1eb1736..66b837b 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -25,9 +25,11 @@
class AutocompleteEditController;
class AutocompleteEditModel;
class AutocompletePopupView;
-class BubblePositioner;
class Profile;
class TabContents;
+namespace views {
+class View;
+}
#if !defined(TOOLKIT_VIEWS)
class GtkThemeProvider;
@@ -53,14 +55,16 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
Profile* profile,
CommandUpdater* command_updater,
bool popup_window_mode,
- const BubblePositioner* bubble_positioner);
+#if defined(TOOLKIT_VIEWS)
+ const views::View* location_bar);
+#else
+ GtkWidget* location_bar);
+#endif
~AutocompleteEditViewGtk();
// Initialize, create the underlying widgets, etc.
void Init();
- GtkWidget* widget() { return alignment_.get(); }
-
// Returns the width, in pixels, needed to display the current text. The
// returned value includes margins and borders.
int TextWidth();
@@ -82,6 +86,9 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
virtual std::wstring GetText() const;
+ virtual bool IsEditingOrEmpty() const;
+ virtual int GetIcon() const;
+
virtual void SetUserText(const std::wstring& text) {
SetUserText(text, text, true);
}
@@ -134,6 +141,9 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
GtkTextBuffer*);
CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSet,
GtkTextBuffer*, GtkTextIter*, GtkTextMark*);
+ // As above, but called after the default handler.
+ CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSetAfter,
+ GtkTextBuffer*, GtkTextIter*, GtkTextMark*);
CHROMEG_CALLBACK_3(AutocompleteEditViewGtk, void, HandleInsertText,
GtkTextBuffer*, GtkTextIter*, const gchar*, gint);
CHROMEG_CALLBACK_0(AutocompleteEditViewGtk, void,
@@ -172,6 +182,20 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void,
HandleWidgetDirectionChanged, GtkTextDirection);
+ // Callback for the PRIMARY selection clipboard.
+ static void ClipboardGetSelectionThunk(GtkClipboard* clipboard,
+ GtkSelectionData* selection_data,
+ guint info,
+ gpointer object);
+ void ClipboardGetSelection(GtkClipboard* clipboard,
+ GtkSelectionData* selection_data,
+ guint info);
+
+ // Take control of the PRIMARY selection clipboard with |text|. Use
+ // |text_buffer_| as the owner, so that this doesn't remove the selection on
+ // it. This makes use of the above callbacks.
+ void OwnPrimarySelection(const std::string& text);
+
// Gets the GTK_TEXT_WINDOW_WIDGET coordinates for |text_view_| that bound the
// given iters.
gfx::Rect WindowBoundsFromIters(GtkTextIter* iter1, GtkTextIter* iter2);
@@ -209,7 +233,8 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
// Internally invoked whenever the text changes in some way.
void TextChanged();
- // Save |selected_text| as the PRIMARY X selection.
+ // Save |selected_text| as the PRIMARY X selection. Unlike
+ // OwnPrimarySelection(), this won't set an owner or use callbacks.
void SavePrimarySelection(const std::string& selected_text);
// Update the field with |text| and set the selection.
@@ -239,7 +264,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
GtkTextBuffer* text_buffer_;
GtkTextTag* faded_text_tag_;
GtkTextTag* secure_scheme_tag_;
- GtkTextTag* insecure_scheme_tag_;
+ GtkTextTag* security_error_scheme_tag_;
GtkTextTag* normal_text_tag_;
scoped_ptr<AutocompleteEditModel> model_;
@@ -255,7 +280,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
// different presentation (smaller font size). This is used for popups.
bool popup_window_mode_;
- ToolbarModel::SecurityLevel scheme_security_level_;
+ ToolbarModel::SecurityLevel security_level_;
// Selection at the point where the user started using the
// arrows to move around in the popup.
@@ -272,8 +297,12 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
// it, we pass this string to SavePrimarySelection()).
std::string selected_text_;
- // ID of the signal handler for "mark-set" on |text_buffer_|.
+ // When we own the X clipboard, this is the text for it.
+ std::string primary_selection_text_;
+
+ // IDs of the signal handlers for "mark-set" on |text_buffer_|.
gulong mark_set_handler_id_;
+ gulong mark_set_handler_id2_;
#if defined(OS_CHROMEOS)
// The following variables are used to implement select-all-on-mouse-up, which
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
index 4cf7aee..740fde7 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h
@@ -13,7 +13,6 @@
class AutocompleteEditController;
class AutocompletePopupViewMac;
-class BubblePositioner;
class Clipboard;
class Profile;
class ToolbarModel;
@@ -24,7 +23,6 @@ class AutocompleteEditViewMac : public AutocompleteEditView,
public AutocompleteTextFieldObserver {
public:
AutocompleteEditViewMac(AutocompleteEditController* controller,
- const BubblePositioner* bubble_positioner,
ToolbarModel* toolbar_model,
Profile* profile,
CommandUpdater* command_updater,
@@ -48,6 +46,10 @@ class AutocompleteEditViewMac : public AutocompleteEditView,
const std::wstring& keyword);
virtual std::wstring GetText() const;
+
+ virtual bool IsEditingOrEmpty() const;
+ virtual int GetIcon() const;
+
virtual void SetUserText(const std::wstring& text) {
SetUserText(text, text, true);
}
@@ -98,6 +100,10 @@ class AutocompleteEditViewMac : public AutocompleteEditView,
// empty string if no appropriate data is found on |clipboard|.
static std::wstring GetClipboardText(Clipboard* clipboard);
+ // If |resource_id| has a PDF image which can be used, return it.
+ // Otherwise return the PNG image from the resource bundle.
+ static NSImage* ImageForResource(int resource_id);
+
private:
// Called when the user hits backspace in |field_|. Checks whether
// keyword search is being terminated. Returns true if the
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
index e337744..a4a54ce 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm
@@ -9,6 +9,7 @@
#include "app/clipboard/clipboard.h"
#include "app/clipboard/scoped_clipboard_writer.h"
#include "app/resource_bundle.h"
+#include "base/nsimage_cache_mac.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
@@ -20,6 +21,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/toolbar_model.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "net/base/escape.h"
// Focus-handling between |field_| and |model_| is a bit subtle.
@@ -61,15 +63,6 @@ const NSColor* ColorWithRGBBytes(int rr, int gg, int bb) {
blue:static_cast<float>(bb)/255.0
alpha:1.0];
}
-const NSColor* SecureBackgroundColor() {
- return ColorWithRGBBytes(255, 245, 195); // Yellow
-}
-const NSColor* NormalBackgroundColor() {
- return [NSColor controlBackgroundColor];
-}
-const NSColor* InsecureBackgroundColor() {
- return [NSColor controlBackgroundColor];
-}
const NSColor* HostTextColor() {
return [NSColor blackColor];
@@ -77,11 +70,14 @@ const NSColor* HostTextColor() {
const NSColor* BaseTextColor() {
return [NSColor darkGrayColor];
}
+const NSColor* EVSecureSchemeColor() {
+ return ColorWithRGBBytes(0x07, 0x95, 0x00);
+}
const NSColor* SecureSchemeColor() {
- return ColorWithRGBBytes(0x00, 0x96, 0x14);
+ return ColorWithRGBBytes(0x00, 0x0e, 0x95);
}
-const NSColor* InsecureSchemeColor() {
- return ColorWithRGBBytes(0xc8, 0x00, 0x00);
+const NSColor* SecurityErrorSchemeColor() {
+ return ColorWithRGBBytes(0xa2, 0x00, 0x00);
}
// Store's the model and view state across tab switches.
@@ -125,20 +121,57 @@ NSRange ComponentToNSRange(const url_parse::Component& component) {
} // namespace
+// static
+NSImage* AutocompleteEditViewMac::ImageForResource(int resource_id) {
+ NSString* image_name = nil;
+
+ switch(resource_id) {
+ // From the autocomplete popup, or the star icon at the RHS of the
+ // text field.
+ case IDR_OMNIBOX_STAR: image_name = @"omnibox_star.pdf"; break;
+ case IDR_OMNIBOX_STAR_LIT: image_name = @"omnibox_star_lit.pdf"; break;
+
+ // Values from |AutocompleteMatch::TypeToIcon()|.
+ case IDR_OMNIBOX_SEARCH: image_name = @"omnibox_search.pdf"; break;
+ case IDR_OMNIBOX_HTTP: image_name = @"omnibox_http.pdf"; break;
+ case IDR_OMNIBOX_HISTORY: image_name = @"omnibox_history.pdf"; break;
+ case IDR_OMNIBOX_MORE: image_name = @"omnibox_more.pdf"; break;
+
+ // Values from |ToolbarModel::GetIcon()|.
+ case IDR_OMNIBOX_HTTPS_VALID:
+ image_name = @"omnibox_https_valid.pdf"; break;
+ case IDR_OMNIBOX_HTTPS_WARNING:
+ image_name = @"omnibox_https_warning.pdf"; break;
+ case IDR_OMNIBOX_HTTPS_INVALID:
+ image_name = @"omnibox_https_invalid.pdf"; break;
+ }
+
+ if (image_name) {
+ if (NSImage* image = nsimage_cache::ImageNamed(image_name)) {
+ return image;
+ } else {
+ NOTREACHED()
+ << "Missing image for " << base::SysNSStringToUTF8(image_name);
+ }
+ }
+
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ return rb.GetNSImageNamed(resource_id);
+}
+
// TODO(shess): AutocompletePopupViewMac doesn't really need an
// NSTextField. It wants to know where the position the popup, what
// font to use, and it also needs to be able to attach the popup to
// the window |field_| is in.
AutocompleteEditViewMac::AutocompleteEditViewMac(
AutocompleteEditController* controller,
- const BubblePositioner* bubble_positioner,
ToolbarModel* toolbar_model,
Profile* profile,
CommandUpdater* command_updater,
AutocompleteTextField* field)
: model_(new AutocompleteEditModel(this, controller, profile)),
- popup_view_(new AutocompletePopupViewMac(
- this, model_.get(), bubble_positioner, profile, field)),
+ popup_view_(new AutocompletePopupViewMac(this, model_.get(), profile,
+ field)),
controller_(controller),
toolbar_model_(toolbar_model),
command_updater_(command_updater),
@@ -272,6 +305,17 @@ std::wstring AutocompleteEditViewMac::GetText() const {
return base::SysNSStringToWide([field_ stringValue]);
}
+bool AutocompleteEditViewMac::IsEditingOrEmpty() const {
+ return model_->user_input_in_progress() ||
+ ([[field_ stringValue] length] == 0);
+}
+
+int AutocompleteEditViewMac::GetIcon() const {
+ return IsEditingOrEmpty() ?
+ AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
+ toolbar_model_->GetIcon();
+}
+
void AutocompleteEditViewMac::SetUserText(const std::wstring& text,
const std::wstring& display_text,
bool update_popup) {
@@ -410,32 +454,23 @@ void AutocompleteEditViewMac::SetText(const std::wstring& display_text) {
// TODO(shess): GTK has this as a member var, figure out why.
// [Could it be to not change if no change? If so, I'm guessing
// AppKit may already handle that.]
- const ToolbarModel::SecurityLevel scheme_security_level =
- toolbar_model_->GetSchemeSecurityLevel();
-
- if (scheme_security_level == ToolbarModel::SECURE) {
- [field_ setBackgroundColor:SecureBackgroundColor()];
- } else if (scheme_security_level == ToolbarModel::NORMAL) {
- [field_ setBackgroundColor:NormalBackgroundColor()];
- } else if (scheme_security_level == ToolbarModel::INSECURE) {
- [field_ setBackgroundColor:InsecureBackgroundColor()];
- } else {
- NOTREACHED() << "Unexpected scheme_security_level: "
- << scheme_security_level;
- }
+ const ToolbarModel::SecurityLevel security_level =
+ toolbar_model_->GetSecurityLevel();
// Emphasize the scheme for security UI display purposes (if necessary).
if (!model_->user_input_in_progress() && scheme.is_nonempty() &&
- (scheme_security_level != ToolbarModel::NORMAL)) {
+ (security_level != ToolbarModel::NONE)) {
NSColor* color;
- if (scheme_security_level == ToolbarModel::SECURE) {
- color = SecureSchemeColor();
- } else {
- color = InsecureSchemeColor();
+ if (security_level == ToolbarModel::EV_SECURE) {
+ color = EVSecureSchemeColor();
+ } else if (security_level == ToolbarModel::SECURITY_ERROR) {
+ color = SecurityErrorSchemeColor();
// Add a strikethrough through the scheme.
[as addAttribute:NSStrikethroughStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:ComponentToNSRange(scheme)];
+ } else {
+ color = SecureSchemeColor();
}
[as addAttribute:NSForegroundColorAttributeName value:color
range:ComponentToNSRange(scheme)];
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
index 6ead1fe..5a0632f 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
@@ -28,7 +28,6 @@
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/autocomplete/autocomplete_accessibility.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/command_updater.h"
@@ -387,10 +386,10 @@ AutocompleteEditViewWin::AutocompleteEditViewWin(
Profile* profile,
CommandUpdater* command_updater,
bool popup_window_mode,
- const BubblePositioner* bubble_positioner)
+ const views::View* location_bar)
: model_(new AutocompleteEditModel(this, controller, profile)),
- popup_view_(AutocompletePopupView::CreatePopupView(
- font, this, model_.get(), profile, bubble_positioner)),
+ popup_view_(new AutocompletePopupContentsView(font, this, model_.get(),
+ profile, location_bar)),
controller_(controller),
parent_view_(parent_view),
toolbar_model_(toolbar_model),
@@ -407,8 +406,9 @@ AutocompleteEditViewWin::AutocompleteEditViewWin(
in_drag_(false),
initiated_drag_(false),
drop_highlight_position_(-1),
- background_color_(0),
- scheme_security_level_(ToolbarModel::NORMAL),
+ background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor(
+ ToolbarModel::NONE, LocationBarView::BACKGROUND))),
+ security_level_(ToolbarModel::NONE),
text_object_model_(NULL) {
// Dummy call to a function exported by riched20.dll to ensure it sets up an
// import dependency on the dll.
@@ -459,6 +459,8 @@ AutocompleteEditViewWin::AutocompleteEditViewWin(
cf.yOffset = -font_y_adjustment_ * kTwipsPerPixel;
SetDefaultCharFormat(cf);
+ SetBackgroundColor(background_color_);
+
// By default RichEdit has a drop target. Revoke it so that we can install our
// own. Revoke takes care of deleting the existing one.
RevokeDragDrop(m_hWnd);
@@ -508,30 +510,21 @@ void AutocompleteEditViewWin::Update(
model_->UpdatePermanentText(toolbar_model_->GetText());
const ToolbarModel::SecurityLevel security_level =
- toolbar_model_->GetSchemeSecurityLevel();
- const COLORREF background_color =
- skia::SkColorToCOLORREF(LocationBarView::GetColor(
- security_level == ToolbarModel::SECURE, LocationBarView::BACKGROUND));
- const bool changed_security_level =
- (security_level != scheme_security_level_);
+ toolbar_model_->GetSecurityLevel();
+ const bool changed_security_level = (security_level != security_level_);
// Bail early when no visible state will actually change (prevents an
// unnecessary ScopedFreeze, and thus UpdateWindow()).
- if ((background_color == background_color_) && !changed_security_level &&
- !visibly_changed_permanent_text && !tab_for_state_restoring)
+ if (!changed_security_level && !visibly_changed_permanent_text &&
+ !tab_for_state_restoring)
return;
- // Update our local state as desired. We set scheme_security_level_ here so
- // it will already be correct before we get to any RevertAll()s below and use
- // it.
- ScopedFreeze freeze(this, GetTextObjectModel());
- if (background_color_ != background_color) {
- background_color_ = background_color;
- SetBackgroundColor(background_color_);
- }
- scheme_security_level_ = security_level;
+ // Update our local state as desired. We set security_level_ here so it will
+ // already be correct before we get to any RevertAll()s below and use it.
+ security_level_ = security_level;
// When we're switching to a new tab, restore its state, if any.
+ ScopedFreeze freeze(this, GetTextObjectModel());
if (tab_for_state_restoring) {
// Make sure we reset our own state first. The new tab may not have any
// saved state, or it may not have had input in progress, in which case we
@@ -605,6 +598,16 @@ std::wstring AutocompleteEditViewWin::GetText() const {
return str;
}
+bool AutocompleteEditViewWin::IsEditingOrEmpty() const {
+ return model_->user_input_in_progress() || (GetTextLength() == 0);
+}
+
+int AutocompleteEditViewWin::GetIcon() const {
+ return IsEditingOrEmpty() ?
+ AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
+ toolbar_model_->GetIcon();
+}
+
void AutocompleteEditViewWin::SetUserText(const std::wstring& text,
const std::wstring& display_text,
bool update_popup) {
@@ -1369,15 +1372,6 @@ void AutocompleteEditViewWin::OnKillFocus(HWND focus_wnd) {
ScopedFreeze freeze(this, GetTextObjectModel());
DefWindowProc(WM_KILLFOCUS, reinterpret_cast<WPARAM>(focus_wnd), 0);
- // Hide the "Type to search" hint if necessary. We do this after calling
- // DefWindowProc() because processing the resulting IME messages may notify
- // the controller that input is in progress, which could cause the visible
- // hints to change. (I don't know if there's a real scenario where they
- // actually do change, but this is safest.)
- if (model_->show_search_hint() ||
- (model_->is_keyword_hint() && !model_->keyword().empty()))
- controller_->OnChanged();
-
// Cancel any user selection and scroll the text back to the beginning of the
// URL. We have to do this after calling DefWindowProc() because otherwise
// an in-progress IME composition will be completed at the new caret position,
@@ -1687,12 +1681,6 @@ void AutocompleteEditViewWin::OnSetFocus(HWND focus_wnd) {
model_->OnSetFocus(GetKeyState(VK_CONTROL) < 0);
- // Notify controller if it needs to show hint UI of some kind.
- ScopedFreeze freeze(this, GetTextObjectModel());
- if (model_->show_search_hint() ||
- (model_->is_keyword_hint() && !model_->keyword().empty()))
- controller_->OnChanged();
-
// Restore saved selection if available.
if (saved_selection_for_focus_change_.cpMin != -1) {
SetSelectionRange(saved_selection_for_focus_change_);
@@ -2060,11 +2048,11 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() {
// Set the baseline emphasis.
CHARFORMAT cf = {0};
cf.dwMask = CFM_COLOR;
- const bool is_secure = (scheme_security_level_ == ToolbarModel::SECURE);
// If we're going to emphasize parts of the text, then the baseline state
// should be "de-emphasized". If not, then everything should be rendered in
// the standard text color.
- cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor(is_secure,
+ cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor(
+ security_level_,
emphasize ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT));
// NOTE: Don't use SetDefaultCharFormat() instead of the below; that sets the
// format that will get applied to text added in the future, not to text
@@ -2075,7 +2063,7 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() {
if (emphasize) {
// We've found a host name, give it more emphasis.
cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor(
- is_secure, LocationBarView::TEXT));
+ security_level_, LocationBarView::TEXT));
SetSelection(host.begin, host.end());
SetSelectionCharFormat(cf);
}
@@ -2083,13 +2071,13 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() {
// Emphasize the scheme for security UI display purposes (if necessary).
insecure_scheme_component_.reset();
if (!model_->user_input_in_progress() && scheme.is_nonempty() &&
- (scheme_security_level_ != ToolbarModel::NORMAL)) {
- if (!is_secure) {
+ (security_level_ != ToolbarModel::NONE)) {
+ if (security_level_ == ToolbarModel::SECURITY_ERROR) {
insecure_scheme_component_.begin = scheme.begin;
insecure_scheme_component_.len = scheme.len;
}
cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor(
- is_secure, LocationBarView::SECURITY_TEXT));
+ security_level_, LocationBarView::SECURITY_TEXT));
SetSelection(scheme.begin, scheme.end());
SetSelectionCharFormat(cf);
}
@@ -2183,8 +2171,8 @@ void AutocompleteEditViewWin::DrawSlashForInsecureScheme(
canvas.save();
if (selection_rect.isEmpty() ||
canvas.clipRect(selection_rect, SkRegion::kDifference_Op)) {
- paint.setColor(LocationBarView::GetColor(false,
- LocationBarView::SCHEME_STRIKEOUT));
+ paint.setColor(LocationBarView::GetColor(security_level_,
+ LocationBarView::SECURITY_TEXT));
canvas.drawLine(start_point.fX, start_point.fY,
end_point.fX, end_point.fY, paint);
}
@@ -2192,7 +2180,7 @@ void AutocompleteEditViewWin::DrawSlashForInsecureScheme(
// Draw the selected portion of the stroke.
if (!selection_rect.isEmpty() && canvas.clipRect(selection_rect)) {
- paint.setColor(LocationBarView::GetColor(false,
+ paint.setColor(LocationBarView::GetColor(security_level_,
LocationBarView::SELECTED_TEXT));
canvas.drawLine(start_point.fX, start_point.fY,
end_point.fX, end_point.fY, paint);
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
index 9de2d34..33af6a7 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
@@ -69,7 +69,7 @@ class AutocompleteEditViewWin
Profile* profile,
CommandUpdater* command_updater,
bool popup_window_mode,
- const BubblePositioner* bubble_positioner);
+ const views::View* location_bar);
~AutocompleteEditViewWin();
views::View* parent_view() const { return parent_view_; }
@@ -91,6 +91,9 @@ class AutocompleteEditViewWin
virtual std::wstring GetText() const;
+ virtual bool IsEditingOrEmpty() const;
+ virtual int GetIcon() const;
+
virtual void SetUserText(const std::wstring& text) {
SetUserText(text, text, true);
}
@@ -476,7 +479,7 @@ class AutocompleteEditViewWin
// Security UI-related data.
COLORREF background_color_;
- ToolbarModel::SecurityLevel scheme_security_level_;
+ ToolbarModel::SecurityLevel security_level_;
// This interface is useful for accessing the CRichEditCtrl at a low level.
mutable ITextDocument* text_object_model_;
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.cc b/chrome/browser/autocomplete/autocomplete_popup_model.cc
index 41e0255..009cc0b 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.cc
@@ -103,12 +103,24 @@ void AutocompletePopupModel::SetSelectedLine(size_t line,
if (line == selected_line_)
return; // Nothing else to do.
+ // We need to update |selected_line_| before calling OnPopupDataChanged(), so
+ // that when the edit notifies its controller that something has changed, the
+ // controller can get the correct updated data.
+ //
+ // NOTE: We should never reach here with no selected line; the same code that
+ // opened the popup and made it possible to get here should have also set a
+ // selected line.
+ CHECK(selected_line_ != kNoMatch);
+ GURL current_destination(result.match_at(selected_line_).destination_url);
+ view_->InvalidateLine(selected_line_);
+ selected_line_ = line;
+ view_->InvalidateLine(selected_line_);
+
// Update the edit with the new data for this match.
// TODO(pkasting): If |selected_line_| moves to the controller, this can be
// eliminated and just become a call to the observer on the edit.
std::wstring keyword;
const bool is_keyword_hint = GetKeywordForMatch(match, &keyword);
-
if (reset_to_default) {
std::wstring inline_autocomplete_text;
if ((match.inline_autocomplete_offset != std::wstring::npos) &&
@@ -116,27 +128,15 @@ void AutocompletePopupModel::SetSelectedLine(size_t line,
inline_autocomplete_text =
match.fill_into_edit.substr(match.inline_autocomplete_offset);
}
- edit_model_->OnPopupDataChanged(inline_autocomplete_text, false,
- keyword, is_keyword_hint, match.type);
+ edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
+ keyword, is_keyword_hint);
} else {
- edit_model_->OnPopupDataChanged(match.fill_into_edit, true,
- keyword, is_keyword_hint, match.type);
+ edit_model_->OnPopupDataChanged(match.fill_into_edit, &current_destination,
+ keyword, is_keyword_hint);
}
// Repaint old and new selected lines immediately, so that the edit doesn't
- // appear to update [much] faster than the popup. We must not update
- // |selected_line_| before calling OnPopupDataChanged() (since the edit may
- // call us back to get data about the old selection), and we must not call
- // UpdateWindow() before updating |selected_line_| (since the paint routine
- // relies on knowing the correct selected line).
- //
- // NOTE: We should never reach here with no selected line; the same code that
- // opened the popup and made it possible to get here should have also set a
- // selected line.
- CHECK(selected_line_ != kNoMatch);
- view_->InvalidateLine(selected_line_);
- selected_line_ = line;
- view_->InvalidateLine(selected_line_);
+ // appear to update [much] faster than the popup.
view_->PaintUpdatesNow();
}
@@ -147,22 +147,21 @@ void AutocompletePopupModel::ResetToDefaultMatch() {
view_->OnDragCanceled();
}
-GURL AutocompletePopupModel::URLsForCurrentSelection(
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
+void AutocompletePopupModel::InfoForCurrentSelection(
+ AutocompleteMatch* match,
GURL* alternate_nav_url) const {
+ DCHECK(match != NULL);
const AutocompleteResult* result;
- AutocompleteResult::const_iterator match;
if (!controller_->done()) {
result = &controller_->latest_result();
// It's technically possible for |result| to be empty if no provider returns
// a synchronous result but the query has not completed synchronously;
// pratically, however, that should never actually happen.
if (result->empty())
- return GURL();
+ return;
// The user cannot have manually selected a match, or the query would have
// stopped. So the default match must be the desired selection.
- match = result->default_match();
+ *match = *result->default_match();
} else {
CHECK(IsOpen());
// The query isn't running, so the standard result set can't possibly be out
@@ -177,15 +176,10 @@ GURL AutocompletePopupModel::URLsForCurrentSelection(
// called instead.
CHECK(!result->empty());
CHECK(selected_line_ < result->size());
- match = result->begin() + selected_line_;
+ *match = result->match_at(selected_line_);
}
- if (transition)
- *transition = match->transition;
- if (is_history_what_you_typed_match)
- *is_history_what_you_typed_match = match->is_history_what_you_typed_match;
if (alternate_nav_url && manually_selected_match_.empty())
*alternate_nav_url = result->alternate_nav_url();
- return match->destination_url;
}
bool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match,
@@ -239,7 +233,7 @@ void AutocompletePopupModel::Move(int count) {
}
void AutocompletePopupModel::TryDeletingCurrentItem() {
- // We could use URLsForCurrentSelection() here, but it seems better to try
+ // We could use InfoForCurrentSelection() here, but it seems better to try
// and shift-delete the actual selection, rather than any "in progress, not
// yet visible" one.
if (selected_line_ == kNoMatch)
diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.h b/chrome/browser/autocomplete/autocomplete_popup_model.h
index 166a238..a986419 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_model.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_model.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -73,15 +73,9 @@ class AutocompletePopupModel : public NotificationObserver {
// will change the selected line back to the default match and redraw.
void ResetToDefaultMatch();
- // Returns the URL for the selected match. If an update is in progress,
- // "selected" means "default in the latest matches". If there are no
- // matches, returns the empty string.
- //
- // If |transition_type| is non-NULL, it will be set to the appropriate
- // transition type for the selected entry (TYPED or GENERATED).
- //
- // If |is_history_what_you_typed_match| is non-NULL, it will be set based on
- // the selected entry's is_history_what_you_typed value.
+ // Copies the selected match into |match|. If an update is in progress,
+ // "selected" means "default in the latest matches". If there are no matches,
+ // does not update |match|.
//
// If |alternate_nav_url| is non-NULL, it will be set to the alternate
// navigation URL for |url| if one exists, or left unchanged otherwise. See
@@ -89,10 +83,8 @@ class AutocompletePopupModel : public NotificationObserver {
//
// TODO(pkasting): When manually_selected_match_ moves to the controller, this
// can move too.
- GURL URLsForCurrentSelection(
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
- GURL* alternate_nav_url) const;
+ void InfoForCurrentSelection(AutocompleteMatch* match,
+ GURL* alternate_nav_url) const;
// Gets the selected keyword or keyword hint for the given match. Returns
// true if |keyword| represents a keyword hint, or false if |keyword|
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view.h b/chrome/browser/autocomplete/autocomplete_popup_view.h
index 41b21a6..5674e4b 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view.h
@@ -13,15 +13,7 @@
#include "build/build_config.h"
-class AutocompleteEditView;
class AutocompletePopupModel;
-class BubblePositioner;
-namespace gfx {
-class Font;
-}
-class AutocompleteEditViewWin;
-class AutocompleteEditModel;
-class Profile;
class AutocompletePopupView {
public:
@@ -48,17 +40,6 @@ class AutocompletePopupView {
// Returns the popup's model.
virtual AutocompletePopupModel* GetModel() = 0;
-
-#if !defined(OS_MACOSX)
- // Create a popup view implementation. It may make sense for this to become
- // platform independent eventually.
- static AutocompletePopupView* CreatePopupView(
- const gfx::Font& font,
- AutocompleteEditView* edit_view,
- AutocompleteEditModel* edit_model,
- Profile* profile,
- const BubblePositioner* bubble_positioner);
-#endif
};
#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_H_
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
index 0332c28..2f9895d 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -18,16 +18,18 @@
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/defaults.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/notification_service.h"
+#include "gfx/color_utils.h"
#include "gfx/font.h"
#include "gfx/gtk_util.h"
#include "gfx/rect.h"
+#include "gfx/skia_utils_gtk.h"
#include "grit/theme_resources.h"
namespace {
@@ -44,27 +46,40 @@ const GdkColor kDescriptionSelectedTextColor = GDK_COLOR_RGB(0x78, 0x82, 0xb1);
// We have a 1 pixel border around the entire results popup.
const int kBorderThickness = 1;
+
// The vertical height of each result.
const int kHeightPerResult = 24;
+
// Width of the icons.
-const int kIconWidth = 16;
+const int kIconWidth = 17;
+
// We want to vertically center the image in the result space.
-const int kIconTopPadding = 4;
+const int kIconTopPadding = 2;
+
// Space between the left edge (including the border) and the text.
-const int kIconLeftPadding = 6 + kBorderThickness;
-// Space between the image and the text. Would be 6 to line up with the
-// entry, but nudge it a bit more to match with the text in the entry.
-const int kIconRightPadding = 10;
+const int kIconLeftPadding = 5 + kBorderThickness;
+
+// Space between the image and the text.
+const int kIconRightPadding = 7;
+
// Space between the left edge (including the border) and the text.
const int kIconAreaWidth =
kIconLeftPadding + kIconWidth + kIconRightPadding;
+
// Space between the right edge (including the border) and the text.
const int kRightPadding = 3;
+
// When we have both a content and description string, we don't want the
// content to push the description off. Limit the content to a percentage of
// the total width.
const float kContentWidthPercentage = 0.7;
+// How much to offset the popup from the bottom of the location bar in gtk mode.
+const int kGtkVerticalOffset = 3;
+
+// How much we shrink the popup on the left/right in gtk mode.
+const int kGtkHorizontalOffset = 1;
+
// UTF-8 Left-to-right embedding.
const char* kLRE = "\xe2\x80\xaa";
@@ -103,6 +118,7 @@ void SetupLayoutForMatch(PangoLayout* layout,
const std::wstring& text,
AutocompleteMatch::ACMatchClassifications classifications,
const GdkColor* base_color,
+ const GdkColor* url_color,
const std::string& prefix_text) {
// We can have a prefix, or insert additional characters while processing the
@@ -139,7 +155,7 @@ void SetupLayoutForMatch(PangoLayout* layout,
// support it.
const GdkColor* color = base_color;
if (i->style & ACMatchClassification::URL) {
- color = &kURLTextColor;
+ color = url_color;
// Insert a left to right embedding to make sure that URLs are shown LTR.
std::string lre(kLRE);
text_utf8.insert(offset, lre);
@@ -164,48 +180,81 @@ void SetupLayoutForMatch(PangoLayout* layout,
pango_attr_list_unref(attrs);
}
-GdkPixbuf* IconForMatch(const AutocompleteMatch& match, bool selected) {
- // TODO(deanm): These would be better as pixmaps someday.
- // TODO(estade): Do we want to flip these for RTL? (Windows doesn't).
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- static GdkPixbuf* o2_globe = rb.GetPixbufNamed(IDR_O2_GLOBE);
- static GdkPixbuf* o2_globe_s = rb.GetPixbufNamed(IDR_O2_GLOBE_SELECTED_DARK);
- static GdkPixbuf* o2_history = rb.GetPixbufNamed(IDR_O2_HISTORY);
- static GdkPixbuf* o2_history_s =
- rb.GetPixbufNamed(IDR_O2_HISTORY_SELECTED_DARK);
- static GdkPixbuf* o2_more = rb.GetPixbufNamed(IDR_O2_MORE);
- static GdkPixbuf* o2_more_s = rb.GetPixbufNamed(IDR_O2_MORE_SELECTED_DARK);
- static GdkPixbuf* o2_search = rb.GetPixbufNamed(IDR_O2_SEARCH);
- static GdkPixbuf* o2_search_s =
- rb.GetPixbufNamed(IDR_O2_SEARCH_SELECTED_DARK);
- static GdkPixbuf* o2_star = rb.GetPixbufNamed(IDR_O2_STAR);
- static GdkPixbuf* o2_star_s = rb.GetPixbufNamed(IDR_O2_STAR_SELECTED_DARK);
-
- if (match.starred)
- return selected ? o2_star_s : o2_star;
-
- switch (match.type) {
- case AutocompleteMatch::URL_WHAT_YOU_TYPED:
- case AutocompleteMatch::NAVSUGGEST:
- return selected ? o2_globe_s : o2_globe;
- case AutocompleteMatch::HISTORY_URL:
- case AutocompleteMatch::HISTORY_TITLE:
- case AutocompleteMatch::HISTORY_BODY:
- case AutocompleteMatch::HISTORY_KEYWORD:
- return selected ? o2_history_s : o2_history;
- case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
- case AutocompleteMatch::SEARCH_HISTORY:
- case AutocompleteMatch::SEARCH_SUGGEST:
- case AutocompleteMatch::SEARCH_OTHER_ENGINE:
- return selected ? o2_search_s : o2_search;
- case AutocompleteMatch::OPEN_HISTORY_PAGE:
- return selected ? o2_more_s : o2_more;
- default:
- NOTREACHED();
- break;
+GdkPixbuf* IconForMatch(BrowserThemeProvider* theme,
+ const AutocompleteMatch& match,
+ bool selected) {
+ int icon = match.starred ?
+ IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type);
+ if (selected) {
+ switch (icon) {
+ case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break;
+ case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break;
+ case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break;
+ case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break;
+ case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break;
+ default: NOTREACHED(); break;
+ }
}
- return NULL;
+ // TODO(estade): Do we want to flip these for RTL? (Windows doesn't).
+ return theme->GetPixbufNamed(icon);
+}
+
+// Generates the normal URL color, a green color used in unhighlighted URL
+// text. It is a mix of |kURLTextColor| and the current text color. Unlike the
+// selected text color, It is more important to match the qualities of the
+// foreground typeface color instead of taking the background into account.
+GdkColor NormalURLColor(GdkColor foreground) {
+ color_utils::HSL fg_hsl;
+ color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl);
+
+ color_utils::HSL hue_hsl;
+ color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl);
+
+ // Only allow colors that have a fair amount of saturation in them (color vs
+ // white). This means that our output color will always be fairly green.
+ double s = std::max(0.5, fg_hsl.s);
+
+ // Make sure the luminance is at least as bright as the |kURLTextColor| green
+ // would be if we were to use that.
+ double l;
+ if (fg_hsl.l < hue_hsl.l)
+ l = hue_hsl.l;
+ else
+ l = (fg_hsl.l + hue_hsl.l) / 2;
+
+ color_utils::HSL output = { hue_hsl.h, s, l };
+ return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255));
+}
+
+// Generates the selected URL color, a green color used on URL text in the
+// currently highlighted entry in the autocomplete popup. It's a mix of
+// |kURLTextColor|, the current text color, and the background color (the
+// select highlight). It is more important to contrast with the background
+// saturation than to look exactly like the foreground color.
+GdkColor SelectedURLColor(GdkColor foreground, GdkColor background) {
+ color_utils::HSL fg_hsl;
+ color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl);
+
+ color_utils::HSL bg_hsl;
+ color_utils::SkColorToHSL(gfx::GdkColorToSkColor(background), &bg_hsl);
+
+ color_utils::HSL hue_hsl;
+ color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl);
+
+ // The saturation of the text should be opposite of the background, clamped
+ // to 0.2-0.8. We make sure it's greater than 0.2 so there's some color, but
+ // less than 0.8 so it's not the oversaturated neon-color.
+ double opposite_s = 1 - bg_hsl.s;
+ double s = std::max(0.2, std::min(0.8, opposite_s));
+
+ // The luminance should match the luminance of the foreground text. Again,
+ // we clamp so as to have at some amount of color (green) in the text.
+ double opposite_l = fg_hsl.l;
+ double l = std::max(0.1, std::min(0.9, opposite_l));
+
+ color_utils::HSL output = { hue_hsl.h, s, l };
+ return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255));
}
} // namespace
@@ -214,12 +263,13 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk(
AutocompleteEditView* edit_view,
AutocompleteEditModel* edit_model,
Profile* profile,
- const BubblePositioner* bubble_positioner)
+ GtkWidget* location_bar)
: model_(new AutocompletePopupModel(this, edit_model, profile)),
edit_view_(edit_view),
- bubble_positioner_(bubble_positioner),
+ location_bar_(location_bar),
window_(gtk_window_new(GTK_WINDOW_POPUP)),
layout_(NULL),
+ theme_provider_(GtkThemeProvider::GetFrom(profile)),
ignore_mouse_drag_(false),
opened_(false) {
GTK_WIDGET_UNSET_FLAGS(window_, GTK_CAN_FOCUS);
@@ -229,8 +279,6 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk(
gtk_widget_set_app_paintable(window_, TRUE);
// Have GTK double buffer around the expose signal.
gtk_widget_set_double_buffered(window_, TRUE);
- // Set the background color, so we don't need to paint it manually.
- gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor);
// Cache the layout so we don't have to create it for every expose. If we
// were a real widget we should handle changing directions, but we're not
@@ -263,6 +311,11 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk(
g_signal_connect(window_, "expose-event",
G_CALLBACK(&HandleExposeThunk), this);
+ registrar_.Add(this,
+ NotificationType::BROWSER_THEME_CHANGED,
+ NotificationService::AllSources());
+ theme_provider_->InitThemesFor(this);
+
// TODO(erg): There appears to be a bug somewhere in something which shows
// itself when we're in NX. Previously, we called
// gtk_util::ActAsRoundedWindow() to make this popup have rounded
@@ -317,16 +370,85 @@ AutocompletePopupModel* AutocompletePopupViewGtk::GetModel() {
return model_.get();
}
+void AutocompletePopupViewGtk::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
+
+ if (theme_provider_->UseGtkTheme()) {
+ border_color_ = theme_provider_->GetBorderColor();
+
+ // Create a fake gtk table
+ GtkWidget* fake_tree = gtk_entry_new();
+ GtkStyle* style = gtk_rc_get_style(fake_tree);
+
+ background_color_ = style->base[GTK_STATE_NORMAL];
+ selected_background_color_ = style->base[GTK_STATE_SELECTED];
+ hovered_background_color_ = gtk_util::AverageColors(
+ background_color_, selected_background_color_);
+
+ content_text_color_ = style->text[GTK_STATE_NORMAL];
+ selected_content_text_color_ = style->text[GTK_STATE_SELECTED];
+ url_text_color_ =
+ NormalURLColor(style->text[GTK_STATE_NORMAL]);
+ url_selected_text_color_ =
+ SelectedURLColor(style->text[GTK_STATE_SELECTED],
+ style->base[GTK_STATE_SELECTED]);
+
+ description_text_color_ = style->text[GTK_STATE_NORMAL];
+ description_selected_text_color_ = style->text[GTK_STATE_SELECTED];
+
+ g_object_ref_sink(fake_tree);
+ g_object_unref(fake_tree);
+ } else {
+ border_color_ = kBorderColor;
+ background_color_ = kBackgroundColor;
+ selected_background_color_ = kSelectedBackgroundColor;
+ hovered_background_color_ = kHoveredBackgroundColor;
+
+ content_text_color_ = kContentTextColor;
+ selected_content_text_color_ = kContentTextColor;
+ url_text_color_ = kURLTextColor;
+ url_selected_text_color_ = kURLTextColor;
+ description_text_color_ = kDescriptionTextColor;
+ description_selected_text_color_ = kDescriptionSelectedTextColor;
+ }
+
+ // Set the background color, so we don't need to paint it manually.
+ gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &background_color_);
+}
+
void AutocompletePopupViewGtk::Show(size_t num_results) {
- gfx::Rect rect = bubble_positioner_->GetLocationStackBounds();
- rect.set_y(rect.bottom());
- rect.set_height((num_results * kHeightPerResult) + (kBorderThickness * 2));
-
- gtk_window_move(GTK_WINDOW(window_), rect.x(), rect.y());
- gtk_widget_set_size_request(window_, rect.width(), rect.height());
- gtk_widget_show(window_);
- StackWindow();
- opened_ = true;
+ gint origin_x, origin_y;
+ gdk_window_get_origin(location_bar_->window, &origin_x, &origin_y);
+ GtkAllocation allocation = location_bar_->allocation;
+ int vertical_offset = 0;
+ int horizontal_offset = 0;
+ if (theme_provider_->UseGtkTheme()) {
+ // Shrink the popup by 1 pixel on both sides in gtk mode. The darkest line
+ // is usually one pixel in, and is almost always +/-1 pixel from this,
+ // meaning the vertical offset will hide (hopefully) problems when this is
+ // wrong.
+ horizontal_offset = kGtkHorizontalOffset;
+
+ // We offset the the popup from the bottom of the location bar in gtk
+ // mode. The background color between the bottom of the location bar and
+ // the popup helps hide the fact that we can't really reliably match what
+ // the user would otherwise preceive as the left/right edges of the
+ // location bar.
+ vertical_offset = kGtkVerticalOffset;
+ }
+
+ gtk_window_move(GTK_WINDOW(window_),
+ origin_x + allocation.x - kBorderThickness + horizontal_offset,
+ origin_y + allocation.y + allocation.height - kBorderThickness - 1 +
+ vertical_offset);
+ gtk_widget_set_size_request(window_,
+ allocation.width + (kBorderThickness * 2) - (horizontal_offset * 2),
+ (num_results * kHeightPerResult) + (kBorderThickness * 2));
+ gtk_widget_show(window_);
+ StackWindow();
+ opened_ = true;
}
void AutocompletePopupViewGtk::Hide() {
@@ -426,7 +548,7 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
GdkGC* gc = gdk_gc_new(drawable);
// kBorderColor is unallocated, so use the GdkRGB routine.
- gdk_gc_set_rgb_fg_color(gc, &kBorderColor);
+ gdk_gc_set_rgb_fg_color(gc, &border_color_);
// This assert is kinda ugly, but it would be more currently unneeded work
// to support painting a border that isn't 1 pixel thick. There is no point
@@ -439,8 +561,17 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE);
- // TODO(deanm): Intersect the line and damage rects, and only repaint and
- // layout the lines that are actually damaged. For now paint everything.
+ // An offset to align text in gtk mode. The hard coded constants in this file
+ // are all created for the chrome-theme. In an effort to make this look good
+ // on the majority of gtk themes, we shrink the popup by one pixel on each
+ // side and push it downwards a bit so there's space between the drawn
+ // location bar and the popup so we don't touch it (contrast with
+ // chrome-theme where that's exactly what we want). Because of that, we need
+ // to shift the content inside the popup by one pixel.
+ int gtk_offset = 0;
+ if (theme_provider_->UseGtkTheme())
+ gtk_offset = kGtkHorizontalOffset;
+
for (size_t i = 0; i < result.size(); ++i) {
gfx::Rect line_rect = GetRectForLine(i, window_rect.width());
// Only repaint and layout damaged lines.
@@ -451,18 +582,19 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
bool is_selected = (model_->selected_line() == i);
bool is_hovered = (model_->hovered_line() == i);
if (is_selected || is_hovered) {
- gdk_gc_set_rgb_fg_color(gc, is_selected ? &kSelectedBackgroundColor :
- &kHoveredBackgroundColor);
+ gdk_gc_set_rgb_fg_color(gc, is_selected ? &selected_background_color_ :
+ &hovered_background_color_);
// This entry is selected or hovered, fill a rect with the color.
gdk_draw_rectangle(drawable, gc, TRUE,
line_rect.x(), line_rect.y(),
line_rect.width(), line_rect.height());
}
- int icon_start_x = ltr ? kIconLeftPadding :
- line_rect.width() - kIconLeftPadding - kIconWidth;
+ int icon_start_x = ltr ? (kIconLeftPadding - gtk_offset) :
+ (line_rect.width() - kIconLeftPadding - kIconWidth + gtk_offset);
// Draw the icon for this result.
- DrawFullPixbuf(drawable, gc, IconForMatch(match, is_selected),
+ DrawFullPixbuf(drawable, gc,
+ IconForMatch(theme_provider_, match, is_selected),
icon_start_x, line_rect.y() + kIconTopPadding);
// Draw the results text vertically centered in the results space.
@@ -476,7 +608,11 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
// Note: We force to URL to LTR for all text directions.
SetupLayoutForMatch(layout_, match.contents, match.contents_class,
- &kContentTextColor, std::string());
+ is_selected ? &selected_content_text_color_ :
+ &content_text_color_,
+ is_selected ? &url_selected_text_color_ :
+ &url_text_color_,
+ std::string());
int actual_content_width, actual_content_height;
pango_layout_get_size(layout_,
@@ -490,22 +626,25 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
line_rect.y() + ((kHeightPerResult - actual_content_height) / 2));
gdk_draw_layout(drawable, gc,
- ltr ? kIconAreaWidth : text_width - actual_content_width,
+ ltr ? (kIconAreaWidth - gtk_offset) :
+ (text_width - actual_content_width + gtk_offset),
content_y, layout_);
if (has_description) {
pango_layout_set_width(layout_,
(text_width - actual_content_width) * PANGO_SCALE);
SetupLayoutForMatch(layout_, match.description, match.description_class,
- is_selected ? &kDescriptionSelectedTextColor :
- &kDescriptionTextColor,
+ is_selected ? &description_selected_text_color_ :
+ &description_text_color_,
+ is_selected ? &url_selected_text_color_ :
+ &url_text_color_,
std::string(" - "));
gint actual_description_width;
pango_layout_get_size(layout_, &actual_description_width, NULL);
- gdk_draw_layout(drawable, gc,
- ltr ? kIconAreaWidth + actual_content_width :
- text_width - actual_content_width -
- actual_description_width / PANGO_SCALE,
+ gdk_draw_layout(drawable, gc, ltr ?
+ (kIconAreaWidth - gtk_offset + actual_content_width) :
+ (text_width - actual_content_width + gtk_offset -
+ (actual_description_width / PANGO_SCALE)),
content_y, layout_);
}
}
@@ -514,14 +653,3 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget,
return TRUE;
}
-
-// static
-AutocompletePopupView* AutocompletePopupView::CreatePopupView(
- const gfx::Font& font,
- AutocompleteEditView* edit_view,
- AutocompleteEditModel* edit_model,
- Profile* profile,
- const BubblePositioner* bubble_positioner) {
- return new AutocompletePopupViewGtk(edit_view, edit_model, profile,
- bubble_positioner);
-}
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
index a56a55a..4759417 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -10,23 +10,27 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
#include "webkit/glue/window_open_disposition.h"
class AutocompleteEditModel;
class AutocompleteEditView;
class AutocompletePopupModel;
+class GtkThemeProvider;
class Profile;
class SkBitmap;
-class AutocompletePopupViewGtk : public AutocompletePopupView {
+class AutocompletePopupViewGtk : public AutocompletePopupView,
+ public NotificationObserver {
public:
AutocompletePopupViewGtk(AutocompleteEditView* edit_view,
AutocompleteEditModel* edit_model,
Profile* profile,
- const BubblePositioner* bubble_positioner);
+ GtkWidget* location_bar);
~AutocompletePopupViewGtk();
- // Implement the AutocompletePopupView interface.
+ // Overridden from AutocompletePopupView:
virtual bool IsOpen() const { return opened_; }
virtual void InvalidateLine(size_t line);
virtual void UpdatePopupAppearance();
@@ -34,6 +38,11 @@ class AutocompletePopupViewGtk : public AutocompletePopupView {
virtual void OnDragCanceled();
virtual AutocompletePopupModel* GetModel();
+ // Overridden from NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
void Show(size_t num_results);
void Hide();
@@ -79,7 +88,7 @@ class AutocompletePopupViewGtk : public AutocompletePopupView {
scoped_ptr<AutocompletePopupModel> model_;
AutocompleteEditView* edit_view_;
- const BubblePositioner* bubble_positioner_;
+ GtkWidget* location_bar_;
// Our popup window, which is the only widget used, and we paint it on our
// own. This widget shouldn't be exposed outside of this class.
@@ -87,6 +96,22 @@ class AutocompletePopupViewGtk : public AutocompletePopupView {
// The pango layout object created from the window, cached across exposes.
PangoLayout* layout_;
+ GtkThemeProvider* theme_provider_;
+ NotificationRegistrar registrar_;
+
+ // A list of colors which we should use for drawing the popup. These change
+ // between gtk and normal mode.
+ GdkColor border_color_;
+ GdkColor background_color_;
+ GdkColor selected_background_color_;
+ GdkColor hovered_background_color_;
+ GdkColor content_text_color_;
+ GdkColor selected_content_text_color_;
+ GdkColor url_text_color_;
+ GdkColor url_selected_text_color_;
+ GdkColor description_text_color_;
+ GdkColor description_selected_text_color_;
+
// If the user cancels a dragging action (i.e. by pressing ESC), we don't have
// a convenient way to release mouse capture. Instead we use this flag to
// simply ignore all remaining drag events, and the eventual mouse release
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
index a430f58..56d20fd 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -32,7 +32,6 @@ class AutocompletePopupViewMac : public AutocompletePopupView {
public:
AutocompletePopupViewMac(AutocompleteEditViewMac* edit_view,
AutocompleteEditModel* edit_model,
- const BubblePositioner* bubble_positioner,
Profile* profile,
NSTextField* field);
virtual ~AutocompletePopupViewMac();
@@ -109,7 +108,6 @@ class AutocompletePopupViewMac : public AutocompletePopupView {
scoped_ptr<AutocompletePopupModel> model_;
AutocompleteEditViewMac* edit_view_;
- const BubblePositioner* bubble_positioner_; // owned by toolbar controller
NSTextField* field_; // owned by tab controller
// Child window containing a matrix which implements the popup.
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
index 2ab01ad..29ea9ab 100644
--- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
+++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -10,11 +10,11 @@
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/cocoa/event_utils.h"
#include "gfx/rect.h"
#include "grit/theme_resources.h"
#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
namespace {
@@ -31,17 +31,17 @@ const int kCellHeightAdjust = 7.0;
const CGFloat kPopupRoundingRadius = 3.5;
// Gap between the field and the popup.
-const CGFloat kPopupFieldGap = 2.0;
+const CGFloat kPopupFieldGap = 0.0;
// How opaque the popup window should be. This matches Windows (see
// autocomplete_popup_contents_view.cc, kGlassPopupTransparency).
const CGFloat kPopupAlpha = 240.0 / 255.0;
// How much space to leave for the left and right margins.
-const CGFloat kLeftRightMargin = 6.0;
+const CGFloat kLeftRightMargin = 5.0;
// How far to offset the text column from the left.
-const CGFloat kTextXOffset = 31.0;
+const CGFloat kTextXOffset = 29.0;
// Animation duration when animating the popup window smaller.
const CGFloat kShrinkAnimationDuration = 0.1;
@@ -78,54 +78,6 @@ static const NSColor* DescriptionTextColor() {
return [NSColor darkGrayColor];
}
-// Helper to fetch and retain an image from the resource bundle.
-NSImage* RetainedResourceImage(int resource_id) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- NSImage* image = rb.GetNSImageNamed(resource_id);
- DCHECK(image);
- return [image retain];
-}
-
-// Return the appropriate icon for the given match. Derived from the
-// gtk code.
-NSImage* MatchIcon(const AutocompleteMatch& match) {
- if (match.starred) {
- static NSImage* starImage = RetainedResourceImage(IDR_O2_STAR);
- return starImage;
- }
-
- switch (match.type) {
- case AutocompleteMatch::URL_WHAT_YOU_TYPED:
- case AutocompleteMatch::NAVSUGGEST: {
- static NSImage* globeImage = RetainedResourceImage(IDR_O2_GLOBE);
- return globeImage;
- }
- case AutocompleteMatch::HISTORY_URL:
- case AutocompleteMatch::HISTORY_TITLE:
- case AutocompleteMatch::HISTORY_BODY:
- case AutocompleteMatch::HISTORY_KEYWORD: {
- static NSImage* historyImage = RetainedResourceImage(IDR_O2_HISTORY);
- return historyImage;
- }
- case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
- case AutocompleteMatch::SEARCH_HISTORY:
- case AutocompleteMatch::SEARCH_SUGGEST:
- case AutocompleteMatch::SEARCH_OTHER_ENGINE: {
- static NSImage* searchImage = RetainedResourceImage(IDR_O2_SEARCH);
- return searchImage;
- }
- case AutocompleteMatch::OPEN_HISTORY_PAGE: {
- static NSImage* moreImage = RetainedResourceImage(IDR_O2_MORE);
- return moreImage;
- }
- default:
- NOTREACHED();
- break;
- }
-
- return nil;
-}
-
} // namespace
// Helper for MatchText() to allow sharing code between the contents
@@ -293,12 +245,10 @@ NSAttributedString* AutocompletePopupViewMac::MatchText(
AutocompletePopupViewMac::AutocompletePopupViewMac(
AutocompleteEditViewMac* edit_view,
AutocompleteEditModel* edit_model,
- const BubblePositioner* bubble_positioner,
Profile* profile,
NSTextField* field)
: model_(new AutocompletePopupModel(this, edit_model, profile)),
edit_view_(edit_view),
- bubble_positioner_(bubble_positioner),
field_(field),
popup_(nil) {
DCHECK(edit_view);
@@ -365,8 +315,12 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() {
CreatePopupIfNeeded();
// Layout the popup and size it to land underneath the field.
- NSRect r =
- NSRectFromCGRect(bubble_positioner_->GetLocationStackBounds().ToCGRect());
+ // The field has a single-pixel border on the left and right. This
+ // needs to be factored out so that the popup window's border (which
+ // is outside the frame) lines up.
+ const int kLocationStackEdgeWidth = 1;
+ NSRect r = NSInsetRect([field_ convertRect:[field_ bounds] toView:nil],
+ kLocationStackEdgeWidth, 0);
r.origin = [[field_ window] convertBaseToScreen:r.origin];
DCHECK_GT(r.size.width, 0.0);
@@ -386,7 +340,9 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() {
for (size_t ii = 0; ii < rows; ++ii) {
AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0];
const AutocompleteMatch& match = model_->result().match_at(ii);
- [cell setImage:MatchIcon(match)];
+ const int resource_id = match.starred ? IDR_OMNIBOX_STAR
+ : AutocompleteMatch::TypeToIcon(match.type);
+ [cell setImage:AutocompleteEditViewMac::ImageForResource(resource_id)];
[cell setAttributedTitle:MatchText(match, resultFont, r.size.width)];
}
@@ -507,7 +463,11 @@ void AutocompletePopupViewMac::OpenURLForRow(int row, bool force_background) {
imageRect.origin.y +=
floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2);
imageRect.origin.x += kLeftRightMargin;
- [self drawImage:image withFrame:imageRect inView:controlView];
+ [image setFlipped:[controlView isFlipped]];
+ [image drawInRect:imageRect
+ fromRect:NSZeroRect // Entire image
+ operation:NSCompositeSourceOver
+ fraction:1.0];
}
// Adjust the title position to be lined up under the field's text.
@@ -704,10 +664,15 @@ void AutocompletePopupViewMac::OpenURLForRow(int row, bool force_background) {
// This handles drawing the decorations of the rounded popup window,
// calling on NSMatrix to draw the actual contents.
- (void)drawRect:(NSRect)rect {
+ // Apparently this expects flipped coordinates, because in order to
+ // round the bottom corners visually, I need to specify the top
+ // corners here.
NSBezierPath* path =
- [NSBezierPath bezierPathWithRoundedRect:[self bounds]
- xRadius:kPopupRoundingRadius
- yRadius:kPopupRoundingRadius];
+ [NSBezierPath gtm_bezierPathWithRoundRect:[self bounds]
+ topLeftCornerRadius:kPopupRoundingRadius
+ topRightCornerRadius:kPopupRoundingRadius
+ bottomLeftCornerRadius:0.0
+ bottomRightCornerRadius:0.0];
// Draw the matrix clipped to our border.
[NSGraphicsContext saveGraphicsState];
diff --git a/chrome/browser/autocomplete/history_contents_provider.cc b/chrome/browser/autocomplete/history_contents_provider.cc
index ac81c31..1e72ceb 100644
--- a/chrome/browser/autocomplete/history_contents_provider.cc
+++ b/chrome/browser/autocomplete/history_contents_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -207,11 +207,9 @@ AutocompleteMatch HistoryContentsProvider::ResultToMatch(
// Also show star in popup.
AutocompleteMatch match(this, score, false, MatchInTitle(result) ?
AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY);
- match.fill_into_edit = StringForURLDisplay(result.url(), true);
+ match.fill_into_edit = StringForURLDisplay(result.url(), true, trim_http_);
match.destination_url = result.url();
match.contents = match.fill_into_edit;
- if (trim_http_)
- TrimHttpPrefix(&match.contents);
match.contents_class.push_back(
ACMatchClassification(0, ACMatchClassification::URL));
match.description = result.title();
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index 2708d47..a748700 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -256,10 +256,14 @@ AutocompleteMatch HistoryURLProvider::SuggestExactInput(
const GURL& url = input.canonicalized_url();
if (url.is_valid()) {
match.destination_url = url;
- match.fill_into_edit = StringForURLDisplay(url, false);
+ match.fill_into_edit = StringForURLDisplay(url, false, false);
// NOTE: Don't set match.input_location (to allow inline autocompletion)
// here, it's surprising and annoying.
// Trim off "http://" if the user didn't type it.
+ // Double NOTE: we use TrimHttpPrefix here rather than StringForURLDisplay
+ // to strip the http as we need to know the offset so we can adjust the
+ // match_location below. StringForURLDisplay and TrimHttpPrefix have
+ // slightly different behavior when stripping http as well.
const size_t offset = trim_http ? TrimHttpPrefix(&match.fill_into_edit) : 0;
// Try to highlight "innermost" match location. If we fix up "w" into
@@ -828,17 +832,13 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
DCHECK(match.destination_url.is_valid());
size_t inline_autocomplete_offset =
history_match.input_location + params->input.text().length();
+ const net::FormatUrlTypes format_types =
+ (params->trim_http && !history_match.match_in_scheme) ?
+ net::kFormatUrlOmitAll : net::kFormatUrlOmitUsernamePassword;
match.fill_into_edit = net::FormatUrl(info.url(),
- match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, true,
- UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset);
- size_t offset = 0;
- if (params->trim_http && !history_match.match_in_scheme) {
- offset = TrimHttpPrefix(&match.fill_into_edit);
- if (inline_autocomplete_offset != std::wstring::npos) {
- DCHECK(inline_autocomplete_offset >= offset);
- inline_autocomplete_offset -= offset;
- }
- }
+ match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages,
+ format_types, UnescapeRule::SPACES, NULL, NULL,
+ &inline_autocomplete_offset);
if (!params->input.prevent_inline_autocomplete())
match.inline_autocomplete_offset = inline_autocomplete_offset;
DCHECK((match.inline_autocomplete_offset == std::wstring::npos) ||
@@ -846,15 +846,8 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
size_t match_start = history_match.input_location;
match.contents = net::FormatUrl(info.url(),
- match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, true,
- UnescapeRule::SPACES, NULL, NULL, &match_start);
- if (offset) {
- TrimHttpPrefix(&match.contents);
- if (match_start != std::wstring::npos) {
- DCHECK(match_start >= offset);
- match_start -= offset;
- }
- }
+ match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages,
+ format_types, UnescapeRule::SPACES, NULL, NULL, &match_start);
if ((match_start != std::wstring::npos) &&
(inline_autocomplete_offset != std::wstring::npos) &&
(inline_autocomplete_offset != match_start)) {
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 5833611..acba81e 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -98,8 +98,8 @@ void SearchProvider::Start(const AutocompleteInput& input,
// User typed "?" alone. Give them a placeholder result indicating what
// this syntax does.
if (default_provider) {
- AutocompleteMatch match(this, 0, false,
- AutocompleteMatch::SEARCH_WHAT_YOU_TYPED);
+ AutocompleteMatch match;
+ match.provider = this;
match.contents.assign(l10n_util::GetString(IDS_EMPTY_KEYWORD_VALUE));
match.contents_class.push_back(
ACMatchClassification(0, ACMatchClassification::NONE));
@@ -737,10 +737,9 @@ AutocompleteMatch SearchProvider::NavigationToMatch(
AutocompleteMatch match(this, relevance, false,
AutocompleteMatch::NAVSUGGEST);
match.destination_url = navigation.url;
- match.contents = StringForURLDisplay(navigation.url, true);
- if (!url_util::FindAndCompareScheme(WideToUTF8(input_text),
- chrome::kHttpScheme, NULL))
- TrimHttpPrefix(&match.contents);
+ const bool trim_http = !url_util::FindAndCompareScheme(
+ WideToUTF8(input_text), chrome::kHttpScheme, NULL);
+ match.contents = StringForURLDisplay(navigation.url, true, trim_http);
AutocompleteMatch::ClassifyMatchInString(input_text, match.contents,
ACMatchClassification::URL,
&match.contents_class);
diff --git a/chrome/browser/bookmarks/bookmark_table_model.cc b/chrome/browser/bookmarks/bookmark_table_model.cc
index f7848e4..0ac5416 100644
--- a/chrome/browser/bookmarks/bookmark_table_model.cc
+++ b/chrome/browser/bookmarks/bookmark_table_model.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -325,8 +325,8 @@ std::wstring BookmarkTableModel::GetText(int row, int column_id) {
std::wstring languages = model_ && model_->profile()
? model_->profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)
: std::wstring();
- std::wstring url_text = net::FormatUrl(node->GetURL(), languages, false,
- UnescapeRule::SPACES, NULL, NULL, NULL);
+ std::wstring url_text = net::FormatUrl(node->GetURL(), languages,
+ net::kFormatUrlOmitAll, UnescapeRule::SPACES, NULL, NULL, NULL);
if (base::i18n::IsRTL())
base::i18n::WrapStringWithLTRFormatting(&url_text);
return url_text;
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index 2214e4c..4ffeeb2 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -224,7 +224,8 @@ bool DoesBookmarkContainWords(const BookmarkNode* node,
DoesBookmarkTextContainWords(
l10n_util::ToLower(UTF8ToWide(node->GetURL().spec())), words) ||
DoesBookmarkTextContainWords(l10n_util::ToLower(net::FormatUrl(
- node->GetURL(), languages, false, true, NULL, NULL, NULL)), words);
+ node->GetURL(), languages, net::kFormatUrlOmitNothing,
+ UnescapeRule::NORMAL, NULL, NULL, NULL)), words);
}
} // namespace
diff --git a/chrome/browser/browser_theme_pack.cc b/chrome/browser/browser_theme_pack.cc
index d0252f1..3159bf7 100644
--- a/chrome/browser/browser_theme_pack.cc
+++ b/chrome/browser/browser_theme_pack.cc
@@ -4,37 +4,26 @@
#include "chrome/browser/browser_theme_pack.h"
-#include <algorithm>
-#include <climits>
-#include <set>
-#include <vector>
-
#include "app/resource_bundle.h"
#include "base/data_pack.h"
-#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-#include "base/values.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/theme_resources_util.h"
-#include "chrome/common/extensions/extension.h"
#include "gfx/codec/png_codec.h"
#include "gfx/skbitmap_operations.h"
#include "grit/app_resources.h"
#include "grit/theme_resources.h"
#include "net/base/file_stream.h"
#include "net/base/net_errors.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkUnPreMultiply.h"
namespace {
// Version number of the current theme pack. We just throw out and rebuild
// theme packs that aren't int-equal to this.
-const int kThemePackVersion = 7;
+const int kThemePackVersion = 8;
// IDs that are in the DataPack won't clash with the positive integer
// int32_t. kHeaderID should always have the maximum value because we want the
@@ -131,42 +120,33 @@ PersistingImagesTable kPersistingImages[] = {
{ 21, IDR_FORWARD_H, NULL },
{ 22, IDR_FORWARD_P, NULL },
{ 23, IDR_RELOAD, NULL },
- { 24, IDR_RELOAD_H, NULL },
- { 25, IDR_RELOAD_P, NULL },
- { 26, IDR_HOME, NULL },
- { 27, IDR_HOME_H, NULL },
- { 28, IDR_HOME_P, NULL },
- { 29, IDR_STAR, NULL },
- { 30, IDR_STAR_NOBORDER, NULL },
- { 31, IDR_STAR_NOBORDER_CENTER, NULL },
- { 32, IDR_STAR_D, NULL },
- { 33, IDR_STAR_H, NULL },
- { 34, IDR_STAR_P, NULL },
- { 35, IDR_STARRED, NULL },
- { 36, IDR_STARRED_NOBORDER, NULL },
- { 37, IDR_STARRED_NOBORDER_CENTER, NULL },
- { 38, IDR_STARRED_H, NULL },
- { 39, IDR_STARRED_P, NULL },
- { 40, IDR_GO, NULL },
- { 41, IDR_GO_NOBORDER, NULL },
- { 42, IDR_GO_NOBORDER_CENTER, NULL },
- { 43, IDR_GO_H, NULL },
- { 44, IDR_GO_P, NULL },
- { 45, IDR_STOP, NULL },
- { 46, IDR_STOP_NOBORDER, NULL },
- { 47, IDR_STOP_NOBORDER_CENTER, NULL },
- { 48, IDR_STOP_H, NULL },
- { 49, IDR_STOP_P, NULL },
- { 50, IDR_MENU_BOOKMARK, NULL },
- { 51, IDR_MENU_PAGE, NULL },
- { 52, IDR_MENU_PAGE_RTL, NULL },
- { 53, IDR_MENU_CHROME, NULL },
- { 54, IDR_MENU_CHROME_RTL, NULL },
- { 55, IDR_MENU_DROPARROW, NULL },
- { 56, IDR_THROBBER, NULL },
- { 57, IDR_THROBBER_WAITING, NULL },
- { 58, IDR_THROBBER_LIGHT, NULL },
- { 59, IDR_LOCATIONBG, NULL }
+ { 24, IDR_RELOAD_NOBORDER, NULL },
+ { 25, IDR_RELOAD_NOBORDER_CENTER, NULL },
+ { 26, IDR_RELOAD_H, NULL },
+ { 27, IDR_RELOAD_P, NULL },
+ { 28, IDR_HOME, NULL },
+ { 29, IDR_HOME_H, NULL },
+ { 30, IDR_HOME_P, NULL },
+ { 31, IDR_GO, NULL },
+ { 32, IDR_GO_NOBORDER, NULL },
+ { 33, IDR_GO_NOBORDER_CENTER, NULL },
+ { 34, IDR_GO_H, NULL },
+ { 35, IDR_GO_P, NULL },
+ { 36, IDR_STOP, NULL },
+ { 37, IDR_STOP_NOBORDER, NULL },
+ { 38, IDR_STOP_NOBORDER_CENTER, NULL },
+ { 39, IDR_STOP_H, NULL },
+ { 40, IDR_STOP_P, NULL },
+ { 41, IDR_MENU_BOOKMARK, NULL },
+ { 42, IDR_MENU_PAGE, NULL },
+ { 43, IDR_MENU_PAGE_RTL, NULL },
+ { 44, IDR_MENU_CHROME, NULL },
+ { 45, IDR_MENU_CHROME_RTL, NULL },
+ { 46, IDR_MENU_DROPARROW, NULL },
+ { 47, IDR_THROBBER, NULL },
+ { 48, IDR_THROBBER_WAITING, NULL },
+ { 49, IDR_THROBBER_LIGHT, NULL },
+ { 50, IDR_LOCATIONBG, NULL }
};
int GetPersistentIDByName(const std::string& key) {
@@ -516,6 +496,8 @@ bool BrowserThemePack::GetDisplayProperty(int id, int* result) const {
SkBitmap* BrowserThemePack::GetBitmapNamed(int idr_id) const {
int prs_id = GetPersistentIDByIDR(idr_id);
+ if (prs_id == -1)
+ return NULL;
// Check our cache of prepared images, first.
ImageCache::const_iterator image_iter = prepared_images_.find(prs_id);
@@ -965,6 +947,7 @@ void BrowserThemePack::GenerateTintedButtons(
for (std::set<int>::const_iterator it = idr_ids.begin();
it != idr_ids.end(); ++it) {
int prs_id = GetPersistentIDByIDR(*it);
+ DCHECK(prs_id > 0);
// Fetch the image by IDR...
scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(*it)));
diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc
index d682548..92fefc3 100644
--- a/chrome/browser/browser_theme_provider.cc
+++ b/chrome/browser/browser_theme_provider.cc
@@ -1,40 +1,21 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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/browser_theme_provider.h"
#include "app/resource_bundle.h"
-#include "base/file_util.h"
-#include "base/stl_util-inl.h"
-#include "base/string_util.h"
-#include "base/thread.h"
-#include "base/values.h"
-#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_theme_pack.h"
-#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/metrics/user_metrics.h"
-#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
-#include "chrome/browser/theme_resources_util.h"
#include "chrome/common/chrome_constants.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
-#include "gfx/codec/png_codec.h"
-#include "gfx/skbitmap_operations.h"
#include "grit/app_resources.h"
#include "grit/theme_resources.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_errors.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkUnPreMultiply.h"
#if defined(OS_WIN)
#include "app/win_util.h"
@@ -62,15 +43,15 @@ SkColor TintForUnderline(SkColor input) {
}
// Default colors.
-const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217);
-const SkColor kDefaultColorFrameInactive = SkColorSetRGB(152, 188, 233);
+const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201);
+const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139);
const SkColor kDefaultColorFrameIncognitoInactive =
SkColorSetRGB(126, 139, 156);
#if defined(OS_MACOSX)
const SkColor kDefaultColorToolbar = SkColorSetRGB(230, 230, 230);
#else
-const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246);
+const SkColor kDefaultColorToolbar = SkColorSetRGB(223, 223, 223);
#endif
const SkColor kDefaultColorTabText = SK_ColorBLACK;
#if defined(OS_MACOSX)
@@ -154,15 +135,16 @@ bool HasThemeableImage(int themeable_image_id) {
}
// The image resources that will be tinted by the 'button' tint value.
+// If you change this list, you must increment the version number in
+// browser_theme_pack.cc and you should assign persistant ids to the
+// data table at the start of said file or otherwise tinted versions of
+// these resources will not be created.
const int kToolbarButtonIDs[] = {
IDR_BACK, IDR_BACK_D, IDR_BACK_H, IDR_BACK_P,
IDR_FORWARD, IDR_FORWARD_D, IDR_FORWARD_H, IDR_FORWARD_P,
- IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P,
+ IDR_RELOAD, IDR_RELOAD_NOBORDER, IDR_RELOAD_NOBORDER_CENTER, IDR_RELOAD_H,
+ IDR_RELOAD_P,
IDR_HOME, IDR_HOME_H, IDR_HOME_P,
- IDR_STAR, IDR_STAR_NOBORDER, IDR_STAR_NOBORDER_CENTER, IDR_STAR_D, IDR_STAR_H,
- IDR_STAR_P,
- IDR_STARRED, IDR_STARRED_NOBORDER, IDR_STARRED_NOBORDER_CENTER, IDR_STARRED_H,
- IDR_STARRED_P,
IDR_GO, IDR_GO_NOBORDER, IDR_GO_NOBORDER_CENTER, IDR_GO_H, IDR_GO_P,
IDR_STOP, IDR_STOP_NOBORDER, IDR_STOP_NOBORDER_CENTER, IDR_STOP_H, IDR_STOP_P,
IDR_MENU_BOOKMARK,
diff --git a/chrome/browser/bubble_positioner.h b/chrome/browser/bubble_positioner.h
deleted file mode 100644
index 7ea4df0..0000000
--- a/chrome/browser/bubble_positioner.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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_BUBBLE_POSITIONER_H_
-#define CHROME_BROWSER_BUBBLE_POSITIONER_H_
-
-namespace gfx {
-class Rect;
-}
-
-// An object in the browser UI can implement this interface to provide display
-// bounds for the omnibox bubble and info bubble views.
-class BubblePositioner {
- public:
- // Returns the bounds of the "location bar" stack (including star/go buttons
- // where relevant). The omnibox dropdown uses this to calculate its width and
- // y-coordinate, and views showing InfoBubbles use it to find the y-coordinate
- // they should show at, so that all "bubble" UIs show up at the same vertical
- // position.
- virtual gfx::Rect GetLocationStackBounds() const = 0;
-};
-
-#endif // CHROME_BROWSER_BUBBLE_POSITIONER_H_
diff --git a/chrome/browser/cert_store.cc b/chrome/browser/cert_store.cc
index 4d804ca..89c5ffe 100644
--- a/chrome/browser/cert_store.cc
+++ b/chrome/browser/cert_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -88,7 +88,8 @@ bool CertStore::RetrieveCert(int cert_id,
CertMap::iterator iter = id_to_cert_.find(cert_id);
if (iter == id_to_cert_.end())
return false;
- *cert = iter->second;
+ if (cert)
+ *cert = iter->second;
return true;
}
diff --git a/chrome/browser/cert_store.h b/chrome/browser/cert_store.h
index 995a3db..0b19540 100644
--- a/chrome/browser/cert_store.h
+++ b/chrome/browser/cert_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -34,9 +34,9 @@ class CertStore : public NotificationObserver {
// Note: ids starts at 1.
int StoreCert(net::X509Certificate* cert, int render_process_host_id);
- // Retrieves the previously stored cert associated with the specified
- // |cert_id| and set it in |cert|. Returns false if no cert was found for
- // that id.
+ // Tries to retrieve the previously stored cert associated with the specified
+ // |cert_id|. Returns whether the cert could be found, and, if |cert| is
+ // non-NULL, copies it in.
bool RetrieveCert(int cert_id, scoped_refptr<net::X509Certificate>* cert);
// NotificationObserver implementation.
diff --git a/chrome/browser/chromeos/compact_location_bar_host.cc b/chrome/browser/chromeos/compact_location_bar_host.cc
index 1806421..4bdbc44 100644
--- a/chrome/browser/chromeos/compact_location_bar_host.cc
+++ b/chrome/browser/chromeos/compact_location_bar_host.cc
@@ -22,7 +22,6 @@
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/tabs/tab.h"
#include "chrome/browser/views/tabs/tab_strip.h"
-#include "chrome/browser/views/toolbar_star_toggle.h"
#include "views/controls/scrollbar/native_scroll_bar.h"
#include "views/focus/external_focus_tracker.h"
#include "views/focus/view_storage.h"
@@ -270,10 +269,6 @@ void CompactLocationBarHost::SetEnabled(bool enabled) {
}
}
-ToolbarStarToggle* CompactLocationBarHost::GetStarButton() {
- return GetClbView()->star_button();
-}
-
void CompactLocationBarHost::Show(bool a) {
MessageLoopForUI::current()->AddObserver(mouse_observer_.get());
DropdownBarHost::Show(a);
diff --git a/chrome/browser/chromeos/compact_location_bar_host.h b/chrome/browser/chromeos/compact_location_bar_host.h
index 5b59afa..b1f4d83 100644
--- a/chrome/browser/chromeos/compact_location_bar_host.h
+++ b/chrome/browser/chromeos/compact_location_bar_host.h
@@ -16,7 +16,6 @@
class BrowserView;
class TabContents;
class Tab;
-class ToolbarStarToggle;
namespace chromeos {
@@ -61,9 +60,6 @@ class CompactLocationBarHost : public DropdownBarHost,
// Enable/disable the compact location bar.
void SetEnabled(bool enabled);
- // Returns the star button for compact location bar.
- ToolbarStarToggle* GetStarButton();
-
// Overridden from DropdownBarhost.
virtual void Show(bool animate);
virtual void Hide(bool animate);
diff --git a/chrome/browser/chromeos/compact_location_bar_view.cc b/chrome/browser/chromeos/compact_location_bar_view.cc
index 93a7d2b..cfffec2 100644
--- a/chrome/browser/chromeos/compact_location_bar_view.cc
+++ b/chrome/browser/chromeos/compact_location_bar_view.cc
@@ -8,10 +8,8 @@
#include <algorithm>
#include "app/l10n_util.h"
-#include "app/drag_drop_types.h"
#include "app/resource_bundle.h"
#include "chrome/app/chrome_dll_resource.h"
-#include "chrome/browser/bookmarks/bookmark_drag_data.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/browser_list.h"
@@ -24,7 +22,6 @@
#include "chrome/browser/views/browser_actions_container.h"
#include "chrome/browser/views/event_utils.h"
#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/toolbar_star_toggle.h"
#include "gfx/canvas.h"
#include "gfx/point.h"
#include "grit/chromium_strings.h"
@@ -33,12 +30,10 @@
#include "views/background.h"
#include "views/controls/button/image_button.h"
#include "views/controls/native/native_view_host.h"
-#include "views/drag_utils.h"
#include "views/widget/widget.h"
#include "views/window/window.h"
namespace chromeos {
-const int kAutocompletePopupWidth = 700;
const int kDefaultLocationEntryWidth = 250;
const int kCompactLocationLeftMargin = 5;
const int kCompactLocationRightMargin = 10;
@@ -51,8 +46,7 @@ const int kWidgetsSeparatorWidth = 2;
CompactLocationBarView::CompactLocationBarView(CompactLocationBarHost* host)
: DropdownBarView(host),
reload_(NULL),
- browser_actions_(NULL),
- star_(NULL) {
+ browser_actions_(NULL) {
SetFocusable(true);
}
@@ -102,7 +96,7 @@ void CompactLocationBarView::Init() {
reload_->SetImage(views::CustomButton::BS_PUSHED,
tp->GetBitmapNamed(IDR_RELOAD_P));
reload_->SetBackground(color, background,
- tp->GetBitmapNamed(IDR_BUTTON_MASK));
+ tp->GetBitmapNamed(IDR_RELOAD_MASK));
AddChildView(reload_);
@@ -121,14 +115,6 @@ void CompactLocationBarView::Init() {
location_entry_view_->set_focus_view(this);
location_entry_view_->Attach(location_entry_->GetNativeView());
- star_ = new ToolbarStarToggle(this);
- star_->SetDragController(this);
- star_->set_profile(browser()->profile());
- star_->set_host_view(this);
- star_->set_bubble_positioner(this);
- star_->Init();
- AddChildView(star_);
-
location_entry_->Update(browser()->GetSelectedTabContents());
// Note: we tell the BrowserActionsContainer not to save its size because
@@ -146,15 +132,12 @@ gfx::Size CompactLocationBarView::GetPreferredSize() {
return gfx::Size(); // Not initialized yet, do nothing.
gfx::Size reload_size = reload_->GetPreferredSize();
- gfx::Size star_size = star_->GetPreferredSize();
gfx::Size location_size = location_entry_view_->GetPreferredSize();
gfx::Size ba_size = browser_actions_->GetPreferredSize();
- int width =
- reload_size.width() + kEntryLeftMargin + star_size.width() +
+ int width = kCompactLocationLeftMargin + reload_size.width() +
std::max(kDefaultLocationEntryWidth,
location_entry_view_->GetPreferredSize().width()) +
ba_size.width() +
- kCompactLocationLeftMargin +
kCompactLocationRightMargin;
return gfx::Size(width, kDefaultLocationBarHeight);
}
@@ -169,12 +152,7 @@ void CompactLocationBarView::Layout() {
int reload_y = (height() - reload_size.height()) / 2;
reload_->SetBounds(cur_x, reload_y,
reload_size.width(), reload_size.height());
- cur_x += reload_size.width() + kEntryLeftMargin;
-
- gfx::Size star_size = star_->GetPreferredSize();
- int star_y = (height() - star_size.height()) / 2;
- star_->SetBounds(cur_x, star_y, star_size.width(), star_size.height());
- cur_x += star_size.width();
+ cur_x += reload_size.width();
gfx::Size ba_size = browser_actions_->GetPreferredSize();
int ba_y = (height() - ba_size.height()) / 2;
@@ -268,62 +246,4 @@ std::wstring CompactLocationBarView::GetTitle() const {
return std::wstring();
}
-////////////////////////////////////////////////////////////////////////////////
-// BubblePositioner overrides:
-gfx::Rect CompactLocationBarView::GetLocationStackBounds() const {
- gfx::Point lower_left(0, height());
- ConvertPointToScreen(this, &lower_left);
- gfx::Rect popup = gfx::Rect(lower_left.x(), lower_left.y(),
- kAutocompletePopupWidth, 0);
- return popup.AdjustToFit(GetWidget()->GetWindow()->GetBounds());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// views::DragController overrides:
-void CompactLocationBarView::WriteDragData(views::View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data) {
- DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE);
-
- UserMetrics::RecordAction(UserMetricsAction("CompactLocationBar_DragStar"),
- browser()->profile());
-
- // If there is a bookmark for the URL, add the bookmark drag data for it. We
- // do this to ensure the bookmark is moved, rather than creating an new
- // bookmark.
- TabContents* tab = browser()->GetSelectedTabContents();
- if (tab) {
- Profile* profile = browser()->profile();
- if (profile && profile->GetBookmarkModel()) {
- const BookmarkNode* node = profile->GetBookmarkModel()->
- GetMostRecentlyAddedNodeForURL(tab->GetURL());
- if (node) {
- BookmarkDragData bookmark_data(node);
- bookmark_data.Write(profile, data);
- }
- }
-
- drag_utils::SetURLAndDragImage(tab->GetURL(),
- UTF16ToWideHack(tab->GetTitle()),
- tab->GetFavIcon(),
- data);
- }
-}
-
-int CompactLocationBarView::GetDragOperations(views::View* sender,
- const gfx::Point& p) {
- DCHECK(sender == star_);
- TabContents* tab = browser()->GetSelectedTabContents();
- if (!tab || !tab->ShouldDisplayURL() || !tab->GetURL().is_valid()) {
- return DragDropTypes::DRAG_NONE;
- }
- Profile* profile = browser()->profile();
- if (profile && profile->GetBookmarkModel() &&
- profile->GetBookmarkModel()->IsBookmarked(tab->GetURL())) {
- return DragDropTypes::DRAG_MOVE | DragDropTypes::DRAG_COPY |
- DragDropTypes::DRAG_LINK;
- }
- return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/compact_location_bar_view.h b/chrome/browser/chromeos/compact_location_bar_view.h
index 889a630..a3c750f 100644
--- a/chrome/browser/chromeos/compact_location_bar_view.h
+++ b/chrome/browser/chromeos/compact_location_bar_view.h
@@ -6,7 +6,6 @@
#define CHROME_BROWSER_CHROMEOS_COMPACT_LOCATION_BAR_VIEW_H_
#include "base/basictypes.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/chromeos/compact_location_bar_host.h"
#include "chrome/browser/views/dropdown_bar_view.h"
@@ -17,11 +16,9 @@ class AutocompleteEditViewGtk;
class Browser;
class BrowserActionsContainer;
class BrowserView;
-class ToolbarStarToggleGtk;
class Tab;
class TabContents;
class TabStrip;
-class ToolbarStarToggle;
namespace views {
class ImageButton;
@@ -35,9 +32,7 @@ namespace chromeos {
// navigation bar mode.
class CompactLocationBarView : public DropdownBarView,
public views::ButtonListener,
- public AutocompleteEditController,
- public BubblePositioner,
- public views::DragController {
+ public AutocompleteEditController {
public:
explicit CompactLocationBarView(CompactLocationBarHost* host);
~CompactLocationBarView();
@@ -47,8 +42,6 @@ class CompactLocationBarView : public DropdownBarView,
void Update(const TabContents* contents);
- ToolbarStarToggle* star_button() const { return star_; }
-
private:
Browser* browser() const;
@@ -81,20 +74,6 @@ class CompactLocationBarView : public DropdownBarView,
virtual SkBitmap GetFavIcon() const;
virtual std::wstring GetTitle() const;
- // BubblePositioner implementation.
- virtual gfx::Rect GetLocationStackBounds() const;
-
- // views::DragController implementation.
- virtual void WriteDragData(View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data);
- virtual int GetDragOperations(View* sender, const gfx::Point& p);
- virtual bool CanStartDrag(View* sender,
- const gfx::Point& press_pt,
- const gfx::Point& p) {
- return true;
- }
-
CompactLocationBarHost* clb_host() {
return static_cast<CompactLocationBarHost*>(host());
}
@@ -103,7 +82,6 @@ class CompactLocationBarView : public DropdownBarView,
scoped_ptr<AutocompleteEditViewGtk> location_entry_;
views::NativeViewHost* location_entry_view_;
BrowserActionsContainer* browser_actions_;
- ToolbarStarToggle* star_;
DISALLOW_COPY_AND_ASSIGN(CompactLocationBarView);
};
diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc
index bf2dac7..d6aff2f 100644
--- a/chrome/browser/chromeos/frame/browser_view.cc
+++ b/chrome/browser/chromeos/frame/browser_view.cc
@@ -28,7 +28,6 @@
#include "chrome/browser/views/tabs/tab.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/browser/views/toolbar_view.h"
-#include "chrome/browser/views/toolbar_star_toggle.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -440,19 +439,6 @@ void BrowserView::ChildPreferredSizeChanged(View* child) {
SchedulePaint();
}
-void BrowserView::SetStarredState(bool is_starred) {
- ::BrowserView::SetStarredState(is_starred);
- compact_location_bar_host_->GetStarButton()->SetToggled(is_starred);
-}
-
-void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) {
- if (is_compact_style())
- compact_location_bar_host_->GetStarButton()->ShowStarBubble(
- url, !already_bookmarked);
- else
- ::BrowserView::ShowBookmarkBubble(url, already_bookmarked);
-}
-
// views::ButtonListener overrides.
void BrowserView::ButtonPressed(views::Button* sender,
const views::Event& event) {
@@ -463,7 +449,7 @@ void BrowserView::ButtonPressed(views::Button* sender,
origin.Offset(kAppLauncherLeftPadding, 0);
views::RootView::ConvertPointToScreen(this, &origin);
bounds.set_origin(origin);
- ::AppLauncher::Show(browser(), bounds);
+ ::AppLauncher::Show(browser(), bounds, gfx::Point());
}
// views::ContextMenuController overrides.
diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h
index 3bdea4f..647211f 100644
--- a/chrome/browser/chromeos/frame/browser_view.h
+++ b/chrome/browser/chromeos/frame/browser_view.h
@@ -66,8 +66,6 @@ class BrowserView : public ::BrowserView,
virtual views::LayoutManager* CreateLayoutManager() const;
virtual BaseTabStrip* CreateTabStrip(TabStripModel* tab_strip_model);
virtual void ChildPreferredSizeChanged(View* child);
- virtual void SetStarredState(bool is_starred);
- virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked);
// views::ButtonListener overrides.
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
diff --git a/chrome/browser/cocoa/autocomplete_text_field.h b/chrome/browser/cocoa/autocomplete_text_field.h
index 1b1856d..8e16705 100644
--- a/chrome/browser/cocoa/autocomplete_text_field.h
+++ b/chrome/browser/cocoa/autocomplete_text_field.h
@@ -119,6 +119,13 @@ class AutocompleteTextFieldObserver {
// is not over an action.
- (NSMenu*)actionMenuForEvent:(NSEvent*)event;
+// Return the rectangle the star is being shown in, for purposes of
+// positioning the bookmark bubble.
+- (NSRect)starIconFrame;
+
+// If the location icon is draggable, return its drag pasteboard.
+- (NSPasteboard*)locationDragPasteboard;
+
@end
#endif // CHROME_BROWSER_COCOA_AUTOCOMPLETE_TEXT_FIELD_H_
diff --git a/chrome/browser/cocoa/autocomplete_text_field.mm b/chrome/browser/cocoa/autocomplete_text_field.mm
index 60d3507..a07cac1 100644
--- a/chrome/browser/cocoa/autocomplete_text_field.mm
+++ b/chrome/browser/cocoa/autocomplete_text_field.mm
@@ -124,14 +124,10 @@
return;
}
- // If the user clicked on one of the icons (security icon, Page
- // Actions, etc), let the icon handle the click.
- for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:bounds]) {
- const NSRect iconRect = [icon rect];
- if (NSMouseInRect(location, iconRect, flipped)) {
- [icon view]->OnMousePressed(iconRect);
- return;
- }
+ // Give the cell a chance to intercept clicks in page-actions and
+ // other decorative items.
+ if ([cell mouseDown:theEvent inRect:bounds ofView:self]) {
+ return;
}
NSText* editor = [self currentEditor];
@@ -199,6 +195,7 @@
// Show the I-beam cursor unless the mouse is over an image within the field
// (Page Actions or the security icon) in which case show the arrow cursor.
+// TODO(rohitrao): Should default to the arrow cursor. http://crbug.com/41612
- (void)resetCursorRects {
NSRect fieldBounds = [self bounds];
[self addCursorRect:fieldBounds cursor:[NSCursor IBeamCursor]];
@@ -206,8 +203,17 @@
AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell];
for (AutocompleteTextFieldIcon* icon in [cell layedOutIcons:fieldBounds])
[self addCursorRect:[icon rect] cursor:[NSCursor arrowCursor]];
+
+ // Special-case the location image, since it is not in |-layedOutIcons|.
+ const NSRect locationIconFrame = [cell locationIconFrameForFrame:fieldBounds];
+ [self addCursorRect:locationIconFrame cursor:[NSCursor arrowCursor]];
}
+// TODO(shess): -resetFieldEditorFrameIfNeeded is the place where
+// changes to the cell layout should be flushed. LocationBarViewMac
+// and ToolbarController are calling this routine directly, and I
+// think they are probably wrong.
+// http://crbug.com/40053
- (void)updateCursorAndToolTipRects {
// This will force |resetCursorRects| to be called, as it is not to be called
// directly.
@@ -371,4 +377,13 @@
actionMenuForEvent:event inRect:[self bounds] ofView:self];
}
+- (NSRect)starIconFrame {
+ AutocompleteTextFieldCell* cell = [self autocompleteTextFieldCell];
+ return [cell starIconFrameForFrame:[self bounds]];
+}
+
+- (NSPasteboard*)locationDragPasteboard {
+ return [[self autocompleteTextFieldCell] locationDragPasteboard];
+}
+
@end
diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.h b/chrome/browser/cocoa/autocomplete_text_field_cell.h
index 1e0a3c5..bc791cf 100644
--- a/chrome/browser/cocoa/autocomplete_text_field_cell.h
+++ b/chrome/browser/cocoa/autocomplete_text_field_cell.h
@@ -13,7 +13,15 @@ class ExtensionAction;
// Holds a |LocationBarImageView| and its current rect. Do not keep references
// to this object, only use it directly after calling |-layedOutIcons:|.
+// TODO(shess): This class is basically a helper for laying out the
+// icons. Try to refactor it away. If that is not reasonable, at
+// least split the image and label cases into subclasses once the
+// Omnibox stuff is settled.
@interface AutocompleteTextFieldIcon : NSObject {
+ // YES to draw the label part of |view_|, otherwise draw the image
+ // part.
+ BOOL isLabel_;
+
// The frame rect of |view_|.
NSRect rect_;
@@ -21,12 +29,20 @@ class ExtensionAction;
LocationBarViewMac::LocationBarImageView* view_;
}
-// Returns a new AutocompleteTextFieldIcon object.
-+ (AutocompleteTextFieldIcon*)
- iconWithRect:(NSRect)rect
- view:(LocationBarViewMac::LocationBarImageView*)view;
@property(assign, nonatomic) NSRect rect;
@property(assign, nonatomic) LocationBarViewMac::LocationBarImageView* view;
+
+- (id)initImageWithView:(LocationBarViewMac::LocationBarImageView*)view;
+- (id)initLabelWithView:(LocationBarViewMac::LocationBarImageView*)view;
+
+// Position |view_| right-justified in |frame|.
+- (void)positionInFrame:(NSRect)frame;
+
+// Draw image or label of |view_| in |rect_| within |controlView|.
+// Only call after |-positionInFrame:| has set |rect_| (or after an
+// explicit |-setRect:|).
+- (void)drawInView:(NSView*)controlView;
+
@end
// AutocompleteTextFieldCell extends StyledTextFieldCell to provide support for
@@ -44,10 +60,17 @@ class ExtensionAction;
// side of the field. Exclusive WRT |keywordString_|;
scoped_nsobject<NSAttributedString> hintString_;
- // View showing the state of the SSL connection. Owned by the location bar.
- // Display is exclusive WRT the |hintString_| and |keywordString_|.
- // This may be NULL during testing.
- LocationBarViewMac::SecurityImageView* security_image_view_;
+ // The location icon sits at the left-hand side of the field.
+ // |keywordString_| overrides.
+ LocationBarViewMac::LocationIconView* locationIconView_;
+
+ // The star icon sits at the right-hand side of the field when an
+ // URL is being shown.
+ LocationBarViewMac::LocationBarImageView* starIconView_;
+
+ // The security label floats to the left of page actions at the
+ // right-hand side.
+ LocationBarViewMac::LocationBarImageView* securityLabelView_;
// List of views showing visible Page Actions. Owned by the location bar.
// Display is exclusive WRT the |hintString_| and |keywordString_|.
@@ -77,34 +100,58 @@ class ExtensionAction;
availableWidth:(CGFloat)width;
- (void)clearKeywordAndHint;
-- (void)setSecurityImageView:(LocationBarViewMac::SecurityImageView*)view;
+- (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view;
+- (void)setStarIconView:(LocationBarViewMac::LocationBarImageView*)view;
+- (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view;
- (void)setPageActionViewList:(LocationBarViewMac::PageActionViewList*)list;
- (void)setContentSettingViewsList:
(LocationBarViewMac::ContentSettingViews*)views;
+// Returns the portion of the cell to use for displaying the location
+// icon.
+- (NSRect)locationIconFrameForFrame:(NSRect)cellFrame;
+
// Returns an array of the visible AutocompleteTextFieldIcon objects. Returns
// only visible icons.
- (NSArray*)layedOutIcons:(NSRect)cellFrame;
+// Return the rectangle the star is being shown in, for purposes of
+// positioning the bookmark bubble.
+- (NSRect)starIconFrameForFrame:(NSRect)cellFrame;
+
+// Returns the portion of the cell to use for displaying the Page
+// Action icon at the given index. May be NSZeroRect if the index's
+// action is not visible. This does a linear walk over all page
+// actions, so do not call this in a loop to get the position of all
+// page actions. Use |-layedOutIcons:| instead in that case.
+- (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame;
// Similar to |pageActionFrameForIndex:inFrame| but accepts an
// ExtensionAction for when the index is not known.
- (NSRect)pageActionFrameForExtensionAction:(ExtensionAction*)action
inFrame:(NSRect)cellFrame;
-// Returns the portion of the cell to use for displaying the Page Action icon
-// at the given index. May be NSZeroRect if the index's action is not visible.
-// This does a linear walk over all page actions, so do not call this in a loop
-// to get the position of all page actions. Use |-layedOutIcons:| instead in that
-// case.
-- (NSRect)pageActionFrameForIndex:(size_t)index inFrame:(NSRect)cellFrame;
+// Find the icon under the event. |nil| if |theEvent| is not over
+// anything.
+- (AutocompleteTextFieldIcon*)iconForEvent:(NSEvent*)theEvent
+ inRect:(NSRect)cellFrame
+ ofView:(AutocompleteTextField*)controlView;
// Return the appropriate menu for any page actions under event.
// Returns nil if no menu is present for the action, or if the event
// is not over an action.
-- (NSMenu*)actionMenuForEvent:(NSEvent*)event
+- (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent
inRect:(NSRect)cellFrame
- ofView:(NSView*)aView;
+ ofView:(AutocompleteTextField*)controlView;
+
+// Called by |AutocompleteTextField| to let page actions intercept
+// clicks. Returns |YES| if the click has been intercepted.
+- (BOOL)mouseDown:(NSEvent*)theEvent
+ inRect:(NSRect)cellFrame
+ ofView:(AutocompleteTextField*)controlView;
+
+// If the location icon is draggable, return its drag pasteboard.
+- (NSPasteboard*)locationDragPasteboard;
@end
@@ -118,8 +165,4 @@ class ExtensionAction;
// Returns the total number of installed Page Actions, visible or not.
- (size_t)pageActionCount;
-// Returns the portion of the cell to use for displaying the security (SSL lock)
-// icon, leaving space for its label if any.
-- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame;
-
@end
diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm
index 7b7f35c..9801892 100644
--- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm
+++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm
@@ -7,6 +7,20 @@
#include "app/resource_bundle.h"
#include "base/logging.h"
#include "gfx/font.h"
+#include "grit/theme_resources.h"
+
+@interface AutocompleteTextAttachmentCell : NSTextAttachmentCell {
+}
+
+// TODO(shess):
+// Override -cellBaselineOffset to allow the image to be shifted up or
+// down relative to the containing text's baseline.
+
+// Draw the image using |DrawImageInRect()| helper function for
+// |-setFlipped:| consistency with other image drawing.
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView;
+
+@end
namespace {
@@ -35,16 +49,28 @@ const NSInteger kKeywordYInset = 4;
// technique would be nice to have, though.
const NSInteger kKeywordHintImageBaseline = -6;
+// Drops the magnifying glass icon so that it looks centered in the
+// keyword-search bubble.
+const NSInteger kKeywordSearchImageBaseline = -5;
+
// The amount of padding on either side reserved for drawing an icon.
const NSInteger kIconHorizontalPad = 3;
// How far to shift bounding box of hint icon label down from top of field.
-const NSInteger kIconLabelYOffset = 5;
+const NSInteger kIconLabelYOffset = 7;
// How far the editor insets itself, for purposes of determining if
// decorations need to be trimmed.
const CGFloat kEditorHorizontalInset = 3.0;
+// Cause the location icon to line up above the icons in the popup.
+const CGFloat kLocationIconXOffset = 6.0;
+const CGFloat kLocationIconXPad = 1.0;
+
+// How long to wait for mouse-up on the location icon before assuming
+// that the user wants to drag.
+const NSTimeInterval kLocationIconDragTimeout = 0.25;
+
// Conveniences to centralize width+offset calculations.
CGFloat WidthForHint(NSAttributedString* hintString) {
return kHintXOffset + ceil([hintString size].width);
@@ -54,20 +80,103 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
2 * kKeywordTokenInset;
}
+// Convenience to draw |image| in the |rect| portion of |view|.
+void DrawImageInRect(NSImage* image, NSView* view, const NSRect& rect) {
+ // If there is an image, make sure we calculated the target size
+ // correctly.
+ DCHECK(!image || NSEqualSizes([image size], rect.size));
+ [image setFlipped:[view isFlipped]];
+ [image drawInRect:rect
+ fromRect:NSZeroRect // Entire image
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+}
+
+// Helper function to generate an attributed string containing
+// |anImage|. If |baselineAdjustment| is 0, the image sits on the
+// text baseline, positive values shift it up, negative values shift
+// it down.
+NSAttributedString* AttributedStringForImage(NSImage* anImage,
+ CGFloat baselineAdjustment) {
+ scoped_nsobject<AutocompleteTextAttachmentCell> attachmentCell(
+ [[AutocompleteTextAttachmentCell alloc] initImageCell:anImage]);
+ scoped_nsobject<NSTextAttachment> attachment(
+ [[NSTextAttachment alloc] init]);
+ [attachment setAttachmentCell:attachmentCell];
+
+ scoped_nsobject<NSMutableAttributedString> as(
+ [[NSAttributedString attributedStringWithAttachment:attachment]
+ mutableCopy]);
+ [as addAttribute:NSBaselineOffsetAttributeName
+ value:[NSNumber numberWithFloat:baselineAdjustment]
+ range:NSMakeRange(0, [as length])];
+
+ return [[as copy] autorelease];
+}
+
} // namespace
+@implementation AutocompleteTextAttachmentCell
+
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView {
+ // Draw image with |DrawImageInRect()| to get consistent
+ // |-setFlipped:| treatment.
+ DrawImageInRect([self image], aView, cellFrame);
+}
+
+@end
+
@implementation AutocompleteTextFieldIcon
@synthesize rect = rect_;
@synthesize view = view_;
-+ (AutocompleteTextFieldIcon*)
- iconWithRect:(NSRect)rect
- view:(LocationBarViewMac::LocationBarImageView*)view {
- AutocompleteTextFieldIcon* result = [[AutocompleteTextFieldIcon alloc] init];
- [result setRect:rect];
- [result setView:view];
- return [result autorelease];
+// Private helper.
+- (id)initWithView:(LocationBarViewMac::LocationBarImageView*)view
+ isLabel:(BOOL)isLabel {
+ self = [super init];
+ if (self) {
+ isLabel_ = isLabel;
+ view_ = view;
+ rect_ = NSZeroRect;
+ }
+ return self;
+}
+
+- (id)initImageWithView:(LocationBarViewMac::LocationBarImageView*)view {
+ return [self initWithView:view isLabel:NO];
+}
+
+- (id)initLabelWithView:(LocationBarViewMac::LocationBarImageView*)view {
+ return [self initWithView:view isLabel:YES];
+}
+
+- (void)positionInFrame:(NSRect)frame {
+ if (isLabel_) {
+ NSAttributedString* label = view_->GetLabel();
+ DCHECK(label);
+ const CGFloat labelWidth = ceil([label size].width);
+ rect_ = NSMakeRect(NSMaxX(frame) - labelWidth,
+ NSMinY(frame) + kIconLabelYOffset,
+ labelWidth, NSHeight(frame) - kIconLabelYOffset);
+ } else {
+ const NSSize imageSize = view_->GetImageSize();
+ const CGFloat yOffset = floor((NSHeight(frame) - imageSize.height) / 2);
+ rect_ = NSMakeRect(NSMaxX(frame) - imageSize.width,
+ NSMinY(frame) + yOffset,
+ imageSize.width, imageSize.height);
+ }
+}
+
+- (void)drawInView:(NSView*)controlView {
+ // Make sure someone called |-positionInFrame:|.
+ DCHECK(!NSIsEmptyRect(rect_));
+ if (isLabel_) {
+ NSAttributedString* label = view_->GetLabel();
+ [label drawInRect:rect_];
+ } else {
+ DrawImageInRect(view_->GetImage(), controlView, rect_);
+ }
}
@end
@@ -96,18 +205,40 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
// Adjust for space between editor and decorations.
width -= 2 * kEditorHorizontalInset;
- // If |fullString| won't fit, choose |partialString|.
+ // Get the magnifying glass to put at the front of the string.
+ NSImage* image =
+ AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_SEARCH);
+ const NSSize imageSize = [image size];
+
+ // Based on what fits, choose |fullString| with the image,
+ // |fullString| without the image, or |partialString|.
NSDictionary* attributes =
[NSDictionary dictionaryWithObject:[self font]
forKey:NSFontAttributeName];
NSString* s = fullString;
- if ([s sizeWithAttributes:attributes].width > width) {
+ const CGFloat sWidth = [s sizeWithAttributes:attributes].width;
+ if (sWidth + imageSize.width > width) {
+ image = nil;
+ }
+ if (sWidth > width) {
if (partialString) {
s = partialString;
}
}
- keywordString_.reset(
- [[NSAttributedString alloc] initWithString:s attributes:attributes]);
+
+ scoped_nsobject<NSMutableAttributedString> as(
+ [[NSMutableAttributedString alloc] initWithString:s
+ attributes:attributes]);
+
+ // Insert the image at the front of the string if it didn't make
+ // things too wide.
+ if (image) {
+ NSAttributedString* is =
+ AttributedStringForImage(image, kKeywordSearchImageBaseline);
+ [as insertAttributedString:is atIndex:0];
+ }
+
+ keywordString_.reset([as copy]);
}
// Convenience for the attributes used in the right-justified info
@@ -155,21 +286,8 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
initWithString:s attributes:[self hintAttributes]]);
// Build an attachment containing the hint image.
- scoped_nsobject<NSTextAttachmentCell> attachmentCell(
- [[NSTextAttachmentCell alloc] initImageCell:anImage]);
- scoped_nsobject<NSTextAttachment> attachment(
- [[NSTextAttachment alloc] init]);
- [attachment setAttachmentCell:attachmentCell];
-
- // The attachment's baseline needs to be adjusted so the image
- // doesn't sit on the same baseline as the text and make
- // everything too tall.
- scoped_nsobject<NSMutableAttributedString> is(
- [[NSAttributedString attributedStringWithAttachment:attachment]
- mutableCopy]);
- [is addAttribute:NSBaselineOffsetAttributeName
- value:[NSNumber numberWithFloat:kKeywordHintImageBaseline]
- range:NSMakeRange(0, [is length])];
+ NSAttributedString* is =
+ AttributedStringForImage(anImage, kKeywordHintImageBaseline);
// Stuff the image attachment between the prefix and suffix.
[as insertAttributedString:is atIndex:[prefixString length]];
@@ -213,8 +331,16 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
page_action_views_ = list;
}
-- (void)setSecurityImageView:(LocationBarViewMac::SecurityImageView*)view {
- security_image_view_ = view;
+- (void)setLocationIconView:(LocationBarViewMac::LocationIconView*)view {
+ locationIconView_ = view;
+}
+
+- (void)setStarIconView:(LocationBarViewMac::LocationBarImageView*)view {
+ starIconView_ = view;
+}
+
+- (void)setSecurityLabelView:(LocationBarViewMac::LocationBarImageView*)view {
+ securityLabelView_ = view;
}
- (void)setContentSettingViewsList:
@@ -226,69 +352,81 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
- (NSRect)textFrameForFrame:(NSRect)cellFrame {
NSRect textFrame([super textFrameForFrame:cellFrame]);
- if (hintString_) {
+ // NOTE: This function must closely match the logic in
+ // |-drawInteriorWithFrame:inView:|.
+
+ // Location icon is not shown in keyword search mode.
+ if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
+ const NSRect iconFrame = [self locationIconFrameForFrame:cellFrame];
+ const CGFloat newOrigin = NSMaxX(iconFrame) + kLocationIconXPad;
+ textFrame.size.width = NSMaxX(textFrame) - newOrigin;
+ textFrame.origin.x = newOrigin;
+ }
+
+ // Leave room for items on the right (SSL label, page actions, etc).
+ // Icons are laid out in |cellFrame| rather than |textFrame| for
+ // consistency with drawing code.
+ NSArray* icons = [self layedOutIcons:cellFrame];
+ if ([icons count]) {
+ // Max x for resulting text frame.
+ const CGFloat maxX = NSMinX([[icons objectAtIndex:0] rect]);
+ textFrame.size.width = maxX - NSMinX(textFrame);
+ }
+
+ // Keyword string or hint string if they fit.
+ if (keywordString_) {
+ DCHECK(!hintString_);
+ const CGFloat keywordWidth(WidthForKeyword(keywordString_));
+
+ if (keywordWidth < NSWidth(textFrame)) {
+ textFrame.origin.x += keywordWidth;
+ textFrame.size.width -= keywordWidth;
+ }
+ } else if (hintString_) {
DCHECK(!keywordString_);
const CGFloat hintWidth(WidthForHint(hintString_));
// TODO(shess): This could be better. Show the hint until the
// non-hint text bumps against it?
- if (hintWidth < NSWidth(cellFrame)) {
+ if (hintWidth < NSWidth(textFrame)) {
textFrame.size.width -= hintWidth;
}
- } else if (keywordString_) {
- DCHECK(!hintString_);
- const CGFloat keywordWidth(WidthForKeyword(keywordString_));
+ }
- // TODO(shess): This could be better. There's support for a
- // "short" version of the keyword string, work that in in a
- // follow-on pass.
- if (keywordWidth < NSWidth(cellFrame)) {
- textFrame.origin.x += keywordWidth;
- textFrame.size.width = NSMaxX(cellFrame) - NSMinX(textFrame);
+ // SSL label if it fits.
+ if (securityLabelView_ && securityLabelView_->IsVisible() &&
+ securityLabelView_->GetLabel()) {
+ NSAttributedString* label = securityLabelView_->GetLabel();
+ const CGFloat labelWidth = ceil([label size].width) + kIconHorizontalPad;
+ if (NSWidth(textFrame) > labelWidth) {
+ textFrame.size.width -= labelWidth;
}
- } else {
- // Leave room for images on the right (lock icon etc).
- NSArray* iconFrames = [self layedOutIcons:cellFrame];
- CGFloat width = 0;
- if ([iconFrames count] > 0)
- width = NSMaxX(cellFrame) - NSMinX([[iconFrames lastObject] rect]);
- if (width > 0)
- width += kIconHorizontalPad;
- if (width < NSWidth(cellFrame))
- textFrame.size.width -= width;
}
return textFrame;
}
-// Returns a rect of size |imageSize| centered vertically and right-justified in
-// the |box|, with its top left corner |margin| pixels from the right end of the
-// box. (The image thus occupies part of the |margin|.)
-- (NSRect)rightJustifyImage:(NSSize)imageSize
- inRect:(NSRect)box
- withMargin:(CGFloat)margin {
- box.origin.x += box.size.width - margin;
- box.origin.y += floor((box.size.height - imageSize.height) / 2);
- box.size = imageSize;
- return box;
+- (NSRect)locationIconFrameForFrame:(NSRect)cellFrame {
+ if (!locationIconView_ || !locationIconView_->IsVisible())
+ return NSZeroRect;
+
+ const NSSize imageSize = locationIconView_->GetImageSize();
+ const CGFloat yOffset = floor((NSHeight(cellFrame) - imageSize.height) / 2);
+ return NSMakeRect(NSMinX(cellFrame) + kLocationIconXOffset,
+ NSMinY(cellFrame) + yOffset,
+ imageSize.width, imageSize.height);
}
-- (NSRect)securityImageFrameForFrame:(NSRect)cellFrame {
- if (!security_image_view_ || !security_image_view_->IsVisible()) {
+- (NSRect)starIconFrameForFrame:(NSRect)cellFrame {
+ if (!starIconView_ || !starIconView_->IsVisible())
return NSZeroRect;
- }
-
- // Calculate the total width occupied by the image, label, and padding.
- NSSize imageSize = [security_image_view_->GetImage() size];
- CGFloat widthUsed = imageSize.width + kIconHorizontalPad;
- NSAttributedString* label = security_image_view_->GetLabel();
- if (label) {
- widthUsed += ceil([label size].width) + kHintXOffset;
- }
- return [self rightJustifyImage:imageSize
- inRect:cellFrame
- withMargin:widthUsed];
+ // The star icon is always at the RHS.
+ scoped_nsobject<AutocompleteTextFieldIcon> icon(
+ [[AutocompleteTextFieldIcon alloc] initImageWithView:starIconView_]);
+ cellFrame.size.width -= kHintXOffset;
+ [icon positionInFrame:cellFrame];
+ return [icon rect];
}
- (size_t)pageActionCount {
@@ -365,118 +503,223 @@ CGFloat WidthForKeyword(NSAttributedString* keywordString) {
[path stroke];
// Draw text w/in the rectangle.
- infoFrame.origin.x += 4.0;
- infoFrame.origin.y += 1.0;
+ infoFrame.origin.x += 3.0;
[keywordString_.get() drawInRect:infoFrame];
}
-- (void)drawImageView:(LocationBarViewMac::LocationBarImageView*)imageView
- inFrame:(NSRect)imageFrame
- inView:(NSView*)controlView {
- // If there's a label, draw it to the right of the icon. The caller must have
- // left sufficient space.
- NSAttributedString* label = imageView->GetLabel();
- if (label) {
- CGFloat labelWidth = ceil([label size].width) + kHintXOffset;
- NSRect textFrame(NSMakeRect(NSMaxX(imageFrame) + kIconHorizontalPad,
- imageFrame.origin.y + kIconLabelYOffset,
- labelWidth,
- imageFrame.size.height - kIconLabelYOffset));
- [label drawInRect:textFrame];
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+ NSRect workingFrame = cellFrame;
+
+ // NOTE: This function must closely match the logic in
+ // |-textFrameForFrame:|.
+
+ // Location icon is not shown in keyword search mode.
+ if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) {
+ const NSRect iconFrame = [self locationIconFrameForFrame:cellFrame];
+ DrawImageInRect(locationIconView_->GetImage(), controlView, iconFrame);
+ const CGFloat newOrigin = NSMaxX(iconFrame) + kLocationIconXPad;
+ workingFrame.size.width = NSMaxX(workingFrame) - newOrigin;
+ workingFrame.origin.x = newOrigin;
}
- // Draw the entire image.
- NSRect imageRect = NSZeroRect;
- NSImage* image = imageView->GetImage();
- image.size = [image size];
- [image setFlipped:[controlView isFlipped]];
- [image drawInRect:imageFrame
- fromRect:imageRect
- operation:NSCompositeSourceOver
- fraction:1.0];
-}
+ NSArray* icons = [self layedOutIcons:cellFrame];
+ for (AutocompleteTextFieldIcon* icon in icons) {
+ [icon drawInView:controlView];
+ }
+ if ([icons count]) {
+ // Max x for resulting text frame.
+ const CGFloat maxX = NSMinX([[icons objectAtIndex:0] rect]);
+ workingFrame.size.width = maxX - NSMinX(workingFrame);
+ }
-- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
- if (hintString_) {
- [self drawHintWithFrame:cellFrame inView:controlView];
- } else if (keywordString_) {
- [self drawKeywordWithFrame:cellFrame inView:controlView];
- } else {
- for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) {
- [self drawImageView:[icon view]
- inFrame:[icon rect]
- inView:controlView];
+ // Keyword string or hint string if they fit.
+ if (keywordString_) {
+ DCHECK(!hintString_);
+ const CGFloat keywordWidth(WidthForKeyword(keywordString_));
+
+ if (keywordWidth < NSWidth(workingFrame)) {
+ [self drawKeywordWithFrame:cellFrame inView:controlView];
+ workingFrame.origin.x += keywordWidth;
+ workingFrame.size.width -= keywordWidth;
+ }
+ } else if (hintString_) {
+ DCHECK(!keywordString_);
+ const CGFloat hintWidth(WidthForHint(hintString_));
+
+ // TODO(shess): This could be better. Show the hint until the
+ // non-hint text bumps against it?
+ if (hintWidth < NSWidth(workingFrame)) {
+ [self drawHintWithFrame:cellFrame inView:controlView];
+ workingFrame.size.width -= hintWidth;
}
}
+ // SSL label if it fits.
+ if (securityLabelView_ && securityLabelView_->IsVisible() &&
+ securityLabelView_->GetLabel()) {
+ NSAttributedString* label = securityLabelView_->GetLabel();
+ const CGFloat labelWidth = ceil([label size].width) + kIconHorizontalPad;
+ if (NSWidth(workingFrame) > labelWidth) {
+ workingFrame.size.width -= kIconHorizontalPad;
+
+ scoped_nsobject<AutocompleteTextFieldIcon> icon(
+ [[AutocompleteTextFieldIcon alloc]
+ initLabelWithView:securityLabelView_]);
+ [icon positionInFrame:workingFrame];
+ [icon drawInView:controlView];
+ DCHECK_EQ(labelWidth, NSWidth([icon rect]) + kIconHorizontalPad);
+ workingFrame.size.width -= NSWidth([icon rect]);
+ }
+ }
+
+ // Superclass draws text portion WRT original |cellFrame|.
[super drawInteriorWithFrame:cellFrame inView:controlView];
}
- (NSArray*)layedOutIcons:(NSRect)cellFrame {
- NSMutableArray* result = [NSMutableArray arrayWithCapacity:0];
- NSRect iconFrame = cellFrame;
- if (security_image_view_ && security_image_view_->IsVisible()) {
- NSRect securityImageFrame = [self securityImageFrameForFrame:iconFrame];
- [result addObject:
- [AutocompleteTextFieldIcon iconWithRect:securityImageFrame
- view:security_image_view_]];
- iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(securityImageFrame);
+ // The set of views to display right-justified in the cell, from
+ // left to right.
+ NSMutableArray* result = [NSMutableArray array];
+
+ // Collect the image views for bulk processing.
+ // TODO(shess): Refactor with LocationBarViewMac to make the
+ // different types of items more consistent.
+ std::vector<LocationBarViewMac::LocationBarImageView*> views;
+
+ if (content_setting_views_) {
+ views.insert(views.end(),
+ content_setting_views_->begin(),
+ content_setting_views_->end());
}
- const size_t pageActionCount = [self pageActionCount];
- for (size_t i = 0; i < pageActionCount; ++i) {
- LocationBarViewMac::PageActionImageView* view =
- page_action_views_->ViewAt(i);
- if (view->IsVisible()) {
- // If this function is called right after a page action icon has been
- // created, the images for all views will still be loading; in this case,
- // each visible view will give us its default size.
- NSSize iconSize = view->GetPreferredImageSize();
- NSRect pageActionFrame =
- [self rightJustifyImage:iconSize
- inRect:iconFrame
- withMargin:kIconHorizontalPad + iconSize.width];
- [result addObject:
- [AutocompleteTextFieldIcon iconWithRect:pageActionFrame view:view]];
- iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(pageActionFrame);
- }
+ // TODO(shess): Previous implementation of this method made a
+ // right-to-left array, so add the page-action items in that order.
+ // As part of the refactor mentioned above, lay everything out
+ // nicely left-to-right.
+ for (size_t i = [self pageActionCount]; i-- > 0;) {
+ views.push_back(page_action_views_->ViewAt(i));
}
- if (content_setting_views_) {
- // We use a reverse_iterator here because we're laying out the views from
- // right to left but in the vector they're ordered left to right.
- for (LocationBarViewMac::ContentSettingViews::const_reverse_iterator
- it(content_setting_views_->rbegin());
- it != const_cast<const LocationBarViewMac::ContentSettingViews*>(
- content_setting_views_)->rend();
- ++it) {
- if ((*it)->IsVisible()) {
- NSImage* image = (*it)->GetImage();
- NSRect blockedContentFrame =
- [self rightJustifyImage:[image size]
- inRect:iconFrame
- withMargin:[image size].width + kIconHorizontalPad];
- [result addObject:
- [AutocompleteTextFieldIcon iconWithRect:blockedContentFrame
- view:*it]];
- iconFrame.size.width -= NSMaxX(iconFrame) - NSMinX(blockedContentFrame);
- }
+ // The star icon should always come last.
+ if (starIconView_)
+ views.push_back(starIconView_);
+
+ // Load the visible views into |result|.
+ for (std::vector<LocationBarViewMac::LocationBarImageView*>::const_iterator
+ iter = views.begin(); iter != views.end(); ++iter) {
+ if ((*iter)->IsVisible()) {
+ scoped_nsobject<AutocompleteTextFieldIcon> icon(
+ [[AutocompleteTextFieldIcon alloc] initImageWithView:*iter]);
+ [result addObject:icon];
}
}
+
+ // Leave a boundary at RHS of field.
+ cellFrame.size.width -= kHintXOffset;
+
+ // Position each view within the frame from right to left.
+ for (AutocompleteTextFieldIcon* icon in [result reverseObjectEnumerator]) {
+ [icon positionInFrame:cellFrame];
+
+ // Trim the icon's space from the frame.
+ cellFrame.size.width = NSMinX([icon rect]) - kIconHorizontalPad;
+ }
return result;
}
-- (NSMenu*)actionMenuForEvent:(NSEvent*)event
- inRect:(NSRect)cellFrame
- ofView:(NSView*)aView {
- NSPoint location = [aView convertPoint:[event locationInWindow] fromView:nil];
+- (AutocompleteTextFieldIcon*)iconForEvent:(NSEvent*)theEvent
+ inRect:(NSRect)cellFrame
+ ofView:(AutocompleteTextField*)controlView {
+ const BOOL flipped = [controlView isFlipped];
+ const NSPoint location =
+ [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
+
+ // Special check for location image, it is not in |-layedOutIcons:|.
+ const NSRect locationIconFrame = [self locationIconFrameForFrame:cellFrame];
+ if (NSMouseInRect(location, locationIconFrame, flipped)) {
+ // Make up an icon to return.
+ AutocompleteTextFieldIcon* icon =
+ [[[AutocompleteTextFieldIcon alloc]
+ initImageWithView:locationIconView_] autorelease];
+ [icon setRect:locationIconFrame];
+ return icon;
+ }
- const BOOL flipped = [aView isFlipped];
for (AutocompleteTextFieldIcon* icon in [self layedOutIcons:cellFrame]) {
- if (NSMouseInRect(location, [icon rect], flipped)) {
- return [icon view]->GetMenu();
+ if (NSMouseInRect(location, [icon rect], flipped))
+ return icon;
+ }
+
+ return nil;
+}
+
+- (NSMenu*)actionMenuForEvent:(NSEvent*)theEvent
+ inRect:(NSRect)cellFrame
+ ofView:(AutocompleteTextField*)controlView {
+ AutocompleteTextFieldIcon*
+ icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
+ if (icon)
+ return [icon view]->GetMenu();
+ return nil;
+}
+
+- (BOOL)mouseDown:(NSEvent*)theEvent
+ inRect:(NSRect)cellFrame
+ ofView:(AutocompleteTextField*)controlView {
+ AutocompleteTextFieldIcon* icon =
+ [self iconForEvent:theEvent inRect:cellFrame ofView:controlView];
+ if (!icon)
+ return NO;
+
+ // If the icon is draggable, then initiate a drag if the user drags
+ // or holds the mouse down for awhile.
+ if ([icon view]->IsDraggable()) {
+ NSDate* timeout =
+ [NSDate dateWithTimeIntervalSinceNow:kLocationIconDragTimeout];
+ NSEvent* event = [NSApp nextEventMatchingMask:(NSLeftMouseDraggedMask |
+ NSLeftMouseUpMask)
+ untilDate:timeout
+ inMode:NSEventTrackingRunLoopMode
+ dequeue:YES];
+ if (!event || [event type] == NSLeftMouseDragged) {
+ NSPasteboard* pboard = [icon view]->GetDragPasteboard();
+ DCHECK(pboard);
+
+ // TODO(shess): My understanding is that the -isFlipped
+ // adjustment should not be necessary. But without it, the
+ // image is nowhere near the cursor. Perhaps the icon's rect is
+ // incorrectly calculated?
+ // http://crbug.com/40711
+ NSPoint dragPoint = [icon rect].origin;
+ if ([controlView isFlipped])
+ dragPoint.y += NSHeight([icon rect]);
+
+ [controlView dragImage:[icon view]->GetImage()
+ at:dragPoint
+ offset:NSZeroSize
+ event:event ? event : theEvent
+ pasteboard:pboard
+ source:self
+ slideBack:YES];
+ return YES;
}
+
+ // On mouse-up fall through to mouse-pressed case.
+ DCHECK_EQ([event type], NSLeftMouseUp);
}
+
+ [icon view]->OnMousePressed([icon rect]);
+ return YES;
+}
+
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
+ return NSDragOperationCopy;
+}
+
+- (NSPasteboard*)locationDragPasteboard {
+ if (locationIconView_ && locationIconView_->IsDraggable())
+ return locationIconView_->GetDragPasteboard();
+
return nil;
}
diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm
index 0a16c48..5bd02cc 100644
--- a/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm
+++ b/chrome/browser/cocoa/autocomplete_text_field_cell_unittest.mm
@@ -4,9 +4,11 @@
#import <Cocoa/Cocoa.h>
+#include "app/resource_bundle.h"
#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/autocomplete_text_field_cell.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "grit/theme_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -43,7 +45,7 @@ class TestPageActionViewList : public LocationBarViewMac::PageActionViewList {
class AutocompleteTextFieldCellTest : public CocoaTest {
public:
- AutocompleteTextFieldCellTest() : security_image_view_(NULL, NULL, NULL),
+ AutocompleteTextFieldCellTest() : location_icon_view_(NULL),
page_action_views_() {
// Make sure this is wide enough to play games with the cell
// decorations.
@@ -57,7 +59,8 @@ class AutocompleteTextFieldCellTest : public CocoaTest {
[[AutocompleteTextFieldCell alloc] initTextCell:@"Testing"]);
[cell setEditable:YES];
[cell setBordered:YES];
- [cell setSecurityImageView:&security_image_view_];
+ [cell setLocationIconView:&location_icon_view_];
+ [cell setSecurityLabelView:&security_label_view_];
[cell setPageActionViewList:&page_action_views_];
[view_ setCell:cell.get()];
@@ -65,7 +68,8 @@ class AutocompleteTextFieldCellTest : public CocoaTest {
}
NSTextField* view_;
- LocationBarViewMac::SecurityImageView security_image_view_;
+ LocationBarViewMac::LocationIconView location_icon_view_;
+ LocationBarViewMac::LocationBarImageView security_label_view_;
TestPageActionViewList page_action_views_;
};
@@ -199,15 +203,16 @@ TEST_F(AutocompleteTextFieldCellTest, TextFrame) {
EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame));
EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame));
- // Security icon takes up space on the right
- security_image_view_.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
- security_image_view_.SetVisible(true);
+ // Location icon takes up space on the left
+ location_icon_view_.SetImage(
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(
+ IDR_OMNIBOX_HTTPS_VALID));
+ location_icon_view_.SetVisible(true);
textFrame = [cell textFrameForFrame:bounds];
EXPECT_FALSE(NSIsEmptyRect(textFrame));
EXPECT_TRUE(NSContainsRect(bounds, textFrame));
- EXPECT_LT(NSMaxX(textFrame), NSMaxX(bounds));
+ EXPECT_GT(NSMinX(textFrame), NSMinX(bounds));
EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame));
// Search hint text takes precedence over the hint icon; the text frame
@@ -265,9 +270,10 @@ TEST_F(AutocompleteTextFieldCellTest, DrawingRectForBounds) {
EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect));
EXPECT_TRUE(NSEqualRects(drawingRect, originalDrawingRect));
- security_image_view_.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
- security_image_view_.SetVisible(true);
+ location_icon_view_.SetImage(
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(
+ IDR_OMNIBOX_HTTPS_VALID));
+ location_icon_view_.SetVisible(true);
textFrame = [cell textFrameForFrame:bounds];
drawingRect = [cell drawingRectForBounds:bounds];
@@ -275,55 +281,60 @@ TEST_F(AutocompleteTextFieldCellTest, DrawingRectForBounds) {
EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect));
}
-// Test that the security icon is at the right side of the cell.
-TEST_F(AutocompleteTextFieldCellTest, SecurityImageFrame) {
+// Test that the location icon is at the right side of the cell.
+TEST_F(AutocompleteTextFieldCellTest, LocationIconFrame) {
AutocompleteTextFieldCell* cell =
static_cast<AutocompleteTextFieldCell*>([view_ cell]);
const NSRect bounds([view_ bounds]);
- security_image_view_.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
-
- security_image_view_.SetVisible(false);
- EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]);
-
- security_image_view_.SetVisible(true);
- NSArray* icons = [cell layedOutIcons:bounds];
- ASSERT_EQ(1u, [icons count]);
- NSRect iconRect = [[icons objectAtIndex:0] rect];
+ location_icon_view_.SetImage(
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(
+ IDR_OMNIBOX_HTTPS_VALID));
+ location_icon_view_.SetVisible(true);
+ const NSRect iconRect = [cell locationIconFrameForFrame:bounds];
EXPECT_FALSE(NSIsEmptyRect(iconRect));
EXPECT_TRUE(NSContainsRect(bounds, iconRect));
- // Make sure we are right of the |drawingRect|.
- NSRect drawingRect = [cell drawingRectForBounds:bounds];
- EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect));
+ // Location icon should be left of |drawingRect|.
+ const NSRect drawingRect = [cell drawingRectForBounds:bounds];
+ EXPECT_GT(NSMinX(drawingRect), NSMinX(iconRect));
- // Make sure we're right of the |textFrame|.
- NSRect textFrame = [cell textFrameForFrame:bounds];
- EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect));
+ // Location icon should be left of |textFrame|.
+ const NSRect textFrame = [cell textFrameForFrame:bounds];
+ EXPECT_GT(NSMinX(textFrame), NSMinX(iconRect));
+}
+
+// Test that security label takes space to the right.
+TEST_F(AutocompleteTextFieldCellTest, SecurityLabelFrame) {
+ AutocompleteTextFieldCell* cell =
+ static_cast<AutocompleteTextFieldCell*>([view_ cell]);
+ const NSRect bounds([view_ bounds]);
+
+ // No label shows nothing, regardless of visibility setting.
+ security_label_view_.SetVisible(false);
+ const NSRect baseTextFrame = [cell textFrameForFrame:bounds];
+ security_label_view_.SetVisible(true);
+ EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds]));
- // Now add a label.
+ // Still not visible even with a label.
NSFont* font = [NSFont controlContentFontOfSize:12.0];
NSColor* color = [NSColor blackColor];
- security_image_view_.SetLabel(@"Label", font, color);
- icons = [cell layedOutIcons:bounds];
- ASSERT_EQ(1u, [icons count]);
- iconRect = [[icons objectAtIndex:0] rect];
+ security_label_view_.SetLabel(@"Label", font, color);
+ security_label_view_.SetVisible(false);
+ EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds]));
- EXPECT_FALSE(NSIsEmptyRect(iconRect));
- EXPECT_TRUE(NSContainsRect(bounds, iconRect));
-
- // Make sure we are right of the |drawingRect|.
- drawingRect = [cell drawingRectForBounds:bounds];
- EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect));
+ // Visible with a label is strictly narrower than without.
+ security_label_view_.SetVisible(true);
+ NSRect textFrame = [cell textFrameForFrame:bounds];
+ const CGFloat labelWidth = [security_label_view_.GetLabel() size].width;
+ EXPECT_TRUE(NSContainsRect(baseTextFrame, textFrame));
+ EXPECT_LT(NSWidth(textFrame), NSWidth(baseTextFrame) - labelWidth);
- // Make sure we're right of the |textFrame|.
+ NSString* longLabel =
+ @"Really super-long labels will not show up if there's not enough room.";
+ security_label_view_.SetLabel(longLabel, font, color);
textFrame = [cell textFrameForFrame:bounds];
- EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect));
-
- // Make sure we clear correctly.
- security_image_view_.SetVisible(false);
- EXPECT_EQ(0u, [[cell layedOutIcons:bounds] count]);
+ EXPECT_TRUE(NSEqualRects(baseTextFrame, [cell textFrameForFrame:bounds]));
}
// Test Page Action counts.
@@ -349,8 +360,6 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) {
AutocompleteTextFieldCell* cell =
static_cast<AutocompleteTextFieldCell*>([view_ cell]);
const NSRect bounds([view_ bounds]);
- security_image_view_.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
TestPageActionImageView page_action_view;
// We'll assume that the extensions code enforces icons smaller than the
@@ -368,13 +377,12 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) {
list.Add(&page_action_view2);
[cell setPageActionViewList:&list];
- security_image_view_.SetVisible(false);
page_action_view.SetVisible(false);
page_action_view2.SetVisible(false);
EXPECT_TRUE(NSIsEmptyRect([cell pageActionFrameForIndex:0 inFrame:bounds]));
EXPECT_TRUE(NSIsEmptyRect([cell pageActionFrameForIndex:1 inFrame:bounds]));
- // One page action, no security icon.
+ // One page action, no lock icon.
page_action_view.SetVisible(true);
NSRect iconRect0 = [cell pageActionFrameForIndex:0 inFrame:bounds];
@@ -389,17 +397,19 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) {
NSRect textFrame = [cell textFrameForFrame:bounds];
EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect0));
- // Two page actions plus a security icon.
+ // Two page actions plus a security label.
page_action_view2.SetVisible(true);
- security_image_view_.SetVisible(true);
NSArray* icons = [cell layedOutIcons:bounds];
- EXPECT_EQ(3u, [icons count]);
+ ASSERT_EQ(2u, [icons count]);
+
+ // TODO(shess): page-action list is inverted from -layedOutIcons:
+ // Yes, this is confusing, fix it.
iconRect0 = [cell pageActionFrameForIndex:0 inFrame:bounds];
NSRect iconRect1 = [cell pageActionFrameForIndex:1 inFrame:bounds];
- NSRect lockRect = [[icons objectAtIndex:0] rect];
+ NSRect labelRect = [[icons objectAtIndex:0] rect];
EXPECT_TRUE(NSEqualRects(iconRect0, [[icons objectAtIndex:1] rect]));
- EXPECT_TRUE(NSEqualRects(iconRect1, [[icons objectAtIndex:2] rect]));
+ EXPECT_TRUE(NSEqualRects(iconRect1, [[icons objectAtIndex:0] rect]));
// Make sure they're all in the expected order, and right of the |drawingRect|
// and |textFrame|.
@@ -410,13 +420,13 @@ TEST_F(AutocompleteTextFieldCellTest, PageActionImageFrame) {
EXPECT_TRUE(NSContainsRect(bounds, iconRect0));
EXPECT_FALSE(NSIsEmptyRect(iconRect1));
EXPECT_TRUE(NSContainsRect(bounds, iconRect1));
- EXPECT_FALSE(NSIsEmptyRect(lockRect));
- EXPECT_TRUE(NSContainsRect(bounds, lockRect));
+ EXPECT_FALSE(NSIsEmptyRect(labelRect));
+ EXPECT_TRUE(NSContainsRect(bounds, labelRect));
EXPECT_LE(NSMaxX(drawingRect), NSMinX(iconRect1));
EXPECT_LE(NSMaxX(textFrame), NSMinX(iconRect1));
EXPECT_LE(NSMaxX(iconRect1), NSMinX(iconRect0));
- EXPECT_LE(NSMaxX(iconRect0), NSMinX(lockRect));
+ EXPECT_LE(NSMaxX(labelRect), NSMinX(iconRect0));
}
// Test that the cell correctly chooses the partial keyword if there's
@@ -428,11 +438,22 @@ TEST_F(AutocompleteTextFieldCellTest, UsesPartialKeywordIfNarrow) {
const NSString* kFullString = @"Search Engine:";
const NSString* kPartialString = @"Search Eng:";
- // Wide width chooses the full string.
+ // Wide width chooses the full string, including an image on the
+ // left.
[cell setKeywordString:kFullString
partialString:kPartialString
availableWidth:kWidth];
EXPECT_TRUE([cell keywordString]);
+ EXPECT_TRUE([[[cell keywordString] string] hasSuffix:kFullString]);
+ EXPECT_TRUE([[cell keywordString] containsAttachments]);
+
+ // If not enough space to include the image, uses exactly the full
+ // string.
+ CGFloat allWidth = [[cell keywordString] size].width;
+ [cell setKeywordString:kFullString
+ partialString:kPartialString
+ availableWidth:allWidth - 5.0];
+ EXPECT_TRUE([cell keywordString]);
EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kFullString]);
// Narrow width chooses the partial string.
diff --git a/chrome/browser/cocoa/autocomplete_text_field_editor.mm b/chrome/browser/cocoa/autocomplete_text_field_editor.mm
index 70aa5cd..974b346 100644
--- a/chrome/browser/cocoa/autocomplete_text_field_editor.mm
+++ b/chrome/browser/cocoa/autocomplete_text_field_editor.mm
@@ -33,6 +33,35 @@ class Extension;
return self;
}
+// If the entire field is selected, drag the same data as would be
+// dragged from the field's location icon. In some cases the textual
+// contents will not contain relevant data (for instance, "http://" is
+// stripped from URLs).
+- (BOOL)dragSelectionWithEvent:(NSEvent *)event
+ offset:(NSSize)mouseOffset
+ slideBack:(BOOL)slideBack {
+ const NSRange allRange = NSMakeRange(0, [[self textStorage] length]);
+ if (NSEqualRanges(allRange, [self selectedRange])) {
+ NSPasteboard* pboard = [[self delegate] locationDragPasteboard];
+ if (pboard) {
+ NSPoint p;
+ NSImage* image = [self dragImageForSelectionWithEvent:event origin:&p];
+
+ [self dragImage:image
+ at:p
+ offset:mouseOffset
+ event:event
+ pasteboard:pboard
+ source:self
+ slideBack:slideBack];
+ return YES;
+ }
+ }
+ return [super dragSelectionWithEvent:event
+ offset:mouseOffset
+ slideBack:slideBack];
+}
+
- (void)copy:(id)sender {
AutocompleteTextFieldObserver* observer = [self observer];
DCHECK(observer);
diff --git a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm
index d695f86..1d0ae49 100644
--- a/chrome/browser/cocoa/autocomplete_text_field_unittest.mm
+++ b/chrome/browser/cocoa/autocomplete_text_field_unittest.mm
@@ -4,6 +4,7 @@
#import <Cocoa/Cocoa.h>
+#include "app/resource_bundle.h"
#import "base/cocoa_protocols_mac.h"
#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/autocomplete_text_field.h"
@@ -11,6 +12,7 @@
#import "chrome/browser/cocoa/autocomplete_text_field_editor.h"
#import "chrome/browser/cocoa/autocomplete_text_field_unittest_helper.h"
#import "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "grit/theme_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -20,18 +22,34 @@ using ::testing::Return;
using ::testing::StrictMock;
namespace {
-class MockSecurityImageView : public LocationBarViewMac::SecurityImageView {
+class MockLocationIconView : public LocationBarViewMac::LocationIconView {
public:
- MockSecurityImageView(LocationBarViewMac* owner,
- Profile* profile,
- ToolbarModel* model)
- : LocationBarViewMac::SecurityImageView(owner, profile, model) {}
+ MockLocationIconView()
+ : LocationBarViewMac::LocationIconView(NULL),
+ is_draggable_(false),
+ mouse_was_pressed_(false) {}
+
+ // |LocationBarViewMac::LocationIconView| dragging support needs
+ // more setup than this test provides.
+ bool IsDraggable() {
+ return is_draggable_;
+ }
+ virtual NSPasteboard* GetDragPasteboard() {
+ return [NSPasteboard pasteboardWithUniqueName];
+ }
+ void SetDraggable(bool is_draggable) {
+ is_draggable_ = is_draggable;
+ }
// We can't use gmock's MOCK_METHOD macro, because it doesn't like the
// NSRect argument to OnMousePressed.
virtual void OnMousePressed(NSRect bounds) {
mouse_was_pressed_ = true;
}
+ bool MouseWasPressed() { return mouse_was_pressed_; }
+
+ private:
+ bool is_draggable_;
bool mouse_was_pressed_;
};
@@ -582,32 +600,35 @@ TEST_F(AutocompleteTextFieldTest, TripleClickSelectsAll) {
}
// Clicking the security icon should call its OnMousePressed.
-TEST_F(AutocompleteTextFieldObserverTest, SecurityIconMouseDown) {
+TEST_F(AutocompleteTextFieldTest, LocationIconMouseDown) {
AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
- MockSecurityImageView security_image_view(NULL, NULL, NULL);
- [cell setSecurityImageView:&security_image_view];
- security_image_view.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
- security_image_view.SetVisible(true);
+ MockLocationIconView location_icon_view;
+ [cell setLocationIconView:&location_icon_view];
+ location_icon_view.SetImage(
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(
+ IDR_OMNIBOX_HTTPS_VALID));
+ location_icon_view.SetVisible(true);
- NSRect iconFrame([cell securityImageFrameForFrame:[field_ bounds]]);
+ NSRect iconFrame([cell locationIconFrameForFrame:[field_ bounds]]);
NSPoint location(NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame)));
- NSEvent* event(Event(field_, location, NSLeftMouseDown, 1));
+ NSEvent* downEvent(Event(field_, location, NSLeftMouseDown, 1));
+ NSEvent* upEvent(Event(field_, location, NSLeftMouseUp, 1));
- [field_ mouseDown:event];
- EXPECT_TRUE(security_image_view.mouse_was_pressed_);
+ // Since location icon can be dragged, the mouse-press is sent on
+ // mouse-up.
+ [NSApp postEvent:upEvent atStart:YES];
+ [field_ mouseDown:downEvent];
+ EXPECT_TRUE(location_icon_view.MouseWasPressed());
+
+ // TODO(shess): Test that mouse drags are initiated if the next
+ // event is a drag, or if the mouse-up takes too long to arrive.
}
// Clicking a Page Action icon should call its OnMousePressed.
-TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) {
+TEST_F(AutocompleteTextFieldTest, PageActionMouseDown) {
AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
- MockSecurityImageView security_image_view(NULL, NULL, NULL);
- security_image_view.SetImageShown(
- LocationBarViewMac::SecurityImageView::LOCK);
- [cell setSecurityImageView:&security_image_view];
-
MockPageActionImageView page_action_view;
NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"];
page_action_view.SetImage(image);
@@ -620,8 +641,7 @@ TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) {
list.Add(&page_action_view2);
[cell setPageActionViewList:&list];
- // One page action, no security lock.
- security_image_view.SetVisible(false);
+ // One page action.
page_action_view.SetVisible(true);
page_action_view2.SetVisible(false);
NSRect iconFrame([cell pageActionFrameForIndex:0 inFrame:[field_ bounds]]);
@@ -631,7 +651,7 @@ TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) {
[field_ mouseDown:event];
EXPECT_TRUE(page_action_view.MouseWasPressed());
- // Two page actions, no security lock.
+ // Two page actions, no lock.
page_action_view2.SetVisible(true);
iconFrame = [cell pageActionFrameForIndex:0 inFrame:[field_ bounds]];
location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame));
@@ -647,8 +667,7 @@ TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) {
[field_ mouseDown:event];
EXPECT_TRUE(page_action_view.MouseWasPressed());
- // Two page actions plus security lock.
- security_image_view.SetVisible(true);
+ // Two page actions.
iconFrame = [cell pageActionFrameForIndex:0 inFrame:[field_ bounds]];
location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame));
event = Event(field_, location, NSLeftMouseDown, 1);
@@ -662,13 +681,6 @@ TEST_F(AutocompleteTextFieldObserverTest, PageActionMouseDown) {
[field_ mouseDown:event];
EXPECT_TRUE(page_action_view.MouseWasPressed());
-
- iconFrame = [cell securityImageFrameForFrame:[field_ bounds]];
- location = NSMakePoint(NSMidX(iconFrame), NSMidY(iconFrame));
- event = Event(field_, location, NSLeftMouseDown, 1);
-
- [field_ mouseDown:event];
- EXPECT_TRUE(security_image_view.mouse_was_pressed_);
}
// Test that page action menus are properly returned.
@@ -860,4 +872,22 @@ TEST_F(AutocompleteTextFieldObserverTest, SendsOnResignKey) {
[test_window() resignKeyWindow];
}
+TEST_F(AutocompleteTextFieldTest, LocationDragPasteboard) {
+ AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
+
+ MockLocationIconView location_icon_view;
+ location_icon_view.SetImage(
+ ResourceBundle::GetSharedInstance().GetNSImageNamed(
+ IDR_OMNIBOX_HTTPS_VALID));
+ location_icon_view.SetVisible(true);
+ [cell setLocationIconView:&location_icon_view];
+
+ // Not draggable, so no pasteboard.
+ EXPECT_FALSE([field_ locationDragPasteboard]);
+
+ // Gets a pasteboard when draggable.
+ location_icon_view.SetDraggable(true);
+ EXPECT_TRUE([field_ locationDragPasteboard]);
+}
+
} // namespace
diff --git a/chrome/browser/cocoa/bookmark_bubble_controller.mm b/chrome/browser/cocoa/bookmark_bubble_controller.mm
index fc2ff7b..465691e 100644
--- a/chrome/browser/cocoa/bookmark_bubble_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bubble_controller.mm
@@ -98,7 +98,7 @@
[BrowserWindowController browserWindowControllerForWindow:parentWindow_];
[bwc lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
NSWindow* window = [self window]; // completes nib load
- [bubble_ setArrowLocation:kTopLeft];
+ [bubble_ setArrowLocation:kTopRight];
// Insure decent positioning even in the absence of a browser controller,
// which will occur for some unit tests.
NSPoint arrowtip = bwc ? [bwc pointForBubbleArrowTip] :
diff --git a/chrome/browser/cocoa/browser_test_helper.h b/chrome/browser/cocoa/browser_test_helper.h
index 0420c7a..b7e3e64 100644
--- a/chrome/browser/cocoa/browser_test_helper.h
+++ b/chrome/browser/cocoa/browser_test_helper.h
@@ -25,6 +25,15 @@ class BrowserTestHelper {
profile_.reset(new TestingProfile());
profile_->CreateBookmarkModel(true);
profile_->BlockUntilBookmarkModelLoaded();
+
+ // TODO(shess): These are needed in case someone creates a browser
+ // window off of browser_. pkasting indicates that other
+ // platforms use a stub |BrowserWindow| and thus don't need to do
+ // this.
+ // http://crbug.com/39725
+ profile_->CreateAutocompleteClassifier();
+ profile_->CreateTemplateURLModel();
+
browser_.reset(new Browser(Browser::TYPE_NORMAL, profile_.get()));
}
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index f482990..d023663 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -1375,7 +1375,7 @@
}
- (NSPoint)pointForBubbleArrowTip {
- NSRect rect = [toolbarController_ starButtonInWindowCoordinates];
+ NSRect rect = [toolbarController_ starIconInWindowCoordinates];
// Determine the point of the arrow of the bubble window.
NSPoint p = rect.origin;
p.x += (NSWidth(rect) / 2.0) + 1.0; // Star is not exactly in center.
diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm
index 5b054fa..d6a3dca 100644
--- a/chrome/browser/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm
@@ -437,10 +437,10 @@ TEST_F(BrowserWindowControllerTest, TestTopRightForBubble) {
NSPoint p = [controller_ pointForBubbleArrowTip];
NSRect all = [[controller_ window] frame];
- // As a sanity check make sure the point is vaguely in the top left
+ // As a sanity check make sure the point is vaguely in the top right
// of the window.
EXPECT_GT(p.y, all.origin.y + (all.size.height/2));
- EXPECT_LT(p.x, all.origin.x + (all.size.width/2));
+ EXPECT_GT(p.x, all.origin.x + (all.size.width/2));
}
// By the "zoom frame", we mean what Apple calls the "standard frame".
diff --git a/chrome/browser/cocoa/location_bar_view_mac.h b/chrome/browser/cocoa/location_bar_view_mac.h
index 5a82d67..08e1524 100644
--- a/chrome/browser/cocoa/location_bar_view_mac.h
+++ b/chrome/browser/cocoa/location_bar_view_mac.h
@@ -24,7 +24,6 @@
#include "third_party/skia/include/core/SkBitmap.h"
@class AutocompleteTextField;
-class BubblePositioner;
class CommandUpdater;
class ContentSettingImageModel;
@class ExtensionPopupController;
@@ -41,7 +40,6 @@ class LocationBarViewMac : public AutocompleteEditController,
public NotificationObserver {
public:
LocationBarViewMac(AutocompleteTextField* field,
- const BubblePositioner* bubble_positioner,
CommandUpdater* command_updater,
ToolbarModel* toolbar_model,
Profile* profile,
@@ -64,6 +62,9 @@ class LocationBarViewMac : public AutocompleteEditController,
virtual void InvalidatePageActions();
virtual void SaveStateToContents(TabContents* contents);
virtual void Revert();
+ virtual const AutocompleteEditView* location_entry() const {
+ return edit_view_.get();
+ }
virtual AutocompleteEditView* location_entry() {
return edit_view_.get();
}
@@ -76,6 +77,13 @@ class LocationBarViewMac : public AutocompleteEditController,
virtual ExtensionAction* GetVisiblePageAction(size_t index);
virtual void TestPageActionPressed(size_t index);
+ // Set/Get the editable state of the field.
+ void SetEditable(bool editable);
+ bool IsEditable();
+
+ // Set the starred state of the bookmark star.
+ void SetStarred(bool starred);
+
// Updates the location bar. Resets the bar's permanent text and
// security style, and if |should_restore_state| is true, restores
// saved state from the tab (for tab switching).
@@ -124,7 +132,6 @@ class LocationBarViewMac : public AutocompleteEditController,
const std::wstring& keyword,
const std::wstring& short_name,
const bool is_keyword_hint,
- const bool show_search_hint,
NSImage* image);
// Overridden from NotificationObserver.
@@ -142,7 +149,9 @@ class LocationBarViewMac : public AutocompleteEditController,
// Sets the image.
void SetImage(NSImage* image);
- void SetImage(SkBitmap* image);
+
+ // Get the |resource_id| image resource and set the image.
+ void SetIcon(int resource_id);
// Sets the label text, font, and color. |text| may be nil; |color| and
// |font| are ignored if |text| is nil.
@@ -156,9 +165,21 @@ class LocationBarViewMac : public AutocompleteEditController,
const NSAttributedString* GetLabel() const { return label_; }
bool IsVisible() const { return visible_; }
+ // Default size when no image is present.
+ virtual NSSize GetDefaultImageSize() const;
+
+ // Returns the size of the image, else the default size.
+ NSSize GetImageSize() const;
+
// Returns the tooltip for this image view or |nil| if there is none.
virtual const NSString* GetToolTip() { return nil; }
+ // Used to determinate if the item can act as a drag source.
+ virtual bool IsDraggable() { return false; }
+
+ // The drag pasteboard to use if a drag is initiated.
+ virtual NSPasteboard* GetDragPasteboard() { return nil; }
+
// Called on mouse down.
virtual void OnMousePressed(NSRect bounds) {}
@@ -176,42 +197,50 @@ class LocationBarViewMac : public AutocompleteEditController,
DISALLOW_COPY_AND_ASSIGN(LocationBarImageView);
};
- // SecurityImageView is used to display the lock or warning icon when the
- // current URL's scheme is https.
- class SecurityImageView : public LocationBarImageView {
+ // LocationIconView is used to display an icon to the left of the address.
+ class LocationIconView : public LocationBarImageView {
public:
- enum Image {
- LOCK = 0,
- WARNING
- };
+ explicit LocationIconView(LocationBarViewMac* owner);
+ virtual ~LocationIconView();
- SecurityImageView(LocationBarViewMac* owner,
- Profile* profile,
- ToolbarModel* model);
- virtual ~SecurityImageView();
+ // Is draggable if the autocomplete edit view has not be changed.
+ virtual bool IsDraggable();
- // Sets the image to the appropriate icon.
- void SetImageShown(Image image);
+ // Drag the URL and title from the current tab.
+ virtual NSPasteboard* GetDragPasteboard();
// Shows the page info dialog.
virtual void OnMousePressed(NSRect bounds);
private:
- // The lock icon shown when using HTTPS. Loaded lazily, the first time it's
- // needed.
- scoped_nsobject<NSImage> lock_icon_;
-
- // The warning icon shown when HTTPS is broken. Loaded lazily, the first
- // time it's needed.
- scoped_nsobject<NSImage> warning_icon_;
-
// The location bar view that owns us.
LocationBarViewMac* owner_;
- Profile* profile_;
- ToolbarModel* model_;
+ DISALLOW_COPY_AND_ASSIGN(LocationIconView);
+ };
- DISALLOW_COPY_AND_ASSIGN(SecurityImageView);
+ // Used to display the bookmark star in the RHS.
+ class StarIconView : public LocationBarImageView {
+ public:
+ explicit StarIconView(CommandUpdater* command_updater);
+ virtual ~StarIconView() {}
+
+ // Shows the bookmark bubble.
+ virtual void OnMousePressed(NSRect bounds);
+
+ // Set the image and tooltip based on |starred|.
+ void SetStarred(bool starred);
+
+ virtual const NSString* GetToolTip();
+
+ private:
+ // For bringing up bookmark bar.
+ CommandUpdater* command_updater_; // Weak, owned by Browser.
+
+ // The string to show for a tooltip.
+ scoped_nsobject<NSString> tooltip_;
+
+ DISALLOW_COPY_AND_ASSIGN(StarIconView);
};
// PageActionImageView is used to display the icon for a given Page Action
@@ -231,14 +260,13 @@ class LocationBarViewMac : public AutocompleteEditController,
void set_preview_enabled(bool enabled) { preview_enabled_ = enabled; }
- bool preview_enabled() { return preview_enabled_; }
+ bool preview_enabled() const { return preview_enabled_; }
- // Returns the size of the image, or a default size if no image available.
// When a new page action is created, all the icons are destroyed and
// recreated; at this point we need to calculate sizes to lay out the
// icons even though no images are available yet. For this case, we return
// the default image size for a page icon.
- virtual NSSize GetPreferredImageSize();
+ virtual NSSize GetDefaultImageSize() const;
// Either notify listeners or show a popup depending on the Page Action.
virtual void OnMousePressed(NSRect bounds);
@@ -384,11 +412,11 @@ class LocationBarViewMac : public AutocompleteEditController,
};
private:
- // Sets the SSL icon we should be showing.
- void SetSecurityIcon(ToolbarModel::Icon icon);
+ // Sets the location icon we should be showing.
+ void SetIcon(int resource_id);
- // Sets the label for the SSL icon.
- void SetSecurityIconLabel();
+ // Sets the label for the SSL state.
+ void SetSecurityLabel();
// Posts |notification| to the default notification center.
void PostNotification(const NSString* notification);
@@ -411,8 +439,14 @@ class LocationBarViewMac : public AutocompleteEditController,
// The user's desired disposition for how their input should be opened.
WindowOpenDisposition disposition_;
- // The view that shows the lock/warning when in HTTPS mode.
- SecurityImageView security_image_view_;
+ // A view that shows an icon to the left of the address.
+ LocationIconView location_icon_view_;
+
+ // Security info as text which floats left of the page actions.
+ LocationBarImageView security_label_view_;
+
+ // Bookmark star right of page actions.
+ StarIconView star_icon_view_;
// Any installed Page Actions.
PageActionViewList page_action_views_;
diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm
index dde3095..35751dc 100644
--- a/chrome/browser/cocoa/location_bar_view_mac.mm
+++ b/chrome/browser/cocoa/location_bar_view_mac.mm
@@ -41,6 +41,7 @@
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "skia/ext/skia_utils_mac.h"
+#import "third_party/mozilla/NSPasteboard+Utils.h"
// TODO(shess): This code is mostly copied from the gtk
@@ -62,11 +63,13 @@ std::wstring GetKeywordName(Profile* profile, const std::wstring& keyword) {
return std::wstring();
}
-// Values for the green text color displayed for EV certificates, based
-// on the values for kEvTextColor in location_bar_view_gtk.cc.
-static const CGFloat kEvTextColorRedComponent = 0.0;
-static const CGFloat kEvTextColorGreenComponent = 0.59;
-static const CGFloat kEvTextColorBlueComponent = 0.08;
+// Values for the label colors for different security states.
+static const CGFloat kEVSecureTextColorRedComponent = 0.03;
+static const CGFloat kEVSecureTextColorGreenComponent = 0.58;
+static const CGFloat kEVSecureTextColorBlueComponent = 0.0;
+static const CGFloat kSecurityErrorTextColorRedComponent = 0.63;
+static const CGFloat kSecurityErrorTextColorGreenComponent = 0.0;
+static const CGFloat kSecurityErrorTextColorBlueComponent = 0.0;
// Build a short string to use in keyword-search when the field isn't
// very big.
@@ -91,17 +94,18 @@ std::wstring CalculateMinString(const std::wstring& description) {
LocationBarViewMac::LocationBarViewMac(
AutocompleteTextField* field,
- const BubblePositioner* bubble_positioner,
CommandUpdater* command_updater,
ToolbarModel* toolbar_model,
Profile* profile,
Browser* browser)
- : edit_view_(new AutocompleteEditViewMac(this, bubble_positioner,
- toolbar_model, profile, command_updater, field)),
+ : edit_view_(new AutocompleteEditViewMac(this, toolbar_model, profile,
+ command_updater, field)),
command_updater_(command_updater),
field_(field),
disposition_(CURRENT_TAB),
- security_image_view_(this, profile, toolbar_model),
+ location_icon_view_(this),
+ security_label_view_(),
+ star_icon_view_(command_updater),
page_action_views_(this, profile, toolbar_model),
profile_(profile),
browser_(browser),
@@ -116,7 +120,9 @@ LocationBarViewMac::LocationBarViewMac(
}
AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
- [cell setSecurityImageView:&security_image_view_];
+ [cell setLocationIconView:&location_icon_view_];
+ [cell setSecurityLabelView:&security_label_view_];
+ [cell setStarIconView:&star_icon_view_];
[cell setPageActionViewList:&page_action_views_];
[cell setContentSettingViewsList:&content_setting_views_];
@@ -129,7 +135,9 @@ LocationBarViewMac::~LocationBarViewMac() {
// Disconnect from cell in case it outlives us.
AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
[cell setPageActionViewList:NULL];
- [cell setSecurityImageView:NULL];
+ [cell setLocationIconView:NULL];
+ [cell setSecurityLabelView:NULL];
+ [cell setStarIconView:NULL];
}
std::wstring LocationBarViewMac::GetInputString() const {
@@ -206,7 +214,7 @@ void LocationBarViewMac::SaveStateToContents(TabContents* contents) {
void LocationBarViewMac::Update(const TabContents* contents,
bool should_restore_state) {
- SetSecurityIcon(toolbar_model_->GetIcon());
+ SetIcon(edit_view_->GetIcon());
page_action_views_.RefreshViews();
RefreshContentSettingsViews();
// AutocompleteEditView restores state if the tab is non-NULL.
@@ -252,7 +260,6 @@ void LocationBarViewMac::OnChangedImpl(AutocompleteTextField* field,
const std::wstring& keyword,
const std::wstring& short_name,
const bool is_keyword_hint,
- const bool show_search_hint,
NSImage* image) {
AutocompleteTextFieldCell* cell = [field autocompleteTextFieldCell];
const CGFloat availableWidth([field availableDecorationWidth]);
@@ -298,12 +305,6 @@ void LocationBarViewMac::OnChangedImpl(AutocompleteTextField* field,
[cell setKeywordHintPrefix:prefix image:image suffix:suffix
availableWidth:availableWidth];
- } else if (show_search_hint) {
- // Show a search hint right-justified in the field if there is no
- // keyword.
- const std::wstring hint(l10n_util::GetString(IDS_OMNIBOX_EMPTY_TEXT));
- [cell setSearchHintString:base::SysWideToNSString(hint)
- availableWidth:availableWidth];
} else {
// Nothing interesting to show, plain old text field.
[cell clearKeywordAndHint];
@@ -330,7 +331,6 @@ void LocationBarViewMac::OnChanged() {
keyword,
short_name,
edit_view_->model()->is_keyword_hint(),
- edit_view_->model()->show_search_hint(),
GetTabButtonImage());
}
@@ -444,6 +444,22 @@ void LocationBarViewMac::TestPageActionPressed(size_t index) {
page_action_views_.OnMousePressed(NSZeroRect, index);
}
+void LocationBarViewMac::SetEditable(bool editable) {
+ [field_ setEditable:editable ? YES : NO];
+ star_icon_view_.SetVisible(editable);
+ UpdatePageActions();
+}
+
+bool LocationBarViewMac::IsEditable() {
+ return [field_ isEditable] ? true : false;
+}
+
+void LocationBarViewMac::SetStarred(bool starred) {
+ star_icon_view_.SetStarred(starred);
+ [field_ updateCursorAndToolTipRects];
+ [field_ resetFieldEditorFrameIfNeeded];
+}
+
NSImage* LocationBarViewMac::GetTabButtonImage() {
if (!tab_button_image_) {
SkBitmap* skiaBitmap = ResourceBundle::GetSharedInstance().
@@ -455,44 +471,37 @@ NSImage* LocationBarViewMac::GetTabButtonImage() {
return tab_button_image_;
}
-void LocationBarViewMac::SetSecurityIconLabel() {
- std::wstring info_text;
- std::wstring info_tooltip;
- ToolbarModel::InfoTextType info_text_type =
- toolbar_model_->GetInfoText(&info_text, &info_tooltip);
- if (info_text_type == ToolbarModel::INFO_EV_TEXT) {
- NSString* icon_label = base::SysWideToNSString(info_text);
- NSColor* color = [NSColor colorWithCalibratedRed:kEvTextColorRedComponent
- green:kEvTextColorGreenComponent
- blue:kEvTextColorBlueComponent
- alpha:1.0];
- security_image_view_.SetLabel(icon_label, [field_ font], color);
+void LocationBarViewMac::SetIcon(int resource_id) {
+ DCHECK(resource_id != 0);
+
+ // The icon is always visible except when there is a keyword hint.
+ if (!edit_view_->model()->keyword().empty() &&
+ !edit_view_->model()->is_keyword_hint()) {
+ location_icon_view_.SetVisible(false);
} else {
- security_image_view_.SetLabel(nil, nil, nil);
+ NSImage* image = AutocompleteEditViewMac::ImageForResource(resource_id);
+ location_icon_view_.SetImage(image);
+ location_icon_view_.SetVisible(true);
+ SetSecurityLabel();
}
+ [field_ resetFieldEditorFrameIfNeeded];
}
-void LocationBarViewMac::SetSecurityIcon(ToolbarModel::Icon icon) {
- switch (icon) {
- case ToolbarModel::LOCK_ICON:
- security_image_view_.SetImageShown(SecurityImageView::LOCK);
- security_image_view_.SetVisible(true);
- SetSecurityIconLabel();
- break;
- case ToolbarModel::WARNING_ICON:
- security_image_view_.SetImageShown(SecurityImageView::WARNING);
- security_image_view_.SetVisible(true);
- SetSecurityIconLabel();
- break;
- case ToolbarModel::NO_ICON:
- security_image_view_.SetVisible(false);
- break;
- default:
- NOTREACHED();
- security_image_view_.SetVisible(false);
- break;
+void LocationBarViewMac::SetSecurityLabel() {
+ if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
+ std::wstring security_info_text(toolbar_model_->GetEVCertName());
+ NSString* icon_label = base::SysWideToNSString(security_info_text);
+ NSColor* color =
+ [NSColor colorWithCalibratedRed:kEVSecureTextColorRedComponent
+ green:kEVSecureTextColorGreenComponent
+ blue:kEVSecureTextColorBlueComponent
+ alpha:1.0];
+ security_label_view_.SetLabel(icon_label, [field_ font], color);
+ security_label_view_.SetVisible(true);
+ } else {
+ security_label_view_.SetLabel(nil, nil, nil);
+ security_label_view_.SetVisible(false);
}
- [field_ resetFieldEditorFrameIfNeeded];
}
void LocationBarViewMac::Observe(NotificationType type,
@@ -535,8 +544,9 @@ void LocationBarViewMac::LocationBarImageView::SetImage(NSImage* image) {
image_.reset([image retain]);
}
-void LocationBarViewMac::LocationBarImageView::SetImage(SkBitmap* image) {
- SetImage(gfx::SkBitmapToNSImage(*image));
+void LocationBarViewMac::LocationBarImageView::SetIcon(int resource_id) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ SetImage(rb.GetNSImageNamed(resource_id));
}
void LocationBarViewMac::LocationBarImageView::SetLabel(NSString* text,
@@ -564,43 +574,32 @@ void LocationBarViewMac::LocationBarImageView::SetVisible(bool visible) {
visible_ = visible;
}
-// SecurityImageView------------------------------------------------------------
+NSSize LocationBarViewMac::LocationBarImageView::GetDefaultImageSize() const {
+ return NSZeroSize;
+}
-LocationBarViewMac::SecurityImageView::SecurityImageView(
- LocationBarViewMac* owner,
- Profile* profile,
- ToolbarModel* model)
- : lock_icon_(nil),
- warning_icon_(nil),
- owner_(owner),
- profile_(profile),
- model_(model) {}
+NSSize LocationBarViewMac::LocationBarImageView::GetImageSize() const {
+ NSImage* image = GetImage();
+ if (image)
+ return [image size];
+ return GetDefaultImageSize();
+}
-LocationBarViewMac::SecurityImageView::~SecurityImageView() {}
+// LocationIconView ------------------------------------------------------------
-void LocationBarViewMac::SecurityImageView::SetImageShown(Image image) {
- switch (image) {
- case LOCK:
- if (!lock_icon_.get()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- lock_icon_.reset([rb.GetNSImageNamed(IDR_LOCK) retain]);
- }
- SetImage(lock_icon_);
- break;
- case WARNING:
- if (!warning_icon_.get()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- warning_icon_.reset([rb.GetNSImageNamed(IDR_WARNING) retain]);
- }
- SetImage(warning_icon_);
- break;
- default:
- NOTREACHED();
- break;
- }
+LocationBarViewMac::LocationIconView::LocationIconView(
+ LocationBarViewMac* owner)
+ : owner_(owner) {
}
-void LocationBarViewMac::SecurityImageView::OnMousePressed(NSRect bounds) {
+LocationBarViewMac::LocationIconView::~LocationIconView() {}
+
+void LocationBarViewMac::LocationIconView::OnMousePressed(NSRect bounds) {
+ // Do not show page info if the user has been editing the location
+ // bar, or the location bar is at the NTP.
+ if (owner_->location_entry()->IsEditingOrEmpty())
+ return;
+
TabContents* tab = owner_->GetTabContents();
NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
if (!nav_entry) {
@@ -610,6 +609,57 @@ void LocationBarViewMac::SecurityImageView::OnMousePressed(NSRect bounds) {
tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
}
+bool LocationBarViewMac::LocationIconView::IsDraggable() {
+ // Do not drag if the user has been editing the location bar, or the
+ // location bar is at the NTP.
+ if (owner_->location_entry()->IsEditingOrEmpty())
+ return false;
+
+ return true;
+}
+
+NSPasteboard* LocationBarViewMac::LocationIconView::GetDragPasteboard() {
+ TabContents* tab = owner_->GetTabContents();
+ DCHECK(tab);
+
+ NSString* url = base::SysUTF8ToNSString(tab->GetURL().spec());
+ NSString* title = base::SysUTF16ToNSString(tab->GetTitle());
+
+ NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ [pboard declareURLPasteboardWithAdditionalTypes:[NSArray array]
+ owner:nil];
+ [pboard setDataForURL:url title:title];
+ return pboard;
+}
+
+// StarIconView-----------------------------------------------------------------
+
+LocationBarViewMac::StarIconView::StarIconView(CommandUpdater* command_updater)
+ : command_updater_(command_updater) {
+ SetVisible(true);
+ SetStarred(false);
+}
+
+void LocationBarViewMac::StarIconView::SetStarred(bool starred) {
+ if (starred) {
+ SetImage(AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_STAR_LIT));
+ tooltip_.reset(
+ [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STARRED) retain]);
+ } else {
+ SetImage(AutocompleteEditViewMac::ImageForResource(IDR_OMNIBOX_STAR));
+ tooltip_.reset(
+ [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STAR) retain]);
+ }
+}
+
+void LocationBarViewMac::StarIconView::OnMousePressed(NSRect bounds) {
+ command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE);
+}
+
+const NSString* LocationBarViewMac::StarIconView::GetToolTip() {
+ return tooltip_.get();
+}
+
// PageActionImageView----------------------------------------------------------
LocationBarViewMac::PageActionImageView::PageActionImageView(
@@ -647,14 +697,9 @@ LocationBarViewMac::PageActionImageView::PageActionImageView(
LocationBarViewMac::PageActionImageView::~PageActionImageView() {
}
-NSSize LocationBarViewMac::PageActionImageView::GetPreferredImageSize() {
- NSImage* image = GetImage();
- if (image) {
- return [image size];
- } else {
- return NSMakeSize(Extension::kPageActionIconMaxSize,
- Extension::kPageActionIconMaxSize);
- }
+NSSize LocationBarViewMac::PageActionImageView::GetDefaultImageSize() const {
+ return NSMakeSize(Extension::kPageActionIconMaxSize,
+ Extension::kPageActionIconMaxSize);
}
// Overridden from LocationBarImageView. Either notify listeners or show a
@@ -868,10 +913,9 @@ void LocationBarViewMac::ContentSettingImageView::UpdateFromTabContents(
const TabContents* tab_contents) {
content_setting_image_model_->UpdateFromTabContents(tab_contents);
if (content_setting_image_model_->is_visible()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
// TODO(thakis): We should use pdfs for these icons on OSX.
// http://crbug.com/35847
- SetImage(rb.GetNSImageNamed(content_setting_image_model_->get_icon()));
+ SetIcon(content_setting_image_model_->get_icon());
SetToolTip(base::SysUTF8ToNSString(
content_setting_image_model_->get_tooltip()));
SetVisible(true);
@@ -895,6 +939,11 @@ void LocationBarViewMac::PageActionViewList::DeleteAll() {
}
void LocationBarViewMac::PageActionViewList::RefreshViews() {
+ if (!owner_->IsEditable()) {
+ DeleteAll();
+ return;
+ }
+
std::vector<ExtensionAction*> page_actions;
ExtensionsService* service = profile_->GetExtensionsService();
if (!service)
diff --git a/chrome/browser/cocoa/location_bar_view_mac_unittest.mm b/chrome/browser/cocoa/location_bar_view_mac_unittest.mm
index aec948d..ecb2a7b 100644
--- a/chrome/browser/cocoa/location_bar_view_mac_unittest.mm
+++ b/chrome/browser/cocoa/location_bar_view_mac_unittest.mm
@@ -81,7 +81,6 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) {
NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"];
const std::wstring kKeyword(L"Google");
- const NSString* kSearchHint = @"Type to search";
const NSString* kKeywordPrefix = @"Press ";
const NSString* kKeywordSuffix = @" to search Google";
const NSString* kKeywordString = @"Search Google:";
@@ -90,39 +89,20 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) {
[NSString stringWithFormat:@"Search Go%C:", 0x2026];
// With no special hints requested, none set.
- LocationBarViewMac::OnChangedImpl(
- field_, std::wstring(), std::wstring(), false, false, image);
+ LocationBarViewMac::OnChangedImpl(field_, std::wstring(), std::wstring(), false, image);
EXPECT_FALSE([cell keywordString]);
EXPECT_FALSE([cell hintString]);
- // Request only a search hint.
- LocationBarViewMac::OnChangedImpl(
- field_, std::wstring(), std::wstring(), false, true, image);
- EXPECT_FALSE([cell keywordString]);
- EXPECT_TRUE([[[cell hintString] string] isEqualToString:kSearchHint]);
-
- // Request a keyword hint, same results whether |search_hint|
- // parameter is true or false.
- LocationBarViewMac::OnChangedImpl(
- field_, kKeyword, kKeyword, true, true, image);
- EXPECT_FALSE([cell keywordString]);
- EXPECT_TRUE([[[cell hintString] string] hasPrefix:kKeywordPrefix]);
- EXPECT_TRUE([[[cell hintString] string] hasSuffix:kKeywordSuffix]);
- LocationBarViewMac::OnChangedImpl(
- field_, kKeyword, kKeyword, true, false, image);
+ // Request a keyword hint.
+ LocationBarViewMac::OnChangedImpl(field_, kKeyword, kKeyword, true, image);
EXPECT_FALSE([cell keywordString]);
EXPECT_TRUE([[[cell hintString] string] hasPrefix:kKeywordPrefix]);
EXPECT_TRUE([[[cell hintString] string] hasSuffix:kKeywordSuffix]);
- // Request keyword-search mode, same results whether |search_hint|
- // parameter is true or false.
+ // Request keyword-search mode.
LocationBarViewMac::OnChangedImpl(
- field_, kKeyword, kKeyword, false, true, image);
- EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kKeywordString]);
- EXPECT_FALSE([cell hintString]);
- LocationBarViewMac::OnChangedImpl(
- field_, kKeyword, kKeyword, false, false, image);
- EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kKeywordString]);
+ field_, kKeyword, kKeyword, false, image);
+ EXPECT_TRUE([[[cell keywordString] string] hasSuffix:kKeywordString]);
EXPECT_FALSE([cell hintString]);
// Check that a partial keyword-search string is passed down in case
@@ -132,14 +112,13 @@ TEST_F(LocationBarViewMacTest, OnChangedImpl) {
NSRect frame([field_ frame]);
frame.size.width = 10.0;
[field_ setFrame:frame];
- LocationBarViewMac::OnChangedImpl(
- field_, kKeyword, kKeyword, false, true, image);
+ LocationBarViewMac::OnChangedImpl(field_, kKeyword, kKeyword, false, image);
EXPECT_TRUE([[[cell keywordString] string] isEqualToString:kPartialString]);
EXPECT_FALSE([cell hintString]);
// Transition back to baseline.
LocationBarViewMac::OnChangedImpl(
- field_, std::wstring(), std::wstring(), false, false, image);
+ field_, std::wstring(), std::wstring(), false, image);
EXPECT_FALSE([cell keywordString]);
EXPECT_FALSE([cell hintString]);
}
diff --git a/chrome/browser/cocoa/status_bubble_mac_unittest.mm b/chrome/browser/cocoa/status_bubble_mac_unittest.mm
index 3dd628e..6f4dab4 100644
--- a/chrome/browser/cocoa/status_bubble_mac_unittest.mm
+++ b/chrome/browser/cocoa/status_bubble_mac_unittest.mm
@@ -141,7 +141,7 @@ TEST_F(StatusBubbleMacTest, SetURL) {
EXPECT_TRUE([GetURLText() isEqualToString:@"foopy://"]);
bubble_->SetURL(GURL("http://www.cnn.com"), L"");
EXPECT_TRUE(IsVisible());
- EXPECT_TRUE([GetURLText() isEqualToString:@"http://www.cnn.com/"]);
+ EXPECT_TRUE([GetURLText() isEqualToString:@"www.cnn.com/"]);
}
// Test hiding bubble that's already hidden.
@@ -162,7 +162,7 @@ TEST_F(StatusBubbleMacTest, SetStatusAndURL) {
EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]);
bubble_->SetURL(GURL("http://www.nytimes.com/"), L"");
EXPECT_TRUE(IsVisible());
- EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]);
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]);
bubble_->SetURL(GURL(), L"");
EXPECT_TRUE(IsVisible());
EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]);
@@ -170,13 +170,13 @@ TEST_F(StatusBubbleMacTest, SetStatusAndURL) {
EXPECT_FALSE(IsVisible());
bubble_->SetURL(GURL("http://www.nytimes.com/"), L"");
EXPECT_TRUE(IsVisible());
- EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]);
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]);
bubble_->SetStatus(L"Status");
EXPECT_TRUE(IsVisible());
EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]);
bubble_->SetStatus(L"");
EXPECT_TRUE(IsVisible());
- EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]);
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"www.nytimes.com/"]);
bubble_->SetURL(GURL(), L"");
EXPECT_FALSE(IsVisible());
}
diff --git a/chrome/browser/cocoa/tab_strip_controller_unittest.mm b/chrome/browser/cocoa/tab_strip_controller_unittest.mm
index 0967ae4..82cea8e 100644
--- a/chrome/browser/cocoa/tab_strip_controller_unittest.mm
+++ b/chrome/browser/cocoa/tab_strip_controller_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h
index 0fdd8c4..1f277c1 100644
--- a/chrome/browser/cocoa/toolbar_controller.h
+++ b/chrome/browser/cocoa/toolbar_controller.h
@@ -22,7 +22,6 @@ class AppMenuModel;
@class BackForwardMenuController;
class Browser;
@class BrowserActionsController;
-class BubblePositioner;
class CommandUpdater;
@class DelayedMenuButton;
class LocationBar;
@@ -70,8 +69,6 @@ class ToolbarModel;
// Used for monitoring the optional toolbar button prefs.
scoped_ptr<ToolbarControllerInternal::PrefObserverBridge> prefObserver_;
- // Used to position the omnibox bubble.
- scoped_ptr<BubblePositioner> bubblePositioner_;
BooleanPrefMember showHomeButton_;
BooleanPrefMember showPageOptionButtons_;
BOOL hasToolbar_; // If NO, we may have only the location bar.
@@ -99,7 +96,6 @@ class ToolbarModel;
IBOutlet DelayedMenuButton* forwardButton_;
IBOutlet NSButton* reloadButton_;
IBOutlet NSButton* homeButton_;
- IBOutlet NSButton* starButton_;
IBOutlet NSButton* goButton_;
IBOutlet MenuButton* pageButton_;
IBOutlet MenuButton* wrenchButton_;
@@ -147,9 +143,10 @@ class ToolbarModel;
// ignored. This changes the behavior of other methods, like |-view|.
- (void)setHasToolbar:(BOOL)toolbar hasLocationBar:(BOOL)locBar;
-// The bookmark bubble (when you click the star) needs to know where to go.
-// Somewhere near the star button seems like a good start.
-- (NSRect)starButtonInWindowCoordinates;
+// The bookmark bubble (when you click the star or hit Command-d)
+// needs to know where to go. Somewhere near the star icon seems like
+// a good start.
+- (NSRect)starIconInWindowCoordinates;
// Returns the desired toolbar height for the given compression factor.
- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight;
@@ -171,7 +168,6 @@ class ToolbarModel;
- (NSArray*)toolbarViews;
- (void)showOptionalHomeButton;
- (void)showOptionalPageWrenchButtons;
-- (gfx::Rect)locationStackBounds;
// Return a hover button for the current event.
- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent;
@end
diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm
index 1412fc1..a9c4a33 100644
--- a/chrome/browser/cocoa/toolbar_controller.mm
+++ b/chrome/browser/cocoa/toolbar_controller.mm
@@ -15,7 +15,6 @@
#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
-#include "chrome/browser/bubble_positioner.h"
#import "chrome/browser/cocoa/autocomplete_text_field.h"
#import "chrome/browser/cocoa/autocomplete_text_field_editor.h"
#import "chrome/browser/cocoa/back_forward_menu_controller.h"
@@ -51,8 +50,6 @@ NSString* const kBackButtonImageName = @"back_Template.pdf";
NSString* const kForwardButtonImageName = @"forward_Template.pdf";
NSString* const kReloadButtonImageName = @"reload_Template.pdf";
NSString* const kHomeButtonImageName = @"home_Template.pdf";
-NSString* const kStarButtonImageName = @"star_Template.pdf";
-NSString* const kStarButtonFillingImageName = @"starred.pdf";
NSString* const kGoButtonGoImageName = @"go_Template.pdf";
NSString* const kGoButtonStopImageName = @"stop_Template.pdf";
NSString* const kPageButtonImageName = @"menu_page_Template.pdf";
@@ -87,26 +84,6 @@ const CGFloat kAnimationDuration = 0.2;
- (void)adjustLocationAndGoPositionsBy:(CGFloat)dX animate:(BOOL)animate;
@end
-namespace {
-
-// A C++ class used to correctly position the omnibox.
-class BubblePositionerMac : public BubblePositioner {
- public:
- BubblePositionerMac(ToolbarController* controller)
- : controller_(controller) { }
- virtual ~BubblePositionerMac() { }
-
- // BubblePositioner:
- virtual gfx::Rect GetLocationStackBounds() const {
- return [controller_ locationStackBounds];
- }
-
- private:
- ToolbarController* controller_; // weak, owns us
-};
-
-} // namespace
-
namespace ToolbarControllerInternal {
// A C++ delegate that handles enabling/disabling menu items and handling when
@@ -225,7 +202,6 @@ class PrefObserverBridge : public NotificationObserver {
[forwardButton_ setImage:nsimage_cache::ImageNamed(kForwardButtonImageName)];
[reloadButton_ setImage:nsimage_cache::ImageNamed(kReloadButtonImageName)];
[homeButton_ setImage:nsimage_cache::ImageNamed(kHomeButtonImageName)];
- [starButton_ setImage:nsimage_cache::ImageNamed(kStarButtonImageName)];
[goButton_ setImage:nsimage_cache::ImageNamed(kGoButtonGoImageName)];
[pageButton_ setImage:nsimage_cache::ImageNamed(kPageButtonImageName)];
[wrenchButton_ setImage:nsimage_cache::ImageNamed(kWrenchButtonImageName)];
@@ -234,9 +210,7 @@ class PrefObserverBridge : public NotificationObserver {
[wrenchButton_ setShowsBorderOnlyWhileMouseInside:YES];
[self initCommandStatus:commands_];
- bubblePositioner_.reset(new BubblePositionerMac(self));
locationBarView_.reset(new LocationBarViewMac(locationBar_,
- bubblePositioner_.get(),
commands_, toolbarModel_,
profile_, browser_));
[locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
@@ -312,10 +286,6 @@ class PrefObserverBridge : public NotificationObserver {
[[homeButton_ cell]
accessibilitySetOverrideValue:description
forAttribute:NSAccessibilityDescriptionAttribute];
- description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_STAR);
- [[starButton_ cell]
- accessibilitySetOverrideValue:description
- forAttribute:NSAccessibilityDescriptionAttribute];
description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_LOCATION);
[[locationBar_ cell]
accessibilitySetOverrideValue:description
@@ -393,9 +363,6 @@ class PrefObserverBridge : public NotificationObserver {
case IDC_HOME:
button = homeButton_;
break;
- case IDC_BOOKMARK_PAGE:
- button = starButton_;
- break;
}
[button setEnabled:enabled];
}
@@ -408,8 +375,6 @@ class PrefObserverBridge : public NotificationObserver {
setEnabled:commands->IsCommandEnabled(IDC_FORWARD) ? YES : NO];
[reloadButton_ setEnabled:commands->IsCommandEnabled(IDC_RELOAD) ? YES : NO];
[homeButton_ setEnabled:commands->IsCommandEnabled(IDC_HOME) ? YES : NO];
- [starButton_
- setEnabled:commands->IsCommandEnabled(IDC_BOOKMARK_PAGE) ? YES : NO];
}
- (void)updateToolbarWithContents:(TabContents*)tab
@@ -424,23 +389,7 @@ class PrefObserverBridge : public NotificationObserver {
}
- (void)setStarredState:(BOOL)isStarred {
- NSImage* starImage = nil;
- NSString* toolTip;
- if (isStarred) {
- starImage = nsimage_cache::ImageNamed(kStarButtonFillingImageName);
- // Cache the string since we'll need it a lot
- static NSString* starredToolTip =
- [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STARRED) retain];
- toolTip = starredToolTip;
- } else {
- // Cache the string since we'll need it a lot
- static NSString* starToolTip =
- [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_STAR) retain];
- toolTip = starToolTip;
- }
-
- [(GradientButtonCell*)[starButton_ cell] setUnderlayImage:starImage];
- [starButton_ setToolTip:toolTip];
+ locationBarView_->SetStarred(isStarred ? true : false);
}
- (void)setIsLoading:(BOOL)isLoading {
@@ -469,7 +418,7 @@ class PrefObserverBridge : public NotificationObserver {
// Make location bar not editable when in a pop-up.
// TODO(viettrungluu): is this right (all the time)?
- [locationBar_ setEditable:toolbar];
+ locationBarView_->SetEditable(toolbar ? true : false);
}
- (NSView*)view {
@@ -507,7 +456,7 @@ class PrefObserverBridge : public NotificationObserver {
// Returns an array of views in the order of the outlets above.
- (NSArray*)toolbarViews {
return [NSArray arrayWithObjects:backButton_, forwardButton_, reloadButton_,
- homeButton_, starButton_, goButton_, pageButton_, wrenchButton_,
+ homeButton_, goButton_, pageButton_, wrenchButton_,
locationBar_, browserActionsContainerView_, nil];
}
@@ -520,14 +469,16 @@ class PrefObserverBridge : public NotificationObserver {
return frame;
}
-// Computes the padding between the buttons that should have a separation from
-// the positions in the nib. Since the forward and reload buttons are always
-// visible, we use those buttons as the canonical spacing.
+// Computes the padding between the buttons that should have a
+// separation from the positions in the nib. |homeButton_| is right
+// of |forwardButton_| unless it has been hidden, in which case
+// |reloadButton_| is in that spot.
- (CGFloat)interButtonSpacing {
- NSRect forwardFrame = [forwardButton_ frame];
- NSRect reloadFrame = [reloadButton_ frame];
- DCHECK(NSMinX(reloadFrame) > NSMaxX(forwardFrame));
- return NSMinX(reloadFrame) - NSMaxX(forwardFrame);
+ const NSRect forwardFrame = [forwardButton_ frame];
+ NSButton* nextButton = [homeButton_ isHidden] ? reloadButton_ : homeButton_;
+ const NSRect nextButtonFrame = [nextButton frame];
+ DCHECK_GT(NSMinX(nextButtonFrame), NSMaxX(forwardFrame));
+ return NSMinX(nextButtonFrame) - NSMaxX(forwardFrame);
}
// Show or hide the home button based on the pref.
@@ -546,7 +497,7 @@ class PrefObserverBridge : public NotificationObserver {
if (hide)
moveX *= -1; // Reverse the direction of the move.
- [starButton_ setFrame:NSOffsetRect([starButton_ frame], moveX, 0)];
+ [reloadButton_ setFrame:NSOffsetRect([reloadButton_ frame], moveX, 0)];
[locationBar_ setFrame:[self adjustRect:[locationBar_ frame]
byAmount:moveX]];
[homeButton_ setHidden:hide];
@@ -769,8 +720,8 @@ class PrefObserverBridge : public NotificationObserver {
[NSAnimationContext endGrouping];
}
-- (NSRect)starButtonInWindowCoordinates {
- return [starButton_ convertRect:[starButton_ bounds] toView:nil];
+- (NSRect)starIconInWindowCoordinates {
+ return [locationBar_ convertRect:[locationBar_ starIconFrame] toView:nil];
}
- (CGFloat)desiredHeightForCompression:(CGFloat)compressByHeight {
@@ -845,31 +796,6 @@ class PrefObserverBridge : public NotificationObserver {
}
-- (gfx::Rect)locationStackBounds {
- // The number of pixels from the left or right edges of the location stack to
- // "just inside the visible borders". When the omnibox bubble contents are
- // aligned with this, the visible borders tacked on to the outsides will line
- // up with the visible borders on the location stack.
- const int kLocationStackEdgeWidth = 2;
-
- const NSRect locationFrame = [locationBar_ frame];
-
- // Expand to include star and go buttons. Including the widths
- // rather that calculating from their current placement because this
- // method can be called while the resize is still rearranging the
- // views involved.
- const CGFloat minX = NSMinX(locationFrame) - NSWidth([starButton_ frame]);
- const CGFloat maxX = NSMaxX(locationFrame) + NSWidth([goButton_ frame]);
-
- NSRect r = NSMakeRect(minX, NSMinY(locationFrame), maxX - minX,
- NSHeight(locationFrame));
- gfx::Rect stack_bounds(
- NSRectToCGRect([[self view] convertRect:r toView:nil]));
- // Inset the bounds to just inside the visible edges (see comment above).
- stack_bounds.Inset(kLocationStackEdgeWidth, 0);
- return stack_bounds;
-}
-
// (URLDropTargetController protocol)
- (void)dropURLs:(NSArray*)urls inView:(NSView*)view at:(NSPoint)point {
// TODO(viettrungluu): This code is more or less copied from the code in
diff --git a/chrome/browser/cocoa/toolbar_controller_unittest.mm b/chrome/browser/cocoa/toolbar_controller_unittest.mm
index 7c718c4..dcea565 100644
--- a/chrome/browser/cocoa/toolbar_controller_unittest.mm
+++ b/chrome/browser/cocoa/toolbar_controller_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -43,7 +43,7 @@ class ToolbarControllerTest : public CocoaTest {
// Indexes that match the ordering returned by the private ToolbarController
// |-toolbarViews| method.
enum {
- kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex, kStarIndex, kGoIndex,
+ kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex, kGoIndex,
kPageIndex, kWrenchIndex, kLocationIndex,
kBrowserActionContainerViewIndex
};
@@ -78,8 +78,6 @@ class ToolbarControllerTest : public CocoaTest {
[[views objectAtIndex:kReloadIndex] isEnabled] ? true : false);
EXPECT_EQ(updater->IsCommandEnabled(IDC_HOME),
[[views objectAtIndex:kHomeIndex] isEnabled] ? true : false);
- EXPECT_EQ(updater->IsCommandEnabled(IDC_BOOKMARK_PAGE),
- [[views objectAtIndex:kStarIndex] isEnabled] ? true : false);
}
BrowserTestHelper helper_;
@@ -160,16 +158,16 @@ TEST_F(ToolbarControllerTest, ToggleHome) {
NSView* homeButton = [[bar_ toolbarViews] objectAtIndex:kHomeIndex];
EXPECT_EQ(showHome, ![homeButton isHidden]);
- NSView* starButton = [[bar_ toolbarViews] objectAtIndex:kStarIndex];
+ NSView* reloadButton = [[bar_ toolbarViews] objectAtIndex:kReloadIndex];
NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
- NSRect originalStarFrame = [starButton frame];
+ NSRect originalReloadFrame = [reloadButton frame];
NSRect originalLocationBarFrame = [locationBar frame];
// Toggle the pref and make sure the button changed state and the other
// views moved.
prefs->SetBoolean(prefs::kShowHomeButton, !showHome);
EXPECT_EQ(showHome, [homeButton isHidden]);
- EXPECT_NE(NSMinX(originalStarFrame), NSMinX([starButton frame]));
+ EXPECT_NE(NSMinX(originalReloadFrame), NSMinX([reloadButton frame]));
EXPECT_NE(NSMinX(originalLocationBarFrame), NSMinX([locationBar frame]));
EXPECT_NE(NSWidth(originalLocationBarFrame), NSWidth([locationBar frame]));
}
@@ -220,32 +218,14 @@ TEST_F(ToolbarControllerTest, DontToggleWhenNoToolbar) {
EXPECT_TRUE(NSEqualRects(locationBarFrame, newLocationBarFrame));
}
-TEST_F(ToolbarControllerTest, StarButtonInWindowCoordinates) {
- NSRect star = [bar_ starButtonInWindowCoordinates];
+TEST_F(ToolbarControllerTest, StarIconInWindowCoordinates) {
+ NSRect star = [bar_ starIconInWindowCoordinates];
NSRect all = [[[bar_ view] window] frame];
// Make sure the star is completely inside the window rect
EXPECT_TRUE(NSContainsRect(all, star));
}
-TEST_F(ToolbarControllerTest, BubblePosition) {
- NSView* locationBar = [[bar_ toolbarViews] objectAtIndex:kLocationIndex];
-
- // The window frame (in window base coordinates).
- NSRect all = [[[bar_ view] window] frame];
- // The frame of the location bar in window base coordinates.
- NSRect locationFrame =
- [locationBar convertRect:[locationBar bounds] toView:nil];
- // The frame of the location stack in window base coordinates. The horizontal
- // coordinates here are used for the omnibox dropdown.
- gfx::Rect locationStackFrame = [bar_ locationStackBounds];
-
- // Make sure the location stack starts to the left of and ends to the right of
- // the location bar.
- EXPECT_LT(locationStackFrame.x(), NSMinX(locationFrame));
- EXPECT_GT(locationStackFrame.right(), NSMaxX(locationFrame));
-}
-
TEST_F(ToolbarControllerTest, HoverButtonForEvent) {
scoped_nsobject<HitView> view([[HitView alloc]
initWithFrame:NSMakeRect(0,0,100,100)]);
diff --git a/chrome/browser/gtk/accelerators_gtk.cc b/chrome/browser/gtk/accelerators_gtk.cc
index 21ffe03..c93d8f0 100644
--- a/chrome/browser/gtk/accelerators_gtk.cc
+++ b/chrome/browser/gtk/accelerators_gtk.cc
@@ -151,8 +151,7 @@ const struct AcceleratorMapping {
{ GDK_o, IDC_OPEN_FILE, GDK_CONTROL_MASK },
{ GDK_f, IDC_FIND, GDK_CONTROL_MASK },
{ GDK_p, IDC_PRINT, GDK_CONTROL_MASK },
- { GDK_b, IDC_SHOW_BOOKMARK_BAR, GDK_CONTROL_MASK },
- { GDK_b, IDC_SHOW_BOOKMARK_MANAGER,
+ { GDK_b, IDC_SHOW_BOOKMARK_BAR,
GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) },
{ GDK_F11, IDC_FULLSCREEN, GdkModifierType(0) },
{ GDK_Delete, IDC_CLEAR_BROWSING_DATA,
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.cc b/chrome/browser/gtk/bookmark_bubble_gtk.cc
index 524c9c3..2bf86e2 100644
--- a/chrome/browser/gtk/bookmark_bubble_gtk.cc
+++ b/chrome/browser/gtk/bookmark_bubble_gtk.cc
@@ -219,7 +219,7 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWidget* anchor,
gtk_container_set_focus_child(GTK_CONTAINER(content), table);
InfoBubbleGtk::ArrowLocationGtk arrow_location =
- !base::i18n::IsRTL() ?
+ base::i18n::IsRTL() ?
InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
bubble_ = InfoBubbleGtk::Show(anchor_,
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index a4e79b0..bfe25fc 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -35,7 +35,6 @@
#include "chrome/browser/gtk/location_bar_view_gtk.h"
#include "chrome/browser/gtk/standard_menus.h"
#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/gtk/toolbar_star_toggle_gtk.h"
#include "chrome/browser/gtk/view_id_util.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/pref_service.h"
@@ -66,17 +65,13 @@ const int kToolbarHeightLocationBarOnly = kToolbarHeight - 2;
// Interior spacing between toolbar widgets.
const int kToolbarWidgetSpacing = 2;
-// The color used as the base[] color of the location entry during a secure
-// connection.
-const GdkColor kSecureColor = GDK_COLOR_RGB(255, 245, 195);
-
} // namespace
// BrowserToolbarGtk, public ---------------------------------------------------
BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
: toolbar_(NULL),
- location_bar_(new LocationBarViewGtk(this, browser)),
+ location_bar_(new LocationBarViewGtk(browser)),
model_(browser->toolbar_model()),
page_menu_model_(this, browser),
app_menu_model_(this, browser),
@@ -160,11 +155,6 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_box_pack_start(GTK_BOX(toolbar_), back_forward_hbox_, FALSE, FALSE,
kToolbarWidgetSpacing);
- reload_.reset(BuildToolbarButton(IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0,
- IDR_BUTTON_MASK,
- l10n_util::GetStringUTF8(IDS_TOOLTIP_RELOAD),
- GTK_STOCK_REFRESH));
-
home_.reset(BuildToolbarButton(IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0,
IDR_BUTTON_MASK,
l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME),
@@ -172,23 +162,25 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_util::SetButtonTriggersNavigation(home_->widget());
SetUpDragForHomeButton();
- // Group the start, omnibox, and go button into an hbox.
- GtkWidget* location_hbox = gtk_hbox_new(FALSE, 0);
- star_.reset(BuildStarButton(l10n_util::GetStringUTF8(IDS_TOOLTIP_STAR)));
- gtk_box_pack_start(GTK_BOX(location_hbox), star_->widget(), FALSE, FALSE, 0);
+ reload_.reset(BuildToolbarButton(IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0,
+ IDR_RELOAD_MASK,
+ l10n_util::GetStringUTF8(IDS_TOOLTIP_RELOAD),
+ GTK_STOCK_REFRESH));
+
+ location_hbox_ = gtk_hbox_new(FALSE, 0);
location_bar_->Init(ShouldOnlyShowLocation());
- gtk_box_pack_start(GTK_BOX(location_hbox), location_bar_->widget(), TRUE,
+ gtk_box_pack_start(GTK_BOX(location_hbox_), location_bar_->widget(), TRUE,
TRUE, 0);
- go_.reset(new GoButtonGtk(location_bar_.get(), browser_));
- gtk_box_pack_start(GTK_BOX(location_hbox), go_->widget(), FALSE, FALSE, 0);
-
- g_signal_connect(location_hbox, "expose-event",
+ g_signal_connect(location_hbox_, "expose-event",
G_CALLBACK(OnLocationHboxExposeThunk), this);
- gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox, TRUE, TRUE,
+ gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox_, TRUE, TRUE,
kToolbarWidgetSpacing + (ShouldOnlyShowLocation() ? 1 : 0));
+ go_.reset(new GoButtonGtk(location_bar_.get(), browser_));
+ gtk_box_pack_start(GTK_BOX(toolbar_), go_->widget(), FALSE, FALSE, 0);
+
if (!ShouldOnlyShowLocation()) {
actions_toolbar_.reset(new BrowserActionsToolbarGtk(browser_));
gtk_box_pack_start(GTK_BOX(toolbar_), actions_toolbar_->widget(),
@@ -227,17 +219,16 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_widget_show(event_box_);
gtk_widget_show(alignment_);
gtk_widget_show(toolbar_);
- gtk_widget_show_all(location_hbox);
- gtk_widget_hide(star_->widget());
+ gtk_widget_show_all(location_hbox_);
+ gtk_widget_hide(reload_->widget());
gtk_widget_hide(go_->widget());
} else {
gtk_widget_show_all(event_box_);
- if (show_home_button_.GetValue()) {
+ if (show_home_button_.GetValue())
gtk_widget_show(home_->widget());
- } else {
+ else
gtk_widget_hide(home_->widget());
- }
if (actions_toolbar_->button_count() == 0)
gtk_widget_hide(actions_toolbar_->widget());
@@ -248,6 +239,7 @@ void BrowserToolbarGtk::Init(Profile* profile,
location_bar_->UpdateContentSettingsIcons();
SetViewIDs();
+ theme_provider_->InitThemesFor(this);
}
void BrowserToolbarGtk::SetViewIDs() {
@@ -256,7 +248,6 @@ void BrowserToolbarGtk::SetViewIDs() {
ViewIDUtil::SetID(forward_->widget(), VIEW_ID_FORWARD_BUTTON);
ViewIDUtil::SetID(reload_->widget(), VIEW_ID_RELOAD_BUTTON);
ViewIDUtil::SetID(home_->widget(), VIEW_ID_HOME_BUTTON);
- ViewIDUtil::SetID(star_->widget(), VIEW_ID_STAR_BUTTON);
ViewIDUtil::SetID(location_bar_->widget(), VIEW_ID_LOCATION_BAR);
ViewIDUtil::SetID(go_->widget(), VIEW_ID_GO_BUTTON);
ViewIDUtil::SetID(page_menu_button_.get(), VIEW_ID_PAGE_MENU);
@@ -312,9 +303,6 @@ void BrowserToolbarGtk::EnabledStateChangedForCommand(int id, bool enabled) {
if (home_.get())
widget = home_->widget();
break;
- case IDC_BOOKMARK_PAGE:
- widget = star_->widget();
- break;
}
if (widget) {
if (!enabled && GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) {
@@ -410,6 +398,19 @@ void BrowserToolbarGtk::Observe(NotificationType type,
gtk_image_set_from_pixbuf(GTK_IMAGE(app_menu_image_),
theme_provider_->GetRTLEnabledPixbufNamed(IDR_MENU_CHROME));
+ // Update the spacing between the reload button and the location bar.
+ gtk_box_set_child_packing(
+ GTK_BOX(toolbar_), reload_->widget(),
+ FALSE, FALSE,
+ theme_provider_->UseGtkTheme() ? kToolbarWidgetSpacing : 0,
+ GTK_PACK_START);
+ gtk_box_set_child_packing(
+ GTK_BOX(toolbar_), location_hbox_,
+ TRUE, TRUE,
+ (theme_provider_->UseGtkTheme() ? kToolbarWidgetSpacing : 0) +
+ (ShouldOnlyShowLocation() ? 1 : 0),
+ GTK_PACK_START);
+
// When using the GTK+ theme, we need to have the event box be visible so
// buttons don't get a halo color from the background. When using Chromium
// themes, we want to let the background show through the toolbar.
@@ -445,38 +446,6 @@ void BrowserToolbarGtk::UpdateTabContents(TabContents* contents,
actions_toolbar_->Update();
}
-gfx::Rect BrowserToolbarGtk::GetLocationStackBounds() const {
- // The number of pixels from the left or right edges of the location stack to
- // "just inside the visible borders". When the omnibox bubble contents are
- // aligned with this, the visible borders tacked on to the outsides will line
- // up with the visible borders on the location stack.
- const int kLocationStackEdgeWidth = 1;
-
- GtkWidget* left;
- GtkWidget* right;
- if (base::i18n::IsRTL()) {
- left = go_->widget();
- right = star_->widget();
- } else {
- left = star_->widget();
- right = go_->widget();
- }
-
- gint origin_x, origin_y;
- DCHECK_EQ(left->window, right->window);
- gdk_window_get_origin(left->window, &origin_x, &origin_y);
-
- gint right_x = origin_x + right->allocation.x + right->allocation.width;
- gint left_x = origin_x + left->allocation.x;
- DCHECK_LE(left_x, right_x);
-
- gfx::Rect stack_bounds(left_x, origin_y + left->allocation.y,
- right_x - left_x, left->allocation.height);
- // Inset the bounds to just inside the visible edges (see comment above).
- stack_bounds.Inset(kLocationStackEdgeWidth, 0);
- return stack_bounds;
-}
-
// BrowserToolbarGtk, private --------------------------------------------------
CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton(
@@ -498,18 +467,6 @@ CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton(
return button;
}
-ToolbarStarToggleGtk* BrowserToolbarGtk::BuildStarButton(
- const std::string& localized_tooltip) {
- ToolbarStarToggleGtk* button = new ToolbarStarToggleGtk(this);
-
- gtk_widget_set_tooltip_text(button->widget(),
- localized_tooltip.c_str());
- g_signal_connect(button->widget(), "clicked",
- G_CALLBACK(OnButtonClickThunk), this);
-
- return button;
-}
-
GtkWidget* BrowserToolbarGtk::BuildToolbarMenuButton(
const std::string& localized_tooltip,
OwnedWidgetGtk* owner) {
@@ -579,42 +536,9 @@ gboolean BrowserToolbarGtk::OnAlignmentExpose(GtkWidget* widget,
gboolean BrowserToolbarGtk::OnLocationHboxExpose(GtkWidget* location_hbox,
GdkEventExpose* e) {
if (theme_provider_->UseGtkTheme()) {
- // To get the proper look surrounding the location bar, we issue raw gtk
- // painting commands to the theme engine. We figure out the region from the
- // leftmost widget to the rightmost and then tell GTK to perform the same
- // drawing commands that draw a GtkEntry on that region.
- GtkWidget* star = star_->widget();
- GtkWidget* left = NULL;
- GtkWidget* right = NULL;
- if (ShouldOnlyShowLocation()) {
- left = location_hbox;
- right = location_hbox;
- } else if (gtk_widget_get_direction(star) == GTK_TEXT_DIR_LTR) {
- left = star_->widget();
- right = go_->widget();
- } else {
- left = go_->widget();
- right = star_->widget();
- }
-
- GdkRectangle rec = {
- left->allocation.x,
- left->allocation.y,
- (right->allocation.x - left->allocation.x) + right->allocation.width,
- (right->allocation.y - left->allocation.y) + right->allocation.height
- };
-
- // Make sure our off screen entry has the correct base color if we're in
- // secure mode.
- gtk_widget_modify_base(
- offscreen_entry_.get(), GTK_STATE_NORMAL,
- (browser_->toolbar_model()->GetSchemeSecurityLevel() ==
- ToolbarModel::SECURE) ?
- &kSecureColor : NULL);
-
gtk_util::DrawTextEntryBackground(offscreen_entry_.get(),
location_hbox, &e->area,
- &rec);
+ &location_hbox->allocation);
}
return FALSE;
@@ -639,8 +563,6 @@ void BrowserToolbarGtk::OnButtonClick(GtkWidget* button) {
location_bar_->Revert();
} else if (home_.get() && button == home_->widget()) {
tag = IDC_HOME;
- } else if (button == star_->widget()) {
- tag = IDC_BOOKMARK_PAGE;
}
DCHECK_NE(tag, -1) << "Unexpected button click callback";
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h
index 1ece0db..9c5f2c8 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.h
+++ b/chrome/browser/gtk/browser_toolbar_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -12,8 +12,8 @@
#include "app/menus/simple_menu_model.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/app_menu_model.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/command_updater.h"
+#include "chrome/browser/gtk/custom_button.h"
#include "chrome/browser/gtk/menu_bar_helper.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/page_menu_model.h"
@@ -35,7 +35,6 @@ class LocationBarViewGtk;
class Profile;
class TabContents;
class ToolbarModel;
-class ToolbarStarToggleGtk;
// View class that displays the GTK version of the toolbar and routes gtk
// events back to the Browser.
@@ -44,7 +43,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
public menus::SimpleMenuModel::Delegate,
public MenuGtk::Delegate,
public NotificationObserver,
- public BubblePositioner,
public MenuBarHelper::Delegate {
public:
explicit BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window);
@@ -113,11 +111,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
// Message that we should react to a state change.
void UpdateTabContents(TabContents* contents, bool should_restore_state);
- ToolbarStarToggleGtk* star() { return star_.get(); }
-
- // BubblePositioner:
- virtual gfx::Rect GetLocationStackBounds() const;
-
// MenuBarHelper::Delegate implementation ------------------------------------
virtual void PopupForButton(GtkWidget* button);
virtual void PopupForButtonNextTo(GtkWidget* button,
@@ -135,9 +128,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
const std::string& localized_tooltip,
const char* stock_id);
- // Create the star button given the tooltip. Returns the widget created.
- ToolbarStarToggleGtk* BuildStarButton(const std::string& localized_tooltip);
-
// Create a menu for the toolbar given the icon id and tooltip. Returns the
// widget created.
GtkWidget* BuildToolbarMenuButton(const std::string& localized_tooltip,
@@ -191,14 +181,16 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
// toolbar placed side by side.
GtkWidget* toolbar_;
+ // Contains all the widgets of the location bar.
+ GtkWidget* location_hbox_;
+
// The location bar view.
scoped_ptr<LocationBarViewGtk> location_bar_;
// All the buttons in the toolbar.
scoped_ptr<BackForwardButtonGtk> back_, forward_;
- scoped_ptr<CustomDrawButton> reload_;
scoped_ptr<CustomDrawButton> home_;
- scoped_ptr<ToolbarStarToggleGtk> star_;
+ scoped_ptr<CustomDrawButton> reload_;
scoped_ptr<GoButtonGtk> go_;
scoped_ptr<BrowserActionsToolbarGtk> actions_toolbar_;
OwnedWidgetGtk page_menu_button_, app_menu_button_;
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 3eba2c5..5bdb347 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -57,6 +57,7 @@
#include "chrome/browser/gtk/info_bubble_gtk.h"
#include "chrome/browser/gtk/infobar_container_gtk.h"
#include "chrome/browser/gtk/keyword_editor_view.h"
+#include "chrome/browser/gtk/location_bar_view_gtk.h"
#include "chrome/browser/gtk/nine_box.h"
#include "chrome/browser/gtk/options/content_settings_window_gtk.h"
#include "chrome/browser/gtk/repost_form_warning_gtk.h"
@@ -65,7 +66,6 @@
#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
#include "chrome/browser/gtk/task_manager_gtk.h"
#include "chrome/browser/gtk/theme_install_bubble_view_gtk.h"
-#include "chrome/browser/gtk/toolbar_star_toggle_gtk.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/browser/pref_service.h"
@@ -742,7 +742,7 @@ void BrowserWindowGtk::LoadingAnimationCallback() {
}
void BrowserWindowGtk::SetStarredState(bool is_starred) {
- toolbar_->star()->SetStarred(is_starred);
+ toolbar_->GetLocationBarView()->SetStarred(is_starred);
}
gfx::Rect BrowserWindowGtk::GetRestoredBounds() const {
@@ -845,7 +845,7 @@ void BrowserWindowGtk::ShowBookmarkManager() {
void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) {
- toolbar_->star()->ShowStarBubble(url, !already_bookmarked);
+ toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
}
bool BrowserWindowGtk::IsDownloadShelfVisible() const {
diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc
index e3bc7ff..b8785da 100644
--- a/chrome/browser/gtk/find_bar_gtk.cc
+++ b/chrome/browser/gtk/find_bar_gtk.cc
@@ -456,6 +456,7 @@ void FindBarGtk::Observe(NotificationType type,
container_height_ = -1;
if (theme_provider_->UseGtkTheme()) {
+ gtk_widget_modify_cursor(text_entry_, NULL, NULL);
gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL, NULL);
gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL, NULL);
@@ -482,6 +483,7 @@ void FindBarGtk::Observe(NotificationType type,
gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 0.5);
} else {
+ gtk_widget_modify_cursor(text_entry_, &gfx::kGdkBlack, &gfx::kGdkGray);
gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL,
&kEntryBackgroundColor);
gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL,
diff --git a/chrome/browser/gtk/gtk_theme_provider.cc b/chrome/browser/gtk/gtk_theme_provider.cc
index 2f0f142..24e7266 100644
--- a/chrome/browser/gtk/gtk_theme_provider.cc
+++ b/chrome/browser/gtk/gtk_theme_provider.cc
@@ -91,10 +91,30 @@ const int kThemeImages[] = {
IDR_THEME_FRAME_INCOGNITO_INACTIVE,
};
+// A list of icons used in the autocomplete view that should be tinted to the
+// current gtk theme selection color so they stand out against the GtkEntry's
+// base color.
+const int kAutocompleteImages[] = {
+ IDR_OMNIBOX_HTTP,
+ IDR_OMNIBOX_HTTP_DARK,
+ IDR_OMNIBOX_HISTORY,
+ IDR_OMNIBOX_HISTORY_DARK,
+ IDR_OMNIBOX_SEARCH,
+ IDR_OMNIBOX_SEARCH_DARK,
+ IDR_OMNIBOX_MORE,
+ IDR_OMNIBOX_MORE_DARK,
+ IDR_OMNIBOX_STAR,
+ IDR_OMNIBOX_STAR_DARK,
+ IDR_GEOLOCATION_ALLOWED_LOCATIONBAR_ICON,
+ IDR_GEOLOCATION_DENIED_LOCATIONBAR_ICON
+};
+
bool IsOverridableImage(int id) {
static std::set<int> images;
if (images.empty()) {
images.insert(kThemeImages, kThemeImages + arraysize(kThemeImages));
+ images.insert(kAutocompleteImages,
+ kAutocompleteImages + arraysize(kAutocompleteImages));
const std::set<int>& buttons =
BrowserThemeProvider::GetTintableToolbarButtons();
@@ -738,15 +758,49 @@ SkBitmap* GtkThemeProvider::GenerateGtkThemeBitmap(int id) const {
return GenerateFrameImage(
BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE);
}
+ // Two sets of omnibox icons, the one for normal http and the one for
+ // history, include white backgrounds (and are supposed to, for the windows
+ // chrome-theme). On linux, where we have all sorts of wacky themes and
+ // color combinations we need to deal with, switch them out with
+ // transparent background versions.
+ case IDR_OMNIBOX_HTTP: {
+ TintMap::const_iterator it = tints_.find(
+ BrowserThemeProvider::TINT_BUTTONS);
+ DCHECK(it != tints_.end());
+ return GenerateTintedIcon(IDR_OMNIBOX_HTTP_TRANSPARENT, it->second);
+ }
+ case IDR_OMNIBOX_HISTORY: {
+ TintMap::const_iterator it = tints_.find(
+ BrowserThemeProvider::TINT_BUTTONS);
+ DCHECK(it != tints_.end());
+ return GenerateTintedIcon(IDR_OMNIBOX_HISTORY_TRANSPARENT, it->second);
+ }
+ // In GTK mode, the dark versions of the omnibox icons only ever appear in
+ // the autocomplete popup and only against the current theme's GtkEntry
+ // base[GTK_STATE_SELECTED] color, so tint the icons so they won't collide
+ // with the selected color.
+ case IDR_OMNIBOX_HTTP_DARK: {
+ color_utils::HSL tint;
+ GetEntryForegroundHSL(&tint);
+ return GenerateTintedIcon(IDR_OMNIBOX_HTTP_DARK_TRANSPARENT, tint);
+ }
+ case IDR_OMNIBOX_HISTORY_DARK: {
+ color_utils::HSL tint;
+ GetEntryForegroundHSL(&tint);
+ return GenerateTintedIcon(IDR_OMNIBOX_HISTORY_DARK_TRANSPARENT, tint);
+ }
+ case IDR_OMNIBOX_SEARCH_DARK:
+ case IDR_OMNIBOX_MORE_DARK:
+ case IDR_OMNIBOX_STAR_DARK: {
+ color_utils::HSL tint;
+ GetEntryForegroundHSL(&tint);
+ return GenerateTintedIcon(id, tint);
+ }
default: {
- // This is a tinted button. Tint it and return it.
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(id)));
TintMap::const_iterator it = tints_.find(
BrowserThemeProvider::TINT_BUTTONS);
DCHECK(it != tints_.end());
- return new SkBitmap(SkBitmapOperations::CreateHSLShiftedBitmap(
- *button, it->second));
+ return GenerateTintedIcon(id, it->second);
}
}
}
@@ -768,6 +822,20 @@ SkBitmap* GtkThemeProvider::GenerateTabImage(int base_id) const {
bg_tint, 0, 0, bg_tint.width(), bg_tint.height()));
}
+SkBitmap* GtkThemeProvider::GenerateTintedIcon(int base_id,
+ color_utils::HSL tint) const {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ scoped_ptr<SkBitmap> button(new SkBitmap(*rb.GetBitmapNamed(base_id)));
+ return new SkBitmap(SkBitmapOperations::CreateHSLShiftedBitmap(
+ *button, tint));
+}
+
+void GtkThemeProvider::GetEntryForegroundHSL(color_utils::HSL* tint) const {
+ GtkStyle* style = gtk_rc_get_style(fake_entry_.get());
+ const GdkColor color = style->text[GTK_STATE_SELECTED];
+ color_utils::SkColorToHSL(GdkToSkColor(&color), tint);
+}
+
void GtkThemeProvider::OnDestroyChromeButton(GtkWidget* button) {
std::vector<GtkWidget*>::iterator it =
find(chrome_buttons_.begin(), chrome_buttons_.end(), button);
diff --git a/chrome/browser/gtk/gtk_theme_provider.h b/chrome/browser/gtk/gtk_theme_provider.h
index 23c0a57..227bbbe 100644
--- a/chrome/browser/gtk/gtk_theme_provider.h
+++ b/chrome/browser/gtk/gtk_theme_provider.h
@@ -163,6 +163,13 @@ class GtkThemeProvider : public BrowserThemeProvider,
// Takes the base frame image |base_id| and tints it with |tint_id|.
SkBitmap* GenerateTabImage(int base_id) const;
+ // Tints an icon based on tint.
+ SkBitmap* GenerateTintedIcon(int base_id, color_utils::HSL tint) const;
+
+ // Returns a tint that's the color of the current highlighted text in an
+ // entry.
+ void GetEntryForegroundHSL(color_utils::HSL* tint) const;
+
// A notification from the GtkChromeButton GObject destructor that we should
// remove it from our internal list.
CHROMEGTK_CALLBACK_0(GtkThemeProvider, void, OnDestroyChromeButton);
diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc
index 3013b12..4d5796a 100644
--- a/chrome/browser/gtk/gtk_util.cc
+++ b/chrome/browser/gtk/gtk_util.cc
@@ -17,11 +17,13 @@
#include "base/i18n/rtl.h"
#include "base/linux_util.h"
#include "base/logging.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/gtk/cairo_cached_surface.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/common/renderer_preferences.h"
+#include "googleurl/src/gurl.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -869,4 +871,32 @@ guint32 XTimeNow() {
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}
+bool URLFromPrimarySelection(Profile* profile, GURL* url) {
+ GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+ DCHECK(clipboard);
+ gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
+ if (!selection_text)
+ return false;
+
+ // Use autocomplete to clean up the text, going so far as to turn it into
+ // a search query if necessary.
+ AutocompleteController controller(profile);
+ controller.Start(UTF8ToWide(selection_text),
+ std::wstring(), // desired_tld
+ true, // prevent_inline_autocomplete
+ false, // prefer_keyword
+ true); // synchronous_only
+ g_free(selection_text);
+ const AutocompleteResult& result = controller.result();
+ AutocompleteResult::const_iterator it = result.default_match();
+ if (it == result.end())
+ return false;
+
+ if (!it->destination_url.is_valid())
+ return false;
+
+ *url = it->destination_url;
+ return true;
+}
+
} // namespace gtk_util
diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h
index e28778a..1d8b6d3 100644
--- a/chrome/browser/gtk/gtk_util.h
+++ b/chrome/browser/gtk/gtk_util.h
@@ -17,6 +17,8 @@
typedef struct _GtkWidget GtkWidget;
class GtkThemeProvider;
+class GURL;
+class Profile;
struct RendererPreferences; // from common/renderer_preferences.h
namespace event_utils {
@@ -270,6 +272,11 @@ void SetWMLastUserActionTime(GtkWindow* window);
// function, instead using the timestamp from the latest GDK event.
guint32 XTimeNow();
+// Uses the autocomplete controller for |profile| to convert the contents of the
+// PRIMARY selection to a parsed URL. Returns true and sets |url| on success,
+// otherwise returns false.
+bool URLFromPrimarySelection(Profile* profile, GURL* url);
+
} // namespace gtk_util
#endif // CHROME_BROWSER_GTK_GTK_UTIL_H_
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 7c0685c..18eda70 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "app/gtk_dnd_util.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/basictypes.h"
@@ -26,6 +27,7 @@
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/gtk/bookmark_bubble_gtk.h"
#include "chrome/browser/gtk/cairo_cached_surface.h"
#include "chrome/browser/gtk/content_setting_bubble_gtk.h"
#include "chrome/browser/gtk/extension_popup_gtk.h"
@@ -33,6 +35,7 @@
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/rounded_window.h"
+#include "chrome/browser/gtk/view_id_util.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
@@ -73,10 +76,12 @@ const int kHboxBorder = 4;
// Padding between the elements in the bar.
static const int kInnerPadding = 4;
-// TODO(deanm): Eventually this should be painted with the background png
-// image, but for now we get pretty close by just drawing a solid border.
-const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4);
-const GdkColor kEvTextColor = GDK_COLOR_RGB(0x00, 0x96, 0x14); // Green.
+// Colors used to draw the EV certificate rounded bubble.
+const GdkColor kEvSecureTextColor = GDK_COLOR_RGB(0x07, 0x95, 0x00);
+const GdkColor kEvSecureBackgroundColor = GDK_COLOR_RGB(0xef, 0xfc, 0xef);
+const GdkColor kEvSecureBorderColor = GDK_COLOR_RGB(0x90, 0xc3, 0x90);
+
+// Colors used to draw the Tab to Search rounded bubble.
const GdkColor kKeywordBackgroundColor = GDK_COLOR_RGB(0xf0, 0xf4, 0xfa);
const GdkColor kKeywordBorderColor = GDK_COLOR_RGB(0xcb, 0xde, 0xf7);
@@ -131,19 +136,22 @@ std::wstring CalculateMinString(const std::wstring& description) {
// LocationBarViewGtk
// static
-const GdkColor LocationBarViewGtk::kBackgroundColorByLevel[3] = {
- GDK_COLOR_RGB(255, 245, 195), // SecurityLevel SECURE: Yellow.
- GDK_COLOR_RGB(255, 255, 255), // SecurityLevel NORMAL: White.
- GDK_COLOR_RGB(255, 255, 255), // SecurityLevel INSECURE: White.
-};
-
-LocationBarViewGtk::LocationBarViewGtk(
- const BubblePositioner* bubble_positioner,
- Browser* browser)
- : security_icon_event_box_(NULL),
- security_lock_icon_image_(NULL),
+const GdkColor LocationBarViewGtk::kBackgroundColor =
+ GDK_COLOR_RGB(255, 255, 255);
+
+LocationBarViewGtk::LocationBarViewGtk(Browser* browser)
+ : star_image_(NULL),
+ starred_(false),
+ security_icon_event_box_(NULL),
+ ev_secure_icon_image_(NULL),
+ secure_icon_image_(NULL),
security_warning_icon_image_(NULL),
- info_label_(NULL),
+ security_error_icon_image_(NULL),
+ site_type_alignment_(NULL),
+ site_type_event_box_(NULL),
+ location_icon_image_(NULL),
+ enable_location_drag_(false),
+ security_info_label_(NULL),
tab_to_search_box_(NULL),
tab_to_search_full_label_(NULL),
tab_to_search_partial_label_(NULL),
@@ -151,12 +159,10 @@ LocationBarViewGtk::LocationBarViewGtk(
tab_to_search_hint_leading_label_(NULL),
tab_to_search_hint_icon_(NULL),
tab_to_search_hint_trailing_label_(NULL),
- type_to_search_hint_(NULL),
profile_(NULL),
command_updater_(browser->command_updater()),
toolbar_model_(browser->toolbar_model()),
browser_(browser),
- bubble_positioner_(bubble_positioner),
disposition_(CURRENT_TAB),
transition_(PageTransition::TYPED),
first_run_bubble_(this),
@@ -164,12 +170,12 @@ LocationBarViewGtk::LocationBarViewGtk(
theme_provider_(NULL),
entry_box_width_(0),
show_selected_keyword_(false),
- show_keyword_hint_(false),
- show_search_hint_(false) {
+ show_keyword_hint_(false) {
}
LocationBarViewGtk::~LocationBarViewGtk() {
// All of our widgets should have be children of / owned by the alignment.
+ star_.Destroy();
hbox_.Destroy();
content_setting_hbox_.Destroy();
page_action_hbox_.Destroy();
@@ -177,14 +183,8 @@ LocationBarViewGtk::~LocationBarViewGtk() {
void LocationBarViewGtk::Init(bool popup_window_mode) {
popup_window_mode_ = popup_window_mode;
- location_entry_.reset(new AutocompleteEditViewGtk(this,
- toolbar_model_,
- profile_,
- command_updater_,
- popup_window_mode_,
- bubble_positioner_));
- location_entry_->Init();
+ // Create the widget first, so we can pass it to the AutocompleteEditViewGtk.
hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
gtk_container_set_border_width(GTK_CONTAINER(hbox_.get()), kHboxBorder);
// We will paint for the alignment, to paint the background and border.
@@ -193,30 +193,23 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
// the home button on/off.
gtk_widget_set_redraw_on_allocate(hbox_.get(), TRUE);
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- security_lock_icon_image_ = gtk_image_new_from_pixbuf(
- rb.GetPixbufNamed(IDR_LOCK));
- gtk_widget_set_name(security_lock_icon_image_, "chrome-security-lock-icon");
- gtk_widget_hide(GTK_WIDGET(security_lock_icon_image_));
- security_warning_icon_image_ = gtk_image_new();
- gtk_widget_set_name(security_warning_icon_image_,
- "chrome-security-warning-icon");
- gtk_widget_hide(GTK_WIDGET(security_warning_icon_image_));
-
- info_label_ = gtk_label_new(NULL);
- gtk_widget_modify_base(info_label_, GTK_STATE_NORMAL,
- &LocationBarViewGtk::kBackgroundColorByLevel[0]);
- gtk_widget_hide(GTK_WIDGET(info_label_));
- gtk_widget_set_name(info_label_,
- "chrome-location-bar-info-label");
+ // Now initialize the AutocompleteEditViewGtk.
+ location_entry_.reset(new AutocompleteEditViewGtk(this,
+ toolbar_model_,
+ profile_,
+ command_updater_,
+ popup_window_mode_,
+ hbox_.get()));
+ location_entry_->Init();
g_signal_connect(hbox_.get(), "expose-event",
G_CALLBACK(&HandleExposeThunk), this);
- // Put |tab_to_search_box_|, |location_entry_|, |tab_to_search_hint_| and
- // |type_to_search_hint_| into a sub hbox, so that we can make this part
- // horizontally shrinkable without affecting other elements in the location
- // bar.
+ BuildSiteTypeArea();
+
+ // Put |tab_to_search_box_|, |location_entry_|, and |tab_to_search_hint_| into
+ // a sub hbox, so that we can make this part horizontally shrinkable without
+ // affecting other elements in the location bar.
GtkWidget* entry_box = gtk_hbox_new(FALSE, kInnerPadding);
gtk_widget_show(entry_box);
gtk_widget_set_size_request(entry_box, 0, -1);
@@ -237,13 +230,22 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
tab_to_search_full_label_, 0, 0);
gtk_fixed_put(GTK_FIXED(tab_to_search_label_fixed),
tab_to_search_partial_label_, 0, 0);
+ GtkWidget* tab_to_search_hbox = gtk_hbox_new(FALSE, 0);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ GtkWidget* tab_to_search_lens = gtk_image_new_from_pixbuf(
+ rb.GetPixbufNamed(IDR_OMNIBOX_SEARCH));
+ gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_lens,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_label_fixed,
+ FALSE, FALSE, 0);
// This creates a box around the keyword text with a border, background color,
// and padding around the text.
tab_to_search_box_ = gtk_util::CreateGtkBorderBin(
- tab_to_search_label_fixed, NULL, 1, 1, 2, 2);
+ tab_to_search_hbox, NULL, 1, 1, 1, 3);
gtk_widget_set_name(tab_to_search_box_, "chrome-tab-to-search-box");
- gtk_util::ActAsRoundedWindow(tab_to_search_box_, kBorderColor, kCornerSize,
+ gtk_util::ActAsRoundedWindow(tab_to_search_box_, kKeywordBorderColor,
+ kCornerSize,
gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
// Show all children widgets of |tab_to_search_box_| initially, except
// |tab_to_search_partial_label_|.
@@ -269,7 +271,7 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
kBottomMargin + kBorderThickness,
0, 0);
}
- gtk_container_add(GTK_CONTAINER(align), location_entry_->widget());
+ gtk_container_add(GTK_CONTAINER(align), location_entry_->GetNativeView());
gtk_box_pack_start(GTK_BOX(entry_box), align, TRUE, TRUE, 0);
// Tab to search notification (the hint on the right hand side).
@@ -297,36 +299,11 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
// doesn't work, someone is probably calling show_all on our parent box.
gtk_box_pack_end(GTK_BOX(entry_box), tab_to_search_hint_, FALSE, FALSE, 0);
- // Type to search hint is on the right hand side.
- type_to_search_hint_ =
- gtk_label_new(l10n_util::GetStringUTF8(IDS_OMNIBOX_EMPTY_TEXT).c_str());
- gtk_widget_set_sensitive(type_to_search_hint_, FALSE);
- gtk_box_pack_end(GTK_BOX(entry_box), type_to_search_hint_, FALSE, FALSE, 0);
-
- // Pack info_label_ and security icons in hbox. We hide/show them
- // by SetSecurityIcon() and SetInfoText().
- gtk_box_pack_end(GTK_BOX(hbox_.get()), info_label_, FALSE, FALSE, 0);
-
- GtkWidget* security_icon_box = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(security_icon_box),
- security_lock_icon_image_, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(security_icon_box),
- security_warning_icon_image_, FALSE, FALSE, 0);
-
- // GtkImage is a "no window" widget and requires a GtkEventBox to receive
- // events.
- security_icon_event_box_ = gtk_event_box_new();
- // Make the event box not visible so it does not paint a background.
- gtk_event_box_set_visible_window(GTK_EVENT_BOX(security_icon_event_box_),
- FALSE);
- g_signal_connect(security_icon_event_box_, "button-press-event",
- G_CALLBACK(&OnSecurityIconPressed), this);
-
- gtk_container_add(GTK_CONTAINER(security_icon_event_box_), security_icon_box);
- gtk_widget_set_name(security_icon_event_box_,
- "chrome-security-icon-eventbox");
- gtk_box_pack_end(GTK_BOX(hbox_.get()), security_icon_event_box_,
- FALSE, FALSE, 0);
+ // We don't show the star in popups, app windows, etc.
+ if (!ShouldOnlyShowLocation()) {
+ CreateStarButton();
+ gtk_box_pack_end(GTK_BOX(hbox_.get()), star_.get(), FALSE, FALSE, 0);
+ }
content_setting_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
gtk_widget_set_name(content_setting_hbox_.get(),
@@ -350,9 +327,7 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
FALSE, FALSE, 0);
// Until we switch to vector graphics, force the font size of labels.
- gtk_util::ForceFontSizePixels(type_to_search_hint_,
- browser_defaults::kAutocompleteEditFontPixelSize);
- gtk_util::ForceFontSizePixels(info_label_,
+ gtk_util::ForceFontSizePixels(security_info_label_,
browser_defaults::kAutocompleteEditFontPixelSize);
gtk_util::ForceFontSizePixels(tab_to_search_full_label_,
browser_defaults::kAutocompleteEditFontPixelSize);
@@ -362,8 +337,6 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
browser_defaults::kAutocompleteEditFontPixelSize);
gtk_util::ForceFontSizePixels(tab_to_search_hint_trailing_label_,
browser_defaults::kAutocompleteEditFontPixelSize);
- gtk_util::ForceFontSizePixels(type_to_search_hint_,
- browser_defaults::kAutocompleteEditFontPixelSize);
registrar_.Add(this,
NotificationType::BROWSER_THEME_CHANGED,
@@ -372,6 +345,71 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
theme_provider_->InitThemesFor(this);
}
+void LocationBarViewGtk::BuildSiteTypeArea() {
+ location_icon_image_ = gtk_image_new();
+ gtk_widget_set_name(location_icon_image_, "chrome-location-icon");
+ gtk_widget_show(location_icon_image_);
+
+ security_info_label_ = gtk_label_new(NULL);
+ gtk_widget_modify_fg(GTK_WIDGET(security_info_label_), GTK_STATE_NORMAL,
+ &kEvSecureTextColor);
+ gtk_widget_set_name(security_info_label_,
+ "chrome-location-bar-security-info-label");
+
+ GtkWidget* site_type_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(site_type_hbox), location_icon_image_,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(site_type_hbox), security_info_label_,
+ FALSE, FALSE, kCornerSize);
+
+ site_type_event_box_ = gtk_event_box_new();
+ gtk_widget_modify_bg(site_type_event_box_, GTK_STATE_NORMAL,
+ &kEvSecureBackgroundColor);
+
+ // Make the event box not visible so it does not paint a background.
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+ FALSE);
+ gtk_widget_set_name(site_type_event_box_,
+ "chrome-location-icon-eventbox");
+ gtk_container_add(GTK_CONTAINER(site_type_event_box_),
+ site_type_hbox);
+
+ // Put the event box in an alignment to get the padding correct.
+ site_type_alignment_ = gtk_alignment_new(0, 0, 1, 1);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_),
+ 0, 0, 1, 0);
+ gtk_container_add(GTK_CONTAINER(site_type_alignment_),
+ site_type_event_box_);
+ gtk_box_pack_start(GTK_BOX(hbox_.get()), site_type_alignment_,
+ FALSE, FALSE, 0);
+
+ // Set up drags.
+}
+
+void LocationBarViewGtk::SetSiteTypeDragSource() {
+ bool enable = !location_entry()->IsEditingOrEmpty();
+ if (enable_location_drag_ == enable)
+ return;
+ enable_location_drag_ = enable;
+
+ if (!enable) {
+ gtk_drag_source_unset(site_type_event_box_);
+ return;
+ }
+
+ gtk_drag_source_set(site_type_event_box_, GDK_BUTTON1_MASK,
+ NULL, 0, GDK_ACTION_COPY);
+ gtk_dnd_util::SetSourceTargetListFromCodeMask(site_type_event_box_,
+ gtk_dnd_util::TEXT_PLAIN |
+ gtk_dnd_util::TEXT_URI_LIST |
+ gtk_dnd_util::CHROME_NAMED_URL);
+
+ g_signal_connect(site_type_event_box_, "button-release-event",
+ G_CALLBACK(&OnIconReleasedThunk), this);
+ g_signal_connect(site_type_event_box_, "drag-data-get",
+ G_CALLBACK(&OnIconDragDataThunk), this);
+}
+
void LocationBarViewGtk::SetProfile(Profile* profile) {
profile_ = profile;
}
@@ -410,10 +448,9 @@ GtkWidget* LocationBarViewGtk::GetPageActionWidget(
}
void LocationBarViewGtk::Update(const TabContents* contents) {
- SetSecurityIcon(toolbar_model_->GetIcon());
+ UpdateSiteTypeArea();
UpdateContentSettingsIcons();
UpdatePageActions();
- SetInfoText();
location_entry_->Update(contents);
// The security level (background color) could have changed, etc.
if (theme_provider_->UseGtkTheme()) {
@@ -461,12 +498,12 @@ void LocationBarViewGtk::OnAutocompleteAccept(const GURL& url,
}
void LocationBarViewGtk::OnChanged() {
+ UpdateSiteTypeArea();
+
const std::wstring keyword(location_entry_->model()->keyword());
const bool is_keyword_hint = location_entry_->model()->is_keyword_hint();
show_selected_keyword_ = !keyword.empty() && !is_keyword_hint;
show_keyword_hint_ = !keyword.empty() && is_keyword_hint;
- show_search_hint_ = location_entry_->model()->show_search_hint();
- DCHECK(keyword.empty() || !show_search_hint_);
if (show_selected_keyword_)
SetKeywordLabel(keyword);
@@ -477,6 +514,20 @@ void LocationBarViewGtk::OnChanged() {
AdjustChildrenVisibility();
}
+void LocationBarViewGtk::CreateStarButton() {
+ star_.Own(gtk_event_box_new());
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(star_.get()), FALSE);
+ star_image_ = gtk_image_new();
+ gtk_container_add(GTK_CONTAINER(star_.get()), star_image_);
+ gtk_widget_show_all(star_.get());
+ ViewIDUtil::SetID(star_.get(), VIEW_ID_STAR_BUTTON);
+
+ gtk_widget_set_tooltip_text(star_.get(),
+ l10n_util::GetStringUTF8(IDS_TOOLTIP_STAR).c_str());
+ g_signal_connect(star_.get(), "button-press-event",
+ G_CALLBACK(OnStarButtonPressThunk), this);
+}
+
void LocationBarViewGtk::OnInputInProgress(bool in_progress) {
// This is identical to the Windows code, except that we don't proxy the call
// back through the Toolbar, and just access the model here.
@@ -612,7 +663,7 @@ void LocationBarViewGtk::UpdatePageActions() {
// If there are no visible page actions, hide the hbox too, so that it does
// not affect the padding in the location bar.
- if (PageActionVisibleCount())
+ if (PageActionVisibleCount() && !ShouldOnlyShowLocation())
gtk_widget_show(page_action_hbox_.get());
else
gtk_widget_hide(page_action_hbox_.get());
@@ -691,11 +742,6 @@ void LocationBarViewGtk::Observe(NotificationType type,
gtk_util::SetLabelColor(tab_to_search_partial_label_, NULL);
gtk_util::SetLabelColor(tab_to_search_hint_leading_label_, NULL);
gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_, NULL);
- gtk_util::SetLabelColor(type_to_search_hint_, NULL);
-
- gtk_image_set_from_stock(GTK_IMAGE(security_warning_icon_image_),
- GTK_STOCK_DIALOG_WARNING,
- GTK_ICON_SIZE_SMALL_TOOLBAR);
} else {
gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL,
&kKeywordBackgroundColor);
@@ -708,12 +754,11 @@ void LocationBarViewGtk::Observe(NotificationType type,
&kHintTextColor);
gtk_util::SetLabelColor(tab_to_search_hint_trailing_label_,
&kHintTextColor);
- gtk_util::SetLabelColor(type_to_search_hint_, &kHintTextColor);
-
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gtk_image_set_from_pixbuf(GTK_IMAGE(security_warning_icon_image_),
- rb.GetPixbufNamed(IDR_WARNING));
}
+
+ UpdateStarIcon();
+ UpdateSiteTypeArea();
+ UpdateContentSettingsIcons();
}
gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
@@ -746,8 +791,7 @@ gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
alloc_rect->width,
alloc_rect->height - kTopMargin -
kBottomMargin - 2 * kBorderThickness);
- gdk_cairo_set_source_color(cr, const_cast<GdkColor*>(
- &kBackgroundColorByLevel[toolbar_model_->GetSchemeSecurityLevel()]));
+ gdk_cairo_set_source_color(cr, const_cast<GdkColor*>(&kBackgroundColor));
cairo_fill(cr);
cairo_destroy(cr);
@@ -756,45 +800,52 @@ gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget,
return FALSE; // Continue propagating the expose.
}
-void LocationBarViewGtk::SetSecurityIcon(ToolbarModel::Icon icon) {
- gtk_widget_hide(GTK_WIDGET(security_lock_icon_image_));
- gtk_widget_hide(GTK_WIDGET(security_warning_icon_image_));
- if (icon != ToolbarModel::NO_ICON)
- gtk_widget_show(GTK_WIDGET(security_icon_event_box_));
- else
- gtk_widget_hide(GTK_WIDGET(security_icon_event_box_));
- switch (icon) {
- case ToolbarModel::LOCK_ICON:
- gtk_widget_show(GTK_WIDGET(security_lock_icon_image_));
- break;
- case ToolbarModel::WARNING_ICON:
- gtk_widget_show(GTK_WIDGET(security_warning_icon_image_));
- break;
- case ToolbarModel::NO_ICON:
- break;
- default:
- NOTREACHED();
- break;
+void LocationBarViewGtk::UpdateSiteTypeArea() {
+ // The icon is always visible except when the |tab_to_search_box_| is visible.
+ if (!location_entry_->model()->keyword().empty() &&
+ !location_entry_->model()->is_keyword_hint()) {
+ gtk_widget_hide(site_type_area());
+ return;
}
-}
-void LocationBarViewGtk::SetInfoText() {
- std::wstring info_text, info_tooltip;
- ToolbarModel::InfoTextType info_text_type =
- toolbar_model_->GetInfoText(&info_text, &info_tooltip);
- if (info_text_type == ToolbarModel::INFO_EV_TEXT) {
- gtk_widget_modify_fg(GTK_WIDGET(info_label_), GTK_STATE_NORMAL,
- &kEvTextColor);
- gtk_widget_show(GTK_WIDGET(info_label_));
+ int resource_id = location_entry_->GetIcon();
+ gtk_image_set_from_pixbuf(GTK_IMAGE(location_icon_image_),
+ theme_provider_->GetPixbufNamed(resource_id));
+
+ if (toolbar_model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
+ if (!gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
+ // Fun fact: If wee try to make |site_type_event_box_| act as a
+ // rounded window while it doesn't have a visible window, GTK interprets
+ // this as a sign that it should paint the skyline texture into the
+ // omnibox.
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+ TRUE);
+
+ gtk_util::ActAsRoundedWindow(site_type_event_box_,
+ kEvSecureBorderColor,
+ kCornerSize,
+ gtk_util::ROUNDED_ALL,
+ gtk_util::BORDER_ALL);
+ }
+
+ std::wstring info_text = toolbar_model_->GetEVCertName();
+ gtk_label_set_text(GTK_LABEL(security_info_label_),
+ WideToUTF8(info_text).c_str());
+ gtk_widget_show(GTK_WIDGET(security_info_label_));
} else {
- DCHECK_EQ(info_text_type, ToolbarModel::INFO_NO_INFO);
- DCHECK(info_text.empty());
- // Clear info_text. Should we reset the fg here?
- gtk_widget_hide(GTK_WIDGET(info_label_));
+ if (gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) {
+ gtk_util::StopActingAsRoundedWindow(site_type_event_box_);
+
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_),
+ FALSE);
+ }
+
+ gtk_widget_hide(GTK_WIDGET(security_info_label_));
}
- gtk_label_set_text(GTK_LABEL(info_label_), WideToUTF8(info_text).c_str());
- gtk_widget_set_tooltip_text(GTK_WIDGET(info_label_),
- WideToUTF8(info_tooltip).c_str());
+
+ gtk_widget_show(site_type_area());
+
+ SetSiteTypeDragSource();
}
void LocationBarViewGtk::SetKeywordLabel(const std::wstring& keyword) {
@@ -865,46 +916,114 @@ void LocationBarViewGtk::ShowFirstRunBubbleInternal(
FirstRunBubble::Show(profile_, anchor, rect, bubble_type);
}
-// static
-gboolean LocationBarViewGtk::OnSecurityIconPressed(
- GtkWidget* sender,
- GdkEventButton* event,
- LocationBarViewGtk* location_bar) {
- TabContents* tab = location_bar->GetTabContents();
- NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
- if (!nav_entry) {
- NOTREACHED();
- return true;
+gboolean LocationBarViewGtk::OnIconReleased(GtkWidget* sender,
+ GdkEventButton* event) {
+ TabContents* tab = GetTabContents();
+
+ if (event->button == 1) {
+ // Do not show page info if the user has been editing the location
+ // bar, or the location bar is at the NTP.
+ if (location_entry()->IsEditingOrEmpty())
+ return FALSE;
+
+ // (0,0) event coordinates indicates that the release came at the end of
+ // a drag.
+ if (event->x == 0 && event->y == 0)
+ return FALSE;
+
+ NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
+ if (!nav_entry) {
+ NOTREACHED();
+ return FALSE;
+ }
+ tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
+ return TRUE;
+ } else if (event->button == 2) {
+ // When the user middle clicks on the location icon, try to open the
+ // contents of the PRIMARY selection in the current tab.
+ // If the click was outside our bounds, do nothing.
+ if (!gtk_util::WidgetBounds(sender).Contains(
+ gfx::Point(event->x, event->y))) {
+ return FALSE;
+ }
+
+ GURL url;
+ if (!gtk_util::URLFromPrimarySelection(profile_, &url))
+ return FALSE;
+
+ tab->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+ return TRUE;
}
- tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
- return true;
+
+ return FALSE;
+}
+
+void LocationBarViewGtk::OnIconDragData(GtkWidget* sender,
+ GdkDragContext* context,
+ GtkSelectionData* data,
+ guint info, guint time) {
+ TabContents* tab = GetTabContents();
+ if (!tab)
+ return;
+ gtk_dnd_util::WriteURLWithName(data, tab->GetURL(), tab->GetTitle(), info);
}
-void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkAllocation* allocation) {
+void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkWidget* sender,
+ GtkAllocation* allocation) {
if (entry_box_width_ != allocation->width) {
entry_box_width_ = allocation->width;
AdjustChildrenVisibility();
}
}
+gboolean LocationBarViewGtk::OnStarButtonPress(GtkWidget* widget,
+ GdkEventButton* event) {
+ browser_->ExecuteCommand(IDC_BOOKMARK_PAGE);
+ return FALSE;
+}
+
+void LocationBarViewGtk::ShowStarBubble(const GURL& url,
+ bool newly_bookmarked) {
+ if (!star_.get())
+ return;
+
+ BookmarkBubbleGtk::Show(star_.get(), profile_, url, newly_bookmarked);
+}
+
+void LocationBarViewGtk::SetStarred(bool starred) {
+ if (starred == starred_)
+ return;
+
+ starred_ = starred;
+ UpdateStarIcon();
+}
+
+void LocationBarViewGtk::UpdateStarIcon() {
+ if (!star_.get())
+ return;
+
+ gtk_image_set_from_pixbuf(GTK_IMAGE(star_image_),
+ theme_provider_->GetPixbufNamed(
+ starred_ ? IDR_OMNIBOX_STAR_LIT : IDR_OMNIBOX_STAR));
+}
+
+bool LocationBarViewGtk::ShouldOnlyShowLocation() {
+ return browser_->type() != Browser::TYPE_NORMAL;
+}
+
void LocationBarViewGtk::AdjustChildrenVisibility() {
int text_width = location_entry_->TextWidth();
int available_width = entry_box_width_ - text_width - kInnerPadding;
- // Only one of |tab_to_search_box_|, |tab_to_search_hint_| and
- // |type_to_search_hint_| can be visible at the same time.
+ // Only one of |tab_to_search_box_| and |tab_to_search_hint_| can be visible
+ // at the same time.
if (!show_selected_keyword_ && GTK_WIDGET_VISIBLE(tab_to_search_box_)) {
gtk_widget_hide(tab_to_search_box_);
} else if (!show_keyword_hint_ && GTK_WIDGET_VISIBLE(tab_to_search_hint_)) {
gtk_widget_hide(tab_to_search_hint_);
location_entry_->set_enable_tab_to_search(false);
- } else if (!show_search_hint_ && GTK_WIDGET_VISIBLE(type_to_search_hint_)) {
- gtk_widget_hide(type_to_search_hint_);
}
- if (!show_selected_keyword_ && !show_keyword_hint_ && !show_search_hint_)
- return;
-
if (show_selected_keyword_) {
GtkRequisition box, full_label, partial_label;
gtk_widget_size_request(tab_to_search_box_, &box);
@@ -953,13 +1072,6 @@ void LocationBarViewGtk::AdjustChildrenVisibility() {
gtk_widget_show(tab_to_search_hint_);
location_entry_->set_enable_tab_to_search(true);
}
- } else if (show_search_hint_) {
- GtkRequisition requisition;
- gtk_widget_size_request(type_to_search_hint_, &requisition);
- if (requisition.width >= available_width)
- gtk_widget_hide(type_to_search_hint_);
- else if (requisition.width < available_width)
- gtk_widget_show(type_to_search_hint_);
}
}
@@ -997,14 +1109,12 @@ LocationBarViewGtk::ContentSettingImageViewGtk::~ContentSettingImageViewGtk() {
void LocationBarViewGtk::ContentSettingImageViewGtk::UpdateFromTabContents(
const TabContents* tab_contents) {
- int old_icon = content_setting_image_model_->get_icon();
content_setting_image_model_->UpdateFromTabContents(tab_contents);
if (content_setting_image_model_->is_visible()) {
- if (old_icon != content_setting_image_model_->get_icon()) {
- gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
- ResourceBundle::GetSharedInstance().GetPixbufNamed(
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
+ GtkThemeProvider::GetFrom(profile_)->GetPixbufNamed(
content_setting_image_model_->get_icon()));
- }
+
gtk_widget_set_tooltip_text(widget(),
content_setting_image_model_->get_tooltip().c_str());
gtk_widget_show(widget());
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index 97ac60c6..fe9d26c 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -10,6 +10,7 @@
#include <map>
#include <string>
+#include "app/gtk_signal.h"
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/scoped_vector.h"
@@ -30,7 +31,6 @@
#include "webkit/glue/window_open_disposition.h"
class AutocompleteEditViewGtk;
-class BubblePositioner;
class Browser;
class CommandUpdater;
class ContentSettingImageModel;
@@ -47,8 +47,7 @@ class LocationBarViewGtk : public AutocompleteEditController,
public LocationBarTesting,
public NotificationObserver {
public:
- LocationBarViewGtk(const BubblePositioner* bubble_positioner,
- Browser* browser_);
+ explicit LocationBarViewGtk(Browser* browser);
virtual ~LocationBarViewGtk();
void Init(bool popup_window_mode);
@@ -78,6 +77,12 @@ class LocationBarViewGtk : public AutocompleteEditController,
// restore saved state that the tab holds.
void Update(const TabContents* tab_for_state_restoring);
+ // Show the bookmark bubble.
+ void ShowStarBubble(const GURL& url, bool newly_boomkarked);
+
+ // Set the starred state of the bookmark star.
+ void SetStarred(bool starred);
+
// Implement the AutocompleteEditController interface.
virtual void OnAutocompleteAccept(const GURL& url,
WindowOpenDisposition disposition,
@@ -104,6 +109,9 @@ class LocationBarViewGtk : public AutocompleteEditController,
virtual void InvalidatePageActions();
virtual void SaveStateToContents(TabContents* contents);
virtual void Revert();
+ virtual const AutocompleteEditView* location_entry() const {
+ return location_entry_.get();
+ }
virtual AutocompleteEditView* location_entry() {
return location_entry_.get();
}
@@ -121,9 +129,8 @@ class LocationBarViewGtk : public AutocompleteEditController,
const NotificationSource& source,
const NotificationDetails& details);
- // Translation between a security level and the background color. Both the
- // location bar and edit have to manage and match the background color.
- static const GdkColor kBackgroundColorByLevel[3];
+ // Edit background color.
+ static const GdkColor kBackgroundColor;
private:
class ContentSettingImageViewGtk : public InfoBubbleGtkDelegate {
@@ -141,12 +148,8 @@ class LocationBarViewGtk : public AutocompleteEditController,
void UpdateFromTabContents(const TabContents* tab_contents);
private:
- static gboolean OnButtonPressedThunk(GtkWidget* sender,
- GdkEvent* event,
- ContentSettingImageViewGtk* view) {
- return view->OnButtonPressed(sender, event);
- }
- gboolean OnButtonPressed(GtkWidget* sender, GdkEvent* event);
+ CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnButtonPressed,
+ GdkEvent*);
// InfoBubbleDelegate overrides:
virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
@@ -208,19 +211,10 @@ class LocationBarViewGtk : public AutocompleteEditController,
// with a debugger window attached. Returns true if a popup was shown.
bool ShowPopup(bool devtools);
- static gboolean OnButtonPressedThunk(GtkWidget* sender,
- GdkEvent* event,
- PageActionViewGtk* page_action_view) {
- return page_action_view->OnButtonPressed(sender, event);
- }
- gboolean OnButtonPressed(GtkWidget* sender, GdkEvent* event);
-
- static gboolean OnExposeEventThunk(GtkWidget* widget,
- GdkEventExpose* event,
- PageActionViewGtk* page_action_view) {
- return page_action_view->OnExposeEvent(widget, event);
- }
- gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event);
+ CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed,
+ GdkEvent*);
+ CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent,
+ GdkEventExpose*);
// The location bar view that owns us.
LocationBarViewGtk* owner_;
@@ -268,20 +262,30 @@ class LocationBarViewGtk : public AutocompleteEditController,
};
friend class PageActionViewGtk;
- static gboolean HandleExposeThunk(GtkWidget* widget, GdkEventExpose* event,
- gpointer userdata) {
- return reinterpret_cast<LocationBarViewGtk*>(userdata)->
- HandleExpose(widget, event);
- }
+ // Creates, initializes, and packs the location icon, EV certificate name,
+ // and optional border.
+ void BuildSiteTypeArea();
+
+ // Enable or disable the location icon/EV certificate as a drag source for
+ // the URL.
+ void SetSiteTypeDragSource();
- gboolean HandleExpose(GtkWidget* widget, GdkEventExpose* event);
+ GtkWidget* site_type_area() { return site_type_alignment_; }
- static gboolean OnSecurityIconPressed(GtkWidget* sender,
- GdkEventButton* event,
- LocationBarViewGtk* location_bar);
+ CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, HandleExpose,
+ GdkEventExpose*);
+ CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnIconReleased,
+ GdkEventButton*);
+ CHROMEGTK_CALLBACK_4(LocationBarViewGtk, void, OnIconDragData,
+ GdkDragContext*, GtkSelectionData*, guint, guint);
+ CHROMEGTK_CALLBACK_1(LocationBarViewGtk, void, OnEntryBoxSizeAllocate,
+ GtkAllocation*);
+ CHROMEGTK_CALLBACK_1(LocationBarViewGtk, gboolean, OnStarButtonPress,
+ GdkEventButton*);
- // Set the SSL icon we should be showing.
- void SetSecurityIcon(ToolbarModel::Icon icon);
+ // Updates the site type area: changes the icon and shows/hides the EV
+ // certificate information.
+ void UpdateSiteTypeArea();
// Sets the text that should be displayed in the info label and its associated
// tooltip text. Call with an empty string if the info label should be
@@ -296,29 +300,43 @@ class LocationBarViewGtk : public AutocompleteEditController,
void ShowFirstRunBubbleInternal(FirstRun::BubbleType bubble_type);
- static void OnEntryBoxSizeAllocateThunk(GtkWidget* widget,
- GtkAllocation* allocation,
- gpointer userdata) {
- reinterpret_cast<LocationBarViewGtk*>(userdata)->
- OnEntryBoxSizeAllocate(allocation);
- }
- void OnEntryBoxSizeAllocate(GtkAllocation* allocation);
-
- // Show or hide |tab_to_search_box_|, |tab_to_search_hint_| and
- // |type_to_search_hint_| according to the value of |show_selected_keyword_|,
- // |show_keyword_hint_|, |show_search_hint_| and the available horizontal
- // space in the location bar.
+ // Show or hide |tab_to_search_box_| and |tab_to_search_hint_| according to
+ // the value of |show_selected_keyword_|, |show_keyword_hint_|, and the
+ // available horizontal space in the location bar.
void AdjustChildrenVisibility();
+ // Build the star icon.
+ void CreateStarButton();
+
+ // Update the star icon after it is toggled or the theme changes.
+ void UpdateStarIcon();
+
+ // Returns true if we should only show the URL and none of the extras like
+ // the star button or page actions.
+ bool ShouldOnlyShowLocation();
+
// The outermost widget we want to be hosted.
OwnedWidgetGtk hbox_;
- // SSL icons.
+ // Star button.
+ OwnedWidgetGtk star_;
+ GtkWidget* star_image_;
+ bool starred_;
+
+ // SSL state.
GtkWidget* security_icon_event_box_;
- GtkWidget* security_lock_icon_image_;
+ GtkWidget* ev_secure_icon_image_;
+ GtkWidget* secure_icon_image_;
GtkWidget* security_warning_icon_image_;
- // Toolbar info text (EV cert info).
- GtkWidget* info_label_;
+ GtkWidget* security_error_icon_image_;
+ // An icon to the left of the address bar.
+ GtkWidget* site_type_alignment_;
+ GtkWidget* site_type_event_box_;
+ GtkWidget* location_icon_image_;
+ bool enable_location_drag_;
+ // TODO(pkasting): Split this label off and move the rest of the items to the
+ // left of the address bar.
+ GtkWidget* security_info_label_;
// Content setting icons.
OwnedWidgetGtk content_setting_hbox_;
@@ -339,9 +357,6 @@ class LocationBarViewGtk : public AutocompleteEditController,
GtkWidget* tab_to_search_hint_icon_;
GtkWidget* tab_to_search_hint_trailing_label_;
- // Hint to user that the inputted text is not a keyword or url.
- GtkWidget* type_to_search_hint_;
-
scoped_ptr<AutocompleteEditViewGtk> location_entry_;
Profile* profile_;
@@ -349,9 +364,6 @@ class LocationBarViewGtk : public AutocompleteEditController,
ToolbarModel* toolbar_model_;
Browser* browser_;
- // We need to hold on to this just to it pass to the edit.
- const BubblePositioner* bubble_positioner_;
-
// When we get an OnAutocompleteAccept notification from the autocomplete
// edit, we save the input string so we can give it back to the browser on
// the LocationBar interface via GetInputString().
@@ -385,9 +397,6 @@ class LocationBarViewGtk : public AutocompleteEditController,
// Indicate if |tab_to_search_hint_| should be shown.
bool show_keyword_hint_;
- // Indicate if |type_to_search_hint_| should be shown.
- bool show_search_hint_;
-
DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk);
};
diff --git a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc b/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc
index 5488e4f..8162610 100644
--- a/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc
+++ b/chrome/browser/gtk/options/passwords_exceptions_page_gtk.cc
@@ -116,7 +116,7 @@ void PasswordsExceptionsPageGtk::SetExceptionList(
for (size_t i = 0; i < result.size(); ++i) {
exception_list_[i] = *result[i];
std::wstring formatted = net::FormatUrl(result[i]->origin, languages,
- false, UnescapeRule::NONE, NULL, NULL, NULL);
+ net::kFormatUrlOmitAll, UnescapeRule::NONE, NULL, NULL, NULL);
std::string site = WideToUTF8(formatted);
GtkTreeIter iter;
gtk_list_store_insert_with_values(exception_list_store_, &iter, (gint) i,
diff --git a/chrome/browser/gtk/options/passwords_page_gtk.cc b/chrome/browser/gtk/options/passwords_page_gtk.cc
index 0de0403..9ecf89f 100644
--- a/chrome/browser/gtk/options/passwords_page_gtk.cc
+++ b/chrome/browser/gtk/options/passwords_page_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -160,7 +160,7 @@ void PasswordsPageGtk::SetPasswordList(
for (size_t i = 0; i < result.size(); ++i) {
password_list_[i] = *result[i];
std::wstring formatted = net::FormatUrl(result[i]->origin, languages,
- false, UnescapeRule::NONE, NULL, NULL, NULL);
+ net::kFormatUrlOmitAll, UnescapeRule::NONE, NULL, NULL, NULL);
std::string site = WideToUTF8(formatted);
std::string user = UTF16ToUTF8(result[i]->username_value);
GtkTreeIter iter;
diff --git a/chrome/browser/gtk/options/url_picker_dialog_gtk.cc b/chrome/browser/gtk/options/url_picker_dialog_gtk.cc
index df45b14..b5e5a5b 100644
--- a/chrome/browser/gtk/options/url_picker_dialog_gtk.cc
+++ b/chrome/browser/gtk/options/url_picker_dialog_gtk.cc
@@ -198,7 +198,8 @@ std::string UrlPickerDialogGtk::GetURLForPath(GtkTreePath* path) const {
// Because the url_field_ is user-editable, we set the URL with
// username:password and escaped path and query.
std::wstring formatted = net::FormatUrl(url_table_model_->GetURL(row),
- languages, false, UnescapeRule::NONE, NULL, NULL, NULL);
+ languages, net::kFormatUrlOmitNothing, UnescapeRule::NONE, NULL, NULL,
+ NULL);
return WideToUTF8(formatted);
}
diff --git a/chrome/browser/gtk/rounded_window.cc b/chrome/browser/gtk/rounded_window.cc
index 540a465..52bedc9 100644
--- a/chrome/browser/gtk/rounded_window.cc
+++ b/chrome/browser/gtk/rounded_window.cc
@@ -287,6 +287,10 @@ void StopActingAsRoundedWindow(GtkWidget* widget) {
gdk_window_shape_combine_mask(widget->window, NULL, 0, 0);
}
+bool IsActingAsRoundedWindow(GtkWidget* widget) {
+ return g_object_get_data(G_OBJECT(widget), kRoundedData) != NULL;
+}
+
void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
int corner_size,
int rounded_edges,
diff --git a/chrome/browser/gtk/rounded_window.h b/chrome/browser/gtk/rounded_window.h
index 95f91d9..cd98e71 100644
--- a/chrome/browser/gtk/rounded_window.h
+++ b/chrome/browser/gtk/rounded_window.h
@@ -42,6 +42,9 @@ void ActAsRoundedWindow(
// Undoes most of the actions of ActAsRoundedWindow().
void StopActingAsRoundedWindow(GtkWidget* widget);
+// Returns true if the window is rounded.
+bool IsActingAsRoundedWindow(GtkWidget* widget);
+
// Sets edge and border properties on a widget that has already been configured
// with ActAsRoundedWindow().
void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
index 25a02c3..8d1d1c8 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
@@ -1980,28 +1980,8 @@ void TabStripGtk::OnNewTabClicked(GtkWidget* widget, TabStripGtk* tabstrip) {
case 2: {
// On middle-click, try to parse the PRIMARY selection as a URL and load
// it instead of creating a blank page.
- GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
- DCHECK(clipboard);
- gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
- if (!selection_text)
- return;
-
- // Use autocomplete to clean up the text, going so far as to turn it into
- // a search query if necessary.
- AutocompleteController controller(tabstrip->model_->profile());
- controller.Start(UTF8ToWide(selection_text),
- std::wstring(), // desired_tld
- true, // prevent_inline_autocomplete
- false, // prefer_keyword
- true); // synchronous_only
- g_free(selection_text);
- const AutocompleteResult& result = controller.result();
- AutocompleteResult::const_iterator it = result.default_match();
- if (it == result.end())
- return;
-
- GURL url(it->destination_url);
- if (!url.is_valid())
+ GURL url;
+ if (!gtk_util::URLFromPrimarySelection(tabstrip->model_->profile(), &url))
return;
TabContents* contents =
diff --git a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc b/chrome/browser/gtk/toolbar_star_toggle_gtk.cc
deleted file mode 100644
index b688b00..0000000
--- a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2010 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/gtk/toolbar_star_toggle_gtk.h"
-
-#include "app/gtk_dnd_util.h"
-#include "app/resource_bundle.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/gtk/bookmark_bubble_gtk.h"
-#include "chrome/browser/gtk/browser_toolbar_gtk.h"
-#include "chrome/browser/gtk/gtk_chrome_button.h"
-#include "chrome/browser/gtk/gtk_theme_provider.h"
-#include "chrome/browser/gtk/gtk_util.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/rect.h"
-#include "grit/theme_resources.h"
-
-ToolbarStarToggleGtk::ToolbarStarToggleGtk(BrowserToolbarGtk* host)
- : host_(host),
- widget_(gtk_chrome_button_new()),
- is_starred_(false),
- theme_provider_(GtkThemeProvider::GetFrom(host->profile())),
- unstarred_(theme_provider_, IDR_STAR, IDR_STAR_P, IDR_STAR_H, IDR_STAR_D,
- IDR_STAR_MASK),
- starred_(theme_provider_, IDR_STARRED, IDR_STARRED_P, IDR_STARRED_H, 0,
- IDR_STAR_MASK) {
- gtk_widget_set_size_request(widget_.get(), unstarred_.Width(),
- unstarred_.Height());
-
- gtk_widget_set_app_paintable(widget_.get(), TRUE);
- // We effectively double-buffer by virtue of having only one image...
- gtk_widget_set_double_buffered(widget_.get(), FALSE);
-
- g_signal_connect(widget(), "expose-event",
- G_CALLBACK(OnExpose), this);
- GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS);
-
- gtk_drag_source_set(widget(), GDK_BUTTON1_MASK, NULL, 0,
- static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_LINK));
- gtk_dnd_util::SetSourceTargetListFromCodeMask(widget(),
- gtk_dnd_util::TEXT_PLAIN |
- gtk_dnd_util::TEXT_URI_LIST |
- gtk_dnd_util::CHROME_NAMED_URL |
- gtk_dnd_util::NETSCAPE_URL);
- g_signal_connect(widget(), "drag-data-get", G_CALLBACK(OnDragDataGet), this);
-
- theme_provider_->InitThemesFor(this);
- registrar_.Add(this,
- NotificationType::BROWSER_THEME_CHANGED,
- NotificationService::AllSources());
-
- hover_controller_.Init(widget());
-}
-
-ToolbarStarToggleGtk::~ToolbarStarToggleGtk() {
- widget_.Destroy();
-}
-
-void ToolbarStarToggleGtk::Observe(NotificationType type,
- const NotificationSource& source, const NotificationDetails& details) {
- DCHECK(NotificationType::BROWSER_THEME_CHANGED == type);
-
- GtkThemeProvider* provider = static_cast<GtkThemeProvider*>(
- Source<GtkThemeProvider>(source).ptr());
- DCHECK(provider == theme_provider_);
- UpdateGTKButton();
-}
-
-void ToolbarStarToggleGtk::ShowStarBubble(const GURL& url,
- bool newly_bookmarked) {
- GtkWidget* widget = widget_.get();
- BookmarkBubbleGtk::Show(widget,
- host_->profile(),
- url,
- newly_bookmarked);
-}
-
-void ToolbarStarToggleGtk::SetStarred(bool starred) {
- is_starred_ = starred;
- gtk_widget_queue_draw(widget_.get());
- UpdateGTKButton();
-}
-
-// static
-gboolean ToolbarStarToggleGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e,
- ToolbarStarToggleGtk* button) {
- if (button->theme_provider_->UseGtkTheme()) {
- return FALSE;
- } else {
- double hover_state = button->hover_controller_.GetCurrentValue();
- if (button->is_starred_)
- return button->starred_.OnExpose(widget, e, hover_state);
- else
- return button->unstarred_.OnExpose(widget, e, hover_state);
- }
-}
-
-// static
-void ToolbarStarToggleGtk::OnDragDataGet(GtkWidget* widget,
- GdkDragContext* drag_context, GtkSelectionData* data, guint info,
- guint time, ToolbarStarToggleGtk* star) {
- const TabContents* tab = star->host_->browser()->tabstrip_model()->
- GetSelectedTabContents();
- if (!tab)
- return;
- gtk_dnd_util::WriteURLWithName(data, tab->GetURL(), tab->GetTitle(), info);
-}
-
-void ToolbarStarToggleGtk::UpdateGTKButton() {
- bool use_gtk = theme_provider_ && theme_provider_->UseGtkTheme();
-
- if (use_gtk) {
- GdkPixbuf* pixbuf = NULL;
- if (is_starred_) {
- pixbuf = theme_provider_->GetPixbufNamed(IDR_STARRED_NOBORDER_CENTER);
- } else {
- pixbuf = theme_provider_->GetPixbufNamed(IDR_STAR_NOBORDER_CENTER);
- }
-
- gtk_button_set_image(
- GTK_BUTTON(widget_.get()),
- gtk_image_new_from_pixbuf(pixbuf));
-
- gtk_widget_set_size_request(widget_.get(), -1, -1);
- gtk_widget_set_app_paintable(widget_.get(), FALSE);
- gtk_widget_set_double_buffered(widget_.get(), TRUE);
- } else {
- gtk_widget_set_size_request(widget_.get(), unstarred_.Width(),
- unstarred_.Height());
-
- gtk_widget_set_app_paintable(widget_.get(), TRUE);
- // We effectively double-buffer by virtue of having only one image...
- gtk_widget_set_double_buffered(widget_.get(), FALSE);
- }
-
- gtk_chrome_button_set_use_gtk_rendering(
- GTK_CHROME_BUTTON(widget_.get()), use_gtk);
-}
diff --git a/chrome/browser/gtk/toolbar_star_toggle_gtk.h b/chrome/browser/gtk/toolbar_star_toggle_gtk.h
deleted file mode 100644
index faa025a..0000000
--- a/chrome/browser/gtk/toolbar_star_toggle_gtk.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2010 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_GTK_TOOLBAR_STAR_TOGGLE_GTK_H_
-#define CHROME_BROWSER_GTK_TOOLBAR_STAR_TOGGLE_GTK_H_
-
-#include <gtk/gtk.h>
-
-#include "base/basictypes.h"
-#include "chrome/browser/gtk/custom_button.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/owned_widget_gtk.h"
-
-class BrowserToolbarGtk;
-class GtkThemeProvider;
-class GURL;
-
-// Displays the bookmark star button, which toggles between two images.
-class ToolbarStarToggleGtk : public NotificationObserver {
- public:
- explicit ToolbarStarToggleGtk(BrowserToolbarGtk* host);
- ~ToolbarStarToggleGtk();
-
- // Provide NotificationObserver implementation.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
- // If the bubble isn't showing, shows it above the star button.
- void ShowStarBubble(const GURL& url, bool newly_bookmarked);
-
- void SetStarred(bool starred);
-
- GtkWidget* widget() const { return widget_.get(); }
-
- private:
- // Updates the properties of |widget_| when we would need to change its
- // state.
- void UpdateGTKButton();
-
- // Callback for expose, used to draw the custom graphics.
- static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e,
- ToolbarStarToggleGtk* obj);
-
- // Callback to get the data associated with a drag.
- static void OnDragDataGet(GtkWidget* widget,
- GdkDragContext* drag_context,
- GtkSelectionData* data,
- guint info,
- guint time,
- ToolbarStarToggleGtk* star);
-
- // Used to listen for theme change notifications.
- NotificationRegistrar registrar_;
-
- // The browser toolbar hosting this widget, for getting the current profile.
- BrowserToolbarGtk* host_;
-
- // The actual button widget.
- OwnedWidgetGtk widget_;
-
- // Whether we show the yellow star.
- bool is_starred_;
-
- GtkThemeProvider* theme_provider_;
-
- CustomDrawButtonBase unstarred_;
- CustomDrawButtonBase starred_;
- CustomDrawHoverController hover_controller_;
-
- DISALLOW_COPY_AND_ASSIGN(ToolbarStarToggleGtk);
-};
-
-#endif // CHROME_BROWSER_GTK_TOOLBAR_STAR_TOGGLE_GTK_H_
diff --git a/chrome/browser/location_bar.h b/chrome/browser/location_bar.h
index a1924fc..1d71dd2 100644
--- a/chrome/browser/location_bar.h
+++ b/chrome/browser/location_bar.h
@@ -69,6 +69,7 @@ class LocationBar {
virtual void Revert() = 0;
// Returns a pointer to the text entry view.
+ virtual const AutocompleteEditView* location_entry() const = 0;
virtual AutocompleteEditView* location_entry() = 0;
// Returns a pointer to the testing interface.
diff --git a/chrome/browser/net/browser_url_util.cc b/chrome/browser/net/browser_url_util.cc
index 9c8ab48..24747b2 100644
--- a/chrome/browser/net/browser_url_util.cc
+++ b/chrome/browser/net/browser_url_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -23,8 +23,8 @@ void WriteURLToClipboard(const GURL& url,
// may not encode non-ASCII characters in UTF-8. See crbug.com/2820.
string16 text = url.SchemeIs(chrome::kMailToScheme) ?
ASCIIToUTF16(url.path()) :
- WideToUTF16(net::FormatUrl(url, languages, false, UnescapeRule::NONE,
- NULL, NULL, NULL));
+ WideToUTF16(net::FormatUrl(url, languages, net::kFormatUrlOmitNothing,
+ UnescapeRule::NONE, NULL, NULL, NULL));
ScopedClipboardWriter scw(clipboard);
scw.WriteURL(text);
diff --git a/chrome/browser/net/url_fixer_upper.cc b/chrome/browser/net/url_fixer_upper.cc
index edacefd..9d974db 100644
--- a/chrome/browser/net/url_fixer_upper.cc
+++ b/chrome/browser/net/url_fixer_upper.cc
@@ -170,8 +170,9 @@ static std::string FixupPath(const std::string& text) {
// Here, we know the input looks like a file.
GURL file_url = net::FilePathToFileURL(FilePath(filename));
if (file_url.is_valid()) {
- return WideToUTF8(net::FormatUrl(file_url, std::wstring(), true,
- UnescapeRule::NORMAL, NULL, NULL, NULL));
+ return WideToUTF8(net::FormatUrl(file_url, std::wstring(),
+ net::kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, NULL,
+ NULL, NULL));
}
// Invalid file URL, just return the input.
@@ -557,7 +558,8 @@ std::string URLFixerUpper::FixupRelativeFile(const FilePath& base_dir,
GURL file_url = net::FilePathToFileURL(full_path);
if (file_url.is_valid())
return WideToUTF8(net::FormatUrl(file_url, std::wstring(),
- true, UnescapeRule::NORMAL, NULL, NULL, NULL));
+ net::kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, NULL,
+ NULL, NULL));
// Invalid files fall through to regular processing.
}
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 340f168..fd82db1 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -14,6 +14,7 @@
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "chrome/browser/appcache/chrome_appcache_service.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser_list.h"
@@ -47,7 +48,6 @@
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
-#include "chrome/browser/search_versus_navigate_classifier.h"
#include "chrome/browser/search_engines/template_url_fetcher.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/sessions/session_service.h"
@@ -340,8 +340,8 @@ class OffTheRecordProfileImpl : public Profile,
return NULL;
}
- virtual SearchVersusNavigateClassifier* GetSearchVersusNavigateClassifier() {
- return profile_->GetSearchVersusNavigateClassifier();
+ virtual AutocompleteClassifier* GetAutocompleteClassifier() {
+ return profile_->GetAutocompleteClassifier();
}
virtual WebDataService* GetWebDataService(ServiceAccessType sat) {
@@ -1161,13 +1161,10 @@ TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() {
return template_url_fetcher_.get();
}
-SearchVersusNavigateClassifier*
-ProfileImpl::GetSearchVersusNavigateClassifier() {
- if (!search_versus_navigate_classifier_.get()) {
- search_versus_navigate_classifier_.reset(
- new SearchVersusNavigateClassifier(this));
- }
- return search_versus_navigate_classifier_.get();
+AutocompleteClassifier* ProfileImpl::GetAutocompleteClassifier() {
+ if (!autocomplete_classifier_.get())
+ autocomplete_classifier_.reset(new AutocompleteClassifier(this));
+ return autocomplete_classifier_.get();
}
WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index a4f680ad..751d2e2 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -30,6 +30,7 @@ namespace webkit_database {
class DatabaseTracker;
}
+class AutocompleteClassifier;
class Blacklist;
class BookmarkModel;
class BrowserThemeProvider;
@@ -55,7 +56,6 @@ class PinnedTabService;
class PrefService;
class ProfileSyncService;
class ProfileSyncFactory;
-class SearchVersusNavigateClassifier;
class SessionService;
class SpellCheckHost;
class SSLConfigServiceManager;
@@ -217,11 +217,10 @@ class Profile {
// doesn't already exist.
virtual HistoryService* GetHistoryServiceWithoutCreating() = 0;
- // Retrieves a pointer to the SearchVersusNavigateClassifier associated with
- // this profile. The SearchVersusNavigateClassifier is lazily created the
- // first time that this method is called.
- virtual SearchVersusNavigateClassifier*
- GetSearchVersusNavigateClassifier() = 0;
+ // Retrieves a pointer to the AutocompleteClassifier associated with this
+ // profile. The AutocompleteClassifier is lazily created the first time that
+ // this method is called.
+ virtual AutocompleteClassifier* GetAutocompleteClassifier() = 0;
// Returns the WebDataService for this profile. This is owned by
// the Profile. Callers that outlive the life of this profile need to be
@@ -473,7 +472,7 @@ class ProfileImpl : public Profile,
virtual FaviconService* GetFaviconService(ServiceAccessType sat);
virtual HistoryService* GetHistoryService(ServiceAccessType sat);
virtual HistoryService* GetHistoryServiceWithoutCreating();
- virtual SearchVersusNavigateClassifier* GetSearchVersusNavigateClassifier();
+ virtual AutocompleteClassifier* GetAutocompleteClassifier();
virtual WebDataService* GetWebDataService(ServiceAccessType sat);
virtual WebDataService* GetWebDataServiceWithoutCreating();
virtual PasswordStore* GetPasswordStore(ServiceAccessType sat);
@@ -598,7 +597,7 @@ class ProfileImpl : public Profile,
scoped_refptr<DownloadManager> download_manager_;
scoped_refptr<HistoryService> history_service_;
scoped_refptr<FaviconService> favicon_service_;
- scoped_ptr<SearchVersusNavigateClassifier> search_versus_navigate_classifier_;
+ scoped_ptr<AutocompleteClassifier> autocomplete_classifier_;
scoped_refptr<WebDataService> web_data_service_;
scoped_refptr<PasswordStore> password_store_;
scoped_refptr<SessionService> session_service_;
diff --git a/chrome/browser/search_versus_navigate_classifier.cc b/chrome/browser/search_versus_navigate_classifier.cc
deleted file mode 100644
index b32b92b..0000000
--- a/chrome/browser/search_versus_navigate_classifier.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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/search_versus_navigate_classifier.h"
-
-#include "chrome/browser/autocomplete/autocomplete.h"
-#include "googleurl/src/gurl.h"
-
-SearchVersusNavigateClassifier::SearchVersusNavigateClassifier(Profile* profile)
- : controller_(new AutocompleteController(profile)) {
-}
-
-SearchVersusNavigateClassifier::~SearchVersusNavigateClassifier() {
-}
-
-void SearchVersusNavigateClassifier::Classify(const std::wstring& text,
- const std::wstring& desired_tld,
- bool* is_search,
- GURL* destination_url,
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
- GURL* alternate_nav_url) {
- controller_->Start(text, desired_tld, true, false, true);
- DCHECK(controller_->done());
- const AutocompleteResult& result = controller_->result();
- if (result.empty()) {
- if (is_search)
- *is_search = false;
- if (destination_url)
- *destination_url = GURL();
- if (transition)
- *transition = PageTransition::TYPED;
- if (is_history_what_you_typed_match)
- *is_history_what_you_typed_match = false;
- if (alternate_nav_url)
- *alternate_nav_url = GURL();
- return;
- }
-
- const AutocompleteResult::const_iterator match(result.default_match());
- DCHECK(match != result.end());
-
- // If this is a search, the page transition will be GENERATED rather than
- // TYPED.
- if (is_search)
- *is_search = (match->transition != PageTransition::TYPED);
- if (destination_url)
- *destination_url = match->destination_url;
- if (transition)
- *transition = match->transition;
- if (is_history_what_you_typed_match)
- *is_history_what_you_typed_match = match->is_history_what_you_typed_match;
- if (alternate_nav_url)
- *alternate_nav_url = result.alternate_nav_url();
-}
diff --git a/chrome/browser/search_versus_navigate_classifier.h b/chrome/browser/search_versus_navigate_classifier.h
deleted file mode 100644
index 94471b8..0000000
--- a/chrome/browser/search_versus_navigate_classifier.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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_SEARCH_VERSUS_NAVIGATE_CLASSIFIER_H_
-#define CHROME_BROWSER_SEARCH_VERSUS_NAVIGATE_CLASSIFIER_H_
-
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "chrome/common/page_transition_types.h"
-
-class AutocompleteController;
-class GURL;
-class Profile;
-
-class SearchVersusNavigateClassifier {
- public:
- explicit SearchVersusNavigateClassifier(Profile* profile);
- virtual ~SearchVersusNavigateClassifier();
-
- // Given some string |text| that the user wants to use for navigation,
- // determines whether to treat it as a search query or a URL, and returns the
- // details of the resulting navigation.
- // NOTE: After |desired_tld|, all parameters are potentially-NULL outparams.
- // |desired_tld| - User's desired TLD.
- // See AutocompleteInput::desired_tld().
- // |is_search| - Set to true if this is to be treated as a
- // query rather than URL.
- // |destination_url| - The URL to load. It may be empty if there is no
- // possible navigation (when |text| is empty).
- // |transition| - The transition type.
- // |is_history_what_you_typed_match|
- // - Set to true when the default match is the
- // "what you typed" match from the history.
- // |alternate_nav_url| - The navigational URL in case of an accidental
- // search; see comments on
- // AutocompleteResult::alternate_nav_url_ in
- // autocomplete.h.
- void Classify(const std::wstring& text,
- const std::wstring& desired_tld,
- bool* is_search,
- GURL* destination_url,
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
- GURL* alternate_nav_url);
-
- private:
- scoped_ptr<AutocompleteController> controller_;
-};
-
-#endif // CHROME_BROWSER_SEARCH_VERSUS_NAVIGATE_CLASSIFIER_H_
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 9f83867..5d6ba7b 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -65,6 +65,9 @@ class SSLUITest : public InProcessBrowserTest {
entry->page_type());
EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN,
entry->ssl().security_style());
+ // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION doesn't lower the security style
+ // to SECURITY_STYLE_AUTHENTICATION_BROKEN.
+ ASSERT_NE(net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, error);
EXPECT_EQ(error, entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS);
EXPECT_FALSE(entry->ssl().has_mixed_content());
EXPECT_FALSE(entry->ssl().has_unsafe_content());
diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc
index c1350e4..7683221 100644
--- a/chrome/browser/ssl/ssl_manager.cc
+++ b/chrome/browser/ssl/ssl_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -271,30 +271,15 @@ bool SSLManager::DeserializeSecurityInfo(const std::string& state,
}
// static
-bool SSLManager::GetEVCertNames(const net::X509Certificate& cert,
- std::wstring* short_name,
- std::wstring* ca_name) {
- DCHECK(short_name || ca_name);
-
+std::wstring SSLManager::GetEVCertName(const net::X509Certificate& cert) {
// EV are required to have an organization name and country.
if (cert.subject().organization_names.empty() ||
cert.subject().country_name.empty()) {
NOTREACHED();
- return false;
+ return std::wstring();
}
- if (short_name) {
- *short_name = l10n_util::GetStringF(
- IDS_SECURE_CONNECTION_EV,
- UTF8ToWide(cert.subject().organization_names[0]),
- UTF8ToWide(cert.subject().country_name));
- }
-
- if (ca_name) {
- // TODO(wtc): should we show the root CA's name instead?
- *ca_name = l10n_util::GetStringF(
- IDS_SECURE_CONNECTION_EV_CA,
- UTF8ToWide(cert.issuer().organization_names[0]));
- }
- return true;
+ return l10n_util::GetStringF(IDS_SECURE_CONNECTION_EV,
+ UTF8ToWide(cert.subject().organization_names[0]),
+ UTF8ToWide(cert.subject().country_name));
}
diff --git a/chrome/browser/ssl/ssl_manager.h b/chrome/browser/ssl/ssl_manager.h
index b0f18e1..f9e1685 100644
--- a/chrome/browser/ssl/ssl_manager.h
+++ b/chrome/browser/ssl/ssl_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -92,12 +92,8 @@ class SSLManager : public NotificationObserver {
int* cert_status,
int* security_bits);
- // Sets |short_name| to <organization_name> [<country>] and |ca_name|
- // to something like:
- // "Verified by <issuer_organization_name>"
- static bool GetEVCertNames(const net::X509Certificate& cert,
- std::wstring* short_name,
- std::wstring* ca_name);
+ // Returns "<organization_name> [<country>]".
+ static std::wstring GetEVCertName(const net::X509Certificate& cert);
private:
// SSLMessageInfo contains the information necessary for displaying a message
diff --git a/chrome/browser/ssl/ssl_policy.cc b/chrome/browser/ssl/ssl_policy.cc
index 9b4a6e9..7f3ad87 100644
--- a/chrome/browser/ssl/ssl_policy.cc
+++ b/chrome/browser/ssl/ssl_policy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -67,10 +67,9 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
handler->ContinueRequest();
break;
case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
- // We ignore this error and display an infobar.
+ // We ignore this error but will show a warning status in the location
+ // bar.
handler->ContinueRequest();
- backend_->ShowMessage(l10n_util::GetString(
- IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR));
break;
case net::ERR_CERT_CONTAINS_ERRORS:
case net::ERR_CERT_REVOKED:
@@ -127,8 +126,12 @@ void SSLPolicy::UpdateEntry(NavigationEntry* entry) {
return;
}
- if (net::IsCertStatusError(entry->ssl().cert_status())) {
- entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
+ // If CERT_STATUS_UNABLE_TO_CHECK_REVOCATION is the only certificate error,
+ // don't lower the security style to SECURITY_STYLE_AUTHENTICATION_BROKEN.
+ int cert_errors = entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS;
+ if (cert_errors) {
+ if (cert_errors != net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION)
+ entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
return;
}
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 105e95d..471d2b8 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/browser/debugger/devtools_manager.h"
@@ -27,7 +28,6 @@
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/search_versus_navigate_classifier.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/spellcheck_host.h"
#include "chrome/browser/spellchecker_platform_engine.h"
@@ -445,10 +445,10 @@ void RenderViewContextMenu::AppendSearchProvider() {
if (params_.selection_text.empty())
return;
- bool is_search;
- profile_->GetSearchVersusNavigateClassifier()->Classify(
- params_.selection_text, std::wstring(), &is_search,
- &selection_navigation_url_, NULL, NULL, NULL);
+ AutocompleteMatch match;
+ profile_->GetAutocompleteClassifier()->Classify(params_.selection_text,
+ std::wstring(), &match, NULL);
+ selection_navigation_url_ = match.destination_url;
if (!selection_navigation_url_.is_valid())
return;
@@ -458,7 +458,14 @@ void RenderViewContextMenu::AppendSearchProvider() {
i = printable_selection_text.find('&', i + 2))
printable_selection_text.insert(i, 1, '&');
- if (is_search) {
+ if (match.transition == PageTransition::TYPED) {
+ if (ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
+ selection_navigation_url_.scheme())) {
+ AppendMenuItem(IDS_CONTENT_CONTEXT_GOTOURL,
+ l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_GOTOURL,
+ printable_selection_text));
+ }
+ } else {
const TemplateURL* const default_provider =
profile_->GetTemplateURLModel()->GetDefaultSearchProvider();
if (!default_provider)
@@ -467,13 +474,6 @@ void RenderViewContextMenu::AppendSearchProvider() {
l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR,
WideToUTF16(default_provider->short_name()),
printable_selection_text));
- } else {
- if (ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
- selection_navigation_url_.scheme())) {
- AppendMenuItem(IDS_CONTENT_CONTEXT_GOTOURL,
- l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_GOTOURL,
- printable_selection_text));
- }
}
}
diff --git a/chrome/browser/theme_resources_util_unittest.cc b/chrome/browser/theme_resources_util_unittest.cc
index 4bd6bd0..6153e75 100644
--- a/chrome/browser/theme_resources_util_unittest.cc
+++ b/chrome/browser/theme_resources_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -20,7 +20,7 @@ TEST(ThemeResourcesUtil, SpotCheckIds) {
const TestCase kTestCases[] = {
{"back", IDR_BACK},
{"go", IDR_GO},
- {"star", IDR_STAR},
+ {"omnibox_star", IDR_OMNIBOX_STAR},
{"sad_tab", IDR_SAD_TAB},
};
for (size_t i = 0; i < arraysize(kTestCases); ++i) {
diff --git a/chrome/browser/toolbar_model.cc b/chrome/browser/toolbar_model.cc
index c651e3d..c641539 100644
--- a/chrome/browser/toolbar_model.cc
+++ b/chrome/browser/toolbar_model.cc
@@ -17,6 +17,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "net/base/cert_status_flags.h"
#include "net/base/net_util.h"
@@ -38,7 +39,6 @@ std::wstring ToolbarModel::GetText() const {
languages = navigation_controller->profile()->GetPrefs()->GetString(
prefs::kAcceptLanguages);
NavigationEntry* entry = navigation_controller->GetActiveEntry();
- // We may not have a navigation entry yet
if (!navigation_controller->tab_contents()->ShouldDisplayURL()) {
// Explicitly hide the URL for this tab.
url = GURL();
@@ -53,144 +53,70 @@ std::wstring ToolbarModel::GetText() const {
url = GURL(url.scheme() + ":");
}
}
- return net::FormatUrl(url, languages, true, UnescapeRule::NORMAL, NULL, NULL,
- NULL);
+ return net::FormatUrl(url, languages, net::kFormatUrlOmitAll,
+ UnescapeRule::NORMAL, NULL, NULL, NULL);
}
ToolbarModel::SecurityLevel ToolbarModel::GetSecurityLevel() const {
if (input_in_progress_) // When editing, assume no security style.
- return ToolbarModel::NORMAL;
+ return NONE;
NavigationController* navigation_controller = GetNavigationController();
if (!navigation_controller) // We might not have a controller on init.
- return ToolbarModel::NORMAL;
+ return NONE;
NavigationEntry* entry = navigation_controller->GetActiveEntry();
if (!entry)
- return ToolbarModel::NORMAL;
+ return NONE;
- switch (entry->ssl().security_style()) {
- case SECURITY_STYLE_AUTHENTICATED:
- if (entry->ssl().has_mixed_content())
- return ToolbarModel::NORMAL;
- return ToolbarModel::SECURE;
- case SECURITY_STYLE_AUTHENTICATION_BROKEN:
- return ToolbarModel::INSECURE;
+ const NavigationEntry::SSLStatus& ssl = entry->ssl();
+ switch (ssl.security_style()) {
case SECURITY_STYLE_UNKNOWN:
case SECURITY_STYLE_UNAUTHENTICATED:
- return ToolbarModel::NORMAL;
- default:
- NOTREACHED();
- return ToolbarModel::NORMAL;
- }
-}
-
-ToolbarModel::SecurityLevel ToolbarModel::GetSchemeSecurityLevel() const {
- // For now, in sync with the security level.
- return GetSecurityLevel();
-}
-
-ToolbarModel::Icon ToolbarModel::GetIcon() const {
- if (input_in_progress_)
- return ToolbarModel::NO_ICON;
-
- NavigationController* navigation_controller = GetNavigationController();
- if (!navigation_controller) // We might not have a controller on init.
- return ToolbarModel::NO_ICON;
+ return NONE;
- NavigationEntry* entry = navigation_controller->GetActiveEntry();
- if (!entry)
- return ToolbarModel::NO_ICON;
+ case SECURITY_STYLE_AUTHENTICATION_BROKEN:
+ return SECURITY_ERROR;
- const NavigationEntry::SSLStatus& ssl = entry->ssl();
- switch (ssl.security_style()) {
case SECURITY_STYLE_AUTHENTICATED:
if (ssl.has_mixed_content())
- return ToolbarModel::WARNING_ICON;
- return ToolbarModel::LOCK_ICON;
- case SECURITY_STYLE_AUTHENTICATION_BROKEN:
- return ToolbarModel::WARNING_ICON;
- case SECURITY_STYLE_UNKNOWN:
- case SECURITY_STYLE_UNAUTHENTICATED:
- return ToolbarModel::NO_ICON;
+ return SECURITY_WARNING;
+ if (net::IsCertStatusError(ssl.cert_status())) {
+ DCHECK_EQ(ssl.cert_status() & net::CERT_STATUS_ALL_ERRORS,
+ net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION);
+ return SECURITY_WARNING;
+ }
+ if ((ssl.cert_status() & net::CERT_STATUS_IS_EV) &&
+ CertStore::GetSharedInstance()->RetrieveCert(ssl.cert_id(), NULL))
+ return EV_SECURE;
+ return SECURE;
+
default:
NOTREACHED();
- return ToolbarModel::NO_ICON;
+ return NONE;
}
}
-void ToolbarModel::GetIconHoverText(std::wstring* text) const {
- DCHECK(text);
-
- NavigationController* navigation_controller = GetNavigationController();
- // We don't expect to be called during initialization, so the controller
- // should never be NULL.
- DCHECK(navigation_controller);
- NavigationEntry* entry = navigation_controller->GetActiveEntry();
- DCHECK(entry);
-
-
- const NavigationEntry::SSLStatus& ssl = entry->ssl();
- switch (ssl.security_style()) {
- case SECURITY_STYLE_AUTHENTICATED: {
- if (ssl.has_mixed_content()) {
- SSLErrorInfo error_info = SSLErrorInfo::CreateError(
- SSLErrorInfo::MIXED_CONTENTS, NULL, GURL());
- text->assign(error_info.short_description());
- } else {
- DCHECK(entry->url().has_host());
- text->assign(l10n_util::GetStringF(IDS_SECURE_CONNECTION,
- UTF8ToWide(entry->url().host())));
- }
- break;
- }
- case SECURITY_STYLE_AUTHENTICATION_BROKEN: {
- CreateErrorText(entry, text);
- if (text->empty()) {
- // If the authentication is broken, we should always have at least one
- // error.
- NOTREACHED();
- return;
- }
- break;
- }
- default:
- // Don't show the info bubble in any other cases.
- text->clear();
- break;
- }
+int ToolbarModel::GetIcon() const {
+ static int icon_ids[NUM_SECURITY_LEVELS] = {
+ IDR_OMNIBOX_HTTP,
+ IDR_OMNIBOX_HTTPS_VALID,
+ IDR_OMNIBOX_HTTPS_VALID,
+ IDR_OMNIBOX_HTTPS_WARNING,
+ IDR_OMNIBOX_HTTPS_INVALID,
+ };
+ DCHECK(arraysize(icon_ids) == NUM_SECURITY_LEVELS);
+ return icon_ids[GetSecurityLevel()];
}
-ToolbarModel::InfoTextType ToolbarModel::GetInfoText(
- std::wstring* text,
- std::wstring* tooltip) const {
- DCHECK(text && tooltip);
- text->clear();
- tooltip->clear();
-
- if (input_in_progress_)
- return INFO_NO_INFO;
-
- NavigationController* navigation_controller = GetNavigationController();
- if (!navigation_controller) // We might not have a controller on init.
- return INFO_NO_INFO;
-
- NavigationEntry* entry = navigation_controller->GetActiveEntry();
- const NavigationEntry::SSLStatus& ssl = entry->ssl();
- if (!entry || ssl.has_mixed_content() ||
- net::IsCertStatusError(ssl.cert_status()) ||
- ((ssl.cert_status() & net::CERT_STATUS_IS_EV) == 0))
- return INFO_NO_INFO;
-
+std::wstring ToolbarModel::GetEVCertName() const {
+ DCHECK_EQ(GetSecurityLevel(), EV_SECURE);
scoped_refptr<net::X509Certificate> cert;
- CertStore::GetSharedInstance()->RetrieveCert(ssl.cert_id(), &cert);
- if (!cert.get()) {
- NOTREACHED();
- return INFO_NO_INFO;
- }
-
- SSLManager::GetEVCertNames(*cert, text, tooltip);
- return INFO_EV_TEXT;
+ // Note: Navigation controller and active entry are guaranteed non-NULL or
+ // the security level would be NONE.
+ CertStore::GetSharedInstance()->RetrieveCert(
+ GetNavigationController()->GetActiveEntry()->ssl().cert_id(), &cert);
+ return SSLManager::GetEVCertName(*cert);
}
NavigationController* ToolbarModel::GetNavigationController() const {
@@ -200,37 +126,3 @@ NavigationController* ToolbarModel::GetNavigationController() const {
TabContents* current_tab = browser_->GetSelectedTabContents();
return current_tab ? &current_tab->controller() : NULL;
}
-
-void ToolbarModel::CreateErrorText(NavigationEntry* entry,
- std::wstring* text) const {
- const NavigationEntry::SSLStatus& ssl = entry->ssl();
- std::vector<SSLErrorInfo> errors;
- SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id(),
- ssl.cert_status(),
- entry->url(),
- &errors);
- if (ssl.has_mixed_content()) {
- errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::MIXED_CONTENTS,
- NULL, GURL()));
- }
- if (ssl.has_unsafe_content()) {
- errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::UNSAFE_CONTENTS,
- NULL, GURL()));
- }
-
- int error_count = static_cast<int>(errors.size());
- if (error_count == 0) {
- text->assign(L"");
- } else if (error_count == 1) {
- text->assign(errors[0].short_description());
- } else {
- // Multiple errors.
- text->assign(l10n_util::GetString(IDS_SEVERAL_SSL_ERRORS));
- text->append(L"\n");
- for (int i = 0; i < error_count; ++i) {
- text->append(errors[i].short_description());
- if (i != error_count - 1)
- text->append(L"\n");
- }
- }
-}
diff --git a/chrome/browser/toolbar_model.h b/chrome/browser/toolbar_model.h
index 1d959c5..a4959e6fd 100644
--- a/chrome/browser/toolbar_model.h
+++ b/chrome/browser/toolbar_model.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -18,54 +18,36 @@ class NavigationEntry;
// from the navigation controller returned by GetNavigationController().
class ToolbarModel {
public:
+ // TODO(wtc): unify ToolbarModel::SecurityLevel with SecurityStyle. We
+ // don't need two sets of security UI levels. SECURITY_STYLE_AUTHENTICATED
+ // needs to be refined into three levels: warning, standard, and EV.
enum SecurityLevel {
- SECURE = 0,
- NORMAL,
- INSECURE
- };
-
- enum Icon {
- NO_ICON = 0,
- LOCK_ICON,
- WARNING_ICON
- };
-
- enum InfoTextType {
- INFO_NO_INFO = 0,
- INFO_EV_TEXT,
+ NONE = 0, // HTTP/no URL/user is editing
+ EV_SECURE, // HTTPS with valid EV cert
+ SECURE, // HTTPS (non-EV)
+ SECURITY_WARNING, // HTTPS, but unable to check certificate revocation
+ // status or with mixed content on the page
+ SECURITY_ERROR, // Attempted HTTPS and failed, page not authenticated
+ NUM_SECURITY_LEVELS,
};
explicit ToolbarModel(Browser* browser);
~ToolbarModel();
// Returns the text that should be displayed in the location bar.
- // Default value: empty string.
std::wstring GetText() const;
// Returns the security level that the toolbar should display.
- // Default value: NORMAL.
SecurityLevel GetSecurityLevel() const;
- // Returns the security level that should be used in the scheme part of the
- // displayed URL. If SECURE, then the scheme is painted in green. If
- // INSECURE, it is painted in red and stricken-out.
- // Default value: NORMAL.
- SecurityLevel GetSchemeSecurityLevel() const;
+ // Returns the resource_id of the icon to show to the left of the address,
+ // based on the current URL. This doesn't cover specialized icons while the
+ // user is editing; see AutocompleteEditView::GetIcon().
+ int GetIcon() const;
- // Returns the icon that should be displayed on the right of the location bar.
- // Default value: NO_ICON.
- Icon GetIcon() const;
-
- // Sets the text displayed in the info bubble that appears when the user
- // hovers the mouse over the icon.
- // Default value: empty string.
- void GetIconHoverText(std::wstring* text) const;
-
- // Sets |text| to contain the text that should be displayed on the right of
- // the location bar, and |tooltip| to the tooltip text that should be shown
- // when the mouse hover over that info label.
- // Default value: NO_INFO and empty string for |text| and |tooltip|.
- InfoTextType GetInfoText(std::wstring* text, std::wstring* tooltip) const;
+ // Returns the name of the EV cert holder. Only call this when the security
+ // level is EV_SECURE.
+ std::wstring GetEVCertName() const;
// Getter/setter of whether the text in location bar is currently being
// edited.
@@ -78,10 +60,6 @@ class ToolbarModel {
// If this returns NULL, default values are used.
NavigationController* GetNavigationController() const;
- // Builds a short error message from the SSL status code found in |entry|.
- // The message is set in |text|.
- void CreateErrorText(NavigationEntry* entry, std::wstring* text) const;
-
Browser* browser_;
// Whether the text in the location bar is currently being edited.
diff --git a/chrome/browser/views/accelerator_table_gtk.cc b/chrome/browser/views/accelerator_table_gtk.cc
index c8b54f7..9e1f6c9 100644
--- a/chrome/browser/views/accelerator_table_gtk.cc
+++ b/chrome/browser/views/accelerator_table_gtk.cc
@@ -115,7 +115,6 @@ const AcceleratorMapping kAcceleratorMap[] = {
// Miscellany.
{ base::VKEY_D, false, true, false, IDC_BOOKMARK_PAGE },
{ base::VKEY_D, true, true, false, IDC_BOOKMARK_ALL_TABS },
- { base::VKEY_B, false, true, false, IDC_SHOW_BOOKMARK_BAR },
{ base::VKEY_DELETE, true, true, false, IDC_CLEAR_BROWSING_DATA },
{ base::VKEY_H, false, true, false, IDC_SHOW_HISTORY },
{ base::VKEY_J, false, true, false, IDC_SHOW_DOWNLOADS },
@@ -129,7 +128,7 @@ const AcceleratorMapping kAcceleratorMap[] = {
{ base::VKEY_F11, false, true, true, IDC_FULLSCREEN },
{ base::VKEY_DELETE, false, true, true, IDC_TASK_MANAGER },
{ base::VKEY_OEM_COMMA, false, true, false, IDC_SYSTEM_OPTIONS },
- { base::VKEY_B, true, true, false, IDC_SHOW_BOOKMARK_MANAGER },
+ { base::VKEY_B, true, true, false, IDC_SHOW_BOOKMARK_BAR },
#if !defined(OS_CHROMEOS)
{ base::VKEY_F1, false, false, false, IDC_HELP_PAGE },
#endif
diff --git a/chrome/browser/views/app_launcher.cc b/chrome/browser/views/app_launcher.cc
index b5fc226..7cea6af 100644
--- a/chrome/browser/views/app_launcher.cc
+++ b/chrome/browser/views/app_launcher.cc
@@ -16,12 +16,13 @@
#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/dom_view.h"
#include "chrome/browser/views/info_bubble.h"
#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/toolbar_view.h"
#include "chrome/common/url_constants.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"
@@ -45,10 +46,11 @@ const int kNavigationEntryYMargin = 1;
// Padding between the navigation bar and the render view contents.
const int kNavigationBarBottomPadding = 3;
-// NavigationBar size.
-const int kNavigationBarHeight = 25;
+// NavigationBar constants.
+const int kNavigationBarHeight = 23;
+const int kNavigationBarBorderThickness = 1;
-// The delta applied to the default font size for the omnibox.
+// The delta applied to the default font size for the Omnibox.
const int kAutocompleteEditFontDelta = 3;
// Command line switch for specifying url of the page.
@@ -74,8 +76,7 @@ static GURL GetMenuURL() {
// mode.
class NavigationBar : public views::View,
- public AutocompleteEditController,
- public BubblePositioner {
+ public AutocompleteEditController {
public:
explicit NavigationBar(AppLauncher* app_launcher)
: app_launcher_(app_launcher),
@@ -83,7 +84,12 @@ class NavigationBar : public views::View,
SetFocusable(true);
location_entry_view_ = new views::NativeViewHost;
AddChildView(location_entry_view_);
- set_border(views::Border::CreateSolidBorder(1, SK_ColorGRAY));
+ set_border(views::Border::CreateSolidBorder(kNavigationBarBorderThickness,
+ SK_ColorGRAY));
+
+ AddChildView(&popup_positioning_view_);
+ popup_positioning_view_.SetVisible(false);
+ popup_positioning_view_.set_parent_owned(false);
}
virtual ~NavigationBar() {
@@ -113,7 +119,8 @@ class NavigationBar : public views::View,
new AutocompleteEditViewWin(font, this, browser->toolbar_model(),
this, GetWidget()->GetNativeView(),
browser->profile(),
- browser->command_updater(), false, this);
+ browser->command_updater(), false,
+ &popup_positioning_view_);
location_entry_.reset(autocomplete_view);
autocomplete_view->Update(NULL);
// The Update call above sets the autocomplete text to the current one in
@@ -123,10 +130,11 @@ class NavigationBar : public views::View,
AutocompleteEditViewGtk* autocomplete_view =
new AutocompleteEditViewGtk(this, browser->toolbar_model(),
browser->profile(),
- browser->command_updater(), false, this);
+ browser->command_updater(), false,
+ &popup_positioning_view_);
autocomplete_view->Init();
- gtk_widget_show_all(autocomplete_view->widget());
- gtk_widget_hide(autocomplete_view->widget());
+ gtk_widget_show_all(autocomplete_view->GetNativeView());
+ gtk_widget_hide(autocomplete_view->GetNativeView());
location_entry_.reset(autocomplete_view);
#else
NOTIMPLEMENTED();
@@ -143,21 +151,10 @@ class NavigationBar : public views::View,
bounds.width() - 2 * (kNavigationEntryPadding +
kNavigationEntryXMargin),
bounds.height() - kNavigationEntryYMargin * 2);
- }
- // BubblePositioner implementation.
- virtual gfx::Rect GetLocationStackBounds() const {
- gfx::Rect bounds = location_entry_view_->GetBounds(
- views::View::APPLY_MIRRORING_TRANSFORMATION);
- gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding);
- views::View::ConvertPointToScreen(this, &origin);
- gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0));
- if (UILayoutIsRightToLeft()) {
- // Align the window to the right side of the entry view when
- // UI is RTL mode.
- rect.set_x(rect.x() - (rect.width() - location_entry_view_->width()));
- }
- return rect;
+ gfx::Rect popup_positioning_bounds(bounds);
+ popup_positioning_bounds.Inset(0, -(kNavigationBarBorderThickness + 1));
+ popup_positioning_view_.SetBounds(popup_positioning_bounds);
}
// AutocompleteController implementation.
@@ -197,6 +194,11 @@ class NavigationBar : public views::View,
NOTIMPLEMENTED();
#endif
+ // This invisible view is provided to the popup in place of |this|, so the
+ // popup can size itself against it using the same offsets it does with the
+ // LocationBarView.
+ views::View popup_positioning_view_;
+
DISALLOW_COPY_AND_ASSIGN(NavigationBar);
};
@@ -239,6 +241,7 @@ InfoBubbleContentsView::InfoBubbleContentsView(AppLauncher* app_launcher)
: app_launcher_(app_launcher),
navigation_bar_(NULL),
dom_view_(NULL) {
+ DCHECK(app_launcher);
}
InfoBubbleContentsView::~InfoBubbleContentsView() {
@@ -301,6 +304,7 @@ void InfoBubbleContentsView::Layout() {
AppLauncher::AppLauncher(Browser* browser)
: browser_(browser),
info_bubble_(NULL) {
+ DCHECK(browser);
info_bubble_content_ = new InfoBubbleContentsView(this);
}
@@ -308,12 +312,15 @@ AppLauncher::~AppLauncher() {
}
// static
-AppLauncher* AppLauncher::Show(Browser* browser, const gfx::Rect& bounds) {
+AppLauncher* AppLauncher::Show(Browser* browser,
+ const gfx::Rect& bounds,
+ const gfx::Point& bubble_anchor) {
AppLauncher* app_launcher = new AppLauncher(browser);
BrowserView* browser_view = static_cast<BrowserView*>(browser->window());
app_launcher->info_bubble_ =
- InfoBubble::Show(browser_view->frame()->GetWindow(), bounds,
- app_launcher->info_bubble_content_, app_launcher);
+ PinnedContentsInfoBubble::Show(browser_view->frame()->GetWindow(),
+ bounds, bubble_anchor, app_launcher->info_bubble_content_,
+ app_launcher);
app_launcher->info_bubble_content_->BubbleShown();
return app_launcher;
}
@@ -328,7 +335,17 @@ AppLauncher* AppLauncher::ShowForNewTab(Browser* browser) {
gfx::Point origin = bounds.origin();
views::RootView::ConvertPointToScreen(tabstrip, &origin);
bounds.set_origin(origin);
- return Show(browser, bounds);
+
+ // Figure out where the location bar is, so we can pin the bubble to
+ // make our url bar appear exactly over it.
+ views::RootView* root_view = views::Widget::GetWidgetFromNativeWindow(
+ browser_view->GetNativeHandle())->GetRootView();
+ views::View* location_bar = root_view->GetViewByID(VIEW_ID_LOCATION_BAR);
+ gfx::Point location_bar_origin = location_bar->bounds().origin();
+ views::RootView::ConvertPointToScreen(location_bar->GetParent(),
+ &location_bar_origin);
+
+ return Show(browser, bounds, location_bar_origin);
}
void AppLauncher::Hide() {
@@ -368,7 +385,6 @@ void AppLauncher::InfoBubbleClosing(InfoBubble* info_bubble,
new DeleteTask<AppLauncher>(this));
}
-
void AppLauncher::AddTabWithURL(const GURL& url,
PageTransition::Type transition) {
#if defined(OS_CHROMEOS)
diff --git a/chrome/browser/views/app_launcher.h b/chrome/browser/views/app_launcher.h
index bd18cfb..1472f06 100644
--- a/chrome/browser/views/app_launcher.h
+++ b/chrome/browser/views/app_launcher.h
@@ -7,7 +7,7 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
-#include "chrome/browser/views/info_bubble.h"
+#include "chrome/browser/views/pinned_contents_info_bubble.h"
#include "views/view.h"
class Browser;
@@ -39,13 +39,17 @@ class TabContentsDelegateImpl;
// When a new url is opened, or the user clicks outsides the bounds of the
// widget the app launcher is closed.
class AppLauncher : public InfoBubbleDelegate,
- public TabContentsDelegate {
+ public TabContentsDelegate {
public:
// Shows an application launcher bubble pointing to the |bounds| (which should
- // be in screen coordinates).
+ // be in screen coordinates). |bubble_anchor| specifies at which coordinates
+ // the bubble contents should appear (in screen coordinates). The bubble will
+ // be moved accordingly.
// The caller DOES NOT OWN the AppLauncher returned. It is deleted
// automatically when the AppLauncher is closed.
- static AppLauncher* Show(Browser* browser, const gfx::Rect& bounds);
+ static AppLauncher* Show(Browser* browser,
+ const gfx::Rect& bounds,
+ const gfx::Point& bubble_anchor);
// Shows an application launcher bubble pointing to the new tab button.
// The caller DOES NOT OWN the AppLauncher returned. It is deleted
@@ -97,8 +101,8 @@ class AppLauncher : public InfoBubbleDelegate,
// The currently active browser. We use this to open urls.
Browser* browser_;
- // The InfoBubble displaying the omnibox and app contents.
- InfoBubble* info_bubble_;
+ // The InfoBubble displaying the Omnibox and app contents.
+ PinnedContentsInfoBubble* info_bubble_;
// The view with the navigation bar and render view, shown in the info-bubble.
InfoBubbleContentsView* info_bubble_content_;
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
index d5eb1f3..de0464e 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
@@ -12,7 +12,6 @@
#include "base/i18n/rtl.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/views/bubble_border.h"
#include "gfx/canvas.h"
#include "gfx/color_utils.h"
@@ -91,13 +90,8 @@ const int kIconVerticalPadding = 2;
// bottom of the row. See comment about the use of "minimum" for
// kIconVerticalPadding.
const int kTextVerticalPadding = 3;
-// The padding at the left edge of the row, left of the icon.
-const int kRowLeftPadding = 6;
-// The padding on the right edge of the row, right of the text.
-const int kRowRightPadding = 3;
-// The horizontal distance between the right edge of the icon and the left edge
-// of the text.
-const int kIconTextSpacing = 9;
+// The padding between horizontally adjacent items (including row edges).
+const int kHorizontalPadding = 3;
// The size delta between the font used for the edit and the result rows. Passed
// to gfx::Font::DeriveFont.
#if !defined(OS_CHROMEOS)
@@ -170,40 +164,15 @@ class AutocompleteResultView : public views::View {
gfx::Rect icon_bounds_;
gfx::Rect text_bounds_;
- // Icons for rows.
- static SkBitmap* icon_url_;
- static SkBitmap* icon_url_selected_;
- static SkBitmap* icon_history_;
- static SkBitmap* icon_history_selected_;
- static SkBitmap* icon_search_;
- static SkBitmap* icon_search_selected_;
- static SkBitmap* icon_more_;
- static SkBitmap* icon_more_selected_;
- static SkBitmap* icon_star_;
- static SkBitmap* icon_star_selected_;
static int icon_size_;
AutocompleteMatch match_;
- static bool initialized_;
- static void InitClass();
-
DISALLOW_COPY_AND_ASSIGN(AutocompleteResultView);
};
// static
-SkBitmap* AutocompleteResultView::icon_url_ = NULL;
-SkBitmap* AutocompleteResultView::icon_url_selected_ = NULL;
-SkBitmap* AutocompleteResultView::icon_history_ = NULL;
-SkBitmap* AutocompleteResultView::icon_history_selected_ = NULL;
-SkBitmap* AutocompleteResultView::icon_search_ = NULL;
-SkBitmap* AutocompleteResultView::icon_search_selected_ = NULL;
-SkBitmap* AutocompleteResultView::icon_star_ = NULL;
-SkBitmap* AutocompleteResultView::icon_star_selected_ = NULL;
-SkBitmap* AutocompleteResultView::icon_more_ = NULL;
-SkBitmap* AutocompleteResultView::icon_more_selected_ = NULL;
int AutocompleteResultView::icon_size_ = 0;
-bool AutocompleteResultView::initialized_ = false;
// This class is a utility class which mirrors an x position, calculates the
// index of the i-th run of a text, and calculates the index of the i-th
@@ -322,7 +291,11 @@ AutocompleteResultView::AutocompleteResultView(
mirroring_context_(new MirroringContext()),
match_(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED) {
CHECK(model_index >= 0);
- InitClass();
+ if (icon_size_ == 0) {
+ icon_size_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ AutocompleteMatch::TypeToIcon(AutocompleteMatch::URL_WHAT_YOU_TYPED))->
+ width();
+ }
}
AutocompleteResultView::~AutocompleteResultView() {
@@ -344,7 +317,8 @@ void AutocompleteResultView::Paint(gfx::Canvas* canvas) {
// position of an input text.
bool text_mirroring = View::UILayoutIsRightToLeft();
int text_left = MirroredLeftPointForRect(text_bounds_);
- int text_right = text_mirroring ? x - kIconTextSpacing : text_bounds_.right();
+ int text_right =
+ text_mirroring ? (x - kHorizontalPadding) : text_bounds_.right();
x = mirroring_context_->Initialize(text_left, text_right, text_mirroring);
x = DrawString(canvas, match_.contents, match_.contents_class, false, x,
text_bounds_.y());
@@ -365,13 +339,11 @@ void AutocompleteResultView::Paint(gfx::Canvas* canvas) {
}
void AutocompleteResultView::Layout() {
- icon_bounds_.SetRect(kRowLeftPadding, (height() - icon_size_) / 2,
+ icon_bounds_.SetRect(kHorizontalPadding, (height() - icon_size_) / 2,
icon_size_, icon_size_);
- int text_x = icon_bounds_.right() + kIconTextSpacing;
- text_bounds_.SetRect(
- text_x,
- std::max(0, (height() - font_.height()) / 2),
- std::max(0, bounds().right() - text_x - kRowRightPadding),
+ int text_x = icon_bounds_.right() + kHorizontalPadding;
+ text_bounds_.SetRect(text_x, std::max(0, (height() - font_.height()) / 2),
+ std::max(0, bounds().right() - text_x - kHorizontalPadding),
font_.height());
}
@@ -389,29 +361,19 @@ ResultViewState AutocompleteResultView::GetState() const {
}
SkBitmap* AutocompleteResultView::GetIcon() const {
- bool selected = model_->IsSelectedIndex(model_index_);
- if (match_.starred)
- return selected ? icon_star_selected_ : icon_star_;
- switch (match_.type) {
- case AutocompleteMatch::URL_WHAT_YOU_TYPED:
- case AutocompleteMatch::HISTORY_URL:
- case AutocompleteMatch::NAVSUGGEST:
- return selected ? icon_url_selected_ : icon_url_;
- case AutocompleteMatch::HISTORY_TITLE:
- case AutocompleteMatch::HISTORY_BODY:
- case AutocompleteMatch::HISTORY_KEYWORD:
- return selected ? icon_history_selected_ : icon_history_;
- case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
- case AutocompleteMatch::SEARCH_HISTORY:
- case AutocompleteMatch::SEARCH_SUGGEST:
- case AutocompleteMatch::SEARCH_OTHER_ENGINE:
- return selected ? icon_search_selected_ : icon_search_;
- case AutocompleteMatch::OPEN_HISTORY_PAGE:
- return selected ? icon_more_selected_ : icon_more_;
- default:
- NOTREACHED();
- return NULL;
+ int icon = match_.starred ?
+ IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type);
+ if (model_->IsSelectedIndex(model_index_)) {
+ switch (icon) {
+ case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_SELECTED; break;
+ case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_SELECTED; break;
+ case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_SELECTED; break;
+ case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_SELECTED; break;
+ case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_SELECTED; break;
+ default: NOTREACHED(); break;
+ }
}
+ return ResourceBundle::GetSharedInstance().GetBitmapNamed(icon);
}
int AutocompleteResultView::DrawString(
@@ -508,7 +470,7 @@ int AutocompleteResultView::DrawStringFragment(
// Clamp text width to the available width within the popup so we elide if
// necessary.
int string_width = std::min(display_font.GetStringWidth(text),
- width() - kRowRightPadding - x);
+ width() - kHorizontalPadding - x);
int string_left = mirroring_context_->GetLeft(x, x + string_width);
const int flags = force_rtl_directionality ?
gfx::Canvas::FORCE_RTL_DIRECTIONALITY : 0;
@@ -531,25 +493,6 @@ SkColor AutocompleteResultView::GetFragmentTextColor(int style) const {
(style & ACMatchClassification::DIM) ? DIMMED_TEXT : TEXT);
}
-void AutocompleteResultView::InitClass() {
- if (!initialized_) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- icon_url_ = rb.GetBitmapNamed(IDR_O2_GLOBE);
- icon_url_selected_ = rb.GetBitmapNamed(IDR_O2_GLOBE_SELECTED);
- icon_history_ = rb.GetBitmapNamed(IDR_O2_HISTORY);
- icon_history_selected_ = rb.GetBitmapNamed(IDR_O2_HISTORY_SELECTED);
- icon_search_ = rb.GetBitmapNamed(IDR_O2_SEARCH);
- icon_search_selected_ = rb.GetBitmapNamed(IDR_O2_SEARCH_SELECTED);
- icon_star_ = rb.GetBitmapNamed(IDR_O2_STAR);
- icon_star_selected_ = rb.GetBitmapNamed(IDR_O2_STAR_SELECTED);
- icon_more_ = rb.GetBitmapNamed(IDR_O2_MORE);
- icon_more_selected_ = rb.GetBitmapNamed(IDR_O2_MORE_SELECTED);
- // All icons are assumed to be square, and the same size.
- icon_size_ = icon_url_->width();
- initialized_ = true;
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
// AutocompletePopupContentsView, public:
@@ -558,10 +501,10 @@ AutocompletePopupContentsView::AutocompletePopupContentsView(
AutocompleteEditView* edit_view,
AutocompleteEditModel* edit_model,
Profile* profile,
- const BubblePositioner* bubble_positioner)
+ const views::View* location_bar)
: model_(new AutocompletePopupModel(this, edit_model, profile)),
edit_view_(edit_view),
- bubble_positioner_(bubble_positioner),
+ location_bar_(location_bar),
result_font_(font.DeriveFont(kEditFontAdjust)),
ignore_mouse_drag_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) {
@@ -637,10 +580,13 @@ void AutocompletePopupContentsView::UpdatePopupAppearance() {
}
// Calculate desired bounds.
- gfx::Rect location_stack_bounds =
- bubble_positioner_->GetLocationStackBounds();
- gfx::Rect new_target_bounds(bubble_border_->GetBounds(location_stack_bounds,
- gfx::Size(location_stack_bounds.width(), total_child_height)));
+ gfx::Rect location_bar_bounds(location_bar_->bounds());
+ gfx::Point location;
+ views::View::ConvertPointToScreen(location_bar_, &location);
+ location_bar_bounds.set_origin(location);
+ location_bar_bounds.set_height(location_bar_bounds.height() - 1);
+ gfx::Rect new_target_bounds(bubble_border_->GetBounds(location_bar_bounds,
+ gfx::Size(location_bar_bounds.width(), total_child_height)));
// If we're animating and our target height changes, reset the animation.
// NOTE: If we just reset blindly on _every_ update, then when the user types
@@ -847,7 +793,19 @@ void AutocompletePopupContentsView::MakeContentsPath(
SkIntToScalar(bounding_rect.bottom()));
SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius());
- path->addRoundRect(rect, radius, radius);
+ SkScalar scaled_radius =
+ SkScalarMul(radius, (SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3);
+ path->moveTo(rect.fRight, rect.fTop);
+ path->lineTo(rect.fRight, rect.fBottom - radius);
+ path->cubicTo(rect.fRight, rect.fBottom - radius + scaled_radius,
+ rect.fRight - radius + scaled_radius, rect.fBottom,
+ rect.fRight - radius, rect.fBottom);
+ path->lineTo(rect.fLeft + radius, rect.fBottom);
+ path->cubicTo(rect.fLeft + radius - scaled_radius, rect.fBottom,
+ rect.fLeft, rect.fBottom - radius + scaled_radius,
+ rect.fLeft, rect.fBottom - radius);
+ path->lineTo(rect.fLeft, rect.fTop);
+ path->close();
}
void AutocompletePopupContentsView::UpdateBlurRegion() {
@@ -920,14 +878,3 @@ size_t AutocompletePopupContentsView::GetIndexForPoint(
}
return AutocompletePopupModel::kNoMatch;
}
-
-// static
-AutocompletePopupView* AutocompletePopupView::CreatePopupView(
- const gfx::Font& font,
- AutocompleteEditView* edit_view,
- AutocompleteEditModel* edit_model,
- Profile* profile,
- const BubblePositioner* bubble_positioner) {
- return new AutocompletePopupContentsView(font, edit_view, edit_model,
- profile, bubble_positioner);
-}
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
index 30a9bf1..d814206 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h
@@ -45,7 +45,7 @@ class AutocompletePopupContentsView : public views::View,
AutocompleteEditView* edit_view,
AutocompleteEditModel* edit_model,
Profile* profile,
- const BubblePositioner* bubble_positioner);
+ const views::View* location_bar);
virtual ~AutocompletePopupContentsView();
// Returns the bounds the popup should be shown at. This is the display bounds
@@ -125,8 +125,8 @@ class AutocompletePopupContentsView : public views::View,
// The edit view that invokes us.
AutocompleteEditView* edit_view_;
- // An object that tells the popup how to position itself.
- const BubblePositioner* bubble_positioner_;
+ // An object that the popup positions itself against.
+ const views::View* location_bar_;
// Our border, which can compute our desired bounds.
const BubbleBorder* bubble_border_;
diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc
index 34f8e91..bd61ab3 100644
--- a/chrome/browser/views/bookmark_editor_view.cc
+++ b/chrome/browser/views/bookmark_editor_view.cc
@@ -282,10 +282,9 @@ void BookmarkEditorView::Init() {
std::wstring languages = profile_
? profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)
: std::wstring();
- // The following URL is user-editable. We specify omit_username_password=
- // false and unescape=false to show the original URL except IDN.
+ // The following URL is user-editable, so we don't strip anything from it.
url_text = net::FormatUrl(details_.existing_node->GetURL(), languages,
- false, UnescapeRule::NONE, NULL, NULL, NULL);
+ net::kFormatUrlOmitNothing, UnescapeRule::NONE, NULL, NULL, NULL);
}
url_tf_.SetText(url_text);
url_tf_.SetController(this);
diff --git a/chrome/browser/views/browser_views_accessibility_browsertest.cc b/chrome/browser/views/browser_views_accessibility_browsertest.cc
index ac20277..6a5bcf1 100644
--- a/chrome/browser/views/browser_views_accessibility_browsertest.cc
+++ b/chrome/browser/views/browser_views_accessibility_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -218,7 +218,8 @@ IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest, TestHomeButtonAccObj) {
}
// Retrieve accessibility object for Star button and verify accessibility info.
-IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest, TestStarButtonAccObj) {
+IN_PROC_BROWSER_TEST_F(BrowserViewsAccessibilityTest,
+ TestStarButtonAccObj) {
// Verify Star button MSAA name and role.
TestViewAccessibilityObject(
GetToolbarView()->GetViewByID(VIEW_ID_STAR_BUTTON),
diff --git a/chrome/browser/views/bubble_border.cc b/chrome/browser/views/bubble_border.cc
index 230a0f4..3548286 100644
--- a/chrome/browser/views/bubble_border.cc
+++ b/chrome/browser/views/bubble_border.cc
@@ -1,6 +1,6 @@
-// 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.
+// Copyright (c) 2010 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/bubble_border.h"
@@ -31,10 +31,6 @@ static const int kArrowInteriorHeight = 7;
gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
const gfx::Size& contents_size) const {
- // The spacing (in pixels) between |position_relative_to| and the bubble
- // content.
- const int kBubbleSpacing = 2;
-
// Desired size is size of contents enlarged by the size of the border images.
gfx::Size border_size(contents_size);
gfx::Insets insets;
@@ -43,33 +39,40 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
insets.top() + insets.bottom());
// Screen position depends on the arrow location.
+ // The arrow should overlap the target by some amount since the bottom arrow
+ // has lots of shadow below it and the top arrow is given an equivalent amount
+ // of padding.
+ const int kArrowOverlap = 3;
int x = position_relative_to.x() + (position_relative_to.width() / 2);
+ int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ :
+ arrow_x_offset_;
if (arrow_is_left())
- x -= arrow_x_offset_;
+ x -= arrow_offset;
else if (arrow_location_ == NONE)
x -= ((contents_size.width() / 2) + insets.left());
else
- x += (arrow_x_offset_ - border_size.width() + 1);
+ x += (arrow_offset - border_size.width() + 1);
int y = position_relative_to.y();
- if (arrow_is_top()) {
- y += (position_relative_to.height() -
- (top_arrow_->height() - kBubbleSpacing));
- } else if (arrow_location_ == NONE) {
- y += (position_relative_to.height() - (top_->height() - kBubbleSpacing));
- } else {
- y += ((bottom_arrow_->height() - kBubbleSpacing) - border_size.height());
- }
+ if (arrow_is_bottom())
+ y += (kArrowOverlap - border_size.height());
+ else if (arrow_location_ == NONE)
+ y += position_relative_to.height();
+ else
+ y += (position_relative_to.height() - kArrowOverlap);
return gfx::Rect(x, y, border_size.width(), border_size.height());
}
void BubbleBorder::GetInsets(gfx::Insets* insets) const {
- int top = top_->height();
- int bottom = bottom_->height();
- if (arrow_is_top())
- top = std::max(top, top_arrow_->height());
- else if (arrow_location_ != NONE)
- bottom = std::max(bottom, bottom_arrow_->height());
+ int top, bottom;
+ if (arrow_is_bottom()) {
+ top = top_->height();
+ bottom = std::max(bottom_->height(), bottom_arrow_->height());
+ } else {
+ top = (arrow_location_ == NONE) ?
+ 0 : std::max(top_->height(), top_arrow_->height());
+ bottom = bottom_->height();
+ }
insets->Set(top, left_->width(), bottom, right_->width());
}
@@ -102,7 +105,7 @@ void BubbleBorder::InitClass() {
}
void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
- // Convenience shorthand variables
+ // Convenience shorthand variables.
int width = view.width();
int tl_width = top_left_->width();
int tl_height = top_left_->height();
@@ -132,25 +135,33 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
* border_bottom∙∙∙∙└────┴─┤ ▼ ├──────┤ ▼ ├─┴────┘
* view.height()∙∙∙∙∙∙∙∙∙∙∙└───┘ └───┘
*
- * (At most one of the arrows will be drawn)
+ * If |arrow_location_| == NONE, the entire top edge is ommitted, and
+ * |tl_bottom| == |tr_bottom| == 0. Otherwise, one of the four arrows will be
+ * drawn.
*/
gfx::Insets insets;
GetInsets(&insets);
int top = insets.top();
- int border_top = top - t_height;
- int tl_bottom = border_top + tl_height;
- int tr_bottom = border_top + tr_height;
int bottom = view.height() - insets.bottom();
int border_bottom = bottom + b_height;
int bl_y = border_bottom - bl_height;
int br_y = border_bottom - br_height;
- // Top left corner
- canvas->DrawBitmapInt(*top_left_, 0, border_top);
+ int border_top, tl_bottom, tr_bottom;
+ if (arrow_location_ == NONE) {
+ border_top = tl_bottom = tr_bottom = 0;
+ } else {
+ border_top = top - t_height;
+ tl_bottom = border_top + tl_height;
+ tr_bottom = border_top + tr_height;
+
+ // Top left corner
+ canvas->DrawBitmapInt(*top_left_, 0, border_top);
- // Top right corner
- canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top);
+ // Top right corner
+ canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top);
+ }
// Right edge
canvas->TileImageInt(*right_, width - r_width, tr_bottom, r_width,
@@ -167,7 +178,7 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
canvas->TileImageInt(*left_, 0, tl_bottom, left_->width(), bl_y - tl_bottom);
// Arrow edge, if necessary
- bool should_draw_top_edge = true;
+ bool should_draw_top_edge = false;
bool should_draw_bottom_edge = true;
if (arrow_location_ != NONE) {
/* Here's what the variables below mean (without loss of generality):
@@ -194,17 +205,8 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
SkBitmap* arrow;
int left_of_edge, right_of_edge, edge_y, arrow_y;
SkScalar border_y, tip_y;
- if (arrow_is_top()) {
- should_draw_top_edge = false;
- edge = top_;
- arrow = top_arrow_;
- left_of_edge = tl_width;
- right_of_edge = tr_width;
- edge_y = border_top;
- arrow_y = top - top_arrow_->height();
- border_y = SkIntToScalar(top);
- tip_y = SkIntToScalar(top - kArrowInteriorHeight);
- } else {
+ if (arrow_is_bottom()) {
+ should_draw_top_edge = true;
should_draw_bottom_edge = false;
edge = bottom_;
arrow = bottom_arrow_;
@@ -213,10 +215,21 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
edge_y = arrow_y = bottom;
border_y = SkIntToScalar(bottom);
tip_y = SkIntToScalar(bottom + kArrowInteriorHeight);
+ } else {
+ edge = top_;
+ arrow = top_arrow_;
+ left_of_edge = tl_width;
+ right_of_edge = tr_width;
+ edge_y = border_top;
+ arrow_y = top - top_arrow_->height();
+ border_y = SkIntToScalar(top);
+ tip_y = SkIntToScalar(top - kArrowInteriorHeight);
}
- int arrow_width = (arrow_is_top() ? top_arrow_ : bottom_arrow_)->width();
+ int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ :
+ arrow_x_offset_;
+ int arrow_width = arrow->width();
int arrow_center = arrow_is_left() ?
- arrow_x_offset_ : width - arrow_x_offset_ - 1;
+ arrow_offset : width - arrow_offset - 1;
int arrow_x = arrow_center - (arrow_width / 2);
SkScalar arrow_interior_x =
SkIntToScalar(arrow_center - kArrowInteriorHeight);
@@ -271,6 +284,8 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
// The border of this view creates an anti-aliased round-rect region for the
// contents, which we need to fill with the background color.
+ // NOTE: This doesn't handle an arrow location of "NONE", which has square top
+ // corners.
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kFill_Style);
diff --git a/chrome/browser/views/bubble_border.h b/chrome/browser/views/bubble_border.h
index 3b48048..3670503 100644
--- a/chrome/browser/views/bubble_border.h
+++ b/chrome/browser/views/bubble_border.h
@@ -1,6 +1,6 @@
-// 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.
+// Copyright (c) 2010 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_BUBBLE_BORDER_H_
#define CHROME_BROWSER_VIEWS_BUBBLE_BORDER_H_
@@ -11,8 +11,11 @@
class SkBitmap;
-// Renders a round-rect border, with optional arrow (off by default), and a
-// custom dropshadow. This can be used to produce floating "bubble" objects.
+// Renders a border, with optional arrow (off by default), and a custom
+// dropshadow. This can be used to produce floating "bubble" objects.
+//
+// If the arrow is on, the bubble has four round corner. If not, it has round
+// corners on the bottom and square corners on the top, and lacks a top border.
class BubbleBorder : public views::Border {
public:
// Possible locations for the (optional) arrow.
@@ -24,7 +27,9 @@ class BubbleBorder : public views::Border {
BOTTOM_RIGHT
};
- BubbleBorder() : arrow_location_(NONE), background_color_(SK_ColorWHITE) {
+ BubbleBorder() : override_arrow_x_offset_(0),
+ arrow_location_(NONE),
+ background_color_(SK_ColorWHITE) {
InitClass();
}
@@ -42,6 +47,12 @@ class BubbleBorder : public views::Border {
arrow_location_ = arrow_location;
}
+ // Sets a fixed x offset for the arrow. The arrow will still point to the
+ // same location but the bubble will shift horizontally to make that happen.
+ void set_arrow_offset(int offset) {
+ override_arrow_x_offset_ = offset;
+ }
+
// Sets the background color for the arrow body. This is irrelevant if you do
// not also set the arrow location to something other than NONE.
void set_background_color(SkColor background_color) {
@@ -68,9 +79,10 @@ class BubbleBorder : public views::Border {
virtual ~BubbleBorder() { }
- // Returns true if there is an arrow and it is positioned on the top edge.
- bool arrow_is_top() const {
- return (arrow_location_ == TOP_LEFT) || (arrow_location_ == TOP_RIGHT);
+ // Returns true if there is an arrow and it is positioned on the bottom edge.
+ bool arrow_is_bottom() const {
+ return (arrow_location_ == BOTTOM_LEFT) ||
+ (arrow_location_ == BOTTOM_RIGHT);
}
// Returns true if there is an arrow and it is positioned on the left side.
@@ -95,6 +107,9 @@ class BubbleBorder : public views::Border {
static int arrow_x_offset_;
+ // If specified, overrides the pre-calculated |arrow_x_offset_| of the arrow.
+ int override_arrow_x_offset_;
+
ArrowLocation arrow_location_;
SkColor background_color_;
diff --git a/chrome/browser/views/constrained_window_win.cc b/chrome/browser/views/constrained_window_win.cc
index 488f1a4..c70ec75 100644
--- a/chrome/browser/views/constrained_window_win.cc
+++ b/chrome/browser/views/constrained_window_win.cc
@@ -34,6 +34,7 @@
#include "views/window/client_view.h"
#include "views/window/non_client_view.h"
#include "views/window/window_resources.h"
+#include "views/window/window_shape.h"
using base::TimeDelta;
@@ -349,24 +350,7 @@ int ConstrainedWindowFrameView::NonClientHitTest(const gfx::Point& point) {
void ConstrainedWindowFrameView::GetWindowMask(const gfx::Size& size,
gfx::Path* window_mask) {
DCHECK(window_mask);
-
- // Redefine the window visible region for the new size.
- window_mask->moveTo(0, 3);
- window_mask->lineTo(1, 2);
- window_mask->lineTo(1, 1);
- window_mask->lineTo(2, 1);
- window_mask->lineTo(3, 0);
-
- window_mask->lineTo(SkIntToScalar(size.width() - 3), 0);
- window_mask->lineTo(SkIntToScalar(size.width() - 2), 1);
- window_mask->lineTo(SkIntToScalar(size.width() - 1), 1);
- window_mask->lineTo(SkIntToScalar(size.width() - 1), 2);
- window_mask->lineTo(SkIntToScalar(size.width()), 3);
-
- window_mask->lineTo(SkIntToScalar(size.width()),
- SkIntToScalar(size.height()));
- window_mask->lineTo(0, SkIntToScalar(size.height()));
- window_mask->close();
+ views::GetDefaultWindowMask(size, window_mask);
}
void ConstrainedWindowFrameView::EnableClose(bool enable) {
diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc
index d12963f..0092fa7 100644
--- a/chrome/browser/views/frame/browser_frame_win.cc
+++ b/chrome/browser/views/frame/browser_frame_win.cc
@@ -28,6 +28,9 @@
// static
static const int kClientEdgeThickness = 3;
static const int kTabDragWindowAlpha = 200;
+// We need to offset the DWMFrame into the toolbar so that the blackness
+// doesn't show up on our rounded corners.
+static const int kDWMFrameTopOffset = 3;
// static (Factory method.)
BrowserFrame* BrowserFrame::Create(BrowserView* browser_view,
@@ -303,7 +306,8 @@ void BrowserFrameWin::UpdateDWMFrame() {
margins.cyTopHeight += GetSystemMetrics(SM_CYSIZEFRAME);
} else {
margins.cyTopHeight =
- GetBoundsForTabStrip(browser_view_->tabstrip()).bottom();
+ GetBoundsForTabStrip(browser_view_->tabstrip()).bottom() +
+ kDWMFrameTopOffset;
}
}
} else {
diff --git a/chrome/browser/views/frame/browser_root_view.cc b/chrome/browser/views/frame/browser_root_view.cc
index d789b94..d2985dd 100644
--- a/chrome/browser/views/frame/browser_root_view.cc
+++ b/chrome/browser/views/frame/browser_root_view.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -7,9 +7,10 @@
#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
#include "app/os_exchange_data.h"
+#include "chrome/browser/autocomplete/autocomplete.h"
+#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/profile.h"
-#include "chrome/browser/search_versus_navigate_classifier.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/browser/views/tabs/tab_strip.h"
@@ -141,13 +142,13 @@ bool BrowserRootView::GetPasteAndGoURL(const OSExchangeData& data, GURL* url) {
if (!data.GetString(&text) || text.empty())
return false;
- GURL destination_url;
- browser_view_->browser()->profile()->GetSearchVersusNavigateClassifier()->
- Classify(text, std::wstring(), NULL, &destination_url, NULL, NULL, NULL);
- if (!destination_url.is_valid())
+ AutocompleteMatch match;
+ browser_view_->browser()->profile()->GetAutocompleteClassifier()->Classify(
+ text, std::wstring(), &match, NULL);
+ if (!match.destination_url.is_valid())
return false;
if (url)
- *url = destination_url;
+ *url = match.destination_url;
return true;
}
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 732a1fb..614659e 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -8,20 +8,13 @@
#include <gtk/gtk.h>
#endif
-#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
-#include "app/os_exchange_data.h"
#include "app/resource_bundle.h"
-#include "base/command_line.h"
#include "base/i18n/rtl.h"
-#include "base/keyboard_codes.h"
-#include "base/time.h"
-#include "build/build_config.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_modal_dialog_queue.h"
#include "chrome/browser/automation/ui_controls.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_theme_provider.h"
@@ -30,40 +23,30 @@
#include "chrome/browser/ntp_background_util.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/browser/pref_service.h"
-#include "chrome/browser/profile.h"
+#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/accessible_view_helper.h"
#include "chrome/browser/views/bookmark_bar_view.h"
-#include "chrome/browser/views/browser_bubble.h"
#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/views/chrome_views_delegate.h"
#include "chrome/browser/views/download_shelf_view.h"
#include "chrome/browser/views/extensions/extension_shelf.h"
-#include "chrome/browser/views/frame/browser_view_layout.h"
#include "chrome/browser/views/frame/browser_extender.h"
-#include "chrome/browser/views/frame/browser_frame.h"
+#include "chrome/browser/views/frame/browser_view_layout.h"
#include "chrome/browser/views/fullscreen_exit_bubble.h"
-#include "chrome/browser/views/infobars/infobar_container.h"
#include "chrome/browser/views/status_bubble_views.h"
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
#include "chrome/browser/views/tabs/browser_tab_strip_controller.h"
#include "chrome/browser/views/tabs/side_tab_strip.h"
-#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/browser/views/theme_install_bubble_view.h"
-#include "chrome/browser/views/toolbar_star_toggle.h"
#include "chrome/browser/views/toolbar_view.h"
-#include "chrome/browser/sessions/tab_restore_service.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/native_window_notification_source.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "gfx/canvas.h"
-#include "gfx/scrollbar_size.h"
#include "grit/app_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -71,14 +54,11 @@
#include "grit/theme_resources.h"
#include "grit/webkit_resources.h"
#include "views/controls/single_split_view.h"
-#include "views/fill_layout.h"
#include "views/focus/external_focus_tracker.h"
#include "views/focus/view_storage.h"
#include "views/grid_layout.h"
-#include "views/view.h"
#include "views/widget/root_view.h"
#include "views/window/dialog_delegate.h"
-#include "views/window/non_client_view.h"
#include "views/window/window.h"
#if defined(OS_WIN)
@@ -789,7 +769,7 @@ void BrowserView::UpdateLoadingAnimations(bool should_animate) {
}
void BrowserView::SetStarredState(bool is_starred) {
- toolbar_->star_button()->SetToggled(is_starred);
+ toolbar_->location_bar()->SetStarToggled(is_starred);
}
gfx::Rect BrowserView::GetRestoredBounds() const {
@@ -969,7 +949,7 @@ void BrowserView::ShowBookmarkManager() {
}
void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) {
- toolbar_->star_button()->ShowStarBubble(url, !already_bookmarked);
+ toolbar_->location_bar()->ShowStarBubble(url, !already_bookmarked);
}
void BrowserView::SetDownloadShelfVisible(bool visible) {
diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc
index 608fea9..9a665f7 100644
--- a/chrome/browser/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/views/frame/glass_browser_frame_view.cc
@@ -40,6 +40,8 @@ const int kOTRBottomSpacing = 2;
// There are 2 px on each side of the OTR avatar (between the frame border and
// it on the left, and between it and the tabstrip on the right).
const int kOTRSideSpacing = 2;
+// The content left/right images have a shadow built into them.
+const int kContentEdgeShadowThickness = 2;
// The top 1 px of the tabstrip is shadow; in maximized mode we push this off
// the top of the screen so the tabs appear flush against the screen edge.
const int kTabstripTopShadowThickness = 1;
@@ -261,19 +263,46 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
toolbar_bounds.x() - 1, toolbar_bounds.y() + 2,
toolbar_bounds.width() + 2, theme_toolbar->height());
- SkBitmap* toolbar_left =
- tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER);
- canvas->DrawBitmapInt(*toolbar_left,
- toolbar_bounds.x() - toolbar_left->width(),
- toolbar_bounds.y());
-
+ // Draw rounded corners for the tab.
+ SkBitmap* toolbar_left_mask =
+ tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK);
+ SkBitmap* toolbar_right_mask =
+ tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK);
+
+ // We mask out the corners by using the DestinationIn transfer mode,
+ // which keeps the RGB pixels from the destination and the alpha from
+ // the source.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+
+ // Mask out the top left corner.
+ int left_x = toolbar_bounds.x() - kContentEdgeShadowThickness -
+ kClientEdgeThickness;
+ canvas->DrawBitmapInt(*toolbar_left_mask,
+ left_x, toolbar_bounds.y(), paint);
+
+ // Mask out the top right corner.
+ int right_x = toolbar_bounds.right() - toolbar_right_mask->width() +
+ kContentEdgeShadowThickness + kClientEdgeThickness;
+ canvas->DrawBitmapInt(*toolbar_right_mask,
+ right_x, toolbar_bounds.y(),
+ paint);
+
+ // Draw left edge.
+ SkBitmap* toolbar_left = tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER);
+ canvas->DrawBitmapInt(*toolbar_left, left_x, toolbar_bounds.y());
+
+ // Draw center edge.
SkBitmap* toolbar_center =
tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER);
- canvas->TileImageInt(*toolbar_center, toolbar_bounds.x(), toolbar_bounds.y(),
- toolbar_bounds.width(), toolbar_center->height());
+ canvas->TileImageInt(*toolbar_center, left_x + toolbar_left->width(),
+ toolbar_bounds.y(),
+ right_x - (left_x + toolbar_left->width()),
+ toolbar_center->height());
+ // Right edge.
canvas->DrawBitmapInt(*tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER),
- toolbar_bounds.right(), toolbar_bounds.y());
+ right_x, toolbar_bounds.y());
// Draw the content/toolbar separator.
canvas->DrawLineInt(ResourceBundle::toolbar_separator_color,
diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc
index e9276f8..c91cb51 100644
--- a/chrome/browser/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc
@@ -26,6 +26,7 @@
#include "views/widget/root_view.h"
#include "views/window/window.h"
#include "views/window/window_resources.h"
+#include "views/window/window_shape.h"
#if defined(OS_WIN)
#include "app/win_util.h"
@@ -58,6 +59,8 @@ const int kResizeAreaCornerSize = 16;
// The titlebar never shrinks too short to show the caption button plus some
// padding below it.
const int kCaptionButtonHeightWithPadding = 19;
+// The content left/right images have a shadow built into them.
+const int kContentEdgeShadowThickness = 2;
// The titlebar has a 2 px 3D edge along the top and bottom.
const int kTitlebarTopAndBottomEdgeThickness = 2;
// The icon is inset 2 px from the left frame border.
@@ -89,6 +92,9 @@ const int kNewTabCaptionRestoredSpacing = 5;
// similar vertical coordinates, we need to reserve a larger, 16 px gap to avoid
// looking too cluttered.
const int kNewTabCaptionMaximizedSpacing = 16;
+// How far to indent the tabstrip from the left side of the screen when there
+// is no OTR icon.
+const int kTabStripIndent = 1;
}
///////////////////////////////////////////////////////////////////////////////
@@ -188,7 +194,7 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip(
BaseTabStrip* tabstrip) const {
int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ?
(otr_avatar_icon_->bounds().right() + kOTRSideSpacing) :
- NonClientBorderThickness();
+ NonClientBorderThickness() + kTabStripIndent;
int tabstrip_width = minimize_button_->x() - tabstrip_x -
(frame_->GetWindow()->IsMaximized() ?
kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing);
@@ -298,23 +304,7 @@ void OpaqueBrowserFrameView::GetWindowMask(const gfx::Size& size,
if (frame_->GetWindow()->IsMaximized() || frame_->GetWindow()->IsFullscreen())
return;
- // Redefine the window visible region for the new size.
- window_mask->moveTo(0, 3);
- window_mask->lineTo(1, 2);
- window_mask->lineTo(1, 1);
- window_mask->lineTo(2, 1);
- window_mask->lineTo(3, 0);
-
- window_mask->lineTo(SkIntToScalar(size.width() - 3), 0);
- window_mask->lineTo(SkIntToScalar(size.width() - 2), 1);
- window_mask->lineTo(SkIntToScalar(size.width() - 1), 1);
- window_mask->lineTo(SkIntToScalar(size.width() - 1), 2);
- window_mask->lineTo(SkIntToScalar(size.width()), 3);
-
- window_mask->lineTo(SkIntToScalar(size.width()),
- SkIntToScalar(size.height()));
- window_mask->lineTo(0, SkIntToScalar(size.height()));
- window_mask->close();
+ views::GetDefaultWindowMask(size, window_mask);
}
void OpaqueBrowserFrameView::EnableClose(bool enable) {
@@ -717,6 +707,17 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
int bottom_edge_height =
std::min(toolbar_left->height(), toolbar_bounds.height()) - split_point;
+ // Split our canvas out so we can mask out the corners of the toolbar
+ // without masking out the frame.
+ SkRect bounds;
+ bounds.set(SkIntToScalar(toolbar_bounds.x() - kClientEdgeThickness),
+ SkIntToScalar(toolbar_bounds.y()),
+ SkIntToScalar(toolbar_bounds.x() + toolbar_bounds.width() +
+ kClientEdgeThickness * 2),
+ SkIntToScalar(toolbar_bounds.y() + toolbar_bounds.height()));
+ canvas->saveLayerAlpha(&bounds, 255);
+ canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
+
SkColor theme_toolbar_color =
tp->GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
canvas->FillRectInt(theme_toolbar_color, toolbar_bounds.x(), bottom_y,
@@ -732,26 +733,65 @@ void OpaqueBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
toolbar_bounds.width() + (2 * kClientEdgeThickness),
theme_toolbar->height());
+ // Draw rounded corners for the tab.
+ SkBitmap* toolbar_left_mask =
+ tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER_MASK);
+ SkBitmap* toolbar_right_mask =
+ tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER_MASK);
+
+ // We mask out the corners by using the DestinationIn transfer mode,
+ // which keeps the RGB pixels from the destination and the alpha from
+ // the source.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+
+ // Make the left edge.
+ int left_x = toolbar_bounds.x() - kClientEdgeThickness -
+ kContentEdgeShadowThickness;
+ canvas->DrawBitmapInt(*toolbar_left_mask, 0, 0,
+ toolbar_left_mask->width(), split_point,
+ left_x, toolbar_bounds.y(),
+ toolbar_left_mask->width(), split_point, false, paint);
+ canvas->DrawBitmapInt(*toolbar_left_mask, 0,
+ toolbar_left_mask->height() - bottom_edge_height,
+ toolbar_left_mask->width(), bottom_edge_height,
+ left_x, bottom_y,
+ toolbar_left_mask->width(), bottom_edge_height, false, paint);
+
+ // Mask the right edge.
+ int right_x = toolbar_bounds.right() -
+ toolbar_right_mask->width() + kClientEdgeThickness +
+ kContentEdgeShadowThickness;
+ canvas->DrawBitmapInt(*toolbar_right_mask, 0, 0,
+ toolbar_right_mask->width(), split_point, right_x, toolbar_bounds.y(),
+ toolbar_right_mask->width(), split_point, false, paint);
+ canvas->DrawBitmapInt(*toolbar_right_mask, 0,
+ toolbar_right_mask->height() - bottom_edge_height,
+ toolbar_right_mask->width(), bottom_edge_height, right_x, bottom_y,
+ toolbar_right_mask->width(), bottom_edge_height, false, paint);
+ canvas->restore();
+
canvas->DrawBitmapInt(*toolbar_left, 0, 0, toolbar_left->width(), split_point,
- toolbar_bounds.x() - toolbar_left->width(), toolbar_bounds.y(),
+ left_x, toolbar_bounds.y(),
toolbar_left->width(), split_point, false);
canvas->DrawBitmapInt(*toolbar_left, 0,
toolbar_left->height() - bottom_edge_height, toolbar_left->width(),
- bottom_edge_height, toolbar_bounds.x() - toolbar_left->width(), bottom_y,
+ bottom_edge_height, left_x, bottom_y,
toolbar_left->width(), bottom_edge_height, false);
SkBitmap* toolbar_center =
tp->GetBitmapNamed(IDR_CONTENT_TOP_CENTER);
- canvas->TileImageInt(*toolbar_center, 0, 0, toolbar_bounds.x(),
- toolbar_bounds.y(), toolbar_bounds.width(), split_point);
+ canvas->TileImageInt(*toolbar_center, 0, 0, left_x + toolbar_left->width(),
+ toolbar_bounds.y(), right_x - (left_x + toolbar_left->width()),
+ split_point);
SkBitmap* toolbar_right = tp->GetBitmapNamed(IDR_CONTENT_TOP_RIGHT_CORNER);
canvas->DrawBitmapInt(*toolbar_right, 0, 0, toolbar_right->width(),
- split_point, toolbar_bounds.right(), toolbar_bounds.y(),
+ split_point, right_x, toolbar_bounds.y(),
toolbar_right->width(), split_point, false);
canvas->DrawBitmapInt(*toolbar_right, 0,
toolbar_right->height() - bottom_edge_height, toolbar_right->width(),
- bottom_edge_height, toolbar_bounds.right(), bottom_y,
+ bottom_edge_height, right_x, bottom_y,
toolbar_right->width(), bottom_edge_height, false);
// Draw the content/toolbar separator.
diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc
index e5c4858..8150db9 100644
--- a/chrome/browser/views/info_bubble.cc
+++ b/chrome/browser/views/info_bubble.cc
@@ -29,55 +29,17 @@ const SkColor InfoBubble::kBackgroundColor =
const SkColor InfoBubble::kBackgroundColor = SK_ColorWHITE;
#endif
-// BorderContents -------------------------------------------------------------
-
-// This is used to paint the border of the InfoBubble. Windows uses this via
-// BorderWidget (see below), while others can use it directly in the bubble.
-class BorderContents : public views::View {
- public:
- BorderContents() { }
-
- // Given the size of the contents and the rect to point at, initializes the
- // bubble and returns the bounds of both the border
- // and the contents inside the bubble.
- // |prefer_arrow_on_right| specifies the preferred location for the arrow
- // anchor. If the bubble does not fit on the monitor, the arrow location may
- // changed so it can.
- //
- // TODO(pkasting): Maybe this should use mirroring transformations instead,
- // which would hopefully simplify this code.
- void InitAndGetBounds(
- const gfx::Rect& position_relative_to, // In screen coordinates
- const gfx::Size& contents_size,
- bool prefer_arrow_on_right,
- gfx::Rect* contents_bounds, // Returned in window coordinates
- gfx::Rect* window_bounds); // Returned in screen coordinates
-
- private:
- virtual ~BorderContents() { }
-
- // Overridden from View:
- virtual void Paint(gfx::Canvas* canvas);
-
- DISALLOW_COPY_AND_ASSIGN(BorderContents);
-};
-
void BorderContents::InitAndGetBounds(
const gfx::Rect& position_relative_to,
const gfx::Size& contents_size,
bool prefer_arrow_on_right,
gfx::Rect* contents_bounds,
gfx::Rect* window_bounds) {
- // Margins between the contents and the inside of the border, in pixels.
- const int kLeftMargin = 6;
- const int kTopMargin = 6;
- const int kRightMargin = 6;
- const int kBottomMargin = 9;
-
// Set the border.
- BubbleBorder* bubble_border = new BubbleBorder;
- set_border(bubble_border);
- bubble_border->set_background_color(InfoBubble::kBackgroundColor);
+ if (!bubble_border_)
+ bubble_border_ = new BubbleBorder;
+ set_border(bubble_border_);
+ bubble_border_->set_background_color(InfoBubble::kBackgroundColor);
// Give the contents a margin.
gfx::Size local_contents_size(contents_size);
@@ -88,9 +50,9 @@ void BorderContents::InitAndGetBounds(
// bounds.
BubbleBorder::ArrowLocation arrow_location(prefer_arrow_on_right ?
BubbleBorder::TOP_RIGHT : BubbleBorder::TOP_LEFT);
- bubble_border->set_arrow_location(arrow_location);
+ bubble_border_->set_arrow_location(arrow_location);
*window_bounds =
- bubble_border->GetBounds(position_relative_to, local_contents_size);
+ bubble_border_->GetBounds(position_relative_to, local_contents_size);
// See if those bounds will fit on the monitor.
scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
@@ -109,10 +71,10 @@ void BorderContents::InitAndGetBounds(
arrow_location = arrow_on_left ?
BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
}
- bubble_border->set_arrow_location(arrow_location);
+ bubble_border_->set_arrow_location(arrow_location);
// Now get the recalculated bounds.
- *window_bounds = bubble_border->GetBounds(position_relative_to,
+ *window_bounds = bubble_border_->GetBounds(position_relative_to,
local_contents_size);
}
@@ -120,7 +82,7 @@ void BorderContents::InitAndGetBounds(
// subtracting the border dimensions and margin amounts.
*contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size());
gfx::Insets insets;
- bubble_border->GetInsets(&insets);
+ bubble_border_->GetInsets(&insets);
contents_bounds->Inset(insets.left() + kLeftMargin, insets.top() + kTopMargin,
insets.right() + kRightMargin, insets.bottom() + kBottomMargin);
}
@@ -128,6 +90,8 @@ void BorderContents::InitAndGetBounds(
void BorderContents::Paint(gfx::Canvas* canvas) {
// The border of this view creates an anti-aliased round-rect region for the
// contents, which we need to fill with the background color.
+ // NOTE: This doesn't handle an arrow location of "NONE", which has square top
+ // corners.
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kFill_Style);
@@ -150,7 +114,7 @@ void BorderContents::Paint(gfx::Canvas* canvas) {
#if defined(OS_WIN)
// BorderWidget ---------------------------------------------------------------
-BorderWidget::BorderWidget() {
+BorderWidget::BorderWidget() : border_contents_(NULL) {
set_delete_on_destroy(false); // Our owner will free us manually.
set_window_style(WS_POPUP);
set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED);
@@ -163,15 +127,16 @@ gfx::Rect BorderWidget::InitAndGetBounds(
bool prefer_arrow_on_right) {
// Set up the border view and ask it to calculate our bounds (and our
// contents').
- BorderContents* border_contents = new BorderContents;
+ if (!border_contents_)
+ border_contents_ = new BorderContents;
gfx::Rect contents_bounds, window_bounds;
- border_contents->InitAndGetBounds(position_relative_to, contents_size,
- prefer_arrow_on_right, &contents_bounds,
- &window_bounds);
+ border_contents_->InitAndGetBounds(position_relative_to, contents_size,
+ prefer_arrow_on_right, &contents_bounds,
+ &window_bounds);
// Initialize ourselves.
WidgetWin::Init(GetAncestor(owner, GA_ROOT), window_bounds);
- SetContentsView(border_contents);
+ SetContentsView(border_contents_);
SetWindowPos(owner, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW);
@@ -268,7 +233,8 @@ void InfoBubble::Init(views::Window* parent,
(contents->UILayoutIsRightToLeft() == delegate->PreferOriginSideAnchor());
#if defined(OS_WIN)
- border_.reset(new BorderWidget);
+ if (!border_.get())
+ border_.reset(new BorderWidget);
// Initialize and position the border window.
window_bounds = border_->InitAndGetBounds(GetNativeView(),
position_relative_to, contents->GetPreferredSize(),
diff --git a/chrome/browser/views/info_bubble.h b/chrome/browser/views/info_bubble.h
index 90911b5..ea80b0f 100644
--- a/chrome/browser/views/info_bubble.h
+++ b/chrome/browser/views/info_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -7,6 +7,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "views/accelerator.h"
+#include "views/view.h"
#if defined(OS_WIN)
#include "views/widget/widget_win.h"
#elif defined(OS_LINUX)
@@ -23,6 +24,7 @@
// have any additional margins.
class BorderWidget;
+class BubbleBorder;
class InfoBubble;
namespace views {
@@ -33,6 +35,46 @@ namespace gfx {
class Path;
}
+// This is used to paint the border of the InfoBubble. Windows uses this via
+// BorderWidget (see below), while others can use it directly in the bubble.
+class BorderContents : public views::View {
+ public:
+ BorderContents() : bubble_border_(NULL) { }
+
+ // Given the size of the contents and the rect to point at, initializes the
+ // bubble and returns the bounds of both the border
+ // and the contents inside the bubble.
+ // |prefer_arrow_on_right| specifies the preferred location for the arrow
+ // anchor. If the bubble does not fit on the monitor, the arrow location may
+ // changed so it can.
+ //
+ // TODO(pkasting): Maybe this should use mirroring transformations instead,
+ // which would hopefully simplify this code.
+ virtual void InitAndGetBounds(
+ const gfx::Rect& position_relative_to, // In screen coordinates
+ const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
+ gfx::Rect* contents_bounds, // Returned in window coordinates
+ gfx::Rect* window_bounds); // Returned in screen coordinates
+
+ protected:
+ virtual ~BorderContents() { }
+
+ // Margins between the contents and the inside of the border, in pixels.
+ static const int kLeftMargin = 6;
+ static const int kTopMargin = 6;
+ static const int kRightMargin = 6;
+ static const int kBottomMargin = 9;
+
+ BubbleBorder* bubble_border_;
+
+ private:
+ // Overridden from View:
+ virtual void Paint(gfx::Canvas* canvas);
+
+ DISALLOW_COPY_AND_ASSIGN(BorderContents);
+};
+
#if defined(OS_WIN)
// This is a window that surrounds the info bubble and paints the margin and
// border. It is a separate window so that it can be a layered window, so that
@@ -47,12 +89,15 @@ class BorderWidget : public views::WidgetWin {
// Given the owning (parent) window, the size of the contained contents
// (without margins), and the rect (in screen coordinates) to point to,
// initializes the window and returns the bounds (in screen coordinates) the
- // contents should use. |is_rtl| is supplied to
+ // contents should use. |is_rtl| is supplied to
// BorderContents::InitAndGetBounds(), see its declaration for details.
- gfx::Rect InitAndGetBounds(HWND owner,
- const gfx::Rect& position_relative_to,
- const gfx::Size& contents_size,
- bool is_rtl);
+ virtual gfx::Rect InitAndGetBounds(HWND owner,
+ const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size,
+ bool is_rtl);
+
+ protected:
+ BorderContents* border_contents_;
private:
// Overridden from WidgetWin:
@@ -82,7 +127,7 @@ class InfoBubbleDelegate {
virtual bool PreferOriginSideAnchor() { return true; }
};
-// TODO: this code is ifdef-tastic. It might be cleaner to refactor the
+// TODO(sky): this code is ifdef-tastic. It might be cleaner to refactor the
// WidgetFoo subclass into a separate class that calls into InfoBubble.
// That way InfoBubble has no (or very few) ifdefs.
class InfoBubble
@@ -120,10 +165,10 @@ class InfoBubble
virtual ~InfoBubble() {}
// Creates the InfoBubble.
- void Init(views::Window* parent,
- const gfx::Rect& position_relative_to,
- views::View* contents,
- InfoBubbleDelegate* delegate);
+ virtual void Init(views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ views::View* contents,
+ InfoBubbleDelegate* delegate);
#if defined(OS_WIN)
// Overridden from WidgetWin:
@@ -133,6 +178,11 @@ class InfoBubble
virtual void IsActiveChanged();
#endif
+#if defined(OS_WIN)
+ // The window used to render the padding, border and arrow.
+ scoped_ptr<BorderWidget> border_;
+#endif
+
private:
// Closes the window notifying the delegate. |closed_by_escape| is true if
// the close is the result of pressing escape.
@@ -147,11 +197,6 @@ class InfoBubble
// The window that this InfoBubble is parented to.
views::Window* parent_;
-#if defined(OS_WIN)
- // The window used to render the padding, border and arrow.
- scoped_ptr<BorderWidget> border_;
-#endif
-
// Have we been closed?
bool closed_;
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index 7a1e4d9..935598c 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#endif
+#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
@@ -16,8 +17,6 @@
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/alternate_nav_url_fetcher.h"
#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/content_setting_bubble_model.h"
#include "chrome/browser/content_setting_image_model.h"
@@ -26,17 +25,15 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/view_ids.h"
-#include "chrome/browser/views/extensions/extension_popup.h"
-#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/browser_dialogs.h"
#include "chrome/browser/views/content_blocked_bubble_contents.h"
-#include "chrome/common/content_settings.h"
+#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/common/platform_util.h"
-#include "chrome/common/pref_names.h"
#include "gfx/canvas.h"
#include "gfx/color_utils.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "net/base/net_util.h"
+#include "views/drag_utils.h"
#if defined(OS_WIN)
#include "chrome/browser/views/first_run_bubble.h"
@@ -47,20 +44,31 @@ using views::View;
// static
const int LocationBarView::kVertMargin = 2;
-// Padding on the right and left of the entry field.
-static const int kEntryPadding = 3;
+// Padding between items in the location bar.
+static const int kViewPadding = 3;
+
+// Padding before the start of a bubble.
+static const int kBubblePadding = kViewPadding - 1;
+
+// Padding between the location icon and the edit, if they're adjacent.
+static const int kLocationIconEditPadding = kViewPadding - 1;
-// Padding between the entry and the leading/trailing views.
-static const int kInnerPadding = 3;
+static const int kEVBubbleBackgroundImages[] = {
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_L,
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_C,
+ IDR_OMNIBOX_EV_BUBBLE_BACKGROUND_R,
+};
+
+static const int kSelectedKeywordBackgroundImages[] = {
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L,
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C,
+ IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R,
+};
static const SkBitmap* kBackground = NULL;
static const SkBitmap* kPopupBackground = NULL;
-// The delay the mouse has to be hovering over the lock/warning icon before the
-// info bubble is shown.
-static const int kInfoBubbleHoverDelayMs = 500;
-
// The tab key image.
static const SkBitmap* kTabButtonBitmap = NULL;
@@ -132,21 +140,23 @@ LocationBarView::LocationBarView(Profile* profile,
CommandUpdater* command_updater,
ToolbarModel* model,
Delegate* delegate,
- bool popup_window_mode,
- const BubblePositioner* bubble_positioner)
+ bool popup_window_mode)
: profile_(profile),
command_updater_(command_updater),
model_(model),
delegate_(delegate),
disposition_(CURRENT_TAB),
+ ALLOW_THIS_IN_INITIALIZER_LIST(location_icon_view_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(ev_bubble_view_(
+ kEVBubbleBackgroundImages, IDR_OMNIBOX_HTTPS_VALID,
+ GetColor(ToolbarModel::EV_SECURE, SECURITY_TEXT), this)),
location_entry_view_(NULL),
- selected_keyword_view_(profile),
+ selected_keyword_view_(kSelectedKeywordBackgroundImages,
+ IDR_OMNIBOX_SEARCH, SK_ColorBLACK, profile),
keyword_hint_view_(profile),
- type_to_search_view_(l10n_util::GetString(IDS_OMNIBOX_EMPTY_TEXT)),
- security_image_view_(this, profile, model, bubble_positioner),
+ star_view_(command_updater),
popup_window_mode_(popup_window_mode),
- first_run_bubble_(this),
- bubble_positioner_(bubble_positioner) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(first_run_bubble_(this)) {
DCHECK(profile_);
SetID(VIEW_ID_LOCATION_BAR);
SetFocusable(true);
@@ -170,52 +180,45 @@ void LocationBarView::Init() {
font_ = font_.DeriveFont(3);
}
+ AddChildView(&location_icon_view_);
+ location_icon_view_.SetVisible(true);
+ location_icon_view_.SetDragController(this);
+ location_icon_view_.set_parent_owned(false);
+
+ AddChildView(&ev_bubble_view_);
+ ev_bubble_view_.SetVisible(false);
+ ev_bubble_view_.SetDragController(this);
+ ev_bubble_view_.set_parent_owned(false);
+
// URL edit field.
// View container for URL edit field.
#if defined(OS_WIN)
- views::Widget* widget = GetWidget();
location_entry_.reset(new AutocompleteEditViewWin(font_, this, model_, this,
- widget->GetNativeView(),
- profile_, command_updater_,
- popup_window_mode_,
- bubble_positioner_));
+ GetWidget()->GetNativeView(), profile_, command_updater_,
+ popup_window_mode_, this));
#else
location_entry_.reset(new AutocompleteEditViewGtk(this, model_, profile_,
- command_updater_,
- popup_window_mode_,
- bubble_positioner_));
+ command_updater_, popup_window_mode_, this));
location_entry_->Init();
// Make all the children of the widget visible. NOTE: this won't display
// anything, it just toggles the visible flag.
- gtk_widget_show_all(location_entry_->widget());
+ gtk_widget_show_all(location_entry_->GetNativeView());
// Hide the widget. NativeViewHostGtk will make it visible again as
// necessary.
- gtk_widget_hide(location_entry_->widget());
+ gtk_widget_hide(location_entry_->GetNativeView());
#endif
location_entry_view_ = new views::NativeViewHost;
location_entry_view_->SetID(VIEW_ID_AUTOCOMPLETE);
AddChildView(location_entry_view_);
location_entry_view_->set_focus_view(this);
- location_entry_view_->Attach(
-#if defined(OS_WIN)
- location_entry_->m_hWnd
-#else
- location_entry_->widget()
-#endif
- ); // NOLINT
+ location_entry_view_->Attach(location_entry_->GetNativeView());
AddChildView(&selected_keyword_view_);
selected_keyword_view_.SetFont(font_);
selected_keyword_view_.SetVisible(false);
selected_keyword_view_.set_parent_owned(false);
- SkColor dimmed_text = GetColor(false, DEEMPHASIZED_TEXT);
-
- AddChildView(&type_to_search_view_);
- type_to_search_view_.SetVisible(false);
- type_to_search_view_.SetFont(font_);
- type_to_search_view_.SetColor(dimmed_text);
- type_to_search_view_.set_parent_owned(false);
+ SkColor dimmed_text = GetColor(ToolbarModel::NONE, DEEMPHASIZED_TEXT);
AddChildView(&keyword_hint_view_);
keyword_hint_view_.SetVisible(false);
@@ -223,22 +226,19 @@ void LocationBarView::Init() {
keyword_hint_view_.SetColor(dimmed_text);
keyword_hint_view_.set_parent_owned(false);
- AddChildView(&security_image_view_);
- security_image_view_.SetVisible(false);
- security_image_view_.set_parent_owned(false);
-
for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
- ContentSettingImageView* content_blocked_view =
- new ContentSettingImageView(static_cast<ContentSettingsType>(i), this,
- profile_, bubble_positioner_);
+ ContentSettingImageView* content_blocked_view = new ContentSettingImageView(
+ static_cast<ContentSettingsType>(i), this, profile_);
content_setting_views_.push_back(content_blocked_view);
AddChildView(content_blocked_view);
content_blocked_view->SetVisible(false);
}
- AddChildView(&info_label_);
- info_label_.SetVisible(false);
- info_label_.set_parent_owned(false);
+ if (!popup_window_mode_) {
+ AddChildView(&star_view_);
+ star_view_.SetVisible(true);
+ star_view_.set_parent_owned(false);
+ }
// Notify us when any ancestor is resized. In this case we want to tell the
// AutocompleteEditView to close its popup.
@@ -256,63 +256,59 @@ bool LocationBarView::IsInitialized() const {
}
// static
-SkColor LocationBarView::GetColor(bool is_secure, ColorKind kind) {
- enum SecurityState {
- NOT_SECURE = 0,
- SECURE,
- NUM_STATES
- };
-
- static bool initialized = false;
- static SkColor colors[NUM_STATES][NUM_KINDS];
- if (!initialized) {
+SkColor LocationBarView::GetColor(ToolbarModel::SecurityLevel security_level,
+ ColorKind kind) {
+ switch (kind) {
#if defined(OS_WIN)
- colors[NOT_SECURE][BACKGROUND] = color_utils::GetSysSkColor(COLOR_WINDOW);
- colors[NOT_SECURE][TEXT] = color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
- colors[NOT_SECURE][SELECTED_TEXT] =
- color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT);
+ case BACKGROUND: return color_utils::GetSysSkColor(COLOR_WINDOW);
+ case TEXT: return color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
+ case SELECTED_TEXT: return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT);
#else
// TODO(beng): source from theme provider.
- colors[NOT_SECURE][BACKGROUND] = SK_ColorWHITE;
- colors[NOT_SECURE][TEXT] = SK_ColorBLACK;
- colors[NOT_SECURE][SELECTED_TEXT] = SK_ColorWHITE;
+ case BACKGROUND: return SK_ColorWHITE;
+ case TEXT: return SK_ColorBLACK;
+ case SELECTED_TEXT: return SK_ColorWHITE;
#endif
- colors[SECURE][BACKGROUND] = SkColorSetRGB(255, 245, 195);
- colors[SECURE][TEXT] = SK_ColorBLACK;
- colors[SECURE][SELECTED_TEXT] = 0; // Unused
- colors[NOT_SECURE][DEEMPHASIZED_TEXT] =
- color_utils::AlphaBlend(colors[NOT_SECURE][TEXT],
- colors[NOT_SECURE][BACKGROUND], 128);
- colors[SECURE][DEEMPHASIZED_TEXT] =
- color_utils::AlphaBlend(colors[SECURE][TEXT],
- colors[SECURE][BACKGROUND], 128);
- colors[NOT_SECURE][SECURITY_TEXT] = color_utils::GetReadableColor(
- SkColorSetRGB(200, 0, 0), colors[NOT_SECURE][BACKGROUND]);
- colors[SECURE][SECURITY_TEXT] = SkColorSetRGB(0, 150, 20);
- colors[NOT_SECURE][SECURITY_INFO_BUBBLE_TEXT] =
- colors[NOT_SECURE][SECURITY_TEXT];
- colors[SECURE][SECURITY_INFO_BUBBLE_TEXT] = color_utils::GetReadableColor(
- SkColorSetRGB(0, 153, 51), colors[NOT_SECURE][BACKGROUND]);
- colors[NOT_SECURE][SCHEME_STRIKEOUT] = color_utils::GetReadableColor(
- SkColorSetRGB(210, 0, 0), colors[NOT_SECURE][BACKGROUND]);
- colors[SECURE][SCHEME_STRIKEOUT] = 0; // Unused
- initialized = true;
- }
- return colors[is_secure ? SECURE : NOT_SECURE][kind];
+ case DEEMPHASIZED_TEXT:
+ return color_utils::AlphaBlend(GetColor(security_level, TEXT),
+ GetColor(security_level, BACKGROUND), 128);
+
+ case SECURITY_TEXT: {
+ SkColor color;
+ switch (security_level) {
+ case ToolbarModel::EV_SECURE:
+ case ToolbarModel::SECURE:
+ color = SkColorSetRGB(7, 149, 0);
+ break;
+
+ case ToolbarModel::SECURITY_WARNING:
+ return GetColor(security_level, DEEMPHASIZED_TEXT);
+ break;
+
+ case ToolbarModel::SECURITY_ERROR:
+ color = SkColorSetRGB(162, 0, 0);
+ break;
+
+ default:
+ NOTREACHED();
+ return GetColor(security_level, TEXT);
+ }
+ return color_utils::GetReadableColor(color, GetColor(security_level,
+ BACKGROUND));
+ }
+
+ default:
+ NOTREACHED();
+ return GetColor(security_level, TEXT);
+ }
}
void LocationBarView::Update(const TabContents* tab_for_state_restoring) {
- SetSecurityIcon(model_->GetIcon());
RefreshContentSettingViews();
RefreshPageActionViews();
- std::wstring info_text, info_tooltip;
- ToolbarModel::InfoTextType info_text_type =
- model_->GetInfoText(&info_text, &info_tooltip);
- SetInfoText(info_text, info_text_type, info_tooltip);
location_entry_->Update(tab_for_state_restoring);
- Layout();
- SchedulePaint();
+ OnChanged();
}
void LocationBarView::UpdateContentSettingsIcons() {
@@ -362,7 +358,6 @@ void LocationBarView::SetProfile(Profile* profile) {
for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
i != content_setting_views_.end(); ++i)
(*i)->set_profile(profile);
- security_image_view_.set_profile(profile);
}
}
@@ -370,8 +365,11 @@ TabContents* LocationBarView::GetTabContents() const {
return delegate_->GetTabContents();
}
-void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction *page_action,
+void LocationBarView::SetPreviewEnabledPageAction(ExtensionAction* page_action,
bool preview_enabled) {
+ if (popup_window_mode_)
+ return;
+
DCHECK(page_action);
TabContents* contents = delegate_->GetTabContents();
@@ -400,13 +398,156 @@ views::View* LocationBarView::GetPageActionView(
return NULL;
}
+void LocationBarView::SetStarToggled(bool on) {
+ star_view_.SetToggled(on);
+}
+
+void LocationBarView::ShowStarBubble(const GURL& url, bool newly_bookmarked) {
+ gfx::Rect screen_bounds(star_view_.GetImageBounds());
+ // Compensate for some built-in padding in the Star image.
+ screen_bounds.Inset(1, 1, 1, 2);
+ gfx::Point origin(screen_bounds.origin());
+ views::View::ConvertPointToScreen(&star_view_, &origin);
+ screen_bounds.set_origin(origin);
+ browser::ShowBookmarkBubbleView(GetWindow(), screen_bounds, &star_view_,
+ profile_, url, newly_bookmarked);
+}
+
gfx::Size LocationBarView::GetPreferredSize() {
return gfx::Size(0,
(popup_window_mode_ ? kPopupBackground : kBackground)->height());
}
void LocationBarView::Layout() {
- DoLayout(true);
+ if (!location_entry_.get())
+ return;
+
+ int entry_width = width() - kViewPadding;
+
+ // |location_icon_view_| is visible except when |ev_bubble_view_| or
+ // |selected_keyword_view_| are visible.
+ int location_icon_width = 0;
+ int ev_bubble_width = 0;
+ location_icon_view_.SetVisible(false);
+ ev_bubble_view_.SetVisible(false);
+ const std::wstring keyword(location_entry_->model()->keyword());
+ const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
+ const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint;
+ if (show_selected_keyword) {
+ entry_width -= kViewPadding; // Assume the keyword might be hidden.
+ } else if (model_->GetSecurityLevel() == ToolbarModel::EV_SECURE) {
+ ev_bubble_view_.SetVisible(true);
+ ev_bubble_view_.SetLabel(model_->GetEVCertName());
+ ev_bubble_width = ev_bubble_view_.GetPreferredSize().width();
+ entry_width -= kBubblePadding + ev_bubble_width + kViewPadding;
+ } else {
+ location_icon_view_.SetVisible(true);
+ location_icon_width = location_icon_view_.GetPreferredSize().width();
+ entry_width -=
+ kViewPadding + location_icon_width + kLocationIconEditPadding;
+ }
+
+ entry_width -= star_view_.GetPreferredSize().width() + kViewPadding;
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ if ((*i)->IsVisible())
+ entry_width -= (*i)->GetPreferredSize().width() + kViewPadding;
+ }
+ for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
+ i != content_setting_views_.end(); ++i) {
+ if ((*i)->IsVisible())
+ entry_width -= (*i)->GetPreferredSize().width() + kViewPadding;
+ }
+
+#if defined(OS_WIN)
+ RECT formatting_rect;
+ location_entry_->GetRect(&formatting_rect);
+ RECT edit_bounds;
+ location_entry_->GetClientRect(&edit_bounds);
+ int max_edit_width = entry_width - formatting_rect.left -
+ (edit_bounds.right - formatting_rect.right);
+#else
+ int max_edit_width = entry_width;
+#endif
+
+ if (max_edit_width < 0)
+ return;
+ const int available_width = AvailableWidth(max_edit_width);
+
+ const bool show_keyword_hint = !keyword.empty() && is_keyword_hint;
+ selected_keyword_view_.SetVisible(show_selected_keyword);
+ keyword_hint_view_.SetVisible(show_keyword_hint);
+ if (show_selected_keyword) {
+ if (selected_keyword_view_.keyword() != keyword)
+ selected_keyword_view_.SetKeyword(keyword);
+ } else if (show_keyword_hint) {
+ if (keyword_hint_view_.keyword() != keyword)
+ keyword_hint_view_.SetKeyword(keyword);
+ }
+
+ // TODO(sky): baseline layout.
+ int location_y = TopMargin();
+ int location_height = std::max(height() - location_y - kVertMargin, 0);
+
+ // Lay out items to the right of the edit field.
+ int offset = width() - kViewPadding;
+ int star_width = star_view_.GetPreferredSize().width();
+ offset -= star_width;
+ star_view_.SetBounds(offset, location_y, star_width, location_height);
+ offset -= kViewPadding;
+
+ for (PageActionViews::const_iterator i(page_action_views_.begin());
+ i != page_action_views_.end(); ++i) {
+ if ((*i)->IsVisible()) {
+ int page_action_width = (*i)->GetPreferredSize().width();
+ offset -= page_action_width;
+ (*i)->SetBounds(offset, location_y, page_action_width, location_height);
+ offset -= kViewPadding;
+ }
+ }
+ // We use a reverse_iterator here because we're laying out the views from
+ // right to left but in the vector they're ordered left to right.
+ for (ContentSettingViews::const_reverse_iterator
+ i(content_setting_views_.rbegin()); i != content_setting_views_.rend();
+ ++i) {
+ if ((*i)->IsVisible()) {
+ int content_blocked_width = (*i)->GetPreferredSize().width();
+ offset -= content_blocked_width;
+ (*i)->SetBounds(offset, location_y, content_blocked_width,
+ location_height);
+ offset -= kViewPadding;
+ }
+ }
+
+ // Now lay out items to the left of the edit field.
+ if (location_icon_view_.IsVisible()) {
+ location_icon_view_.SetBounds(kViewPadding, location_y, location_icon_width,
+ location_height);
+ offset = location_icon_view_.bounds().right() + kLocationIconEditPadding;
+ } else if (ev_bubble_view_.IsVisible()) {
+ ev_bubble_view_.SetBounds(kBubblePadding, location_y, ev_bubble_width,
+ location_height);
+ offset = ev_bubble_view_.bounds().right() + kViewPadding;
+ } else {
+ offset = show_selected_keyword ? kBubblePadding : kViewPadding;
+ }
+
+ // Now lay out the edit field and views that autocollapse to give it more
+ // room.
+ gfx::Rect location_bounds(offset, location_y, entry_width, location_height);
+ if (show_selected_keyword) {
+ LayoutView(true, &selected_keyword_view_, available_width,
+ &location_bounds);
+ if (!selected_keyword_view_.IsVisible()) {
+ location_bounds.set_x(
+ location_bounds.x() + kViewPadding - kBubblePadding);
+ }
+ } else if (show_keyword_hint) {
+ LayoutView(false, &keyword_hint_view_, available_width,
+ &location_bounds);
+ }
+
+ location_entry_view_->SetBounds(location_bounds);
}
void LocationBarView::Paint(gfx::Canvas* canvas) {
@@ -419,10 +560,9 @@ void LocationBarView::Paint(gfx::Canvas* canvas) {
canvas->TileImageInt(*background, 0, 0, 0, 0, width(), height());
int top_margin = TopMargin();
- canvas->FillRectInt(
- GetColor(model_->GetSchemeSecurityLevel() == ToolbarModel::SECURE,
- BACKGROUND),
- 0, top_margin, width(), std::max(height() - top_margin - kVertMargin, 0));
+ canvas->FillRectInt(GetColor(ToolbarModel::NONE, BACKGROUND), 0,
+ top_margin, width(),
+ std::max(height() - top_margin - kVertMargin, 0));
}
void LocationBarView::VisibleBoundsInRootChanged() {
@@ -509,7 +649,11 @@ void LocationBarView::OnAutocompleteAccept(
}
void LocationBarView::OnChanged() {
- DoLayout(false);
+ location_icon_view_.SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ location_entry_->GetIcon()));
+ Layout();
+ SchedulePaint();
}
void LocationBarView::OnInputInProgress(bool in_progress) {
@@ -540,117 +684,6 @@ std::wstring LocationBarView::GetTitle() const {
return UTF16ToWideHack(delegate_->GetTabContents()->GetTitle());
}
-void LocationBarView::DoLayout(const bool force_layout) {
- if (!location_entry_.get())
- return;
-
- int entry_width = width() - (kEntryPadding * 2);
-
- for (PageActionViews::const_iterator i(page_action_views_.begin());
- i != page_action_views_.end(); ++i) {
- if ((*i)->IsVisible())
- entry_width -= (*i)->GetPreferredSize().width() + kInnerPadding;
- }
- for (ContentSettingViews::const_iterator i(content_setting_views_.begin());
- i != content_setting_views_.end(); ++i) {
- if ((*i)->IsVisible())
- entry_width -= (*i)->GetPreferredSize().width() + kInnerPadding;
- }
- gfx::Size security_image_size;
- if (security_image_view_.IsVisible()) {
- security_image_size = security_image_view_.GetPreferredSize();
- entry_width -= security_image_size.width() + kInnerPadding;
- }
- gfx::Size info_label_size;
- if (info_label_.IsVisible()) {
- info_label_size = info_label_.GetPreferredSize();
- entry_width -= (info_label_size.width() + kInnerPadding);
- }
-
-#if defined(OS_WIN)
- RECT formatting_rect;
- location_entry_->GetRect(&formatting_rect);
- RECT edit_bounds;
- location_entry_->GetClientRect(&edit_bounds);
- int max_edit_width = entry_width - formatting_rect.left -
- (edit_bounds.right - formatting_rect.right);
-#else
- int max_edit_width = entry_width;
-#endif
-
- if (max_edit_width < 0)
- return;
- const int available_width = AvailableWidth(max_edit_width);
- bool needs_layout = force_layout;
- needs_layout |= AdjustHints(available_width);
-
- if (!needs_layout)
- return;
-
- // TODO(sky): baseline layout.
- int location_y = TopMargin();
- int location_height = std::max(height() - location_y - kVertMargin, 0);
-
- // First set the bounds for the label that appears to the right of the
- // security icon.
- int offset = width() - kEntryPadding;
- if (info_label_.IsVisible()) {
- offset -= info_label_size.width();
- info_label_.SetBounds(offset, location_y,
- info_label_size.width(), location_height);
- offset -= kInnerPadding;
- }
- if (security_image_view_.IsVisible()) {
- offset -= security_image_size.width();
- security_image_view_.SetBounds(offset, location_y,
- security_image_size.width(),
- location_height);
- offset -= kInnerPadding;
- }
-
- for (PageActionViews::const_iterator i(page_action_views_.begin());
- i != page_action_views_.end(); ++i) {
- if ((*i)->IsVisible()) {
- int page_action_width = (*i)->GetPreferredSize().width();
- offset -= page_action_width;
- (*i)->SetBounds(offset, location_y, page_action_width, location_height);
- offset -= kInnerPadding;
- }
- }
- // We use a reverse_iterator here because we're laying out the views from
- // right to left but in the vector they're ordered left to right.
- for (ContentSettingViews::const_reverse_iterator
- i(content_setting_views_.rbegin()); i != content_setting_views_.rend();
- ++i) {
- if ((*i)->IsVisible()) {
- int content_blocked_width = (*i)->GetPreferredSize().width();
- offset -= content_blocked_width;
- (*i)->SetBounds(offset, location_y, content_blocked_width,
- location_height);
- offset -= kInnerPadding;
- }
- }
- gfx::Rect location_bounds(kEntryPadding, location_y, entry_width,
- location_height);
- if (selected_keyword_view_.IsVisible()) {
- LayoutView(true, &selected_keyword_view_, available_width,
- &location_bounds);
- } else if (keyword_hint_view_.IsVisible()) {
- LayoutView(false, &keyword_hint_view_, available_width,
- &location_bounds);
- } else if (type_to_search_view_.IsVisible()) {
- LayoutView(false, &type_to_search_view_, available_width,
- &location_bounds);
- }
-
- location_entry_view_->SetBounds(location_bounds);
- if (!force_layout) {
- // If force_layout is false and we got this far it means one of the views
- // was added/removed or changed in size. We need to paint ourselves.
- SchedulePaint();
- }
-}
-
int LocationBarView::TopMargin() const {
return std::min(kVertMargin, height());
}
@@ -669,52 +702,7 @@ int LocationBarView::AvailableWidth(int location_bar_width) {
}
bool LocationBarView::UsePref(int pref_width, int available_width) {
- return (pref_width + kInnerPadding <= available_width);
-}
-
-bool LocationBarView::NeedsResize(View* view, int available_width) {
- gfx::Size size = view->GetPreferredSize();
- if (!UsePref(size.width(), available_width))
- size = view->GetMinimumSize();
- return (view->width() != size.width());
-}
-
-bool LocationBarView::AdjustHints(int available_width) {
- const std::wstring keyword(location_entry_->model()->keyword());
- const bool is_keyword_hint(location_entry_->model()->is_keyword_hint());
- const bool show_selected_keyword = !keyword.empty() && !is_keyword_hint;
- const bool show_keyword_hint = !keyword.empty() && is_keyword_hint;
- bool show_search_hint(location_entry_->model()->show_search_hint());
- DCHECK(keyword.empty() || !show_search_hint);
-
- if (show_search_hint) {
- // Only show type to search if all the text fits.
- gfx::Size view_pref = type_to_search_view_.GetPreferredSize();
- show_search_hint = UsePref(view_pref.width(), available_width);
- }
-
- // NOTE: This isn't just one big || statement as ToggleVisibility MUST be
- // invoked for each view.
- bool needs_layout = false;
- needs_layout |= ToggleVisibility(show_selected_keyword,
- &selected_keyword_view_);
- needs_layout |= ToggleVisibility(show_keyword_hint, &keyword_hint_view_);
- needs_layout |= ToggleVisibility(show_search_hint, &type_to_search_view_);
- if (show_selected_keyword) {
- if (selected_keyword_view_.keyword() != keyword) {
- needs_layout = true;
- selected_keyword_view_.SetKeyword(keyword);
- }
- needs_layout |= NeedsResize(&selected_keyword_view_, available_width);
- } else if (show_keyword_hint) {
- if (keyword_hint_view_.keyword() != keyword) {
- needs_layout = true;
- keyword_hint_view_.SetKeyword(keyword);
- }
- needs_layout |= NeedsResize(&keyword_hint_view_, available_width);
- }
-
- return needs_layout;
+ return (pref_width + kViewPadding <= available_width);
}
void LocationBarView::LayoutView(bool leading,
@@ -725,40 +713,20 @@ void LocationBarView::LayoutView(bool leading,
gfx::Size view_size = view->GetPreferredSize();
if (!UsePref(view_size.width(), available_width))
view_size = view->GetMinimumSize();
- if (view_size.width() + kInnerPadding < bounds->width()) {
- view->SetVisible(true);
- if (leading) {
- view->SetBounds(bounds->x(), bounds->y(), view_size.width(),
- bounds->height());
- bounds->Offset(view_size.width() + kInnerPadding, 0);
- } else {
- view->SetBounds(bounds->right() - view_size.width(), bounds->y(),
- view_size.width(), bounds->height());
- }
- bounds->set_width(bounds->width() - view_size.width() - kInnerPadding);
- } else {
+ if (view_size.width() + kViewPadding >= bounds->width()) {
view->SetVisible(false);
+ return;
}
-}
-
-void LocationBarView::SetSecurityIcon(ToolbarModel::Icon icon) {
- switch (icon) {
- case ToolbarModel::LOCK_ICON:
- security_image_view_.SetImageShown(SecurityImageView::LOCK);
- security_image_view_.SetVisible(true);
- break;
- case ToolbarModel::WARNING_ICON:
- security_image_view_.SetImageShown(SecurityImageView::WARNING);
- security_image_view_.SetVisible(true);
- break;
- case ToolbarModel::NO_ICON:
- security_image_view_.SetVisible(false);
- break;
- default:
- NOTREACHED();
- security_image_view_.SetVisible(false);
- break;
+ if (leading) {
+ view->SetBounds(bounds->x(), bounds->y(), view_size.width(),
+ bounds->height());
+ bounds->Offset(view_size.width() + kViewPadding, 0);
+ } else {
+ view->SetBounds(bounds->right() - view_size.width(), bounds->y(),
+ view_size.width(), bounds->height());
}
+ bounds->set_width(bounds->width() - view_size.width() - kViewPadding);
+ view->SetVisible(true);
}
void LocationBarView::RefreshContentSettingViews() {
@@ -778,7 +746,9 @@ void LocationBarView::DeletePageActionViews() {
}
void LocationBarView::RefreshPageActionViews() {
- std::vector<ExtensionAction*> page_actions;
+ if (popup_window_mode_)
+ return;
+
ExtensionsService* service = profile_->GetExtensionsService();
if (!service)
return;
@@ -790,6 +760,7 @@ void LocationBarView::RefreshPageActionViews() {
// Remember the previous visibility of the page actions so that we can
// notify when this changes.
+ std::vector<ExtensionAction*> page_actions;
for (size_t i = 0; i < service->extensions()->size(); ++i) {
if (service->extensions()->at(i)->page_action())
page_actions.push_back(service->extensions()->at(i)->page_action());
@@ -804,8 +775,7 @@ void LocationBarView::RefreshPageActionViews() {
for (size_t i = 0; i < page_actions.size(); ++i) {
page_action_views_[i] = new PageActionWithBadgeView(
- new PageActionImageView(this, profile_,
- page_actions[i], bubble_positioner_));
+ new PageActionImageView(this, profile_, page_actions[i]));
page_action_views_[i]->SetVisible(false);
AddChildView(page_action_views_[i]);
}
@@ -832,25 +802,6 @@ void LocationBarView::RefreshPageActionViews() {
}
}
-void LocationBarView::SetInfoText(const std::wstring& text,
- ToolbarModel::InfoTextType text_type,
- const std::wstring& tooltip_text) {
- info_label_.SetVisible(!text.empty());
- info_label_.SetText(text);
- if (text_type == ToolbarModel::INFO_EV_TEXT)
- info_label_.SetColor(GetColor(true, SECURITY_TEXT));
- info_label_.SetTooltipText(tooltip_text);
-}
-
-bool LocationBarView::ToggleVisibility(bool new_vis, View* view) {
- DCHECK(view);
- if (view->IsVisible() != new_vis) {
- view->SetVisible(new_vis);
- return true;
- }
- return false;
-}
-
#if defined(OS_WIN)
void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) {
UINT flags = 0;
@@ -867,11 +818,55 @@ void LocationBarView::OnMouseEvent(const views::MouseEvent& event, UINT msg) {
gfx::Point screen_point(event.location());
ConvertPointToScreen(this, &screen_point);
-
location_entry_->HandleExternalMsg(msg, flags, screen_point.ToPOINT());
}
#endif
+void LocationBarView::ShowFirstRunBubbleInternal(
+ FirstRun::BubbleType bubble_type) {
+#if defined(OS_WIN) // First run bubble doesn't make sense for Chrome OS.
+ // If the browser is no longer active, let's not show the info bubble, as this
+ // would make the browser the active window again.
+ if (!location_entry_view_ || !location_entry_view_->GetWidget()->IsActive())
+ return;
+
+ // Point at the start of the edit control; adjust to look as good as possible.
+ const int kXOffset = 1; // Text looks like it actually starts 1 px in.
+ const int kYOffset = -4; // Point into the omnibox, not just at its edge.
+ gfx::Point origin(location_entry_view_->bounds().x() + kXOffset,
+ y() + height() + kYOffset);
+ // If the UI layout is RTL, the coordinate system is not transformed and
+ // therefore we need to adjust the X coordinate so that bubble appears on the
+ // right hand side of the location bar.
+ if (UILayoutIsRightToLeft())
+ origin.set_x(width() - origin.x());
+ views::View::ConvertPointToScreen(this, &origin);
+ FirstRunBubble::Show(profile_, GetWindow(), gfx::Rect(origin, gfx::Size()),
+ bubble_type);
+#endif
+}
+
+bool LocationBarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
+ if (keyword_hint_view_.IsVisible() &&
+ views::FocusManager::IsTabTraversalKeyEvent(e)) {
+ // We want to receive tab key events when the hint is showing.
+ return true;
+ }
+
+#if defined(OS_WIN)
+ return location_entry_->SkipDefaultKeyEventProcessing(e);
+#else
+ // TODO(jcampan): We need to refactor the code of
+ // AutocompleteEditViewWin::SkipDefaultKeyEventProcessing into this class so
+ // it can be shared between Windows and Linux.
+ // For now, we just override back-space as it is the accelerator for back
+ // navigation.
+ if (e.GetKeyCode() == base::VKEY_BACK)
+ return true;
+ return false;
+#endif
+}
+
bool LocationBarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
DCHECK(role);
@@ -879,76 +874,213 @@ bool LocationBarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
return true;
}
-// SelectedKeywordView -------------------------------------------------------
-// The background is drawn using HorizontalPainter. This is the
-// left/center/right image names.
-static const int kBorderImages[] = {
- IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_L,
- IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_C,
- IDR_LOCATION_BAR_SELECTED_KEYWORD_BACKGROUND_R };
+void LocationBarView::WriteDragData(views::View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data) {
+ DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE);
+
+ TabContents* tab_contents = delegate_->GetTabContents();
+ DCHECK(tab_contents);
+ drag_utils::SetURLAndDragImage(tab_contents->GetURL(),
+ UTF16ToWideHack(tab_contents->GetTitle()),
+ tab_contents->GetFavIcon(), data);
+}
+
+int LocationBarView::GetDragOperations(views::View* sender,
+ const gfx::Point& p) {
+ DCHECK((sender == &location_icon_view_) || (sender == &ev_bubble_view_));
+ TabContents* tab_contents = delegate_->GetTabContents();
+ return (tab_contents && tab_contents->GetURL().is_valid() &&
+ !location_entry()->IsEditingOrEmpty()) ?
+ (DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK) :
+ DragDropTypes::DRAG_NONE;
+}
+
+bool LocationBarView::CanStartDrag(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p) {
+ return true;
+}
+
+// ClickHandler ----------------------------------------------------------------
+
+LocationBarView::ClickHandler::ClickHandler(const views::View* owner,
+ const LocationBarView* location_bar)
+ : owner_(owner),
+ location_bar_(location_bar) {
+}
+
+void LocationBarView::ClickHandler::OnMouseReleased(
+ const views::MouseEvent& event,
+ bool canceled) {
+ if (canceled || !owner_->HitTest(event.location()))
+ return;
+
+ // Do not show page info if the user has been editing the location
+ // bar, or the location bar is at the NTP.
+ if (location_bar_->location_entry()->IsEditingOrEmpty())
+ return;
+
+ TabContents* tab = location_bar_->GetTabContents();
+ NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
+ if (!nav_entry) {
+ NOTREACHED();
+ return;
+ }
+ tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
+}
+
+// LocationIconView ------------------------------------------------------------
+
+LocationBarView::LocationIconView::LocationIconView(
+ const LocationBarView* location_bar)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) {
+}
+
+LocationBarView::LocationIconView::~LocationIconView() {
+}
+
+bool LocationBarView::LocationIconView::OnMousePressed(
+ const views::MouseEvent& event) {
+ // We want to show the dialog on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void LocationBarView::LocationIconView::OnMouseReleased(
+ const views::MouseEvent& event,
+ bool canceled) {
+ click_handler_.OnMouseReleased(event, canceled);
+}
+
+// IconLabelBubbleView ---------------------------------------------------------
+
+// Amount to offset the image.
+static const int kImageOffset = 1;
+
+// Amount to offset the label from the image.
+static const int kLabelOffset = 3;
+
+// Amount of padding after the label.
+static const int kLabelPadding = 4;
+
+LocationBarView::IconLabelBubbleView::IconLabelBubbleView(
+ const int background_images[],
+ int contained_image,
+ const SkColor& color)
+ : background_painter_(background_images) {
+ AddChildView(&image_);
+ image_.set_parent_owned(false);
+ image_.SetImage(
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(contained_image));
+ AddChildView(&label_);
+ label_.set_parent_owned(false);
+ label_.SetColor(color);
+}
+
+LocationBarView::IconLabelBubbleView::~IconLabelBubbleView() {
+}
+
+void LocationBarView::IconLabelBubbleView::SetFont(const gfx::Font& font) {
+ label_.SetFont(font);
+}
+
+void LocationBarView::IconLabelBubbleView::SetLabel(const std::wstring& label) {
+ label_.SetText(label);
+}
+
+void LocationBarView::IconLabelBubbleView::Paint(gfx::Canvas* canvas) {
+ int y_offset = (GetParent()->height() - height()) / 2;
+ canvas->TranslateInt(0, y_offset);
+ background_painter_.Paint(width(), height(), canvas);
+ canvas->TranslateInt(0, -y_offset);
+}
+
+gfx::Size LocationBarView::IconLabelBubbleView::GetPreferredSize() {
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(label_.GetPreferredSize().width(), 0);
+ return size;
+}
+
+void LocationBarView::IconLabelBubbleView::Layout() {
+ image_.SetBounds(kImageOffset, 0, image_.GetPreferredSize().width(),
+ height());
+ gfx::Size label_size(label_.GetPreferredSize());
+ label_.SetBounds(image_.x() + image_.width() + kLabelOffset,
+ (height() - label_size.height()) / 2, label_size.width(),
+ label_size.height());
+}
+
+gfx::Size LocationBarView::IconLabelBubbleView::GetNonLabelSize() {
+ return gfx::Size(kImageOffset + image_.GetPreferredSize().width() +
+ kLabelOffset + kLabelPadding, background_painter_.height());
+}
+
+// EVBubbleView ----------------------------------------------------------------
+
+LocationBarView::EVBubbleView::EVBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ const LocationBarView* location_bar)
+ : IconLabelBubbleView(background_images, contained_image, color),
+ ALLOW_THIS_IN_INITIALIZER_LIST(click_handler_(this, location_bar)) {
+}
+
+LocationBarView::EVBubbleView::~EVBubbleView() {
+}
+
+bool LocationBarView::EVBubbleView::OnMousePressed(
+ const views::MouseEvent& event) {
+ // We want to show the dialog on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
-// Insets around the label.
-static const int kTopInset = 0;
-static const int kBottomInset = 0;
-static const int kLeftInset = 4;
-static const int kRightInset = 4;
+void LocationBarView::EVBubbleView::OnMouseReleased(
+ const views::MouseEvent& event,
+ bool canceled) {
+ click_handler_.OnMouseReleased(event, canceled);
+}
-// Offset from the top the background is drawn at.
-static const int kBackgroundYOffset = 2;
+// SelectedKeywordView ---------------------------------------------------------
-LocationBarView::SelectedKeywordView::SelectedKeywordView(Profile* profile)
- : background_painter_(kBorderImages),
+LocationBarView::SelectedKeywordView::SelectedKeywordView(
+ const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ Profile* profile)
+ : IconLabelBubbleView(background_images, contained_image, color),
profile_(profile) {
- AddChildView(&full_label_);
- AddChildView(&partial_label_);
- // Full_label and partial_label are deleted by us, make sure View doesn't
- // delete them too.
- full_label_.set_parent_owned(false);
- partial_label_.set_parent_owned(false);
full_label_.SetVisible(false);
partial_label_.SetVisible(false);
- full_label_.set_border(
- views::Border::CreateEmptyBorder(kTopInset, kLeftInset, kBottomInset,
- kRightInset));
- partial_label_.set_border(
- views::Border::CreateEmptyBorder(kTopInset, kLeftInset, kBottomInset,
- kRightInset));
- full_label_.SetColor(SK_ColorBLACK);
- partial_label_.SetColor(SK_ColorBLACK);
}
LocationBarView::SelectedKeywordView::~SelectedKeywordView() {
}
void LocationBarView::SelectedKeywordView::SetFont(const gfx::Font& font) {
+ IconLabelBubbleView::SetFont(font);
full_label_.SetFont(font);
partial_label_.SetFont(font);
}
-void LocationBarView::SelectedKeywordView::Paint(gfx::Canvas* canvas) {
- canvas->TranslateInt(0, kBackgroundYOffset);
- background_painter_.Paint(width(), height() - kTopInset, canvas);
- canvas->TranslateInt(0, -kBackgroundYOffset);
-}
-
gfx::Size LocationBarView::SelectedKeywordView::GetPreferredSize() {
- return full_label_.GetPreferredSize();
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(full_label_.GetPreferredSize().width(), 0);
+ return size;
}
gfx::Size LocationBarView::SelectedKeywordView::GetMinimumSize() {
- return partial_label_.GetMinimumSize();
+ gfx::Size size(GetNonLabelSize());
+ size.Enlarge(partial_label_.GetMinimumSize().width(), 0);
+ return size;
}
void LocationBarView::SelectedKeywordView::Layout() {
- gfx::Size pref = GetPreferredSize();
- bool at_pref = (width() == pref.width());
- if (at_pref)
- full_label_.SetBounds(0, 0, width(), height());
- else
- partial_label_.SetBounds(0, 0, width(), height());
- full_label_.SetVisible(at_pref);
- partial_label_.SetVisible(!at_pref);
+ SetLabel((width() == GetPreferredSize().width()) ?
+ full_label_.GetText() : partial_label_.GetText());
+ IconLabelBubbleView::Layout();
}
void LocationBarView::SelectedKeywordView::SetKeyword(
@@ -964,12 +1096,9 @@ void LocationBarView::SelectedKeywordView::SetKeyword(
full_label_.SetText(l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT,
short_name));
const std::wstring min_string = CalculateMinString(short_name);
- if (!min_string.empty()) {
- partial_label_.SetText(
- l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, min_string));
- } else {
- partial_label_.SetText(full_label_.GetText());
- }
+ partial_label_.SetText(min_string.empty() ?
+ full_label_.GetText() :
+ l10n_util::GetStringF(IDS_OMNIBOX_KEYWORD_TEXT, min_string));
}
std::wstring LocationBarView::SelectedKeywordView::CalculateMinString(
@@ -1096,250 +1225,18 @@ void LocationBarView::KeywordHintView::Layout() {
}
}
-bool LocationBarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
- if (keyword_hint_view_.IsVisible() &&
- views::FocusManager::IsTabTraversalKeyEvent(e)) {
- // We want to receive tab key events when the hint is showing.
- return true;
- }
-
-#if defined(OS_WIN)
- return location_entry_->SkipDefaultKeyEventProcessing(e);
-#else
- // TODO(jcampan): We need to refactor the code of
- // AutocompleteEditViewWin::SkipDefaultKeyEventProcessing into this class so
- // it can be shared between Windows and Linux.
- // For now, we just override back-space as it is the accelerator for back
- // navigation.
- if (e.GetKeyCode() == base::VKEY_BACK)
- return true;
- return false;
-#endif
-}
-
-// ShowInfoBubbleTask-----------------------------------------------------------
-
-class LocationBarView::ShowInfoBubbleTask : public Task {
- public:
- explicit ShowInfoBubbleTask(
- LocationBarView::LocationBarImageView* image_view);
- virtual void Run();
- void Cancel();
-
- private:
- LocationBarView::LocationBarImageView* image_view_;
- bool cancelled_;
-
- DISALLOW_COPY_AND_ASSIGN(ShowInfoBubbleTask);
-};
-
-LocationBarView::ShowInfoBubbleTask::ShowInfoBubbleTask(
- LocationBarView::LocationBarImageView* image_view)
- : image_view_(image_view),
- cancelled_(false) {
-}
-
-void LocationBarView::ShowInfoBubbleTask::Run() {
- if (cancelled_)
- return;
-
- if (!image_view_->GetWidget()->IsActive()) {
- // The browser is no longer active. Let's not show the info bubble, this
- // would make the browser the active window again. Also makes sure we NULL
- // show_info_bubble_task_ to prevent the SecurityImageView from keeping a
- // dangling pointer.
- image_view_->show_info_bubble_task_ = NULL;
- return;
- }
-
- image_view_->ShowInfoBubble();
-}
-
-void LocationBarView::ShowInfoBubbleTask::Cancel() {
- cancelled_ = true;
-}
-
-// -----------------------------------------------------------------------------
-
-void LocationBarView::ShowFirstRunBubbleInternal(
- FirstRun::BubbleType bubble_type) {
- if (!location_entry_view_)
- return;
- if (!location_entry_view_->GetWidget()->IsActive()) {
- // The browser is no longer active. Let's not show the info bubble, this
- // would make the browser the active window again.
- return;
- }
-
- gfx::Point location;
-
- // If the UI layout is RTL, the coordinate system is not transformed and
- // therefore we need to adjust the X coordinate so that bubble appears on the
- // right hand side of the location bar.
- if (UILayoutIsRightToLeft())
- location.Offset(width(), 0);
- views::View::ConvertPointToScreen(this, &location);
-
- // We try to guess that 20 pixels offset is a good place for the first
- // letter in the OmniBox.
- gfx::Rect bounds(location.x(), location.y(), 20, height());
-
- // Moving the bounds "backwards" so that it appears within the location bar
- // if the UI layout is RTL.
- if (UILayoutIsRightToLeft())
- bounds.set_x(location.x() - 20);
-
-#if defined(OS_WIN)
- FirstRunBubble::Show(profile_, GetWindow(), bounds, bubble_type);
-#else
- // First run bubble doesn't make sense for Chrome OS.
-#endif
-}
-
-// LocationBarImageView---------------------------------------------------------
-
-LocationBarView::LocationBarImageView::LocationBarImageView(
- const BubblePositioner* bubble_positioner)
- : info_bubble_(NULL),
- show_info_bubble_task_(NULL),
- bubble_positioner_(bubble_positioner) {
-}
-
-LocationBarView::LocationBarImageView::~LocationBarImageView() {
- if (show_info_bubble_task_)
- show_info_bubble_task_->Cancel();
-
- if (info_bubble_)
- info_bubble_->Close();
-}
-
-void LocationBarView::LocationBarImageView::OnMouseMoved(
- const views::MouseEvent& event) {
- if (show_info_bubble_task_) {
- show_info_bubble_task_->Cancel();
- show_info_bubble_task_ = NULL;
- }
-
- if (info_bubble_) {
- // If an info bubble is currently showing, nothing to do.
- return;
- }
-
- show_info_bubble_task_ = new ShowInfoBubbleTask(this);
- MessageLoop::current()->PostDelayedTask(FROM_HERE, show_info_bubble_task_,
- kInfoBubbleHoverDelayMs);
-}
-
-void LocationBarView::LocationBarImageView::OnMouseExited(
- const views::MouseEvent& event) {
- if (show_info_bubble_task_) {
- show_info_bubble_task_->Cancel();
- show_info_bubble_task_ = NULL;
- }
-
- if (info_bubble_)
- info_bubble_->Close();
-}
-
-void LocationBarView::LocationBarImageView::InfoBubbleClosing(
- InfoBubble* info_bubble, bool closed_by_escape) {
- info_bubble_ = NULL;
-}
-
-void LocationBarView::LocationBarImageView::ShowInfoBubbleImpl(
- const std::wstring& text, SkColor text_color) {
- gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds());
- gfx::Point location;
- views::View::ConvertPointToScreen(this, &location);
- bounds.set_x(location.x());
- bounds.set_width(width());
-
- views::Label* label = new views::Label(text);
- label->SetMultiLine(true);
- label->SetColor(text_color);
- label->SetFont(ResourceBundle::GetSharedInstance().GetFont(
- ResourceBundle::BaseFont).DeriveFont(2));
- label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
- label->SizeToFit(0);
- DCHECK(info_bubble_ == NULL);
- info_bubble_ = InfoBubble::Show(GetWindow(), bounds, label, this);
- show_info_bubble_task_ = NULL;
-}
-
-// SecurityImageView------------------------------------------------------------
-
-// static
-SkBitmap* LocationBarView::SecurityImageView::lock_icon_ = NULL;
-SkBitmap* LocationBarView::SecurityImageView::warning_icon_ = NULL;
-
-LocationBarView::SecurityImageView::SecurityImageView(
- const LocationBarView* parent,
- Profile* profile,
- ToolbarModel* model,
- const BubblePositioner* bubble_positioner)
- : LocationBarImageView(bubble_positioner),
- parent_(parent),
- profile_(profile),
- model_(model) {
- if (!lock_icon_) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- lock_icon_ = rb.GetBitmapNamed(IDR_LOCK);
- warning_icon_ = rb.GetBitmapNamed(IDR_WARNING);
- }
- SetImageShown(LOCK);
-}
-
-LocationBarView::SecurityImageView::~SecurityImageView() {
-}
-
-void LocationBarView::SecurityImageView::SetImageShown(Image image) {
- switch (image) {
- case LOCK:
- SetImage(lock_icon_);
- break;
- case WARNING:
- SetImage(warning_icon_);
- break;
- default:
- NOTREACHED();
- break;
- }
-}
-
-bool LocationBarView::SecurityImageView::OnMousePressed(
- const views::MouseEvent& event) {
- TabContents* tab = parent_->GetTabContents();
- NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
- if (!nav_entry) {
- NOTREACHED();
- return true;
- }
- tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
- return true;
-}
-
-void LocationBarView::SecurityImageView::ShowInfoBubble() {
- std::wstring text;
- model_->GetIconHoverText(&text);
- ShowInfoBubbleImpl(text, GetColor(
- model_->GetSecurityLevel() == ToolbarModel::SECURE,
- SECURITY_INFO_BUBBLE_TEXT));
-}
-
// ContentSettingImageView------------------------------------------------------
LocationBarView::ContentSettingImageView::ContentSettingImageView(
ContentSettingsType content_type,
const LocationBarView* parent,
- Profile* profile,
- const BubblePositioner* bubble_positioner)
+ Profile* profile)
: content_setting_image_model_(
ContentSettingImageModel::CreateContentSettingImageModel(
content_type)),
parent_(parent),
profile_(profile),
- info_bubble_(NULL),
- bubble_positioner_(bubble_positioner) {
+ info_bubble_(NULL) {
}
LocationBarView::ContentSettingImageView::~ContentSettingImageView() {
@@ -1351,29 +1248,39 @@ void LocationBarView::ContentSettingImageView::UpdateFromTabContents(
const TabContents* tab_contents) {
int old_icon = content_setting_image_model_->get_icon();
content_setting_image_model_->UpdateFromTabContents(tab_contents);
- if (content_setting_image_model_->is_visible()) {
- if (old_icon != content_setting_image_model_->get_icon()) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- SetImage(rb.GetBitmapNamed(content_setting_image_model_->get_icon()));
- }
- SetTooltipText(UTF8ToWide(content_setting_image_model_->get_tooltip()));
- SetVisible(true);
- } else {
+ if (!content_setting_image_model_->is_visible()) {
SetVisible(false);
+ return;
+ }
+ if (old_icon != content_setting_image_model_->get_icon()) {
+ SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ content_setting_image_model_->get_icon()));
}
+ SetTooltipText(UTF8ToWide(content_setting_image_model_->get_tooltip()));
+ SetVisible(true);
}
bool LocationBarView::ContentSettingImageView::OnMousePressed(
const views::MouseEvent& event) {
- gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds());
- gfx::Point location;
- views::View::ConvertPointToScreen(this, &location);
- bounds.set_x(location.x());
- bounds.set_width(width());
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void LocationBarView::ContentSettingImageView::OnMouseReleased(
+ const views::MouseEvent& event,
+ bool canceled) {
+ if (canceled || !HitTest(event.location()))
+ return;
TabContents* tab_contents = parent_->GetTabContents();
if (!tab_contents)
- return true;
+ return;
+
+ gfx::Rect screen_bounds(GetImageBounds());
+ gfx::Point origin(screen_bounds.origin());
+ views::View::ConvertPointToScreen(this, &origin);
+ screen_bounds.set_origin(origin);
ContentSettingBubbleContents* bubble_contents =
new ContentSettingBubbleContents(
ContentSettingBubbleModel::CreateContentSettingBubbleModel(
@@ -1381,9 +1288,9 @@ bool LocationBarView::ContentSettingImageView::OnMousePressed(
content_setting_image_model_->get_content_settings_type()),
profile_, tab_contents);
DCHECK(!info_bubble_);
- info_bubble_ = InfoBubble::Show(GetWindow(), bounds, bubble_contents, this);
+ info_bubble_ =
+ InfoBubble::Show(GetWindow(), screen_bounds, bubble_contents, this);
bubble_contents->set_info_bubble(info_bubble_);
- return true;
}
void LocationBarView::ContentSettingImageView::VisibilityChanged(
@@ -1408,10 +1315,8 @@ bool LocationBarView::ContentSettingImageView::CloseOnEscape() {
LocationBarView::PageActionImageView::PageActionImageView(
LocationBarView* owner,
Profile* profile,
- ExtensionAction* page_action,
- const BubblePositioner* bubble_positioner)
- : LocationBarImageView(bubble_positioner),
- owner_(owner),
+ ExtensionAction* page_action)
+ : owner_(owner),
profile_(profile),
page_action_(page_action),
ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
@@ -1468,19 +1373,17 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button,
if (popup_showing)
return;
- View* parent = GetParent();
- gfx::Point origin;
- View::ConvertPointToScreen(parent, &origin);
- gfx::Rect rect = parent->bounds();
- rect.set_x(origin.x());
- rect.set_y(origin.y());
+ gfx::Rect screen_bounds(GetImageBounds());
+ gfx::Point origin(screen_bounds.origin());
+ View::ConvertPointToScreen(this, &origin);
+ screen_bounds.set_origin(origin);
popup_ = ExtensionPopup::Show(
page_action_->GetPopupUrl(current_tab_id_),
browser,
browser->profile(),
browser->window()->GetNativeHandle(),
- rect,
+ screen_bounds,
BubbleBorder::TOP_RIGHT,
true, // Activate the popup window.
inspect_with_devtools,
@@ -1493,24 +1396,17 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button,
}
}
-void LocationBarView::PageActionImageView::OnMouseMoved(
- const views::MouseEvent& event) {
- // PageActionImageView uses normal tooltips rather than the info bubble,
- // so just do nothing here rather than letting LocationBarImageView start
- // its hover timer.
-}
-
bool LocationBarView::PageActionImageView::OnMousePressed(
const views::MouseEvent& event) {
- // We are interested in capturing mouse messages, but we want want to wait
- // until mouse-up because we might show a context menu. Doing so on mouse-down
- // causes weird bugs like http://crbug.com/33155.
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons. (Also, triggering on mouse press causes bugs like
+ // http://crbug.com/33155.)
return true;
}
void LocationBarView::PageActionImageView::OnMouseReleased(
const views::MouseEvent& event, bool canceled) {
- if (canceled)
+ if (canceled || !HitTest(event.location()))
return;
int button = -1;
@@ -1520,30 +1416,26 @@ void LocationBarView::PageActionImageView::OnMouseReleased(
button = 2;
} else if (event.IsRightMouseButton()) {
// Get the top left point of this button in screen coordinates.
- gfx::Point point = gfx::Point(0, 0);
- ConvertPointToScreen(this, &point);
+ gfx::Point menu_origin;
+ ConvertPointToScreen(this, &menu_origin);
// Make the menu appear below the button.
- point.Offset(0, height());
+ menu_origin.Offset(0, height());
Extension* extension = profile_->GetExtensionsService()->GetExtensionById(
page_action()->extension_id(), false);
Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser();
- context_menu_contents_ = new ExtensionContextMenuModel(
- extension, browser, this);
+ context_menu_contents_ =
+ new ExtensionContextMenuModel(extension, browser, this);
context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
- context_menu_menu_->RunContextMenuAt(point);
+ context_menu_menu_->RunContextMenuAt(menu_origin);
return;
}
ExecuteAction(button, false); // inspect_with_devtools
}
-void LocationBarView::PageActionImageView::ShowInfoBubble() {
- ShowInfoBubbleImpl(ASCIIToWide(tooltip_), GetColor(false, TEXT));
-}
-
void LocationBarView::PageActionImageView::OnImageLoaded(
SkBitmap* image, ExtensionResource resource, int index) {
// We loaded icons()->size() icons, plus one extra if the page action had
@@ -1572,8 +1464,8 @@ void LocationBarView::PageActionImageView::UpdateVisibility(
current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
current_url_ = url;
- bool visible = preview_enabled_ ||
- page_action_->GetIsVisible(current_tab_id_);
+ bool visible =
+ preview_enabled_ || page_action_->GetIsVisible(current_tab_id_);
if (visible) {
// Set the tooltip.
tooltip_ = page_action_->GetTitle(current_tab_id_);
@@ -1629,6 +1521,54 @@ void LocationBarView::PageActionImageView::HidePopup() {
popup_->Close();
}
+// StarView---------------------------------------------------------------------
+
+LocationBarView::StarView::StarView(CommandUpdater* command_updater)
+ : command_updater_(command_updater) {
+ SetID(VIEW_ID_STAR_BUTTON);
+ SetToggled(false);
+}
+
+LocationBarView::StarView::~StarView() {
+}
+
+void LocationBarView::StarView::SetToggled(bool on) {
+ SetTooltipText(l10n_util::GetString(
+ on ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR));
+ // Since StarView is an ImageView, the SetTooltipText changes the accessible
+ // name. To keep the accessible name unchanged, we need to set the accessible
+ // name right after we modify the tooltip text for this view.
+ SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_STAR));
+ SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ on ? IDR_OMNIBOX_STAR_LIT : IDR_OMNIBOX_STAR));
+}
+
+bool LocationBarView::StarView::GetAccessibleRole(
+ AccessibilityTypes::Role* role) {
+ *role = AccessibilityTypes::ROLE_PUSHBUTTON;
+ return true;
+}
+
+bool LocationBarView::StarView::OnMousePressed(const views::MouseEvent& event) {
+ // We want to show the bubble on mouse release; that is the standard behavior
+ // for buttons.
+ return true;
+}
+
+void LocationBarView::StarView::OnMouseReleased(const views::MouseEvent& event,
+ bool canceled) {
+ if (!canceled && HitTest(event.location()))
+ command_updater_->ExecuteCommand(IDC_BOOKMARK_PAGE);
+}
+
+void LocationBarView::StarView::InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape) {
+}
+
+bool LocationBarView::StarView::CloseOnEscape() {
+ return true;
+}
+
////////////////////////////////////////////////////////////////////////////////
// LocationBarView, LocationBar implementation:
diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h
index 681a015..48d72f0 100644
--- a/chrome/browser/views/location_bar_view.h
+++ b/chrome/browser/views/location_bar_view.h
@@ -38,7 +38,6 @@
#endif
class Browser;
-class BubblePositioner;
class CommandUpdater;
class ContentSettingImageModel;
class ExtensionAction;
@@ -57,6 +56,7 @@ class Profile;
class LocationBarView : public LocationBar,
public LocationBarTesting,
public views::View,
+ public views::DragController,
public AutocompleteEditController {
public:
class Delegate {
@@ -76,17 +76,13 @@ class LocationBarView : public LocationBar,
SELECTED_TEXT,
DEEMPHASIZED_TEXT,
SECURITY_TEXT,
- SECURITY_INFO_BUBBLE_TEXT,
- SCHEME_STRIKEOUT,
- NUM_KINDS
};
LocationBarView(Profile* profile,
CommandUpdater* command_updater,
ToolbarModel* model,
Delegate* delegate,
- bool popup_window_mode,
- const BubblePositioner* bubble_positioner);
+ bool popup_window_mode);
virtual ~LocationBarView();
void Init();
@@ -97,7 +93,8 @@ class LocationBarView : public LocationBar,
// Returns the appropriate color for the desired kind, based on the user's
// system theme.
- static SkColor GetColor(bool is_secure, ColorKind kind);
+ static SkColor GetColor(ToolbarModel::SecurityLevel security_level,
+ ColorKind kind);
// Updates the location bar. We also reset the bar's permanent text and
// security style, and, if |tab_for_state_restoring| is non-NULL, also restore
@@ -121,6 +118,12 @@ class LocationBarView : public LocationBar,
// Retrieves the PageAction View which is associated with |page_action|.
views::View* GetPageActionView(ExtensionAction* page_action);
+ // Toggles the star on or off.
+ void SetStarToggled(bool on);
+
+ // Shows the bookmark bubble.
+ void ShowStarBubble(const GURL& url, bool newly_bookmarked);
+
// Sizing functions
virtual gfx::Size GetPreferredSize();
@@ -158,6 +161,15 @@ class LocationBarView : public LocationBar,
virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e);
virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+ // Overridden from views::DragController:
+ virtual void WriteDragData(View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data);
+ virtual int GetDragOperations(View* sender, const gfx::Point& p);
+ virtual bool CanStartDrag(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p);
+
// Overridden from LocationBar:
virtual void ShowFirstRunBubble(FirstRun::BubbleType bubble_type);
virtual std::wstring GetInputString() const;
@@ -172,6 +184,9 @@ class LocationBarView : public LocationBar,
virtual void InvalidatePageActions();
virtual void SaveStateToContents(TabContents* contents);
virtual void Revert();
+ virtual const AutocompleteEditView* location_entry() const {
+ return location_entry_.get();
+ }
virtual AutocompleteEditView* location_entry() {
return location_entry_.get();
}
@@ -190,20 +205,100 @@ class LocationBarView : public LocationBar,
void Focus();
private:
- // View used when the user has selected a keyword.
- //
- // SelectedKeywordView maintains two labels. One label contains the
- // complete description of the keyword, the second contains a truncated
- // version of the description. The second is used if there is not enough room
- // to display the complete description.
- class SelectedKeywordView : public views::View {
+ // This helper class is kept as a member by classes that need to show the Page
+ // Info dialog on click, to encapsulate that logic in one place.
+ class ClickHandler {
public:
- explicit SelectedKeywordView(Profile* profile);
- virtual ~SelectedKeywordView();
+ explicit ClickHandler(const views::View* owner,
+ const LocationBarView* location_bar);
+
+ void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ const views::View* owner_;
+ const LocationBarView* location_bar_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ClickHandler);
+ };
+
+ // LocationIconView is used to display an icon to the left of the edit field.
+ // This shows the user's current action while editing, the page security
+ // status on https pages, or a globe for other URLs.
+ class LocationIconView : public views::ImageView {
+ public:
+ explicit LocationIconView(const LocationBarView* location_bar);
+ virtual ~LocationIconView();
+
+ // Overridden from view.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ ClickHandler click_handler_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LocationIconView);
+ };
+
+ // View used to draw a bubble to the left of the address, containing an icon
+ // and a label. We use this as a base for the classes that handle the EV
+ // bubble and tab-to-search UI.
+ class IconLabelBubbleView : public views::View {
+ public:
+ IconLabelBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color);
+ virtual ~IconLabelBubbleView();
void SetFont(const gfx::Font& font);
+ void SetLabel(const std::wstring& label);
virtual void Paint(gfx::Canvas* canvas);
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+
+ protected:
+ gfx::Size GetNonLabelSize();
+
+ private:
+ // For painting the background.
+ views::HorizontalPainter background_painter_;
+
+ // The contents of the bubble.
+ views::ImageView image_;
+ views::Label label_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IconLabelBubbleView);
+ };
+
+ // EVBubbleView displays the EV Bubble.
+ class EVBubbleView : public IconLabelBubbleView {
+ public:
+ EVBubbleView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ const LocationBarView* location_bar);
+ virtual ~EVBubbleView();
+
+ // Overridden from view.
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ private:
+ ClickHandler click_handler_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(EVBubbleView);
+ };
+
+ // SelectedKeywordView displays the tab-to-search UI.
+ class SelectedKeywordView : public IconLabelBubbleView {
+ public:
+ SelectedKeywordView(const int background_images[],
+ int contained_image,
+ const SkColor& color,
+ Profile* profile);
+ virtual ~SelectedKeywordView();
+
+ void SetFont(const gfx::Font& font);
virtual gfx::Size GetPreferredSize();
virtual gfx::Size GetMinimumSize();
@@ -224,18 +319,16 @@ class LocationBarView : public LocationBar,
// deleted out from under us.
std::wstring keyword_;
- // For painting the background.
- views::HorizontalPainter background_painter_;
-
- // Label containing the complete description.
+ // These labels are never visible. They are used to size the view. One
+ // label contains the complete description of the keyword, the second
+ // contains a truncated version of the description, for if there is not
+ // enough room to display the complete description.
views::Label full_label_;
-
- // Label containing the partial description.
views::Label partial_label_;
Profile* profile_;
- DISALLOW_COPY_AND_ASSIGN(SelectedKeywordView);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SelectedKeywordView);
};
// KeywordHintView is used to display a hint to the user when the selected
@@ -275,96 +368,7 @@ class LocationBarView : public LocationBar,
Profile* profile_;
- DISALLOW_COPY_AND_ASSIGN(KeywordHintView);
- };
-
- class ShowInfoBubbleTask;
- class ShowFirstRunBubbleTask;
-
- class LocationBarImageView : public views::ImageView,
- public InfoBubbleDelegate {
- public:
- explicit LocationBarImageView(const BubblePositioner* bubble_positioner);
- virtual ~LocationBarImageView();
-
- // Overridden from view for the mouse hovering.
- virtual void OnMouseMoved(const views::MouseEvent& event);
- virtual void OnMouseExited(const views::MouseEvent& event);
- virtual bool OnMousePressed(const views::MouseEvent& event) = 0;
-
- // InfoBubbleDelegate
- void InfoBubbleClosing(InfoBubble* info_bubble, bool closed_by_escape);
- bool CloseOnEscape() { return true; }
-
- virtual void ShowInfoBubble() = 0;
-
- protected:
- void ShowInfoBubbleImpl(const std::wstring& text, SkColor text_color);
-
- private:
- friend class ShowInfoBubbleTask;
-
- // The currently shown info bubble if any.
- InfoBubble* info_bubble_;
-
- // A task used to display the info bubble when the mouse hovers on the
- // image.
- ShowInfoBubbleTask* show_info_bubble_task_;
-
- // A positioner used to give the info bubble the correct target bounds. The
- // caller maintains ownership of this and must ensure it's kept alive.
- const BubblePositioner* bubble_positioner_;
-
- DISALLOW_COPY_AND_ASSIGN(LocationBarImageView);
- };
-
- // SecurityImageView is used to display the lock or warning icon when the
- // current URL's scheme is https.
- //
- // If a message has been set with SetInfoBubbleText, it displays an info
- // bubble when the mouse hovers on the image.
- class SecurityImageView : public LocationBarImageView {
- public:
- enum Image {
- LOCK = 0,
- WARNING
- };
-
- SecurityImageView(const LocationBarView* parent,
- Profile* profile,
- ToolbarModel* model_,
- const BubblePositioner* bubble_positioner);
- virtual ~SecurityImageView();
-
- // Sets the image that should be displayed.
- void SetImageShown(Image image);
-
- // Overridden from view for the mouse hovering.
- virtual bool OnMousePressed(const views::MouseEvent& event);
-
- void set_profile(Profile* profile) { profile_ = profile; }
-
- virtual void ShowInfoBubble();
-
- private:
- // The lock icon shown when using HTTPS.
- static SkBitmap* lock_icon_;
-
- // The warning icon shown when HTTPS is broken.
- static SkBitmap* warning_icon_;
-
- // A task used to display the info bubble when the mouse hovers on the
- // image.
- ShowInfoBubbleTask* show_info_bubble_task_;
-
- // The owning LocationBarView.
- const LocationBarView* parent_;
-
- Profile* profile_;
-
- ToolbarModel* model_;
-
- DISALLOW_COPY_AND_ASSIGN(SecurityImageView);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(KeywordHintView);
};
class ContentSettingImageView : public views::ImageView,
@@ -372,8 +376,7 @@ class LocationBarView : public LocationBar,
public:
ContentSettingImageView(ContentSettingsType content_type,
const LocationBarView* parent,
- Profile* profile,
- const BubblePositioner* bubble_positioner);
+ Profile* profile);
virtual ~ContentSettingImageView();
void set_profile(Profile* profile) { profile_ = profile; }
@@ -382,6 +385,7 @@ class LocationBarView : public LocationBar,
private:
// views::ImageView overrides:
virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
virtual void VisibilityChanged(View* starting_from, bool is_visible);
// InfoBubbleDelegate overrides:
@@ -400,25 +404,20 @@ class LocationBarView : public LocationBar,
// The currently shown info bubble if any.
InfoBubble* info_bubble_;
- // A positioner used to give the info bubble the correct target bounds. The
- // caller maintains ownership of this and must ensure it's kept alive.
- const BubblePositioner* bubble_positioner_;
-
DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSettingImageView);
};
typedef std::vector<ContentSettingImageView*> ContentSettingViews;
// PageActionImageView is used to display the icon for a given PageAction
// and notify the extension when the icon is clicked.
- class PageActionImageView : public LocationBarImageView,
+ class PageActionImageView : public views::ImageView,
public ImageLoadingTracker::Observer,
public ExtensionContextMenuModel::PopupDelegate,
public ExtensionPopup::Observer {
public:
PageActionImageView(LocationBarView* owner,
Profile* profile,
- ExtensionAction* page_action,
- const BubblePositioner* bubble_positioner);
+ ExtensionAction* page_action);
virtual ~PageActionImageView();
ExtensionAction* page_action() { return page_action_; }
@@ -430,13 +429,9 @@ class LocationBarView : public LocationBar,
}
// Overridden from view.
- virtual void OnMouseMoved(const views::MouseEvent& event);
virtual bool OnMousePressed(const views::MouseEvent& event);
virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
- // Overridden from LocationBarImageView.
- virtual void ShowInfoBubble();
-
// Overridden from ImageLoadingTracker.
virtual void OnImageLoaded(
SkBitmap* image, ExtensionResource resource, int index);
@@ -497,7 +492,7 @@ class LocationBarView : public LocationBar,
// The current popup and the button it came from. NULL if no popup.
ExtensionPopup* popup_;
- DISALLOW_COPY_AND_ASSIGN(PageActionImageView);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PageActionImageView);
};
friend class PageActionImageView;
@@ -505,11 +500,30 @@ class LocationBarView : public LocationBar,
friend class PageActionWithBadgeView;
typedef std::vector<PageActionWithBadgeView*> PageActionViews;
- // Both Layout and OnChanged call into this. This updates the contents
- // of the 3 views: selected_keyword, keyword_hint and type_search_view. If
- // force_layout is true, or one of these views has changed in such a way as
- // to necessitate a layout, layout occurs as well.
- void DoLayout(bool force_layout);
+ class StarView : public views::ImageView, public InfoBubbleDelegate {
+ public:
+ explicit StarView(CommandUpdater* command_updater);
+ virtual ~StarView();
+
+ // Toggles the star on or off.
+ void SetToggled(bool on);
+
+ private:
+ // views::ImageView overrides:
+ virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+ virtual bool OnMousePressed(const views::MouseEvent& event);
+ virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
+
+ // InfoBubbleDelegate overrides:
+ virtual void InfoBubbleClosing(InfoBubble* info_bubble,
+ bool closed_by_escape);
+ virtual bool CloseOnEscape();
+
+ // The CommandUpdater for the Browser object that owns the location bar.
+ CommandUpdater* command_updater_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StarView);
+ };
// Returns the height in pixels of the margin at the top of the bar.
int TopMargin() const;
@@ -525,25 +539,12 @@ class LocationBarView : public LocationBar,
// minimum size of the view should be used.
bool UsePref(int pref_width, int available_width);
- // Returns true if the view needs to be resized. This determines whether the
- // min or pref should be used, and returns true if the view is not at that
- // size.
- bool NeedsResize(View* view, int available_width);
-
- // Adjusts the keyword hint, selected keyword and type to search views
- // based on the contents of the edit. Returns true if something changed that
- // necessitates a layout.
- bool AdjustHints(int available_width);
-
// If View fits in the specified region, it is made visible and the
// bounds are adjusted appropriately. If the View does not fit, it is
// made invisible.
void LayoutView(bool leading, views::View* view, int available_width,
gfx::Rect* bounds);
- // Sets the security icon to display. Note that no repaint is done.
- void SetSecurityIcon(ToolbarModel::Icon icon);
-
// Update the visibility state of the Content Blocked icons to reflect what is
// actually blocked on the current page.
void RefreshContentSettingViews();
@@ -555,16 +556,8 @@ class LocationBarView : public LocationBar,
// PageActions.
void RefreshPageActionViews();
- // Sets the text that should be displayed in the info label and its associated
- // tooltip text. Call with an empty string if the info label should be
- // hidden.
- void SetInfoText(const std::wstring& text,
- ToolbarModel::InfoTextType text_type,
- const std::wstring& tooltip_text);
-
- // Sets the visibility of view to new_vis. Returns whether the visibility
- // changed.
- bool ToggleVisibility(bool new_vis, views::View* view);
+ // Sets the visibility of view to new_vis.
+ void ToggleVisibility(bool new_vis, views::View* view);
#if defined(OS_WIN)
// Helper for the Mouse event handlers that does all the real work.
@@ -609,13 +602,20 @@ class LocationBarView : public LocationBar,
// Font used by edit and some of the hints.
gfx::Font font_;
+ // An icon to the left of the edit field.
+ LocationIconView location_icon_view_;
+
+ // A bubble displayed for EV HTTPS sites.
+ EVBubbleView ev_bubble_view_;
+
// Location_entry view wrapper
views::NativeViewHost* location_entry_view_;
// The following views are used to provide hints and remind the user as to
// what is going in the edit. They are all added a children of the
// LocationBarView. At most one is visible at a time. Preference is
- // given to the keyword_view_, then hint_view_, then type_to_search_view_.
+ // given to the keyword_view_, then hint_view_.
+ // These autocollapse when the edit needs the room.
// Shown if the user has selected a keyword.
SelectedKeywordView selected_keyword_view_;
@@ -623,20 +623,14 @@ class LocationBarView : public LocationBar,
// Shown if the selected url has a corresponding keyword.
KeywordHintView keyword_hint_view_;
- // Shown if the text is not a keyword or url.
- views::Label type_to_search_view_;
-
- // The view that shows the lock/warning when in HTTPS mode.
- SecurityImageView security_image_view_;
-
// The content setting views.
ContentSettingViews content_setting_views_;
// The page action icon views.
PageActionViews page_action_views_;
- // A label displayed after the lock icon to show some extra information.
- views::Label info_label_;
+ // The star.
+ StarView star_view_;
// When true, the location bar view is read only and also is has a slightly
// different presentation (font size / color). This is used for popups.
@@ -645,13 +639,10 @@ class LocationBarView : public LocationBar,
// Used schedule a task for the first run info bubble.
ScopedRunnableMethodFactory<LocationBarView> first_run_bubble_;
- // The positioner that places the omnibox and info bubbles.
- const BubblePositioner* bubble_positioner_;
-
// Storage of string needed for accessibility.
std::wstring accessible_name_;
- DISALLOW_COPY_AND_ASSIGN(LocationBarView);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(LocationBarView);
};
#endif // CHROME_BROWSER_VIEWS_LOCATION_BAR_VIEW_H_
diff --git a/chrome/browser/views/pinned_contents_info_bubble.cc b/chrome/browser/views/pinned_contents_info_bubble.cc
new file mode 100644
index 0000000..8331db1
--- /dev/null
+++ b/chrome/browser/views/pinned_contents_info_bubble.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010 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/pinned_contents_info_bubble.h"
+
+#include "chrome/browser/views/bubble_border.h"
+
+#if defined(OS_WIN)
+// BorderWidget ---------------------------------------------------------------
+
+void PinnedContentsBorderContents::InitAndGetBounds(
+ const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
+ gfx::Rect* contents_bounds,
+ gfx::Rect* window_bounds) {
+ bubble_border_ = new BubbleBorder;
+
+ // Arrow offset is calculated from the middle of the |position_relative_to|.
+ int offset = position_relative_to.x() + (position_relative_to.width() / 2);
+ offset -= bubble_anchor_.x();
+
+ gfx::Insets insets;
+ bubble_border_->GetInsets(&insets);
+ offset += kLeftMargin + insets.left() + 1;
+ bubble_border_->set_arrow_offset(offset);
+
+ BorderContents::InitAndGetBounds(
+ position_relative_to, contents_size, prefer_arrow_on_right,
+ contents_bounds, window_bounds);
+
+ // Now move the y position to make sure the bubble contents overlap the view.
+ window_bounds->Offset(0, -(kTopMargin + 1));
+}
+
+gfx::Rect PinnedContentsBorderWidget::InitAndGetBounds(
+ HWND owner,
+ const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size,
+ bool prefer_arrow_on_right) {
+ border_contents_ = new PinnedContentsBorderContents(bubble_anchor_);
+ return BorderWidget::InitAndGetBounds(
+ owner, position_relative_to, contents_size,
+ prefer_arrow_on_right);
+}
+#endif
+
+// InfoBubble -----------------------------------------------------------------
+
+// static
+PinnedContentsInfoBubble* PinnedContentsInfoBubble::Show(
+ views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ const gfx::Point& bubble_anchor,
+ views::View* contents,
+ InfoBubbleDelegate* delegate) {
+ PinnedContentsInfoBubble* window =
+ new PinnedContentsInfoBubble(bubble_anchor);
+ window->Init(parent, position_relative_to, contents, delegate);
+ return window;
+}
+
+void PinnedContentsInfoBubble::Init(views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ views::View* contents,
+ InfoBubbleDelegate* delegate) {
+// TODO(finnur): This needs to be implemented for other platforms once we
+// decide this is the way to go.
+#if defined(OS_WIN)
+ border_.reset(new PinnedContentsBorderWidget(bubble_anchor_));
+#endif
+ InfoBubble::Init(parent, position_relative_to, contents, delegate);
+}
diff --git a/chrome/browser/views/pinned_contents_info_bubble.h b/chrome/browser/views/pinned_contents_info_bubble.h
new file mode 100644
index 0000000..92477c0
--- /dev/null
+++ b/chrome/browser/views/pinned_contents_info_bubble.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 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_PINNED_CONTENTS_INFO_BUBBLE_H_
+#define CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
+
+#include "chrome/browser/views/info_bubble.h"
+
+// This is a specialization of BorderContents, used to draw a border around
+// an InfoBubble that has its contents pinned to a specific location. See
+// base class for details.
+class PinnedContentsBorderContents : public BorderContents {
+ public:
+ explicit PinnedContentsBorderContents(const gfx::Point& bubble_anchor)
+ : bubble_anchor_(bubble_anchor) {}
+
+ // BorderContents overrides:
+ virtual void InitAndGetBounds(
+ const gfx::Rect& position_relative_to, // In screen coordinates
+ const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
+ gfx::Rect* contents_bounds, // Returned in window coordinates
+ gfx::Rect* window_bounds); // Returned in screen coordinates
+
+ private:
+ // The location of the pinned contents (in screen coordinates).
+ const gfx::Point bubble_anchor_;
+
+ DISALLOW_COPY_AND_ASSIGN(PinnedContentsBorderContents);
+};
+
+#if defined(OS_WIN)
+// The window that surrounds the info bubble. See base class for details.
+class PinnedContentsBorderWidget : public BorderWidget {
+ public:
+ explicit PinnedContentsBorderWidget(const gfx::Point& bubble_anchor)
+ : bubble_anchor_(bubble_anchor) {}
+ virtual ~PinnedContentsBorderWidget() {}
+
+ // BorderWidget overrides:
+ virtual gfx::Rect InitAndGetBounds(HWND owner,
+ const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size,
+ bool is_rtl);
+
+ private:
+ // The location of the pinned contents (in screen coordinates).
+ const gfx::Point bubble_anchor_;
+
+ DISALLOW_COPY_AND_ASSIGN(PinnedContentsBorderWidget);
+};
+#endif
+
+// A specialization of the InfoBubble. Used to draw an InfoBubble which, in
+// addition to having an arrow pointing to where the user clicked, also shifts
+// the bubble horizontally to fix it to a specific location. See base class
+// for details.
+class PinnedContentsInfoBubble : public InfoBubble {
+ public:
+ // Shows the InfoBubble (see base class function for details).
+ // |bubble_anchor| specifies how far horizontally to shift the bubble in
+ // order to anchor its contents. Once the InfoBubble has been anchored its
+ // arrow may be pointing to a slightly different |y| location than specified
+ // in |position_relative_to|.
+ static PinnedContentsInfoBubble* Show(views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ const gfx::Point& bubble_anchor_,
+ views::View* contents,
+ InfoBubbleDelegate* delegate);
+
+ private:
+ explicit PinnedContentsInfoBubble(const gfx::Point& bubble_anchor)
+ : bubble_anchor_(bubble_anchor) {}
+ virtual ~PinnedContentsInfoBubble() {}
+
+ // InfoBubble overrides:
+ virtual void Init(views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ views::View* contents,
+ InfoBubbleDelegate* delegate);
+
+ // The location of the pinned contents (in screen coordinates).
+ const gfx::Point bubble_anchor_;
+
+ DISALLOW_COPY_AND_ASSIGN(PinnedContentsInfoBubble);
+};
+
+#endif // CHROME_BROWSER_VIEWS_PINNED_CONTENTS_INFO_BUBBLE_H_
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc
index ce26ac7..3521a88 100644
--- a/chrome/browser/views/tabs/dragged_tab_controller.cc
+++ b/chrome/browser/views/tabs/dragged_tab_controller.cc
@@ -316,7 +316,7 @@ DraggedTabController::DraggedTabController(Tab* source_tab,
original_delegate_(NULL),
source_tab_(source_tab),
source_tabstrip_(source_tabstrip),
- source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)),
+ source_model_index_(source_tabstrip->GetModelIndexOfTab(source_tab)),
attached_tabstrip_(source_tabstrip),
old_focused_view_(NULL),
in_destructor_(false),
@@ -508,7 +508,7 @@ void DraggedTabController::InitWindowCreatePoint() {
// first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise,
// the window_create_point_ is not in the correct coordinate system. Please
// refer to http://crbug.com/6223 comment #15 for detailed information.
- Tab* first_tab = source_tabstrip_->GetTabAt(0);
+ Tab* first_tab = source_tabstrip_->GetTabAtTabDataIndex(0);
views::View::ConvertPointToWidget(first_tab, &first_source_tab_point_);
UpdateWindowCreatePoint();
}
@@ -963,8 +963,9 @@ gfx::Point DraggedTabController::GetDraggedViewPoint(
Tab* DraggedTabController::GetTabMatchingDraggedContents(
TabStrip* tabstrip) const {
- int index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_);
- return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index);
+ int model_index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_);
+ return model_index == TabStripModel::kNoTab ?
+ NULL : tabstrip->GetTabAtModelIndex(model_index);
}
bool DraggedTabController::EndDragImpl(EndDragType type) {
diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc
index b363cb5..f089393 100644
--- a/chrome/browser/views/tabs/tab_renderer.cc
+++ b/chrome/browser/views/tabs/tab_renderer.cc
@@ -6,6 +6,7 @@
#include <limits>
+#include "app/animation_container.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "app/slide_animation.h"
@@ -81,9 +82,15 @@ static int loading_animation_frame_count = 0;
static int waiting_animation_frame_count = 0;
static int waiting_to_loading_frame_count_ratio = 0;
+// Used when |render_as_new_tab| is true.
+static SkBitmap* new_tab_mask = NULL;
+static SkBitmap* new_tab_shadow = NULL;
+
TabRenderer::TabImage TabRenderer::tab_alpha = {0};
TabRenderer::TabImage TabRenderer::tab_active = {0};
+TabRenderer::TabImage TabRenderer::tab_active_nano = {0};
TabRenderer::TabImage TabRenderer::tab_inactive = {0};
+TabRenderer::TabImage TabRenderer::tab_alpha_nano = {0};
// Max opacity for the mini-tab title change animation.
const double kMiniTitleChangeThrobOpacity = 0.75;
@@ -205,7 +212,7 @@ class TabCloseButton : public views::ImageButton {
}
private:
- DISALLOW_EVIL_CONSTRUCTORS(TabCloseButton);
+ DISALLOW_COPY_AND_ASSIGN(TabCloseButton);
};
} // namespace
@@ -246,7 +253,7 @@ class TabRenderer::FavIconCrashAnimation : public Animation,
private:
TabRenderer* target_;
- DISALLOW_EVIL_CONSTRUCTORS(FavIconCrashAnimation);
+ DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation);
};
////////////////////////////////////////////////////////////////////////////////
@@ -282,6 +289,10 @@ TabRenderer::~TabRenderer() {
delete crash_animation_;
}
+void TabRenderer::SizeToNewTabButtonImages() {
+ SetBounds(x(), y(), new_tab_shadow->width(), new_tab_shadow->height());
+}
+
void TabRenderer::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
if (parent->GetThemeProvider())
SetThemeProvider(parent->GetThemeProvider());
@@ -407,6 +418,11 @@ void TabRenderer::StopMiniTabTitleAnimation() {
mini_title_animation_->Stop();
}
+void TabRenderer::SetAnimationContainer(AnimationContainer* container) {
+ container_ = container;
+ pulse_animation_->SetContainer(container);
+}
+
void TabRenderer::PaintIcon(gfx::Canvas* canvas) {
if (animation_state_ != ANIMATION_NONE) {
PaintLoadingAnimation(canvas);
@@ -502,6 +518,15 @@ void TabRenderer::OnMouseExited(const views::MouseEvent& e) {
// TabRenderer, views::View overrides:
void TabRenderer::Paint(gfx::Canvas* canvas) {
+ if (data_.render_as_new_tab) {
+ if (UILayoutIsRightToLeft()) {
+ canvas->TranslateInt(width(), 0);
+ canvas->ScaleInt(-1, 1);
+ }
+ PaintAsNewTab(canvas);
+ return;
+ }
+
// Don't paint if we're narrower than we can render correctly. (This should
// only happen during animations).
if (width() < GetMinimumUnselectedSize().width() && !mini())
@@ -715,45 +740,47 @@ void TabRenderer::PaintInactiveTabBackground(gfx::Canvas* canvas) {
int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
0 : background_offset_.y();
- // Draw left edge. Don't draw over the toolbar, as we're not the foreground
- // tab.
- SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
- *tab_bg, offset, bg_offset_y, tab_active.l_width, height());
- SkBitmap theme_l =
- SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l);
- canvas->DrawBitmapInt(theme_l,
- 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
- 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
- false);
-
- // Draw right edge. Again, don't draw over the toolbar.
- SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
- offset + width() - tab_active.r_width, bg_offset_y,
- tab_active.r_width, height());
- SkBitmap theme_r =
- SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r);
- canvas->DrawBitmapInt(theme_r,
- 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap,
- width() - theme_r.width(), 0, theme_r.width(),
- theme_r.height() - kToolbarOverlap, false);
-
- // Draw center. Instead of masking out the top portion we simply skip over it
- // by incrementing by kDropShadowHeight, since it's a simple rectangle. And
- // again, don't draw over the toolbar.
- canvas->TileImageInt(*tab_bg,
- offset + tab_active.l_width, bg_offset_y + kDropShadowHeight,
- tab_active.l_width, kDropShadowHeight,
- width() - tab_active.l_width - tab_active.r_width,
- height() - kDropShadowHeight - kToolbarOverlap);
-
- // Now draw the highlights/shadows around the tab edge.
- canvas->DrawBitmapInt(*tab_inactive.image_l, 0, 0);
- canvas->TileImageInt(*tab_inactive.image_c,
- tab_inactive.l_width, 0,
- width() - tab_inactive.l_width - tab_inactive.r_width,
- height());
- canvas->DrawBitmapInt(*tab_inactive.image_r,
- width() - tab_inactive.r_width, 0);
+ if (!data_.app) {
+ // Draw left edge. Don't draw over the toolbar, as we're not the foreground
+ // tab.
+ SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
+ *tab_bg, offset, bg_offset_y, tab_active.l_width, height());
+ SkBitmap theme_l =
+ SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l);
+ canvas->DrawBitmapInt(theme_l,
+ 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
+ 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
+ false);
+
+ // Draw right edge. Again, don't draw over the toolbar.
+ SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
+ offset + width() - tab_active.r_width, bg_offset_y,
+ tab_active.r_width, height());
+ SkBitmap theme_r =
+ SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r);
+ canvas->DrawBitmapInt(theme_r,
+ 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap,
+ width() - theme_r.width(), 0, theme_r.width(),
+ theme_r.height() - kToolbarOverlap, false);
+
+ // Draw center. Instead of masking out the top portion we simply skip over
+ // it by incrementing by kDropShadowHeight, since it's a simple rectangle.
+ // And again, don't draw over the toolbar.
+ canvas->TileImageInt(*tab_bg,
+ offset + tab_active.l_width, bg_offset_y + kDropShadowHeight,
+ tab_active.l_width, kDropShadowHeight,
+ width() - tab_active.l_width - tab_active.r_width,
+ height() - kDropShadowHeight - kToolbarOverlap);
+
+ // Now draw the highlights/shadows around the tab edge.
+ canvas->DrawBitmapInt(*tab_inactive.image_l, 0, 0);
+ canvas->TileImageInt(*tab_inactive.image_c,
+ tab_inactive.l_width, 0,
+ width() - tab_inactive.l_width - tab_inactive.r_width,
+ height());
+ canvas->DrawBitmapInt(*tab_inactive.image_r,
+ width() - tab_inactive.r_width, 0);
+ }
}
void TabRenderer::PaintActiveTabBackground(gfx::Canvas* canvas) {
@@ -765,33 +792,39 @@ void TabRenderer::PaintActiveTabBackground(gfx::Canvas* canvas) {
SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
+ // App tabs are drawn slightly differently (as nano tabs).
+ TabImage* tab_image = data_.app ? &tab_active_nano : &tab_active;
+ TabImage* alpha = data_.app ? &tab_alpha_nano : &tab_alpha;
+
// Draw left edge.
SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
- *tab_bg, offset, 0, tab_active.l_width, height());
+ *tab_bg, offset, 0, tab_image->l_width, height());
SkBitmap theme_l =
- SkBitmapOperations::CreateMaskedBitmap(tab_l, *tab_alpha.image_l);
+ SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
canvas->DrawBitmapInt(theme_l, 0, 0);
// Draw right edge.
SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
- offset + width() - tab_active.r_width, 0, tab_active.r_width, height());
+ offset + width() - tab_image->r_width, 0, tab_image->r_width, height());
SkBitmap theme_r =
- SkBitmapOperations::CreateMaskedBitmap(tab_r, *tab_alpha.image_r);
- canvas->DrawBitmapInt(theme_r, width() - tab_active.r_width, 0);
+ SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
+ canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0);
// Draw center. Instead of masking out the top portion we simply skip over it
// by incrementing by kDropShadowHeight, since it's a simple rectangle.
canvas->TileImageInt(*tab_bg,
- offset + tab_active.l_width, kDropShadowHeight,
- tab_active.l_width, kDropShadowHeight,
- width() - tab_active.l_width - tab_active.r_width,
- height() - kDropShadowHeight);
+ offset + tab_image->l_width,
+ kDropShadowHeight + tab_image->y_offset,
+ tab_image->l_width,
+ kDropShadowHeight + tab_image->y_offset,
+ width() - tab_image->l_width - tab_image->r_width,
+ height() - kDropShadowHeight - tab_image->y_offset);
// Now draw the highlights/shadows around the tab edge.
- canvas->DrawBitmapInt(*tab_active.image_l, 0, 0);
- canvas->TileImageInt(*tab_active.image_c, tab_active.l_width, 0,
- width() - tab_active.l_width - tab_active.r_width, height());
- canvas->DrawBitmapInt(*tab_active.image_r, width() - tab_active.r_width, 0);
+ canvas->DrawBitmapInt(*tab_image->image_l, 0, 0);
+ canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0,
+ width() - tab_image->l_width - tab_image->r_width, height());
+ canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0);
}
void TabRenderer::PaintLoadingAnimation(gfx::Canvas* canvas) {
@@ -819,6 +852,47 @@ void TabRenderer::PaintLoadingAnimation(gfx::Canvas* canvas) {
false);
}
+void TabRenderer::PaintAsNewTab(gfx::Canvas* canvas) {
+ bool is_otr = data_.off_the_record;
+
+ // The tab image needs to be lined up with the background image
+ // so that it feels partially transparent. These offsets represent the tab
+ // position within the frame background image.
+ int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) +
+ background_offset_.x();
+
+ int tab_id;
+ if (GetWidget() &&
+ GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) {
+ tab_id = IDR_THEME_TAB_BACKGROUND_V;
+ } else {
+ tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
+ IDR_THEME_TAB_BACKGROUND;
+ }
+
+ SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
+
+ // If the theme is providing a custom background image, then its top edge
+ // should be at the top of the tab. Otherwise, we assume that the background
+ // image is a composited foreground + frame image.
+ int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
+ 0 : background_offset_.y();
+
+ SkBitmap image = SkBitmapOperations::CreateTiledBitmap(
+ *tab_bg, offset, bg_offset_y, new_tab_mask->width(),
+ new_tab_mask->height());
+ image = SkBitmapOperations::CreateMaskedBitmap(image, *new_tab_mask);
+ canvas->DrawBitmapInt(image,
+ 0, 0, image.width(), image.height(),
+ 0, 0, image.width(), image.height(),
+ false);
+
+ canvas->DrawBitmapInt(*new_tab_shadow,
+ 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
+ 0, 0, new_tab_shadow->width(), new_tab_shadow->height(),
+ false);
+}
+
int TabRenderer::IconCapacity() const {
if (height() < GetMinimumUnselectedSize().height())
return 0;
@@ -844,6 +918,9 @@ bool TabRenderer::ShouldShowCloseBox() const {
}
double TabRenderer::GetThrobValue() {
+ if (data_.alpha != 1)
+ return data_.alpha;
+
if (pulse_animation_->IsAnimating())
return pulse_animation_->GetCurrentValue() * kHoverOpacity;
@@ -892,21 +969,38 @@ void TabRenderer::LoadTabImages() {
tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
+ tab_alpha_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_LEFT);
+ tab_alpha_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_NANO_RIGHT);
+
tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
tab_active.l_width = tab_active.image_l->width();
tab_active.r_width = tab_active.image_r->width();
+ // This is high much taller *visually* the regular tab is compared to the
+ // nano tabs. The images are the same height, this is really just the
+ // difference in whitespace above the tab image.
+ const int kMiniTabDiffHeight = 14;
+
+ tab_active_nano.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_LEFT);
+ tab_active_nano.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_CENTER);
+ tab_active_nano.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_NANO_RIGHT);
+ tab_active_nano.l_width = tab_active_nano.image_l->width();
+ tab_active_nano.r_width = tab_active_nano.image_r->width();
+ tab_active_nano.y_offset = kMiniTabDiffHeight;
+
tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
-
tab_inactive.l_width = tab_inactive.image_l->width();
tab_inactive.r_width = tab_inactive.image_r->width();
loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
+
+ new_tab_mask = rb.GetBitmapNamed(IDR_TAB_ALPHA_NEW_TAB);
+ new_tab_shadow = rb.GetBitmapNamed(IDR_TAB_NEW_TAB_SHADOW);
}
void TabRenderer::SetBlocked(bool blocked) {
diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h
index 2e309c6..fc01a7a 100644
--- a/chrome/browser/views/tabs/tab_renderer.h
+++ b/chrome/browser/views/tabs/tab_renderer.h
@@ -1,17 +1,19 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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_TABS_TAB_RENDERER_H__
-#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H__
+#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
+#define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
#include "app/animation.h"
+#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/string16.h"
#include "gfx/point.h"
#include "views/controls/button/image_button.h"
#include "views/view.h"
+class AnimationContainer;
class SlideAnimation;
class TabContents;
class ThrobAnimation;
@@ -37,6 +39,11 @@ class TabRenderer : public views::View,
TabRenderer();
virtual ~TabRenderer();
+ // Sizes the renderer to the size of the new tab images. This is used
+ // during the new tab animation. See TabStrip's description of AnimationType
+ // for details.
+ void SizeToNewTabButtonImages();
+
// Overridden from views:
void ViewHierarchyChanged(bool is_add, View* parent, View* child);
ThemeProvider* GetThemeProvider();
@@ -55,10 +62,26 @@ class TabRenderer : public views::View,
void set_mini(bool mini) { data_.mini = mini; }
bool mini() const { return data_.mini; }
+ // Sets the mini-state of the tab.
+ void set_app(bool app) { data_.app = app; }
+ bool app() const { return data_.app; }
+
// Sets the phantom state of the tab.
void set_phantom(bool phantom) { data_.phantom = phantom; }
bool phantom() const { return data_.phantom; }
+ // Used during new tab animation to force the tab to render a new tab like
+ // animation.
+ void set_render_as_new_tab(bool value) { data_.render_as_new_tab = value; }
+
+ // Sets the alpha value to render the tab at. This is used during the new
+ // tab animation.
+ void set_alpha(double value) { data_.alpha = value; }
+
+ // Forces the tab to render unselected even though it is selected.
+ void set_render_unselected(bool value) { data_.render_unselected = value; }
+ bool render_unselected() const { return data_.render_unselected; }
+
// Are we in the process of animating a mini tab state change on this tab?
void set_animating_mini_change(bool value);
@@ -93,6 +116,9 @@ class TabRenderer : public views::View,
theme_provider_ = provider;
}
+ // Sets the container all animations run from.
+ void SetAnimationContainer(AnimationContainer* container);
+
// Paints the icon. Most of the time you'll want to invoke Paint directly, but
// in certain situations this invoked outside of Paint.
void PaintIcon(gfx::Canvas* canvas);
@@ -158,6 +184,7 @@ class TabRenderer : public views::View,
void PaintInactiveTabBackground(gfx::Canvas* canvas);
void PaintActiveTabBackground(gfx::Canvas* canvas);
void PaintLoadingAnimation(gfx::Canvas* canvas);
+ void PaintAsNewTab(gfx::Canvas* canvas);
// Returns the number of favicon-size elements that can fit in the tab's
// current size.
@@ -211,7 +238,11 @@ class TabRenderer : public views::View,
mini(false),
blocked(false),
animating_mini_change(false),
- phantom(false) {
+ phantom(false),
+ app(false),
+ render_as_new_tab(false),
+ render_unselected(false),
+ alpha(1) {
}
SkBitmap favicon;
@@ -224,6 +255,10 @@ class TabRenderer : public views::View,
bool blocked;
bool animating_mini_change;
bool phantom;
+ bool app;
+ bool render_as_new_tab;
+ bool render_unselected;
+ double alpha;
};
TabData data_;
@@ -233,10 +268,13 @@ class TabRenderer : public views::View,
SkBitmap* image_r;
int l_width;
int r_width;
+ int y_offset;
};
static TabImage tab_active;
+ static TabImage tab_active_nano;
static TabImage tab_inactive;
static TabImage tab_alpha;
+ static TabImage tab_alpha_nano;
// Whether we're showing the icon. It is cached so that we can detect when it
// changes and layout appropriately.
@@ -260,10 +298,12 @@ class TabRenderer : public views::View,
ThemeProvider* theme_provider_;
+ scoped_refptr<AnimationContainer> container_;
+
static void InitClass();
static bool initialized_;
- DISALLOW_EVIL_CONSTRUCTORS(TabRenderer);
+ DISALLOW_COPY_AND_ASSIGN(TabRenderer);
};
-#endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H__
+#endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_H_
diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc
index 1a9edb3..a28ff52b 100644
--- a/chrome/browser/views/tabs/tab_strip.cc
+++ b/chrome/browser/views/tabs/tab_strip.cc
@@ -4,12 +4,14 @@
#include "chrome/browser/views/tabs/tab_strip.h"
+#include "app/animation_container.h"
#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
#include "app/os_exchange_data.h"
#include "app/resource_bundle.h"
#include "app/slide_animation.h"
#include "base/command_line.h"
+#include "base/compiler_specific.h"
#include "base/stl_util-inl.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_theme_provider.h"
@@ -25,6 +27,7 @@
#include "chrome/browser/views/tabs/tab.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
#include "gfx/canvas.h"
#include "gfx/path.h"
#include "gfx/size.h"
@@ -54,10 +57,21 @@
using views::DropTargetEvent;
-static const int kDefaultAnimationDurationMs = 200;
-static const int kResizeLayoutAnimationDurationMs = 200;
-static const int kReorderAnimationDurationMs = 200;
-static const int kMiniTabAnimationDurationMs = 200;
+// Duration of the first step in a new tab animation.
+static const int kNewTabDurationMs = 50;
+
+// Duration of the last step in the new tab animation.
+static const int kNewTab3DurationMs = 100;
+
+// Amount in pixels newly inserted tabs go past target bounds before animating
+// to final position. This is used for ANIMATION_NEW_TAB_2.
+static const int kNewTabOvershoot = 9;
+
+// Amount in pixels the newly inserted tab is clipped against the previous
+// tab while animating. This is used to make sure the user doesn't see the
+// newly inserted tab behind other tabs and so that its shadow isn't visible
+// until the user can actually see the tab.
+static const int kNetTabSelectedOffset = -13;
static const int kNewTabButtonHOffset = -5;
static const int kNewTabButtonVOffset = 5;
@@ -81,6 +95,27 @@ static inline int Round(double x) {
return static_cast<int>(floor(x + 0.5));
}
+namespace {
+
+// Animation delegate used during new tab animation step 2 to vary the alpha of
+// the tab.
+class NewTabAlphaDelegate
+ : public views::BoundsAnimator::OwnedAnimationDelegate {
+ public:
+ explicit NewTabAlphaDelegate(Tab* tab) : tab_(tab) {
+ }
+
+ virtual void AnimationProgressed(const Animation* animation) {
+ if (tab_->render_unselected())
+ tab_->set_alpha(animation->GetCurrentValue());
+ }
+
+ private:
+ Tab* tab_;
+
+ DISALLOW_COPY_AND_ASSIGN(NewTabAlphaDelegate);
+};
+
///////////////////////////////////////////////////////////////////////////////
// NewTabButton
//
@@ -124,292 +159,44 @@ class NewTabButton : public views::ImageButton {
DISALLOW_COPY_AND_ASSIGN(NewTabButton);
};
-///////////////////////////////////////////////////////////////////////////////
-//
-// TabAnimation
-//
-// A base class for all TabStrip animations.
-//
-class TabStrip::TabAnimation : public AnimationDelegate {
- public:
- friend class TabStrip;
-
- // Possible types of animation.
- enum Type {
- INSERT,
- REMOVE,
- MOVE,
- RESIZE,
- MINI,
- MINI_MOVE
- };
-
- TabAnimation(TabStrip* tabstrip, Type type)
- : tabstrip_(tabstrip),
- animation_(this),
- start_selected_width_(0),
- start_unselected_width_(0),
- end_selected_width_(0),
- end_unselected_width_(0),
- layout_on_completion_(false),
- type_(type) {
- }
- virtual ~TabAnimation() {}
-
- Type type() const { return type_; }
-
- void Start() {
- animation_.SetSlideDuration(GetDuration());
- animation_.SetTweenType(SlideAnimation::EASE_OUT);
- if (!animation_.IsShowing()) {
- animation_.Reset();
- animation_.Show();
- }
- }
-
- void Stop() {
- animation_.Stop();
- }
-
- void set_layout_on_completion(bool layout_on_completion) {
- layout_on_completion_ = layout_on_completion;
- }
-
- // Retrieves the width for the Tab at the specified index if an animation is
- // active.
- static double GetCurrentTabWidth(TabStrip* tabstrip,
- TabStrip::TabAnimation* animation,
- int index) {
- Tab* tab = tabstrip->GetTabAt(index);
- double tab_width;
- if (tab->mini()) {
- tab_width = Tab::GetMiniWidth();
- } else {
- double unselected, selected;
- tabstrip->GetCurrentTabWidths(&unselected, &selected);
- tab_width = tab->IsSelected() ? selected : unselected;
- }
- if (animation) {
- double specified_tab_width = animation->GetWidthForTab(index);
- if (specified_tab_width != -1)
- tab_width = specified_tab_width;
- }
- return tab_width;
- }
+} // namespace
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation) {
- tabstrip_->AnimationLayout(end_unselected_width_);
+// AnimationDelegate used when removing a tab. Does the necessary cleanup when
+// done.
+class TabStrip::RemoveTabDelegate
+ : public views::BoundsAnimator::OwnedAnimationDelegate {
+ public:
+ RemoveTabDelegate(TabStrip* tab_strip, Tab* tab)
+ : tabstrip_(tab_strip),
+ tab_(tab) {
}
virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->FinishAnimation(this, layout_on_completion_);
- // This object is destroyed now, so we can't do anything else after this.
+ CompleteRemove();
}
virtual void AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
- }
-
- // Returns the gap before the tab at the specified index. Subclass if during
- // an animation you need to insert a gap before a tab.
- virtual double GetGapWidth(int index) {
- return 0;
- }
-
- protected:
- // Returns the duration of the animation.
- virtual int GetDuration() const {
- return kDefaultAnimationDurationMs;
- }
-
- // Subclasses override to return the width of the Tab at the specified index
- // at the current animation frame. -1 indicates the default width should be
- // used for the Tab.
- virtual double GetWidthForTab(int index) const {
- return -1; // Use default.
- }
-
- // Figure out the desired start and end widths for the specified pre- and
- // post- animation tab counts.
- void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count,
- int start_mini_count,
- int end_mini_count) {
- tabstrip_->GetDesiredTabWidths(start_tab_count, start_mini_count,
- &start_unselected_width_,
- &start_selected_width_);
- double standard_tab_width =
- static_cast<double>(TabRenderer::GetStandardSize().width());
- if (start_tab_count < end_tab_count &&
- start_unselected_width_ < standard_tab_width) {
- double minimum_tab_width =
- static_cast<double>(TabRenderer::GetMinimumUnselectedSize().width());
- start_unselected_width_ -= minimum_tab_width / start_tab_count;
- }
- tabstrip_->GenerateIdealBounds();
- tabstrip_->GetDesiredTabWidths(end_tab_count, end_mini_count,
- &end_unselected_width_,
- &end_selected_width_);
- }
-
- TabStrip* tabstrip_;
- SlideAnimation animation_;
-
- double start_selected_width_;
- double start_unselected_width_;
- double end_selected_width_;
- double end_unselected_width_;
-
- private:
- // True if a complete re-layout is required upon completion of the animation.
- // Subclasses set this if they don't perform a complete layout
- // themselves and canceling the animation may leave the strip in an
- // inconsistent state.
- bool layout_on_completion_;
-
- const Type type_;
-
- DISALLOW_COPY_AND_ASSIGN(TabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles insertion of a Tab at |index|.
-class TabStrip::InsertTabAnimation : public TabStrip::TabAnimation {
- public:
- explicit InsertTabAnimation(TabStrip* tabstrip, int index)
- : TabAnimation(tabstrip, INSERT),
- index_(index) {
- int tab_count = tabstrip->GetTabCount();
- int end_mini_count = tabstrip->GetMiniTabCount();
- int start_mini_count = end_mini_count;
- if (index < end_mini_count)
- start_mini_count--;
- GenerateStartAndEndWidths(tab_count - 1, tab_count, start_mini_count,
- end_mini_count);
- }
- virtual ~InsertTabAnimation() {}
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual double GetWidthForTab(int index) const {
- if (index == index_) {
- bool is_selected = tabstrip_->model()->selected_index() == index;
- double start_width, target_width;
- if (index < tabstrip_->GetMiniTabCount()) {
- start_width = Tab::GetMinimumSelectedSize().width();
- target_width = Tab::GetMiniWidth();
- } else {
- target_width =
- is_selected ? end_unselected_width_ : end_selected_width_;
- start_width =
- is_selected ? Tab::GetMinimumSelectedSize().width() :
- Tab::GetMinimumUnselectedSize().width();
- }
- double delta = target_width - start_width;
- if (delta > 0)
- return start_width + (delta * animation_.GetCurrentValue());
- return start_width;
- }
-
- if (tabstrip_->GetTabAt(index)->mini())
- return Tab::GetMiniWidth();
-
- if (tabstrip_->GetTabAt(index)->IsSelected()) {
- double delta = end_selected_width_ - start_selected_width_;
- return start_selected_width_ + (delta * animation_.GetCurrentValue());
- }
-
- double delta = end_unselected_width_ - start_unselected_width_;
- return start_unselected_width_ + (delta * animation_.GetCurrentValue());
+ // We can be canceled for two interesting reasons:
+ // . The tab we reference was dragged back into the tab strip. In this case
+ // we don't want to remove the tab (closing is false).
+ // . The drag was completed before the animation completed
+ // (DestroyDraggedSourceTab). In this case we need to remove the tab
+ // (closing is true).
+ if (tab_->closing())
+ CompleteRemove();
}
private:
- int index_;
-
- DISALLOW_COPY_AND_ASSIGN(InsertTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles removal of a Tab from |index|
-class TabStrip::RemoveTabAnimation : public TabStrip::TabAnimation {
- public:
- RemoveTabAnimation(TabStrip* tabstrip, int index, TabContents* contents)
- : TabAnimation(tabstrip, REMOVE),
- index_(index) {
- int tab_count = tabstrip->GetTabCount();
- int start_mini_count = tabstrip->GetMiniTabCount();
- int end_mini_count = start_mini_count;
- if (index < start_mini_count)
- end_mini_count--;
- GenerateStartAndEndWidths(tab_count, tab_count - 1, start_mini_count,
- end_mini_count);
- // If the last non-mini-tab is being removed we force a layout on
- // completion. This is necessary as the value returned by GetTabHOffset
- // changes once the tab is actually removed (which happens at the end of
- // the animation), and unless we layout GetTabHOffset won't be called after
- // the removal.
- // We do the same when the last mini-tab is being removed for the same
- // reason.
- set_layout_on_completion(start_mini_count > 0 &&
- (end_mini_count == 0 ||
- (start_mini_count == end_mini_count &&
- tab_count == start_mini_count + 1)));
- }
-
- // Returns the index of the tab being removed.
- int index() const { return index_; }
-
- virtual ~RemoveTabAnimation() {
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual double GetWidthForTab(int index) const {
- Tab* tab = tabstrip_->GetTabAt(index);
- if (index == index_) {
- // The tab(s) being removed are gradually shrunken depending on the state
- // of the animation.
- // Removed animated Tabs are never selected.
- if (tab->mini()) {
- return animation_.CurrentValueBetween(Tab::GetMiniWidth(),
- -kTabHOffset);
- }
-
- double start_width = start_unselected_width_;
- // Make sure target_width is at least abs(kTabHOffset), otherwise if
- // less than kTabHOffset during layout tabs get negatively offset.
- double target_width =
- std::max(abs(kTabHOffset),
- Tab::GetMinimumUnselectedSize().width() + kTabHOffset);
- return animation_.CurrentValueBetween(start_width, target_width);
- }
-
- if (tab->mini())
- return Tab::GetMiniWidth();
-
- if (tabstrip_->available_width_for_tabs_ != -1 &&
- index_ != tabstrip_->GetTabCount() - 1) {
- return TabStrip::TabAnimation::GetWidthForTab(index);
- }
- // All other tabs are sized according to the start/end widths specified at
- // the start of the animation.
- if (tab->IsSelected()) {
- double delta = end_selected_width_ - start_selected_width_;
- return start_selected_width_ + (delta * animation_.GetCurrentValue());
+ void CompleteRemove() {
+ if (!tab_->closing()) {
+ // The tab was added back yet we weren't canceled. This shouldn't happen.
+ NOTREACHED();
+ return;
}
- double delta = end_unselected_width_ - start_unselected_width_;
- return start_unselected_width_ + (delta * animation_.GetCurrentValue());
- }
-
- virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->RemoveTabAt(index_);
+ tabstrip_->RemoveTab(tab_);
HighlightCloseButton();
- TabStrip::TabAnimation::AnimationEnded(animation);
}
- private:
// When the animation completes, we send the Container a message to simulate
// a mouse moved event at the current mouse position. This tickles the Tab
// the mouse is currently over to show the "hot" state of the close button.
@@ -439,293 +226,10 @@ class TabStrip::RemoveTabAnimation : public TabStrip::TabAnimation {
#endif
}
- int index_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles the movement of a Tab from one position to another.
-class TabStrip::MoveTabAnimation : public TabStrip::TabAnimation {
- public:
- MoveTabAnimation(TabStrip* tabstrip, int tab_a_index, int tab_b_index)
- : TabAnimation(tabstrip, MOVE),
- start_tab_a_bounds_(tabstrip_->GetIdealBounds(tab_b_index)),
- start_tab_b_bounds_(tabstrip_->GetIdealBounds(tab_a_index)) {
- tab_a_ = tabstrip_->GetTabAt(tab_a_index);
- tab_b_ = tabstrip_->GetTabAt(tab_b_index);
-
- // Since we don't do a full TabStrip re-layout, we need to force a full
- // layout upon completion since we're not guaranteed to be in a good state
- // if for example the animation is canceled.
- set_layout_on_completion(true);
- }
- virtual ~MoveTabAnimation() {}
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation) {
- // Position Tab A
- double distance = start_tab_b_bounds_.x() - start_tab_a_bounds_.x();
- double delta = distance * animation_.GetCurrentValue();
- double new_x = start_tab_a_bounds_.x() + delta;
- tab_a_->SetBounds(Round(new_x), tab_a_->y(), tab_a_->width(),
- tab_a_->height());
-
- // Position Tab B
- distance = start_tab_a_bounds_.x() - start_tab_b_bounds_.x();
- delta = distance * animation_.GetCurrentValue();
- new_x = start_tab_b_bounds_.x() + delta;
- tab_b_->SetBounds(Round(new_x), tab_b_->y(), tab_b_->width(),
- tab_b_->height());
-
- tabstrip_->SchedulePaint();
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const { return kReorderAnimationDurationMs; }
-
- private:
- // The two tabs being exchanged.
- Tab* tab_a_;
- Tab* tab_b_;
-
- // ...and their bounds.
- gfx::Rect start_tab_a_bounds_;
- gfx::Rect start_tab_b_bounds_;
-
- DISALLOW_COPY_AND_ASSIGN(MoveTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles the animated resize layout of the entire TabStrip from one width
-// to another.
-class TabStrip::ResizeLayoutAnimation : public TabStrip::TabAnimation {
- public:
- explicit ResizeLayoutAnimation(TabStrip* tabstrip)
- : TabAnimation(tabstrip, RESIZE) {
- int tab_count = tabstrip->GetTabCount();
- int mini_tab_count = tabstrip->GetMiniTabCount();
- GenerateStartAndEndWidths(tab_count, tab_count, mini_tab_count,
- mini_tab_count);
- InitStartState();
- }
- virtual ~ResizeLayoutAnimation() {
- }
-
- // Overridden from AnimationDelegate:
- virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->needs_resize_layout_ = false;
- TabStrip::TabAnimation::AnimationEnded(animation);
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const {
- return kResizeLayoutAnimationDurationMs;
- }
-
- virtual double GetWidthForTab(int index) const {
- Tab* tab = tabstrip_->GetTabAt(index);
- if (tab->mini())
- return Tab::GetMiniWidth();
-
- if (tab->IsSelected()) {
- return animation_.CurrentValueBetween(start_selected_width_,
- end_selected_width_);
- }
-
- return animation_.CurrentValueBetween(start_unselected_width_,
- end_unselected_width_);
- }
-
- private:
- // We need to start from the current widths of the Tabs as they were last
- // laid out, _not_ the last known good state, which is what'll be done if we
- // don't measure the Tab sizes here and just go with the default TabAnimation
- // behavior...
- void InitStartState() {
- for (int i = 0; i < tabstrip_->GetTabCount(); ++i) {
- Tab* current_tab = tabstrip_->GetTabAt(i);
- if (!current_tab->mini()) {
- if (current_tab->IsSelected()) {
- start_selected_width_ = current_tab->width();
- } else {
- start_unselected_width_ = current_tab->width();
- }
- }
- }
- }
-
- DISALLOW_COPY_AND_ASSIGN(ResizeLayoutAnimation);
-};
-
-// Handles a tabs mini-state changing while the tab does not change position
-// in the model.
-class TabStrip::MiniTabAnimation : public TabStrip::TabAnimation {
- public:
- explicit MiniTabAnimation(TabStrip* tabstrip, int index)
- : TabAnimation(tabstrip, MINI),
- index_(index) {
- int tab_count = tabstrip->GetTabCount();
- int start_mini_count = tabstrip->GetMiniTabCount();
- int end_mini_count = start_mini_count;
- if (tabstrip->GetTabAt(index)->mini())
- start_mini_count--;
- else
- start_mini_count++;
- tabstrip_->GetTabAt(index)->set_animating_mini_change(true);
- GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
- end_mini_count);
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const {
- return kMiniTabAnimationDurationMs;
- }
-
- virtual double GetWidthForTab(int index) const {
- Tab* tab = tabstrip_->GetTabAt(index);
-
- if (index == index_) {
- if (tab->mini()) {
- return animation_.CurrentValueBetween(
- start_selected_width_,
- static_cast<double>(Tab::GetMiniWidth()));
- } else {
- return animation_.CurrentValueBetween(
- static_cast<double>(Tab::GetMiniWidth()),
- end_selected_width_);
- }
- } else if (tab->mini()) {
- return Tab::GetMiniWidth();
- }
-
- if (tab->IsSelected()) {
- return animation_.CurrentValueBetween(start_selected_width_,
- end_selected_width_);
- }
-
- return animation_.CurrentValueBetween(start_unselected_width_,
- end_unselected_width_);
- }
-
- private:
- // Index of the tab whose mini state changed.
- int index_;
-
- DISALLOW_COPY_AND_ASSIGN(MiniTabAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-// Handles the animation when a tabs mini state changes and the tab moves as a
-// result.
-class TabStrip::MiniMoveAnimation : public TabStrip::TabAnimation {
- public:
- explicit MiniMoveAnimation(TabStrip* tabstrip,
- int from_index,
- int to_index,
- const gfx::Rect& start_bounds)
- : TabAnimation(tabstrip, MINI_MOVE),
- tab_(tabstrip->GetTabAt(to_index)),
- start_bounds_(start_bounds),
- from_index_(from_index),
- to_index_(to_index) {
- int tab_count = tabstrip->GetTabCount();
- int start_mini_count = tabstrip->GetMiniTabCount();
- int end_mini_count = start_mini_count;
- if (tabstrip->GetTabAt(to_index)->mini())
- start_mini_count--;
- else
- start_mini_count++;
- GenerateStartAndEndWidths(tab_count, tab_count, start_mini_count,
- end_mini_count);
- target_bounds_ = tabstrip->GetIdealBounds(to_index);
- tab_->set_animating_mini_change(true);
- }
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation) {
- // Do the normal layout.
- TabAnimation::AnimationProgressed(animation);
-
- // Then special case the position of the tab being moved.
- int x = animation_.CurrentValueBetween(start_bounds_.x(),
- target_bounds_.x());
- int width = animation_.CurrentValueBetween(start_bounds_.width(),
- target_bounds_.width());
- gfx::Rect tab_bounds(x, start_bounds_.y(), width,
- start_bounds_.height());
- tab_->SetBounds(tab_bounds);
- }
-
- virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->needs_resize_layout_ = false;
- TabStrip::TabAnimation::AnimationEnded(animation);
- }
-
- virtual double GetGapWidth(int index) {
- if (to_index_ < from_index_) {
- // The tab was mini.
- if (index == to_index_) {
- double current_size =
- animation_.CurrentValueBetween(0, target_bounds_.width());
- if (current_size < -kTabHOffset)
- return -(current_size + kTabHOffset);
- } else if (index == from_index_ + 1) {
- return animation_.CurrentValueBetween(start_bounds_.width(), 0);
- }
- } else {
- // The tab was made a normal tab.
- if (index == from_index_) {
- return animation_.CurrentValueBetween(Tab::GetMiniWidth() +
- kTabHOffset, 0);
- }
- }
- return 0;
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const { return kReorderAnimationDurationMs; }
-
- virtual double GetWidthForTab(int index) const {
- Tab* tab = tabstrip_->GetTabAt(index);
-
- if (index == to_index_)
- return animation_.CurrentValueBetween(0, target_bounds_.width());
-
- if (tab->mini())
- return Tab::GetMiniWidth();
-
- if (tab->IsSelected()) {
- return animation_.CurrentValueBetween(start_selected_width_,
- end_selected_width_);
- }
-
- return animation_.CurrentValueBetween(start_unselected_width_,
- end_unselected_width_);
- }
-
- private:
- // The tab being moved.
+ TabStrip* tabstrip_;
Tab* tab_;
- // Initial bounds of tab_.
- gfx::Rect start_bounds_;
-
- // Target bounds.
- gfx::Rect target_bounds_;
-
- // Start and end indices of the tab.
- int from_index_;
- int to_index_;
-
- DISALLOW_COPY_AND_ASSIGN(MiniMoveAnimation);
+ DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate);
};
///////////////////////////////////////////////////////////////////////////////
@@ -741,13 +245,14 @@ TabStrip::TabStrip(TabStripModel* model)
needs_resize_layout_(false),
current_unselected_width_(Tab::GetStandardSize().width()),
current_selected_width_(Tab::GetStandardSize().width()),
- available_width_for_tabs_(-1) {
+ available_width_for_tabs_(-1),
+ animation_container_(new AnimationContainer()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)),
+ animation_type_(ANIMATION_DEFAULT) {
Init();
}
TabStrip::~TabStrip() {
- active_animation_.reset(NULL);
-
// TODO(beng): (1031854) Restore this line once XPFrame/VistaFrame are dead.
// model_->RemoveObserver(this);
@@ -775,36 +280,34 @@ void TabStrip::DestroyDragController() {
void TabStrip::DestroyDraggedSourceTab(Tab* tab) {
// We could be running an animation that references this Tab.
- if (active_animation_.get())
- active_animation_->Stop();
+ StopAnimating(true);
+
// Make sure we leave the tab_data_ vector in a consistent state, otherwise
// we'll be pointing to tabs that have been deleted and removed from the
// child view list.
- std::vector<TabData>::iterator it = tab_data_.begin();
- for (; it != tab_data_.end(); ++it) {
- if (it->tab == tab) {
- if (!model_->closing_all())
- NOTREACHED() << "Leaving in an inconsistent state!";
- tab_data_.erase(it);
- break;
- }
+ int tab_data_index = TabDataIndexOfTab(tab);
+ if (tab_data_index != -1) {
+ if (!model_->closing_all())
+ NOTREACHED() << "Leaving in an inconsistent state!";
+ tab_data_.erase(tab_data_.begin() + tab_data_index);
}
- tab->GetParent()->RemoveChildView(tab);
+
delete tab;
+
// Force a layout here, because if we've just quickly drag detached a Tab,
// the stopping of the active animation above may have left the TabStrip in a
// bad (visual) state.
Layout();
}
-gfx::Rect TabStrip::GetIdealBounds(int index) {
- DCHECK_GE(index, 0);
- DCHECK_LT(index, GetTabCount());
- return tab_data_.at(index).ideal_bounds;
+gfx::Rect TabStrip::GetIdealBounds(int tab_data_index) {
+ DCHECK_GE(tab_data_index, 0);
+ DCHECK_LT(tab_data_index, GetTabCount());
+ return tab_data_[tab_data_index].ideal_bounds;
}
Tab* TabStrip::GetSelectedTab() const {
- return GetTabAtAdjustForAnimation(model()->selected_index());
+ return GetTabAtModelIndex(model()->selected_index());
}
void TabStrip::InitTabStripButtons() {
@@ -836,7 +339,7 @@ int TabStrip::GetPreferredHeight() {
void TabStrip::SetBackgroundOffset(const gfx::Point& offset) {
int tab_count = GetTabCount();
for (int i = 0; i < tab_count; ++i)
- GetTabAt(i)->SetBackgroundOffset(offset);
+ GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset);
}
bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) {
@@ -871,12 +374,10 @@ bool TabStrip::IsDragSessionActive() const {
}
void TabStrip::UpdateLoadingAnimations() {
- for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab->closing()) {
- --index;
- } else {
- TabContents* contents = model_->GetTabContentsAt(index);
+ for (int i = 0, model_index = 0; i < GetTabCount(); ++i) {
+ Tab* current_tab = GetTabAtTabDataIndex(i);
+ if (!current_tab->closing()) {
+ TabContents* contents = model_->GetTabContentsAt(model_index);
if (!contents || !contents->is_loading()) {
current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE);
} else if (contents->waiting_for_response()) {
@@ -884,12 +385,13 @@ void TabStrip::UpdateLoadingAnimations() {
} else {
current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING);
}
+ model_index++;
}
}
}
bool TabStrip::IsAnimating() const {
- return active_animation_.get() != NULL;
+ return bounds_animator_.IsAnimating() || new_tab_timer_.IsRunning();
}
TabStrip* TabStrip::AsTabStrip() {
@@ -901,6 +403,7 @@ TabStrip* TabStrip::AsTabStrip() {
void TabStrip::PaintChildren(gfx::Canvas* canvas) {
// Tabs are painted in reverse order, so they stack to the left.
+ int tab_count = GetTabCount();
// Phantom tabs appear behind all other tabs and are rendered first. To make
// them slightly transparent we render them to a different layer.
@@ -910,8 +413,8 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) {
canvas->saveLayerAlpha(&bounds, kPhantomTabAlpha,
SkCanvas::kARGB_ClipLayer_SaveFlag);
canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
- for (int i = GetTabCount() - 1; i >= 0; --i) {
- Tab* tab = GetTabAt(i);
+ for (int i = tab_count - 1; i >= 0; --i) {
+ Tab* tab = GetTabAtTabDataIndex(i);
if (tab->phantom())
tab->ProcessPaint(canvas);
}
@@ -920,8 +423,8 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) {
canvas->saveLayerAlpha(&bounds, kPhantomTabIconAlpha,
SkCanvas::kARGB_ClipLayer_SaveFlag);
canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
- for (int i = GetTabCount() - 1; i >= 0; --i) {
- Tab* tab = GetTabAt(i);
+ for (int i = tab_count - 1; i >= 0; --i) {
+ Tab* tab = GetTabAtTabDataIndex(i);
if (tab->phantom()) {
canvas->save();
canvas->ClipRectInt(tab->MirroredX(), tab->y(), tab->width(),
@@ -936,14 +439,27 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) {
Tab* selected_tab = NULL;
- for (int i = GetTabCount() - 1; i >= 0; --i) {
- Tab* tab = GetTabAt(i);
+ for (int i = tab_count - 1; i >= 0; --i) {
+ Tab* tab = GetTabAtTabDataIndex(i);
// We must ask the _Tab's_ model, not ourselves, because in some situations
// the model will be different to this object, e.g. when a Tab is being
// removed after its TabContents has been destroyed.
if (!tab->phantom()) {
if (!tab->IsSelected()) {
- tab->ProcessPaint(canvas);
+ if (tab->render_unselected() && model_->count() > 1) {
+ // See comment above kNetTabAnimationSelectedOffset as to why we do
+ // this.
+ Tab* last_tab = GetTabAtModelIndex(model_->count() - 2);
+ canvas->save();
+ int clip_x = last_tab->bounds().right() + kNetTabSelectedOffset;
+ int clip_width = width() - clip_x;
+ clip_x = MirroredXWithWidthInsideView(clip_x, clip_width);
+ canvas->ClipRectInt(clip_x, 0, clip_width, height());
+ tab->ProcessPaint(canvas);
+ canvas->restore();
+ } else {
+ tab->ProcessPaint(canvas);
+ }
} else {
selected_tab = tab;
}
@@ -962,23 +478,30 @@ void TabStrip::PaintChildren(gfx::Canvas* canvas) {
paint);
}
+ if (animation_type_ == ANIMATION_NEW_TAB_3)
+ newtab_button_->ProcessPaint(canvas);
+
// Paint the selected tab last, so it overlaps all the others.
if (selected_tab)
selected_tab->ProcessPaint(canvas);
// Paint the New Tab button.
- newtab_button_->ProcessPaint(canvas);
+ if (animation_type_ != ANIMATION_NEW_TAB_1 &&
+ animation_type_ != ANIMATION_NEW_TAB_2 &&
+ animation_type_ != ANIMATION_NEW_TAB_3) {
+ newtab_button_->ProcessPaint(canvas);
+ }
}
// Overridden to support automation. See automation_proxy_uitest.cc.
views::View* TabStrip::GetViewByID(int view_id) const {
if (GetTabCount() > 0) {
if (view_id == VIEW_ID_TAB_LAST) {
- return GetTabAt(GetTabCount() - 1);
+ return GetTabAtTabDataIndex(GetTabCount() - 1);
} else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) {
int index = view_id - VIEW_ID_TAB_0;
if (index >= 0 && index < GetTabCount()) {
- return GetTabAt(index);
+ return GetTabAtTabDataIndex(index);
} else {
return NULL;
}
@@ -991,22 +514,15 @@ views::View* TabStrip::GetViewByID(int view_id) const {
void TabStrip::Layout() {
// Called from:
// - window resize
- // - animation completion
- if (active_animation_.get())
- active_animation_->Stop();
+ StopAnimating(false);
+
GenerateIdealBounds();
- int tab_count = GetTabCount();
- int tab_right = 0;
- for (int i = 0; i < tab_count; ++i) {
- const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds;
- Tab* tab = GetTabAt(i);
- tab->set_animating_mini_change(false);
- tab->SetBounds(bounds.x(), bounds.y(), bounds.width(), bounds.height());
- tab_right = bounds.right();
- tab_right += GetTabHOffset(i + 1);
- }
- LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_);
+ for (int i = 0, tab_count = GetTabCount(); i < tab_count; ++i)
+ tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds);
+
+ newtab_button_->SetBounds(newtab_button_bounds_);
+
SchedulePaint();
}
@@ -1015,6 +531,9 @@ gfx::Size TabStrip::GetPreferredSize() {
}
void TabStrip::OnDragEntered(const DropTargetEvent& event) {
+ // Force animations to stop, otherwise it makes the index calculation tricky.
+ StopAnimating(true);
+
UpdateDropIndex(event);
}
@@ -1085,10 +604,10 @@ views::View* TabStrip::GetViewForPoint(const gfx::Point& point) {
// left-adjacent Tab, so we look ahead for it as we walk.
int tab_count = GetTabCount();
for (int i = 0; i < tab_count; ++i) {
- Tab* next_tab = i < (tab_count - 1) ? GetTabAt(i + 1) : NULL;
+ Tab* next_tab = i < (tab_count - 1) ? GetTabAtTabDataIndex(i + 1) : NULL;
if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point))
return next_tab;
- Tab* tab = GetTabAt(i);
+ Tab* tab = GetTabAtTabDataIndex(i);
if (IsPointInTab(tab, point))
return tab;
}
@@ -1117,16 +636,15 @@ void TabStrip::ViewHierarchyChanged(bool is_add,
// TabStrip, TabStripModelObserver implementation:
void TabStrip::TabInsertedAt(TabContents* contents,
- int index,
+ int model_index,
bool foreground) {
DCHECK(contents);
- DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index));
+ DCHECK(model_index == TabStripModel::kNoTab ||
+ model_->ContainsIndex(model_index));
// This tab may be attached to another browser window, we should notify
// renderer.
contents->render_view_host()->UpdateBrowserWindowId(
contents->controller().window_id().id());
- if (active_animation_.get())
- active_animation_->Stop();
bool contains_tab = false;
Tab* tab = NULL;
@@ -1145,10 +663,23 @@ void TabStrip::TabInsertedAt(TabContents* contents,
}
// See if we're already in the list. We don't want to add ourselves twice.
- std::vector<TabData>::const_iterator iter = tab_data_.begin();
- for (; iter != tab_data_.end() && !contains_tab; ++iter) {
- if (iter->tab == tab)
- contains_tab = true;
+ int tab_data_index = TabDataIndexOfTab(tab);
+
+ if (tab_data_index != -1) {
+ contains_tab = true;
+
+ // Make sure we stop animating the view. This is necessary otherwise when
+ // the animation is done it'll try to remove the tab.
+ bounds_animator_.StopAnimatingView(tab);
+
+ // We have the tab, but it might not be at the right index. Reset the data
+ // to ensure it's at the right index.
+ TabData tab_data = tab_data_[tab_data_index];
+ DCHECK(tab_data.tab == tab);
+ tab_data_.erase(tab_data_.begin() + tab_data_index);
+ tab_data_.insert(
+ tab_data_.begin() + ModelIndexToTabDataIndex(model_index),
+ tab_data);
}
}
@@ -1159,40 +690,43 @@ void TabStrip::TabInsertedAt(TabContents* contents,
// Only insert if we're not already in the list.
if (!contains_tab) {
TabData d = { tab, gfx::Rect() };
- tab_data_.insert(tab_data_.begin() + index, d);
- tab->UpdateData(contents, model_->IsPhantomTab(index), false);
+ tab_data_.insert(tab_data_.begin() +
+ ModelIndexToTabDataIndex(model_index), d);
+ tab->UpdateData(contents, model_->IsPhantomTab(model_index), false);
}
- tab->set_mini(model_->IsMiniTab(index));
- tab->SetBlocked(model_->IsTabBlocked(index));
+ tab->set_mini(model_->IsMiniTab(model_index));
+ tab->set_app(model_->IsAppTab(model_index));
+ tab->SetBlocked(model_->IsTabBlocked(model_index));
// We only add the tab to the child list if it's not already - an invisible
// tab maintained by the DraggedTabController will already be parented.
- if (!tab->GetParent())
+ if (!tab->GetParent()) {
AddChildView(tab);
+ tab->SetAnimationContainer(animation_container_.get());
+ }
// Don't animate the first tab, it looks weird, and don't animate anything
// if the containing window isn't visible yet.
if (GetTabCount() > 1 && GetWindow() && GetWindow()->IsVisible()) {
- StartInsertTabAnimation(index);
+ if (!IsDragSessionActive() &&
+ ShouldStartIntertTabAnimationAtEnd(model_index, foreground)) {
+ StartInsertTabAnimationAtEnd();
+ } else {
+ StartInsertTabAnimation(model_index);
+ }
} else {
Layout();
}
}
-void TabStrip::TabDetachedAt(TabContents* contents, int index) {
- GenerateIdealBounds();
- StartRemoveTabAnimation(index, contents);
- // Have to do this _after_ calling StartRemoveTabAnimation, so that any
- // previous remove is completed fully and index is valid in sync with the
- // model index.
- GetTabAt(index)->set_closing(true);
+void TabStrip::TabDetachedAt(TabContents* contents, int model_index) {
+ StartRemoveTabAnimation(model_index);
}
void TabStrip::TabSelectedAt(TabContents* old_contents,
TabContents* new_contents,
- int index,
+ int model_index,
bool user_gesture) {
- DCHECK(index >= 0 && index < GetTabCount());
// We have "tiny tabs" if the tabs are so tiny that the unselected ones are
// a different size to the selected ones.
bool tiny_tabs = current_unselected_width_ != current_selected_width_;
@@ -1202,117 +736,133 @@ void TabStrip::TabSelectedAt(TabContents* old_contents,
SchedulePaint();
}
- int old_index = model_->GetIndexOfTabContents(old_contents);
- if (old_index >= 0)
- GetTabAt(old_index)->StopMiniTabTitleAnimation();
+ int old_model_index = model_->GetIndexOfTabContents(old_contents);
+ if (old_model_index >= 0) {
+ GetTabAtTabDataIndex(ModelIndexToTabDataIndex(old_model_index))->
+ StopMiniTabTitleAnimation();
+ }
}
-void TabStrip::TabMoved(TabContents* contents, int from_index, int to_index) {
- gfx::Rect start_bounds = GetIdealBounds(from_index);
- Tab* tab = GetTabAt(from_index);
- tab_data_.erase(tab_data_.begin() + from_index);
- TabData data = {tab, gfx::Rect()};
- tab->set_mini(model_->IsMiniTab(to_index));
- tab->SetBlocked(model_->IsTabBlocked(to_index));
- tab_data_.insert(tab_data_.begin() + to_index, data);
- if (tab->phantom() != model_->IsPhantomTab(to_index))
- tab->set_phantom(!tab->phantom());
- GenerateIdealBounds();
- StartMoveTabAnimation(from_index, to_index);
+void TabStrip::TabMoved(TabContents* contents,
+ int from_model_index,
+ int to_model_index) {
+ StartMoveTabAnimation(from_model_index, to_model_index);
}
-void TabStrip::TabChangedAt(TabContents* contents, int index,
+void TabStrip::TabChangedAt(TabContents* contents,
+ int model_index,
TabChangeType change_type) {
// Index is in terms of the model. Need to make sure we adjust that index in
// case we have an animation going.
- Tab* tab = GetTabAtAdjustForAnimation(index);
+ Tab* tab = GetTabAtModelIndex(model_index);
if (change_type == TITLE_NOT_LOADING) {
if (tab->mini() && !tab->IsSelected())
tab->StartMiniTabTitleAnimation();
// We'll receive another notification of the change asynchronously.
return;
}
- tab->UpdateData(contents, model_->IsPhantomTab(index),
+ tab->UpdateData(contents, model_->IsPhantomTab(model_index),
change_type == LOADING_ONLY);
tab->UpdateFromModel();
}
void TabStrip::TabReplacedAt(TabContents* old_contents,
TabContents* new_contents,
- int index) {
- TabChangedAt(new_contents, index, ALL);
+ int model_index) {
+ TabChangedAt(new_contents, model_index, ALL);
}
-void TabStrip::TabMiniStateChanged(TabContents* contents, int index) {
- GetTabAt(index)->set_mini(model_->IsMiniTab(index));
+void TabStrip::TabMiniStateChanged(TabContents* contents, int model_index) {
+ GetTabAtModelIndex(model_index)->set_mini(
+ model_->IsMiniTab(model_index));
// Don't animate if the window isn't visible yet. The window won't be visible
// when dragging a mini-tab to a new window.
if (GetWindow() && GetWindow()->IsVisible())
- StartMiniTabAnimation(index);
+ StartMiniTabAnimation();
else
Layout();
}
-void TabStrip::TabBlockedStateChanged(TabContents* contents, int index) {
- GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index));
+void TabStrip::TabBlockedStateChanged(TabContents* contents, int model_index) {
+ GetTabAtModelIndex(model_index)->SetBlocked(
+ model_->IsTabBlocked(model_index));
}
///////////////////////////////////////////////////////////////////////////////
// TabStrip, Tab::Delegate implementation:
bool TabStrip::IsTabSelected(const Tab* tab) const {
- if (tab->closing())
+ if (tab->closing() || tab->render_unselected())
return false;
- return GetIndexOfTab(tab) == model_->selected_index();
+ return GetModelIndexOfTab(tab) == model_->selected_index();
}
bool TabStrip::IsTabPinned(const Tab* tab) const {
if (tab->closing())
return false;
- return model_->IsTabPinned(GetIndexOfTab(tab));
+ return model_->IsTabPinned(GetModelIndexOfTab(tab));
}
void TabStrip::SelectTab(Tab* tab) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- model_->SelectTabContentsAt(index, true);
+ int model_index = GetModelIndexOfTab(tab);
+ if (model_->ContainsIndex(model_index))
+ model_->SelectTabContentsAt(model_index, true);
}
void TabStrip::CloseTab(Tab* tab) {
- int tab_index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(tab_index)) {
- TabContents* contents = model_->GetTabContentsAt(tab_index);
+ int model_index = GetModelIndexOfTab(tab);
+ if (model_->ContainsIndex(model_index)) {
+ TabContents* contents = model_->GetTabContentsAt(model_index);
if (contents)
UserMetrics::RecordAction(UserMetricsAction("CloseTab_Mouse"),
contents->profile());
- Tab* last_tab = GetTabAt(GetTabCount() - 1);
- // Limit the width available to the TabStrip for laying out Tabs, so that
- // Tabs are not resized until a later time (when the mouse pointer leaves
- // the TabStrip).
- available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
- needs_resize_layout_ = true;
- AddMessageLoopObserver();
+ if (model_index + 1 != model_->count() && model_->count() > 1) {
+ Tab* last_tab = GetTabAtModelIndex(model_->count() - 2);
+ // Limit the width available to the TabStrip for laying out Tabs, so that
+ // Tabs are not resized until a later time (when the mouse pointer leaves
+ // the TabStrip).
+ available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
+ needs_resize_layout_ = true;
+ AddMessageLoopObserver();
+ } else if (model_->count() > 1) {
+ Tab* last_tab = GetTabAtModelIndex(model_->count() - 1);
+ // Limit the width available to the TabStrip for laying out Tabs, so that
+ // Tabs are not resized until a later time (when the mouse pointer leaves
+ // the TabStrip).
+ available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
+ needs_resize_layout_ = true;
+ AddMessageLoopObserver();
+ }
// Note that the next call might not close the tab (because of unload
// hanlders or if the delegate veto the close).
- model_->CloseTabContentsAt(tab_index);
+ model_->CloseTabContentsAt(model_index);
}
}
bool TabStrip::IsCommandEnabledForTab(
TabStripModel::ContextMenuCommand command_id, const Tab* tab) const {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- return model_->IsContextMenuCommandEnabled(index, command_id);
+ int model_index = GetModelIndexOfTab(tab);
+ if (model_->ContainsIndex(model_index))
+ return model_->IsContextMenuCommandEnabled(model_index, command_id);
return false;
}
void TabStrip::ExecuteCommandForTab(
TabStripModel::ContextMenuCommand command_id, Tab* tab) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- model_->ExecuteContextMenuCommand(index, command_id);
+ int model_index = GetModelIndexOfTab(tab);
+ if (model_->ContainsIndex(model_index))
+ model_->ExecuteContextMenuCommand(model_index, command_id);
+}
+
+void TabStrip::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
+ AnimationType last_type = animation_type_;
+
+ ResetAnimationState(false);
+
+ if (last_type == ANIMATION_NEW_TAB_2)
+ NewTabAnimation2Done();
}
void TabStrip::StartHighlightTabsForCommand(
@@ -1320,13 +870,13 @@ void TabStrip::StartHighlightTabsForCommand(
if (command_id == TabStripModel::CommandCloseTabsOpenedBy ||
command_id == TabStripModel::CommandCloseOtherTabs ||
command_id == TabStripModel::CommandCloseTabsToRight) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index)) {
+ int model_index = GetModelIndexOfTab(tab);
+ if (model_->ContainsIndex(model_index)) {
std::vector<int> indices =
- model_->GetIndicesClosedByCommand(index, command_id);
+ model_->GetIndicesClosedByCommand(model_index, command_id);
for (std::vector<int>::const_iterator i = indices.begin();
i != indices.end(); ++i) {
- GetTabAtAdjustForAnimation(*i)->StartPulse();
+ GetTabAtModelIndex(*i)->StartPulse();
}
}
}
@@ -1344,7 +894,7 @@ void TabStrip::StopHighlightTabsForCommand(
void TabStrip::StopAllHighlighting() {
for (int i = 0; i < GetTabCount(); ++i)
- GetTabAt(i)->StopPulse();
+ GetTabAtTabDataIndex(i)->StopPulse();
}
void TabStrip::MaybeStartDrag(Tab* tab, const views::MouseEvent& event) {
@@ -1354,8 +904,8 @@ void TabStrip::MaybeStartDrag(Tab* tab, const views::MouseEvent& event) {
// the user is dragging.
if (IsAnimating() || tab->closing() || !HasAvailableDragActions())
return;
- int index = GetIndexOfTab(tab);
- if (!model_->ContainsIndex(index)) {
+ int model_index = GetModelIndexOfTab(tab);
+ if (!model_->ContainsIndex(model_index)) {
CHECK(false);
return;
}
@@ -1463,15 +1013,18 @@ void TabStrip::DidProcessEvent(GdkEvent* event) {
void TabStrip::Init() {
SetID(VIEW_ID_TAB_STRIP);
model_->AddObserver(this);
- newtab_button_size_.SetSize(kNewTabButtonWidth, kNewTabButtonHeight);
- if (browser_defaults::kSizeTabButtonToTopOfTabStrip)
- newtab_button_size_.set_height(kNewTabButtonHeight + kNewTabButtonVOffset);
+ newtab_button_bounds_.SetRect(0, 0, kNewTabButtonWidth, kNewTabButtonHeight);
+ if (browser_defaults::kSizeTabButtonToTopOfTabStrip) {
+ newtab_button_bounds_.set_height(
+ kNewTabButtonHeight + kNewTabButtonVOffset);
+ }
if (drop_indicator_width == 0) {
// Direction doesn't matter, both images are the same size.
SkBitmap* drop_image = GetDropArrowImage(true);
drop_indicator_width = drop_image->width();
drop_indicator_height = drop_image->height();
}
+ bounds_animator_.set_observer(this);
}
void TabStrip::LoadNewTabButtonImage() {
@@ -1501,20 +1054,14 @@ void TabStrip::LoadNewTabButtonImage() {
delete tp;
}
-Tab* TabStrip::GetTabAt(int index) const {
- DCHECK_GE(index, 0);
- DCHECK_LT(index, GetTabCount());
- return tab_data_.at(index).tab;
+Tab* TabStrip::GetTabAtTabDataIndex(int tab_data_index) const {
+ DCHECK_GE(tab_data_index, 0);
+ DCHECK_LT(tab_data_index, GetTabCount());
+ return tab_data_[tab_data_index].tab;
}
-Tab* TabStrip::GetTabAtAdjustForAnimation(int index) const {
- if (active_animation_.get() &&
- active_animation_->type() == TabAnimation::REMOVE &&
- index >=
- static_cast<RemoveTabAnimation*>(active_animation_.get())->index()) {
- index++;
- }
- return GetTabAt(index);
+Tab* TabStrip::GetTabAtModelIndex(int model_index) const {
+ return GetTabAtTabDataIndex(ModelIndexToTabDataIndex(model_index));
}
int TabStrip::GetTabCount() const {
@@ -1547,7 +1094,7 @@ void TabStrip::GetDesiredTabWidths(int tab_count,
int available_width;
if (available_width_for_tabs_ < 0) {
available_width = width();
- available_width -= (kNewTabButtonHOffset + newtab_button_size_.width());
+ available_width -= (kNewTabButtonHOffset + newtab_button_bounds_.width());
} else {
// Interesting corner case: if |available_width_for_tabs_| > the result
// of the calculation in the conditional arm above, the strip is in
@@ -1607,14 +1154,6 @@ void TabStrip::GetDesiredTabWidths(int tab_count,
}
}
-int TabStrip::GetTabHOffset(int tab_index) {
- if (tab_index < GetTabCount() && GetTabAt(tab_index - 1)->mini() &&
- !GetTabAt(tab_index)->mini()) {
- return mini_to_non_mini_gap_ + kTabHOffset;
- }
- return kTabHOffset;
-}
-
void TabStrip::ResizeLayoutTabs() {
// We've been called back after the TabStrip has been emptied out (probably
// just prior to the window being destroyed). We need to do nothing here or
@@ -1635,7 +1174,7 @@ void TabStrip::ResizeLayoutTabs() {
// mini-tabs have the same width), so there is nothing to do.
return;
}
- Tab* first_tab = GetTabAt(mini_tab_count);
+ Tab* first_tab = GetTabAtTabDataIndex(mini_tab_count);
double unselected, selected;
GetDesiredTabWidths(GetTabCount(), mini_tab_count, &unselected, &selected);
int w = Round(first_tab->IsSelected() ? selected : selected);
@@ -1657,7 +1196,7 @@ bool TabStrip::IsCursorInTabStripZone() const {
DWORD pos = GetMessagePos();
gfx::Point cursor_point(pos);
#elif defined(OS_LINUX)
- // TODO: make sure this is right with multiple monitors.
+ // TODO(sky): make sure this is right with multiple monitors.
GdkScreen* screen = gdk_screen_get_default();
GdkDisplay* display = gdk_screen_get_display(screen);
gint x, y;
@@ -1688,14 +1227,13 @@ gfx::Rect TabStrip::GetDropBounds(int drop_index,
DCHECK(drop_index != -1);
int center_x;
if (drop_index < GetTabCount()) {
- Tab* tab = GetTabAt(drop_index);
- // TODO(sky): update these for mini-tabs.
+ Tab* tab = GetTabAtTabDataIndex(drop_index);
if (drop_before)
center_x = tab->x() - (kTabHOffset / 2);
else
center_x = tab->x() + (tab->width() / 2);
} else {
- Tab* last_tab = GetTabAt(drop_index - 1);
+ Tab* last_tab = GetTabAtTabDataIndex(drop_index - 1);
center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2);
}
@@ -1731,7 +1269,7 @@ void TabStrip::UpdateDropIndex(const DropTargetEvent& event) {
const int x = MirroredXCoordinateInsideView(event.x());
// We don't allow replacing the urls of mini-tabs.
for (int i = GetMiniTabCount(); i < GetTabCount(); ++i) {
- Tab* tab = GetTabAt(i);
+ Tab* tab = GetTabAtTabDataIndex(i);
const int tab_max_x = tab->x() + tab->width();
const int hot_width = tab->width() / 3;
if (x < tab_max_x) {
@@ -1749,25 +1287,26 @@ void TabStrip::UpdateDropIndex(const DropTargetEvent& event) {
SetDropIndex(GetTabCount(), true);
}
-void TabStrip::SetDropIndex(int index, bool drop_before) {
- if (index == -1) {
+void TabStrip::SetDropIndex(int tab_data_index, bool drop_before) {
+ if (tab_data_index == -1) {
if (drop_info_.get())
drop_info_.reset(NULL);
return;
}
- if (drop_info_.get() && drop_info_->drop_index == index &&
+ if (drop_info_.get() && drop_info_->drop_index == tab_data_index &&
drop_info_->drop_before == drop_before) {
return;
}
bool is_beneath;
- gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath);
+ gfx::Rect drop_bounds = GetDropBounds(tab_data_index, drop_before,
+ &is_beneath);
if (!drop_info_.get()) {
- drop_info_.reset(new DropInfo(index, drop_before, !is_beneath));
+ drop_info_.reset(new DropInfo(tab_data_index, drop_before, !is_beneath));
} else {
- drop_info_->drop_index = index;
+ drop_info_->drop_index = tab_data_index;
drop_info_->drop_before = drop_before;
if (is_beneath == drop_info_->point_down) {
drop_info_->point_down = !is_beneath;
@@ -1844,8 +1383,19 @@ TabStrip::DropInfo::~DropInfo() {
// - Tab reorder
void TabStrip::GenerateIdealBounds() {
int tab_count = GetTabCount();
+ int non_closing_tab_count = 0;
+ int mini_tab_count = 0;
+ for (int i = 0; i < tab_count; ++i) {
+ if (!tab_data_[i].tab->closing()) {
+ ++non_closing_tab_count;
+ if (tab_data_[i].tab->mini())
+ mini_tab_count++;
+ }
+ }
+
double unselected, selected;
- GetDesiredTabWidths(tab_count, GetMiniTabCount(), &unselected, &selected);
+ GetDesiredTabWidths(non_closing_tab_count, mini_tab_count, &unselected,
+ &selected);
current_unselected_width_ = unselected;
current_selected_width_ = selected;
@@ -1854,139 +1404,259 @@ void TabStrip::GenerateIdealBounds() {
// selected state or the number of tabs in the strip!
int tab_height = Tab::GetStandardSize().height();
double tab_x = 0;
+ bool last_was_mini = false;
for (int i = 0; i < tab_count; ++i) {
- Tab* tab = GetTabAt(i);
- double tab_width = unselected;
- if (tab->mini())
- tab_width = Tab::GetMiniWidth();
- else if (tab->IsSelected())
- tab_width = selected;
- double end_of_tab = tab_x + tab_width;
- int rounded_tab_x = Round(tab_x);
- gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
+ if (!tab_data_[i].tab->closing()) {
+ Tab* tab = GetTabAtTabDataIndex(i);
+ double tab_width = unselected;
+ if (tab->mini()) {
+ tab_width = Tab::GetMiniWidth();
+ } else {
+ if (last_was_mini) {
+ // Give a bigger gap between mini and non-mini tabs.
+ tab_x += mini_to_non_mini_gap_;
+ }
+ if (tab->IsSelected())
+ tab_width = selected;
+ }
+ double end_of_tab = tab_x + tab_width;
+ int rounded_tab_x = Round(tab_x);
+ tab_data_[i].ideal_bounds =
+ gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
tab_height);
- tab_data_.at(i).ideal_bounds = state;
- tab_x = end_of_tab + GetTabHOffset(i + 1);
+ tab_x = end_of_tab + kTabHOffset;
+ last_was_mini = tab->mini();
+ }
}
-}
-void TabStrip::LayoutNewTabButton(double last_tab_right,
- double unselected_width) {
- int delta = abs(Round(unselected_width) - Tab::GetStandardSize().width());
- int v_offset = browser_defaults::kSizeTabButtonToTopOfTabStrip ?
+ // Update bounds of new tab button.
+ int new_tab_x;
+ int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ?
0 : kNewTabButtonVOffset;
- if (delta > 1 && !needs_resize_layout_) {
+ if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 &&
+ available_width_for_tabs_ == -1) {
// We're shrinking tabs, so we need to anchor the New Tab button to the
// right edge of the TabStrip's bounds, rather than the right edge of the
// right-most Tab, otherwise it'll bounce when animating.
- newtab_button_->SetBounds(width() - newtab_button_size_.width(),
- v_offset,
- newtab_button_size_.width(),
- newtab_button_size_.height());
+ new_tab_x = width() - newtab_button_bounds_.width();
} else {
- newtab_button_->SetBounds(
- Round(last_tab_right - kTabHOffset) + kNewTabButtonHOffset,
- v_offset, newtab_button_size_.width(), newtab_button_size_.height());
+ new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset;
}
+ newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y));
}
-// Called from:
-// - animation tick
-void TabStrip::AnimationLayout(double unselected_width) {
- int tab_height = Tab::GetStandardSize().height();
- double tab_x = 0;
- for (int i = 0; i < GetTabCount(); ++i) {
- TabAnimation* animation = active_animation_.get();
- if (animation)
- tab_x += animation->GetGapWidth(i);
- double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i);
- double end_of_tab = tab_x + tab_width;
- int rounded_tab_x = Round(tab_x);
- Tab* tab = GetTabAt(i);
- tab->SetBounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
- tab_height);
- tab_x = end_of_tab + GetTabHOffset(i + 1);
- }
- LayoutNewTabButton(tab_x, unselected_width);
- SchedulePaint();
+void TabStrip::NewTabAnimation1Done() {
+ int tab_data_index = static_cast<int>(tab_data_.size() - 1);
+ Tab* tab = GetTabAtTabDataIndex(tab_data_index);
+
+ gfx::Rect old_tab_bounds = tab->bounds();
+
+ GenerateIdealBounds();
+
+ gfx::Rect& end_bounds = tab_data_[tab_data_index].ideal_bounds;
+ end_bounds.Offset(kNewTabOvershoot, 0);
+
+ int x = old_tab_bounds.right() - end_bounds.width();
+ int w = end_bounds.width();
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+ tab->SetBounds(x, old_tab_bounds.y(), w, end_bounds.height());
+
+ AnimateToIdealBounds();
+
+ animation_type_ = ANIMATION_NEW_TAB_2;
+ tab->set_render_as_new_tab(false);
+ tab->set_render_unselected(true);
+ tab->set_alpha(0);
+
+ // BoundsAnimator takes ownership of NewTabAlphaDelegate.
+ bounds_animator_.SetAnimationDelegate(tab, new NewTabAlphaDelegate(tab),
+ true);
+}
+
+void TabStrip::NewTabAnimation2Done() {
+ animation_type_ = ANIMATION_NEW_TAB_3;
+
+ GenerateIdealBounds();
+
+ AnimateToIdealBounds();
+
+ SlideAnimation* animation = new SlideAnimation(NULL);
+ animation->SetSlideDuration(kNewTab3DurationMs);
+ animation->SetTweenType(SlideAnimation::EASE_IN_OUT);
+
+ // BoundsAnimator takes ownership of animation.
+ bounds_animator_.SetAnimationForView(tab_data_.back().tab, animation);
+}
+
+void TabStrip::AnimateToIdealBounds() {
+ for (size_t i = 0; i < tab_data_.size(); ++i) {
+ if (!tab_data_[i].tab->closing()) {
+ bounds_animator_.AnimateViewTo(tab_data_[i].tab,
+ tab_data_[i].ideal_bounds,
+ false);
+ }
+ }
+
+ if (animation_type_ != ANIMATION_NEW_TAB_3) {
+ bounds_animator_.AnimateViewTo(newtab_button_,
+ newtab_button_bounds_,
+ false);
+ }
+}
+
+bool TabStrip::ShouldStartIntertTabAnimationAtEnd(int model_index,
+ bool foreground) {
+ return foreground && (model_index + 1 == model_->count()) &&
+ (model_->GetTabContentsAt(model_index)->GetURL() ==
+ GURL(chrome::kChromeUINewTabURL));
}
void TabStrip::StartResizeLayoutAnimation() {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new ResizeLayoutAnimation(this));
- active_animation_->Start();
+ ResetAnimationState(true);
+ GenerateIdealBounds();
+ AnimateToIdealBounds();
}
-void TabStrip::StartInsertTabAnimation(int index) {
+void TabStrip::StartInsertTabAnimationAtEnd() {
+ ResetAnimationState(true);
+
// The TabStrip can now use its entire width to lay out Tabs.
available_width_for_tabs_ = -1;
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new InsertTabAnimation(this, index));
- active_animation_->Start();
+
+ animation_type_ = ANIMATION_NEW_TAB_1;
+
+ GenerateIdealBounds();
+
+ int tab_data_index = ModelIndexToTabDataIndex(model_->count() - 1);
+ Tab* tab = tab_data_[tab_data_index].tab;
+ tab->SizeToNewTabButtonImages();
+ tab->SetBounds(newtab_button_->x() +
+ (newtab_button_->width() - tab->width()) / 2,
+ tab_data_[tab_data_index].ideal_bounds.y(),
+ tab->width(), tab->height());
+ tab->set_render_as_new_tab(true);
+
+ new_tab_timer_.Start(base::TimeDelta::FromMilliseconds(kNewTabDurationMs),
+ this, &TabStrip::NewTabAnimation1Done);
}
-void TabStrip::StartRemoveTabAnimation(int index, TabContents* contents) {
- if (active_animation_.get()) {
- // Some animations (e.g. MoveTabAnimation) cause there to be a Layout when
- // they're completed (which includes canceled). Since |tab_data_| is now
- // inconsistent with TabStripModel, doing this Layout will crash now, so
- // we ask the MoveTabAnimation to skip its Layout (the state will be
- // corrected by the RemoveTabAnimation we're about to initiate).
- active_animation_->set_layout_on_completion(false);
- active_animation_->Stop();
+void TabStrip::StartInsertTabAnimation(int model_index) {
+ ResetAnimationState(true);
+
+ // The TabStrip can now use its entire width to lay out Tabs.
+ available_width_for_tabs_ = -1;
+
+ GenerateIdealBounds();
+
+ int tab_data_index = ModelIndexToTabDataIndex(model_index);
+ Tab* tab = tab_data_[tab_data_index].tab;
+ if (model_index == 0) {
+ tab->SetBounds(0, tab_data_[tab_data_index].ideal_bounds.y(), 0,
+ tab_data_[tab_data_index].ideal_bounds.height());
+ } else {
+ Tab* last_tab = tab_data_[tab_data_index - 1].tab;
+ tab->SetBounds(last_tab->bounds().right() + kTabHOffset,
+ tab_data_[tab_data_index].ideal_bounds.y(), 0,
+ tab_data_[tab_data_index].ideal_bounds.height());
}
- active_animation_.reset(new RemoveTabAnimation(this, index, contents));
- active_animation_->Start();
+
+ AnimateToIdealBounds();
}
-void TabStrip::StartMoveTabAnimation(int from_index, int to_index) {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new MoveTabAnimation(this, from_index, to_index));
- active_animation_->Start();
+void TabStrip::StartRemoveTabAnimation(int model_index) {
+ ResetAnimationState(true);
+
+ // Mark the tab as closing.
+ int tab_data_index = ModelIndexToTabDataIndex(model_index);
+ Tab* tab = tab_data_[tab_data_index].tab;
+ tab->set_closing(true);
+
+ // Start an animation for the tabs.
+ GenerateIdealBounds();
+ AnimateToIdealBounds();
+
+ // Animate the tab being closed to 0x0.
+ gfx::Rect tab_bounds = tab->bounds();
+ tab_bounds.set_width(0);
+ bounds_animator_.AnimateViewTo(tab, tab_bounds, false);
+
+ // Register delegate to do cleanup when done, BoundsAnimator takes
+ // ownership of RemoveTabDelegate.
+ bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab),
+ true);
}
-void TabStrip::StartMiniTabAnimation(int index) {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new MiniTabAnimation(this, index));
- active_animation_->Start();
+void TabStrip::StartMoveTabAnimation(int from_model_index,
+ int to_model_index) {
+ ResetAnimationState(true);
+
+ int from_tab_data_index = ModelIndexToTabDataIndex(from_model_index);
+
+ Tab* tab = tab_data_[from_tab_data_index].tab;
+ tab_data_.erase(tab_data_.begin() + from_tab_data_index);
+
+ TabData data = {tab, gfx::Rect()};
+ tab->set_mini(model_->IsMiniTab(to_model_index));
+ //tab->set_app(model_->IsAppTab(to_model_index));
+ tab->SetBlocked(model_->IsTabBlocked(to_model_index));
+
+ int to_tab_data_index = ModelIndexToTabDataIndex(to_model_index);
+
+ tab_data_.insert(tab_data_.begin() + to_tab_data_index, data);
+ if (tab->phantom() != model_->IsPhantomTab(to_model_index))
+ tab->set_phantom(!tab->phantom());
+
+ GenerateIdealBounds();
+ AnimateToIdealBounds();
}
-void TabStrip::StartMiniMoveTabAnimation(int from_index,
- int to_index,
- const gfx::Rect& start_bounds) {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(
- new MiniMoveAnimation(this, from_index, to_index, start_bounds));
- active_animation_->Start();
+void TabStrip::StartMiniTabAnimation() {
+ ResetAnimationState(true);
+
+ GenerateIdealBounds();
+ AnimateToIdealBounds();
}
-void TabStrip::FinishAnimation(TabStrip::TabAnimation* animation,
- bool layout) {
- active_animation_.reset(NULL);
+void TabStrip::StopAnimating(bool layout) {
+ if (!IsAnimating())
+ return;
+
+ new_tab_timer_.Stop();
- // Reset the animation state of each tab.
- for (int i = 0, count = GetTabCount(); i < count; ++i)
- GetTabAt(i)->set_animating_mini_change(false);
+ if (bounds_animator_.IsAnimating()) {
+ // Cancelling the animation triggers OnBoundsAnimatorDone, which invokes
+ // ResetAnimationState.
+ bounds_animator_.Cancel();
+ } else {
+ ResetAnimationState(false);
+ }
+
+ DCHECK(!IsAnimating());
if (layout)
Layout();
}
-int TabStrip::GetIndexOfTab(const Tab* tab) const {
- for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab->closing()) {
- --index;
- } else if (current_tab == tab) {
- return index;
- }
+void TabStrip::ResetAnimationState(bool stop_new_tab_timer) {
+ if (animation_type_ == ANIMATION_NEW_TAB_2)
+ newtab_button_->SchedulePaint();
+
+ if (stop_new_tab_timer)
+ new_tab_timer_.Stop();
+
+ animation_type_ = ANIMATION_DEFAULT;
+
+ // Reset the animation state of each tab.
+ for (int i = 0, count = GetTabCount(); i < count; ++i) {
+ Tab* tab = GetTabAtTabDataIndex(i);
+ tab->set_animating_mini_change(false);
+ tab->set_render_as_new_tab(false);
+ tab->set_render_unselected(false);
+ tab->set_alpha(1);
}
- return -1;
}
int TabStrip::GetMiniTabCount() const {
@@ -2011,22 +1681,21 @@ bool TabStrip::IsPointInTab(Tab* tab,
return tab->HitTest(point_in_tab_coords);
}
-void TabStrip::RemoveTabAt(int index) {
- Tab* removed = tab_data_.at(index).tab;
+void TabStrip::RemoveTab(Tab* tab) {
+ int tab_data_index = TabDataIndexOfTab(tab);
+
+ DCHECK(tab_data_index != -1);
// Remove the Tab from the TabStrip's list...
- tab_data_.erase(tab_data_.begin() + index);
+ tab_data_.erase(tab_data_.begin() + tab_data_index);
// If the TabContents being detached was removed as a result of a drag
// gesture from its corresponding Tab, we don't want to remove the Tab from
// the child list, because if we do so it'll stop receiving events and the
// drag will stall. So we only remove if a drag isn't active, or the Tab
// was for some other TabContents.
- if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(removed)) {
- removed->GetParent()->RemoveChildView(removed);
- delete removed;
- }
- GenerateIdealBounds();
+ if (!IsDragSessionActive() || !drag_controller_->IsDragSourceTab(tab))
+ delete tab;
}
void TabStrip::HandleGlobalMouseMoveEvent() {
@@ -2049,8 +1718,40 @@ void TabStrip::HandleGlobalMouseMoveEvent() {
bool TabStrip::HasPhantomTabs() const {
for (int i = 0; i < GetTabCount(); ++i) {
- if (GetTabAt(i)->phantom())
+ if (GetTabAtTabDataIndex(i)->phantom())
return true;
}
return false;
}
+
+int TabStrip::GetModelIndexOfTab(const Tab* tab) const {
+ for (int i = 0, model_index = 0; i < GetTabCount(); ++i) {
+ Tab* current_tab = GetTabAtTabDataIndex(i);
+ if (!current_tab->closing()) {
+ if (current_tab == tab)
+ return model_index;
+ model_index++;
+ }
+ }
+ return -1;
+}
+
+int TabStrip::ModelIndexToTabDataIndex(int model_index) const {
+ int current_model_index = 0;
+ for (size_t i = 0; i < tab_data_.size(); ++i) {
+ if (!tab_data_[i].tab->closing()) {
+ if (current_model_index == model_index)
+ return i;
+ current_model_index++;
+ }
+ }
+ return tab_data_.size();
+}
+
+int TabStrip::TabDataIndexOfTab(Tab* tab) const {
+ for (size_t i = 0; i < tab_data_.size(); ++i) {
+ if (tab_data_[i].tab == tab)
+ return i;
+ }
+ return -1;
+}
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
index af6cc34..e1cbfda 100644
--- a/chrome/browser/views/tabs/tab_strip.h
+++ b/chrome/browser/views/tabs/tab_strip.h
@@ -5,11 +5,16 @@
#ifndef CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_
#define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_
+#include "app/animation_container.h"
#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/timer.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/tabs/base_tab_strip.h"
#include "chrome/browser/views/tabs/tab.h"
#include "gfx/point.h"
+#include "gfx/rect.h"
+#include "views/animation/bounds_animator.h"
#include "views/controls/button/image_button.h"
class DraggedTabController;
@@ -42,7 +47,8 @@ class TabStrip : public BaseTabStrip,
public TabStripModelObserver,
public Tab::TabDelegate,
public views::ButtonListener,
- public MessageLoopForUI::Observer {
+ public MessageLoopForUI::Observer,
+ public views::BoundsAnimatorObserver {
public:
explicit TabStrip(TabStripModel* model);
virtual ~TabStrip();
@@ -62,7 +68,7 @@ class TabStrip : public BaseTabStrip,
void DestroyDraggedSourceTab(Tab* tab);
// Retrieves the ideal bounds for the Tab at the specified index.
- gfx::Rect GetIdealBounds(int index);
+ gfx::Rect GetIdealBounds(int tab_data_index);
// Returns the currently selected tab.
Tab* GetSelectedTab() const;
@@ -103,6 +109,9 @@ class TabStrip : public BaseTabStrip,
virtual views::View* GetViewForPoint(const gfx::Point& point);
virtual void ThemeChanged();
+ // BoundsAnimator::Observer overrides:
+ virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator);
+
protected:
// Creates a new tab.
virtual Tab* CreateTab();
@@ -114,21 +123,24 @@ class TabStrip : public BaseTabStrip,
// TabStripModelObserver implementation:
virtual void TabInsertedAt(TabContents* contents,
- int index,
+ int model_index,
bool foreground);
- virtual void TabDetachedAt(TabContents* contents, int index);
+ virtual void TabDetachedAt(TabContents* contents, int model_index);
virtual void TabSelectedAt(TabContents* old_contents,
TabContents* contents,
- int index,
+ int model_index,
bool user_gesture);
- virtual void TabMoved(TabContents* contents, int from_index, int to_index);
- virtual void TabChangedAt(TabContents* contents, int index,
+ virtual void TabMoved(TabContents* contents,
+ int from_model_index,
+ int to_model_index);
+ virtual void TabChangedAt(TabContents* contents,
+ int model_index,
TabChangeType change_type);
virtual void TabReplacedAt(TabContents* old_contents,
TabContents* new_contents,
- int index);
- virtual void TabMiniStateChanged(TabContents* contents, int index);
- virtual void TabBlockedStateChanged(TabContents* contents, int index);
+ int model_index);
+ virtual void TabMiniStateChanged(TabContents* contents, int model_index);
+ virtual void TabBlockedStateChanged(TabContents* contents, int model_index);
// Tab::Delegate implementation:
virtual bool IsTabSelected(const Tab* tab) const;
@@ -165,22 +177,70 @@ class TabStrip : public BaseTabStrip,
static const int mini_to_non_mini_gap_;
private:
- class InsertTabAnimation;
- class MiniMoveAnimation;
- class MiniTabAnimation;
- class MoveTabAnimation;
- class RemoveTabAnimation;
- class ResizeLayoutAnimation;
- class TabAnimation;
+ class RemoveTabDelegate;
friend class DraggedTabController;
- friend class InsertTabAnimation;
- friend class MiniMoveAnimation;
- friend class MiniTabAnimation;
- friend class MoveTabAnimation;
- friend class RemoveTabAnimation;
- friend class ResizeLayoutAnimation;
- friend class TabAnimation;
+
+ // AnimationType used for tracking animations that require additional
+ // state beyond just animating the bounds of a view.
+ //
+ // Currently the only animation special cased is that of inserting the new tab
+ // page at the end of the tab strip. Here's the steps that take place when
+ // this happens.
+ // . The newly inserted tab is set to render for the new tab animation
+ // |set_render_as_new_tab|. The timer new_tab_timer_ is used to determine
+ // when to turn this off. This is represented by state ANIMATION_NEW_TAB_1.
+ // . The new tab is rendered in the background with an ever increasing alpha
+ // value and the tab goes slightly past the new tab button. The new tab
+ // button is not visible during this animation. This is represented by the
+ // state ANIMATION_NEW_TAB_2.
+ // . The new tab is animated to its final position and the new tab button is
+ // rendered beneath the selected tab. This is represented by the state
+ // ANIMATION_NEW_TAB_3.
+ enum AnimationType {
+ ANIMATION_DEFAULT,
+
+ ANIMATION_NEW_TAB_1,
+ ANIMATION_NEW_TAB_2,
+ ANIMATION_NEW_TAB_3
+ };
+
+ // Used during a drop session of a url. Tracks the position of the drop as
+ // well as a window used to highlight where the drop occurs.
+ struct DropInfo {
+ DropInfo(int index, bool drop_before, bool paint_down);
+ ~DropInfo();
+
+ // Index of the tab to drop on. If drop_before is true, the drop should
+ // occur between the tab at drop_index - 1 and drop_index.
+ // WARNING: if drop_before is true it is possible this will == tab_count,
+ // which indicates the drop should create a new tab at the end of the tabs.
+ int drop_index;
+ bool drop_before;
+
+ // Direction the arrow should point in. If true, the arrow is displayed
+ // above the tab and points down. If false, the arrow is displayed beneath
+ // the tab and points up.
+ bool point_down;
+
+ // Renders the drop indicator.
+ // TODO(beng): should be views::Widget.
+#if defined(OS_WIN)
+ views::WidgetWin* arrow_window;
+#else
+ views::WidgetGtk* arrow_window;
+#endif
+ views::ImageView* arrow_view;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DropInfo);
+ };
+
+ // The Tabs we contain, and their last generated "good" bounds.
+ struct TabData {
+ Tab* tab;
+ gfx::Rect ideal_bounds;
+ };
TabStrip();
void Init();
@@ -188,9 +248,9 @@ class TabStrip : public BaseTabStrip,
// Set the images for the new tab button.
void LoadNewTabButtonImage();
- // Retrieves the Tab at the specified index. Take care in using this, you may
- // need to use GetTabAtAdjustForAnimation.
- Tab* GetTabAt(int index) const;
+ // Retrieves the Tab at the specified index. Remember, the specified index
+ // is in terms of tab_data, *not* the model.
+ Tab* GetTabAtTabDataIndex(int tab_data_index) const;
// Returns the tab at the specified index. If a remove animation is on going
// and the index is >= the index of the tab being removed, the index is
@@ -198,10 +258,13 @@ class TabStrip : public BaseTabStrip,
// do not line up with the indices of the view. This method adjusts the index
// accordingly.
//
- // Use this instead of GetTabAt if the index comes from the model.
- Tab* GetTabAtAdjustForAnimation(int index) const;
+ // Use this instead of GetTabAtTabDataIndex if the index comes from the model.
+ Tab* GetTabAtModelIndex(int model_index) const;
// Gets the number of Tabs in the collection.
+ // WARNING: this is the number of tabs displayed by the tabstrip, which if
+ // an animation is ongoing is not necessarily the same as the number of tabs
+ // in the model.
int GetTabCount() const;
// Returns the number of mini-tabs.
@@ -224,9 +287,6 @@ class TabStrip : public BaseTabStrip,
double* unselected_width,
double* selected_width) const;
- // Returns the horizontal offset before the tab at |tab_index|.
- int GetTabHOffset(int tab_index);
-
// Perform an animated resize-relayout of the TabStrip immediately.
void ResizeLayoutTabs();
@@ -250,7 +310,7 @@ class TabStrip : public BaseTabStrip,
void UpdateDropIndex(const views::DropTargetEvent& event);
// Sets the location of the drop, repainting as necessary.
- void SetDropIndex(int index, bool drop_before);
+ void SetDropIndex(int tab_data_index, bool drop_before);
// Returns the drop effect for dropping a URL on the tab strip. This does
// not query the data in anyway, it only looks at the source operations.
@@ -268,32 +328,38 @@ class TabStrip : public BaseTabStrip,
// stable representations of Tab positions.
void GenerateIdealBounds();
- // Lays out the New Tab button, assuming the right edge of the last Tab on
- // the TabStrip at |last_tab_right|.
- void LayoutNewTabButton(double last_tab_right, double unselected_width);
+ // Both of these are invoked when a part of the new tab animation completes.
+ // They configure state for the next step in the animation and start it.
+ void NewTabAnimation1Done();
+ void NewTabAnimation2Done();
+
+ // Animates all the views to their ideal bounds.
+ // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds
+ // currently set in ideal_bounds.
+ void AnimateToIdealBounds();
- // A generic Layout method for various classes of TabStrip animations,
- // including Insert, Remove and Resize Layout cases/
- void AnimationLayout(double unselected_width);
+ // Returns true if a new tab inserted at specified index should start the
+ // new tab animation. See description above AnimationType for details on
+ // this animation.
+ bool ShouldStartIntertTabAnimationAtEnd(int model_index, bool foreground);
// Starts various types of TabStrip animations.
void StartResizeLayoutAnimation();
- void StartInsertTabAnimation(int index);
- void StartRemoveTabAnimation(int index, TabContents* contents);
- void StartMoveTabAnimation(int from_index, int to_index);
- void StartMiniTabAnimation(int index);
- void StartMiniMoveTabAnimation(int from_index,
- int to_index,
- const gfx::Rect& start_bounds);
-
- // Notifies the TabStrip that the specified TabAnimation has completed.
- // Optionally a full Layout will be performed, specified by |layout|.
- void FinishAnimation(TabAnimation* animation, bool layout);
-
- // Finds the index of the TabContents corresponding to |tab| in our
- // associated TabStripModel, or -1 if there is none (e.g. the specified |tab|
- // is being animated closed).
- int GetIndexOfTab(const Tab* tab) const;
+ void StartInsertTabAnimationAtEnd();
+ void StartInsertTabAnimation(int model_index);
+ void StartRemoveTabAnimation(int model_index);
+ void StartMoveTabAnimation(int from_model_index,
+ int to_model_index);
+ void StartMiniTabAnimation();
+
+ // Stops any ongoing animations. If |layout| is true and an animation is
+ // ongoing this does a layout.
+ void StopAnimating(bool layout);
+
+ // Resets all state related to animations. This is invoked when an animation
+ // completes, prior to starting an animation or when we cancel an animation.
+ // If |stop_new_tab_timer| is true, |new_tab_timer_| is stopped.
+ void ResetAnimationState(bool stop_new_tab_timer);
// Calculates the available width for tabs, assuming a Tab is to be closed.
int GetAvailableWidthForTabs(Tab* last_tab) const;
@@ -302,9 +368,9 @@ class TabStrip : public BaseTabStrip,
// hit-test region of the specified Tab.
bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords);
- // Cleans up the Tab from the TabStrip at the specified |index|. This is
- // called from the tab animation code and is not a general-purpose method.
- void RemoveTabAt(int index);
+ // Cleans up the Tab from the TabStrip. This is called from the tab animation
+ // code and is not a general-purpose method.
+ void RemoveTab(Tab* tab);
// Called from the message loop observer when a mouse movement has occurred
// anywhere over our containing window.
@@ -313,6 +379,19 @@ class TabStrip : public BaseTabStrip,
// Returns true if any of the tabs are phantom.
bool HasPhantomTabs() const;
+ // Returns the index of the specified tab in the model coordiate system, or
+ // -1 if tab is closing or not in |tab_data_|.
+ int GetModelIndexOfTab(const Tab* tab) const;
+
+ // Returns the index into |tab_data_| corresponding to the index from the
+ // TabStripModel, or |tab_data_.size()| if there is no tab representing
+ // |model_index|.
+ int ModelIndexToTabDataIndex(int model_index) const;
+
+ // Returns the index into |tab_data_| corresponding to the specified tab, or
+ // -1 if the tab isn't in |tab_data_|.
+ int TabDataIndexOfTab(Tab* tab) const;
+
// -- Member Variables ------------------------------------------------------
// Our model.
@@ -331,7 +410,9 @@ class TabStrip : public BaseTabStrip,
// The "New Tab" button.
views::ImageButton* newtab_button_;
- gfx::Size newtab_button_size_;
+
+ // Ideal bounds of the new tab button.
+ gfx::Rect newtab_button_bounds_;
// The current widths of various types of tabs. We save these so that, as
// users close tabs while we're holding them at the same size, we can lay out
@@ -359,37 +440,6 @@ class TabStrip : public BaseTabStrip,
static const int kNewTabButtonWidth = 28;
static const int kNewTabButtonHeight = 18;
- // Used during a drop session of a url. Tracks the position of the drop as
- // well as a window used to highlight where the drop occurs.
- struct DropInfo {
- DropInfo(int index, bool drop_before, bool paint_down);
- ~DropInfo();
-
- // Index of the tab to drop on. If drop_before is true, the drop should
- // occur between the tab at drop_index - 1 and drop_index.
- // WARNING: if drop_before is true it is possible this will == tab_count,
- // which indicates the drop should create a new tab at the end of the tabs.
- int drop_index;
- bool drop_before;
-
- // Direction the arrow should point in. If true, the arrow is displayed
- // above the tab and points down. If false, the arrow is displayed beneath
- // the tab and points up.
- bool point_down;
-
- // Renders the drop indicator.
- // TODO(beng): should be views::Widget.
-#if defined(OS_WIN)
- views::WidgetWin* arrow_window;
-#else
- views::WidgetGtk* arrow_window;
-#endif
- views::ImageView* arrow_view;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DropInfo);
- };
-
// Valid for the lifetime of a drag over us.
scoped_ptr<DropInfo> drop_info_;
@@ -397,15 +447,19 @@ class TabStrip : public BaseTabStrip,
// the drag session.
scoped_ptr<DraggedTabController> drag_controller_;
- // The Tabs we contain, and their last generated "good" bounds.
- struct TabData {
- Tab* tab;
- gfx::Rect ideal_bounds;
- };
std::vector<TabData> tab_data_;
- // The currently running animation.
- scoped_ptr<TabAnimation> active_animation_;
+ // To ensure all tabs pulse at the same time they share the same animation
+ // container. This is that animation container.
+ scoped_refptr<AnimationContainer> animation_container_;
+
+ views::BoundsAnimator bounds_animator_;
+
+ // Used for stage 1 of new tab animation.
+ base::OneShotTimer<TabStrip> new_tab_timer_;
+
+ // Set for special animations.
+ AnimationType animation_type_;
DISALLOW_COPY_AND_ASSIGN(TabStrip);
};
diff --git a/chrome/browser/views/toolbar_star_toggle.cc b/chrome/browser/views/toolbar_star_toggle.cc
deleted file mode 100644
index 710d6fa..0000000
--- a/chrome/browser/views/toolbar_star_toggle.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2006-2008 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/toolbar_star_toggle.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "chrome/app/chrome_dll_resource.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_theme_provider.h"
-#include "chrome/browser/bubble_positioner.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/views/browser_dialogs.h"
-#include "chrome/browser/view_ids.h"
-#include "googleurl/src/gurl.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-
-using base::TimeTicks;
-
-// The amount of time (in milliseconds) between when the bubble closes and when
-// pressing on the button again does something. Yes, this is a hackish. I tried
-// many different options, all to no avail:
-// . Keying off mouse activation: this didn't work as there is no way to know
-// which window receives the activation. Additionally once the mouse
-// activation occurs we have no way to tie the next mouse event to the mouse
-// activation.
-// . Watching all events as we dispatch them in the MessageLoop. Mouse
-// activation isn't an observable event though.
-// Ideally we could use mouse capture for this, but we can't use mouse capture
-// with the bubble because it has other native windows.
-static const int64 kDisallowClickMS = 40;
-
-ToolbarStarToggle::ToolbarStarToggle(views::ButtonListener* listener)
- : ToggleImageButton(listener),
- profile_(NULL),
- host_view_(NULL),
- bubble_positioner_(NULL),
- ignore_click_(false) {
-}
-
-void ToolbarStarToggle::Init() {
- set_tag(IDC_BOOKMARK_PAGE);
- SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_STAR));
- SetToggledTooltipText(l10n_util::GetString(IDS_TOOLTIP_STARRED));
- SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_STAR));
- SetID(VIEW_ID_STAR_BUTTON);
-}
-
-void ToolbarStarToggle::LoadImages() {
- ThemeProvider* tp = profile_->GetThemeProvider();
-
- // Load images.
- SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND);
- SkBitmap* background = tp->GetBitmapNamed(IDR_THEME_BUTTON_BACKGROUND);
-
- SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_STAR));
- SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_STAR_H));
- SetImage(views::CustomButton::BS_PUSHED, tp->GetBitmapNamed(IDR_STAR_P));
- SetImage(views::CustomButton::BS_DISABLED, tp->GetBitmapNamed(IDR_STAR_D));
- SetToggledImage(views::CustomButton::BS_NORMAL,
- tp->GetBitmapNamed(IDR_STARRED));
- SetToggledImage(views::CustomButton::BS_HOT,
- tp->GetBitmapNamed(IDR_STARRED_H));
- SetToggledImage(views::CustomButton::BS_PUSHED,
- tp->GetBitmapNamed(IDR_STARRED_P));
- SetBackground(color, background, tp->GetBitmapNamed(IDR_STAR_MASK));
-}
-
-void ToolbarStarToggle::ShowStarBubble(const GURL& url, bool newly_bookmarked) {
- gfx::Rect bounds(bubble_positioner_->GetLocationStackBounds());
- gfx::Point star_location;
- views::View::ConvertPointToScreen(this, &star_location);
- // The visual center of the star is not centered within the bounds. The star
- // has a single central pixel; there are 13 pixels on the "inside" side of it
- // (toward the location bar) and 16 on the "outside". This means we need to
- // shift the bounds one pixel toward the location bar in order to place the
- // star's outside edge at the horizontal center. However, even this isn't
- // good enough in RTL mode, because the InfoBubble's arrow's central pixel is
- // drawn with its left edge on the target rect center-line in both LTR and RTL
- // modes. So in RTL mode, we need to shift the bounds one more pixel left, in
- // order to place the star's central pixel on the right side of the bounds'
- // center-line, so that the arrow's center will line up.
- //
- // TODO(pkasting): If the InfoBubble used mirroring transformations maybe this
- // could become symmetric (-1 : 1).
- bounds.set_x(star_location.x() + (UILayoutIsRightToLeft() ? -2 : 1));
- bounds.set_width(width());
- browser::ShowBookmarkBubbleView(host_view_->GetWindow(), bounds, this,
- profile_, url, newly_bookmarked);
-}
-
-bool ToolbarStarToggle::OnMousePressed(const views::MouseEvent& e) {
- ignore_click_ = ((TimeTicks::Now() - bubble_closed_time_).InMilliseconds() <
- kDisallowClickMS);
- return ToggleImageButton::OnMousePressed(e);
-}
-
-void ToolbarStarToggle::OnMouseReleased(const views::MouseEvent& e,
- bool canceled) {
- ToggleImageButton::OnMouseReleased(e, canceled);
- ignore_click_ = false;
-}
-
-void ToolbarStarToggle::OnDragDone() {
- ToggleImageButton::OnDragDone();
- ignore_click_ = false;
-}
-
-void ToolbarStarToggle::NotifyClick(const views::Event& event) {
- if (!ignore_click_ && !browser::IsBookmarkBubbleViewShowing())
- ToggleImageButton::NotifyClick(event);
-}
-
-SkBitmap ToolbarStarToggle::GetImageToPaint() {
- if (browser::IsBookmarkBubbleViewShowing()) {
- ResourceBundle &rb = ResourceBundle::GetSharedInstance();
- return *rb.GetBitmapNamed(IDR_STARRED_P);
- }
- return ImageButton::GetImageToPaint();
-}
-
-void ToolbarStarToggle::InfoBubbleClosing(InfoBubble* info_bubble,
- bool closed_by_escape) {
- SchedulePaint();
- bubble_closed_time_ = TimeTicks::Now();
-}
-
-bool ToolbarStarToggle::CloseOnEscape() {
- return true;
-}
diff --git a/chrome/browser/views/toolbar_star_toggle.h b/chrome/browser/views/toolbar_star_toggle.h
deleted file mode 100644
index 4966655..0000000
--- a/chrome/browser/views/toolbar_star_toggle.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2010 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_TOOLBAR_STAR_TOGGLE_H_
-#define CHROME_BROWSER_VIEWS_TOOLBAR_STAR_TOGGLE_H_
-
-#include "base/time.h"
-#include "chrome/browser/views/info_bubble.h"
-#include "views/controls/button/image_button.h"
-
-class BubblePositioner;
-class GURL;
-class Profile;
-
-namespace views {
-class ButtonListener;
-class View;
-} // namespace views
-
-// ToolbarStarToggle is used for the star button on the toolbar, allowing the
-// user to star the current page. ToolbarStarToggle manages showing the
-// InfoBubble and rendering the appropriate state while the bubble is visible.
-
-class ToolbarStarToggle : public views::ToggleImageButton,
- public InfoBubbleDelegate {
- public:
- explicit ToolbarStarToggle(views::ButtonListener* listener);
-
- void set_profile(Profile* profile) { profile_ = profile; }
- void set_host_view(views::View* host_view) { host_view_ = host_view; }
- void set_bubble_positioner(BubblePositioner* bubble_positioner) {
- bubble_positioner_ = bubble_positioner;
- }
-
- // Sets up all labels for the button.
- void Init();
-
- // Sets up all images for the button.
- void LoadImages();
-
- // If the bubble isn't showing, shows it.
- void ShowStarBubble(const GURL& url, bool newly_bookmarked);
-
- // Overridden to update ignore_click_ based on whether the mouse was clicked
- // quickly after the bubble was hidden.
- virtual bool OnMousePressed(const views::MouseEvent& e);
-
- // Overridden to set ignore_click_ to false.
- virtual void OnMouseReleased(const views::MouseEvent& e, bool canceled);
- virtual void OnDragDone();
-
- protected:
- // Only invokes super if ignore_click_ is true and the bubble isn't showing.
- virtual void NotifyClick(const views::Event& event);
-
- // Overridden to so that we appear pressed while the bubble is showing.
- virtual SkBitmap GetImageToPaint();
-
- private:
- // InfoBubbleDelegate.
- virtual void InfoBubbleClosing(InfoBubble* info_bubble,
- bool closed_by_escape);
- virtual bool CloseOnEscape();
-
- // Profile with bookmarks info.
- Profile* profile_;
-
- // View that hosts us.
- views::View* host_view_;
-
- // Positioner for bookmark bubble.
- BubblePositioner* bubble_positioner_;
-
- // Time the bubble last closed.
- base::TimeTicks bubble_closed_time_;
-
- // If true NotifyClick does nothing. This is set in OnMousePressed based on
- // the amount of time between when the bubble clicked and now.
- bool ignore_click_;
-
- DISALLOW_COPY_AND_ASSIGN(ToolbarStarToggle);
-};
-
-#endif // CHROME_BROWSER_VIEWS_TOOLBAR_STAR_TOGGLE_H_
diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc
index 51c405d..b5ba4cc 100644
--- a/chrome/browser/views/toolbar_view.cc
+++ b/chrome/browser/views/toolbar_view.cc
@@ -4,42 +4,20 @@
#include "chrome/browser/views/toolbar_view.h"
-#include <algorithm>
-#include <string>
-
-#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
-#include "app/os_exchange_data.h"
#include "app/resource_bundle.h"
#include "base/command_line.h"
-#include "base/keyboard_codes.h"
-#include "base/logging.h"
-#include "base/path_service.h"
#include "chrome/app/chrome_dll_resource.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/browser_window.h"
-#include "chrome/browser/character_encoding.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/encoding_menu_controller.h"
-#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/bookmark_menu_button.h"
#include "chrome/browser/views/browser_actions_container.h"
#include "chrome/browser/views/event_utils.h"
#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/go_button.h"
-#include "chrome/browser/views/location_bar_view.h"
-#include "chrome/browser/views/toolbar_star_toggle.h"
-#include "chrome/browser/view_ids.h"
-#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
@@ -47,12 +25,7 @@
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
-#include "net/base/net_util.h"
-#include "views/background.h"
#include "views/controls/button/button_dropdown.h"
-#include "views/controls/label.h"
-#include "views/controls/menu/menu_2.h"
-#include "views/drag_utils.h"
#include "views/focus/view_storage.h"
#include "views/widget/tooltip_manager.h"
#include "views/window/non_client_view.h"
@@ -82,9 +55,8 @@ ToolbarView::ToolbarView(Browser* browser)
: model_(browser->toolbar_model()),
back_(NULL),
forward_(NULL),
- reload_(NULL),
home_(NULL),
- star_(NULL),
+ reload_(NULL),
location_bar_(NULL),
go_(NULL),
browser_actions_(NULL),
@@ -100,9 +72,8 @@ ToolbarView::ToolbarView(Browser* browser)
SetID(VIEW_ID_TOOLBAR);
browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
- browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
- browser_->command_updater()->AddCommandObserver(IDC_BOOKMARK_PAGE, this);
+ browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
if (browser->type() == Browser::TYPE_NORMAL)
display_mode_ = DISPLAYMODE_NORMAL;
else
@@ -296,14 +267,11 @@ void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) {
case IDC_FORWARD:
button = forward_;
break;
- case IDC_RELOAD:
- button = reload_;
- break;
case IDC_HOME:
button = home_;
break;
- case IDC_BOOKMARK_PAGE:
- button = star_;
+ case IDC_RELOAD:
+ button = reload_;
break;
}
if (button)
@@ -313,8 +281,8 @@ void ToolbarView::EnabledStateChangedForCommand(int id, bool enabled) {
////////////////////////////////////////////////////////////////////////////////
// ToolbarView, views::Button::ButtonListener implementation:
-void ToolbarView::ButtonPressed(
- views::Button* sender, const views::Event& event) {
+void ToolbarView::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
int id = sender->tag();
switch (id) {
case IDC_BACK:
@@ -337,30 +305,6 @@ void ToolbarView::ButtonPressed(
}
////////////////////////////////////////////////////////////////////////////////
-// ToolbarView, BubblePositioner implementation:
-
-gfx::Rect ToolbarView::GetLocationStackBounds() const {
- // The number of pixels from the left or right edges of the location stack to
- // "just inside the visible borders". When the omnibox bubble contents are
- // aligned with this, the visible borders tacked on to the outsides will line
- // up with the visible borders on the location stack.
- const int kLocationStackEdgeWidth = 2;
-
- gfx::Point origin;
- views::View::ConvertPointToScreen(star_, &origin);
- gfx::Rect stack_bounds(origin.x(), origin.y(),
- star_->width() + location_bar_->width() + go_->width(),
- location_bar_->height());
- if (UILayoutIsRightToLeft()) {
- stack_bounds.set_x(
- stack_bounds.x() - location_bar_->width() - go_->width());
- }
- // Inset the bounds to just inside the visible edges (see comment above).
- stack_bounds.Inset(kLocationStackEdgeWidth, 0);
- return stack_bounds;
-}
-
-////////////////////////////////////////////////////////////////////////////////
// ToolbarView, NotificationObserver implementation:
void ToolbarView::Observe(NotificationType type,
@@ -456,11 +400,12 @@ gfx::Size ToolbarView::GetPreferredSize() {
if (IsDisplayModeNormal()) {
int min_width = kControlIndent + back_->GetPreferredSize().width() +
forward_->GetPreferredSize().width() + kControlHorizOffset +
- reload_->GetPreferredSize().width() + (show_home_button_.GetValue() ?
- (home_->GetPreferredSize().width() + kControlHorizOffset) : 0) +
- star_->GetPreferredSize().width() + go_->GetPreferredSize().width() +
- kMenuButtonOffset +
+ (show_home_button_.GetValue() ?
+ (home_->GetPreferredSize().width() + kControlHorizOffset) : 0) +
+ reload_->GetPreferredSize().width() +
browser_actions_->GetPreferredSize().width() +
+ go_->GetPreferredSize().width() +
+ kMenuButtonOffset +
(bookmark_menu_ ? bookmark_menu_->GetPreferredSize().width() : 0) +
page_menu_->GetPreferredSize().width() +
app_menu_->GetPreferredSize().width() + kPaddingRight;
@@ -515,21 +460,18 @@ void ToolbarView::Layout() {
forward_->SetBounds(back_->x() + back_->width(), child_y,
forward_->GetPreferredSize().width(), child_height);
- reload_->SetBounds(forward_->x() + forward_->width() + kControlHorizOffset,
- child_y, reload_->GetPreferredSize().width(),
- child_height);
-
if (show_home_button_.GetValue()) {
home_->SetVisible(true);
- home_->SetBounds(reload_->x() + reload_->width() + kControlHorizOffset,
+ home_->SetBounds(forward_->x() + forward_->width() + kControlHorizOffset,
child_y, home_->GetPreferredSize().width(), child_height);
} else {
home_->SetVisible(false);
- home_->SetBounds(reload_->x() + reload_->width(), child_y, 0, child_height);
+ home_->SetBounds(forward_->x() + forward_->width(), child_y, 0,
+ child_height);
}
- star_->SetBounds(home_->x() + home_->width() + kControlHorizOffset,
- child_y, star_->GetPreferredSize().width(), child_height);
+ reload_->SetBounds(home_->x() + home_->width() + kControlHorizOffset, child_y,
+ reload_->GetPreferredSize().width(), child_height);
int go_button_width = go_->GetPreferredSize().width();
int browser_actions_width = browser_actions_->GetPreferredSize().width();
@@ -537,7 +479,7 @@ void ToolbarView::Layout() {
int app_menu_width = app_menu_->GetPreferredSize().width();
int bookmark_menu_width = bookmark_menu_ ?
bookmark_menu_->GetPreferredSize().width() : 0;
- int location_x = star_->x() + star_->width();
+ int location_x = reload_->x() + reload_->width();
int available_width = width() - kPaddingRight - bookmark_menu_width -
app_menu_width - page_menu_width - browser_actions_width -
kMenuButtonOffset - go_button_width - location_x;
@@ -604,51 +546,6 @@ void ToolbarView::ThemeChanged() {
}
////////////////////////////////////////////////////////////////////////////////
-// ToolbarView, views::DragController implementation:
-
-void ToolbarView::WriteDragData(views::View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data) {
- DCHECK(GetDragOperations(sender, press_pt) != DragDropTypes::DRAG_NONE);
-
- UserMetrics::RecordAction(UserMetricsAction("Toolbar_DragStar"), profile_);
-
- // If there is a bookmark for the URL, add the bookmark drag data for it. We
- // do this to ensure the bookmark is moved, rather than creating an new
- // bookmark.
- TabContents* tab = browser_->GetSelectedTabContents();
- if (tab) {
- if (profile_ && profile_->GetBookmarkModel()) {
- const BookmarkNode* node = profile_->GetBookmarkModel()->
- GetMostRecentlyAddedNodeForURL(tab->GetURL());
- if (node) {
- BookmarkDragData bookmark_data(node);
- bookmark_data.Write(profile_, data);
- }
- }
-
- drag_utils::SetURLAndDragImage(tab->GetURL(),
- UTF16ToWideHack(tab->GetTitle()),
- tab->GetFavIcon(),
- data);
- }
-}
-
-int ToolbarView::GetDragOperations(views::View* sender, const gfx::Point& p) {
- DCHECK(sender == star_);
- TabContents* tab = browser_->GetSelectedTabContents();
- if (!tab || !tab->ShouldDisplayURL() || !tab->GetURL().is_valid()) {
- return DragDropTypes::DRAG_NONE;
- }
- if (profile_ && profile_->GetBookmarkModel() &&
- profile_->GetBookmarkModel()->IsBookmarked(tab->GetURL())) {
- return DragDropTypes::DRAG_MOVE | DragDropTypes::DRAG_COPY |
- DragDropTypes::DRAG_LINK;
- }
- return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
// ToolbarView, private:
int ToolbarView::PopupTopSpacing() const {
@@ -675,12 +572,6 @@ void ToolbarView::CreateLeftSideControls() {
forward_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_FORWARD));
forward_->SetID(VIEW_ID_FORWARD_BUTTON);
- reload_ = new views::ImageButton(this);
- reload_->set_tag(IDC_RELOAD);
- reload_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_RELOAD));
- reload_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_RELOAD));
- reload_->SetID(VIEW_ID_RELOAD_BUTTON);
-
home_ = new views::ImageButton(this);
home_->set_triggerable_event_flags(views::Event::EF_LEFT_BUTTON_DOWN |
views::Event::EF_MIDDLE_BUTTON_DOWN);
@@ -693,22 +584,19 @@ void ToolbarView::CreateLeftSideControls() {
AddChildView(back_);
AddChildView(forward_);
- AddChildView(reload_);
AddChildView(home_);
}
void ToolbarView::CreateCenterStack(Profile *profile) {
- star_ = new ToolbarStarToggle(this);
- star_->SetDragController(this);
- star_->set_profile(profile);
- star_->set_host_view(this);
- star_->set_bubble_positioner(this);
- star_->Init();
+ reload_ = new views::ImageButton(this);
+ reload_->set_tag(IDC_RELOAD);
+ reload_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_RELOAD));
+ reload_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_RELOAD));
+ reload_->SetID(VIEW_ID_RELOAD_BUTTON);
location_bar_ = new LocationBarView(profile, browser_->command_updater(),
model_, this,
- display_mode_ == DISPLAYMODE_LOCATION,
- this);
+ display_mode_ == DISPLAYMODE_LOCATION);
// The Go button.
go_ = new GoButton(location_bar_, browser_);
@@ -717,7 +605,7 @@ void ToolbarView::CreateCenterStack(Profile *profile) {
LoadCenterStackImages();
- AddChildView(star_);
+ AddChildView(reload_);
location_bar_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_LOCATION));
AddChildView(location_bar_);
location_bar_->Init();
@@ -779,15 +667,6 @@ void ToolbarView::LoadLeftSideControlsImages() {
forward_->SetBackground(color, background,
tp->GetBitmapNamed(IDR_FORWARD_MASK));
- reload_->SetImage(views::CustomButton::BS_NORMAL,
- tp->GetBitmapNamed(IDR_RELOAD));
- reload_->SetImage(views::CustomButton::BS_HOT,
- tp->GetBitmapNamed(IDR_RELOAD_H));
- reload_->SetImage(views::CustomButton::BS_PUSHED,
- tp->GetBitmapNamed(IDR_RELOAD_P));
- reload_->SetBackground(color, background,
- tp->GetBitmapNamed(IDR_BUTTON_MASK));
-
home_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_HOME));
home_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_HOME_H));
home_->SetImage(views::CustomButton::BS_PUSHED,
@@ -797,13 +676,20 @@ void ToolbarView::LoadLeftSideControlsImages() {
}
void ToolbarView::LoadCenterStackImages() {
- star_->LoadImages();
-
ThemeProvider* tp = GetThemeProvider();
SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND);
SkBitmap* background = tp->GetBitmapNamed(IDR_THEME_BUTTON_BACKGROUND);
+ reload_->SetImage(views::CustomButton::BS_NORMAL,
+ tp->GetBitmapNamed(IDR_RELOAD));
+ reload_->SetImage(views::CustomButton::BS_HOT,
+ tp->GetBitmapNamed(IDR_RELOAD_H));
+ reload_->SetImage(views::CustomButton::BS_PUSHED,
+ tp->GetBitmapNamed(IDR_RELOAD_P));
+ reload_->SetBackground(color, background,
+ tp->GetBitmapNamed(IDR_RELOAD_MASK));
+
go_->SetImage(views::CustomButton::BS_NORMAL, tp->GetBitmapNamed(IDR_GO));
go_->SetImage(views::CustomButton::BS_HOT, tp->GetBitmapNamed(IDR_GO_H));
go_->SetImage(views::CustomButton::BS_PUSHED, tp->GetBitmapNamed(IDR_GO_P));
diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h
index 62faebf..6e45799 100644
--- a/chrome/browser/views/toolbar_view.h
+++ b/chrome/browser/views/toolbar_view.h
@@ -11,7 +11,6 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/app_menu_model.h"
#include "chrome/browser/back_forward_menu_model.h"
-#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/page_menu_model.h"
#include "chrome/browser/pref_member.h"
@@ -27,7 +26,6 @@
class BrowserActionsContainer;
class Browser;
class Profile;
-class ToolbarStarToggle;
namespace views {
class Menu2;
@@ -36,14 +34,12 @@ class Menu2;
// The Browser Window's toolbar.
class ToolbarView : public AccessibleToolbarView,
public views::ViewMenuDelegate,
- public views::DragController,
public views::FocusChangeListener,
public menus::SimpleMenuModel::Delegate,
public LocationBarView::Delegate,
public NotificationObserver,
public CommandUpdater::CommandObserver,
- public views::ButtonListener,
- public BubblePositioner {
+ public views::ButtonListener {
public:
explicit ToolbarView(Browser* browser);
virtual ~ToolbarView();
@@ -86,7 +82,6 @@ class ToolbarView : public AccessibleToolbarView,
// Accessors...
Browser* browser() const { return browser_; }
BrowserActionsContainer* browser_actions() const { return browser_actions_; }
- ToolbarStarToggle* star_button() const { return star_; }
GoButton* go_button() const { return go_; }
LocationBarView* location_bar() const { return location_bar_; }
views::MenuButton* page_menu() const { return page_menu_; }
@@ -115,9 +110,6 @@ class ToolbarView : public AccessibleToolbarView,
// Overridden from views::BaseButton::ButtonListener:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
- // BubblePositioner:
- virtual gfx::Rect GetLocationStackBounds() const;
-
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -138,17 +130,6 @@ class ToolbarView : public AccessibleToolbarView,
virtual void ThemeChanged();
private:
- // Overridden from views::DragController:
- virtual void WriteDragData(View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data);
- virtual int GetDragOperations(View* sender, const gfx::Point& p);
- virtual bool CanStartDrag(View* sender,
- const gfx::Point& press_pt,
- const gfx::Point& p) {
- return true;
- }
-
// Returns the number of pixels above the location bar in non-normal display.
int PopupTopSpacing() const;
@@ -198,9 +179,8 @@ class ToolbarView : public AccessibleToolbarView,
// Controls
views::ImageButton* back_;
views::ImageButton* forward_;
- views::ImageButton* reload_;
views::ImageButton* home_;
- ToolbarStarToggle* star_;
+ views::ImageButton* reload_;
LocationBarView* location_bar_;
GoButton* go_;
BrowserActionsContainer* browser_actions_;
diff --git a/chrome/browser/views/url_picker.cc b/chrome/browser/views/url_picker.cc
index 5f82832..3d275d4 100644
--- a/chrome/browser/views/url_picker.cc
+++ b/chrome/browser/views/url_picker.cc
@@ -221,10 +221,10 @@ void UrlPicker::OnSelectionChanged() {
if (selection >= 0 && selection < url_table_model_->RowCount()) {
std::wstring languages =
profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
- // Because the url_field_ is user-editable, we set the URL with
- // username:password and escaped path and query.
+ // Because the url_field_ is user-editable, we don't strip anything.
std::wstring formatted = net::FormatUrl(url_table_model_->GetURL(selection),
- languages, false, UnescapeRule::NONE, NULL, NULL, NULL);
+ languages, net::kFormatUrlOmitNothing, UnescapeRule::NONE, NULL, NULL,
+ NULL);
url_field_->SetText(formatted);
GetDialogClientView()->UpdateDialogButtons();
}