summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/touch
diff options
context:
space:
mode:
authorsaintlou@chromium.org <saintlou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-17 18:04:47 +0000
committersaintlou@chromium.org <saintlou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-17 18:04:47 +0000
commit80d4aeaebaf149c5ba113f9133fd0e067d7e321d (patch)
tree9525850ce740fca5584385674043482a93374ce8 /chrome/browser/ui/touch
parent2b5f8edb264918e897ee7d1e0847d0ffbfeb6b70 (diff)
downloadchromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.zip
chromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.tar.gz
chromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.tar.bz2
Improve large tab strip by leveraging touch icons when present.
BUG=none TEST=TemplateURLParserTest.TestDictionary, TestMSDN, TestWikipedia (as per sadrul) Note: testing with mobile user-agent will also yield better results: --user-agent=iPhone or similar mobile Review URL: http://codereview.chromium.org/7065052 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89512 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/touch')
-rw-r--r--chrome/browser/ui/touch/tabs/tab_strip_factory.cc8
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab.cc55
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab.h14
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab_strip.cc5
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab_strip.h3
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc171
-rw-r--r--chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h46
7 files changed, 257 insertions, 45 deletions
diff --git a/chrome/browser/ui/touch/tabs/tab_strip_factory.cc b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc
index 343a27f..8d6046c 100644
--- a/chrome/browser/ui/touch/tabs/tab_strip_factory.cc
+++ b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc
@@ -7,15 +7,15 @@
#include "chrome/browser/ui/views/tabs/tab_strip_factory.h"
#include "chrome/browser/ui/touch/tabs/touch_tab_strip.h"
-#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
+#include "chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h"
-// The implmentation of CreateTabStrip for touchui creates a TouchTabStrip
+// The implementation of CreateTabStrip for touchui creates a TouchTabStrip
AbstractTabStripView* CreateTabStrip(Browser* browser,
views::View* parent,
TabStripModel* model,
bool use_vertical_tabs) {
- BrowserTabStripController* tabstrip_controller =
- new BrowserTabStripController(browser, model);
+ TouchTabStripController* tabstrip_controller =
+ new TouchTabStripController(browser, model);
// Ownership of this controller is given to a specific tabstrip when we
// construct it below.
diff --git a/chrome/browser/ui/touch/tabs/touch_tab.cc b/chrome/browser/ui/touch/tabs/touch_tab.cc
index dca408a..837ef50 100644
--- a/chrome/browser/ui/touch/tabs/touch_tab.cc
+++ b/chrome/browser/ui/touch/tabs/touch_tab.cc
@@ -19,10 +19,6 @@ static const int kLeftPadding = 16;
static const int kRightPadding = 15;
static const int kDropShadowHeight = 2;
-// The size of the favicon touch area. This generally would be the same as
-// kFaviconSize in ui/gfx/favicon_size.h
-static const int kTouchTabIconSize = 32;
-
TouchTab::TouchTabImage TouchTab::tab_alpha = {0};
TouchTab::TouchTabImage TouchTab::tab_active = {0};
TouchTab::TouchTabImage TouchTab::tab_inactive = {0};
@@ -180,7 +176,6 @@ void TouchTab::PaintActiveTabBackground(gfx::Canvas* canvas) {
}
void TouchTab::PaintIcon(gfx::Canvas* canvas) {
- // TODO(wyck): use thumbnailer to get better page images
int x = favicon_bounds_.x();
int y = favicon_bounds_.y();
@@ -190,23 +185,19 @@ void TouchTab::PaintIcon(gfx::Canvas* canvas) {
x += x_base;
if (base::i18n::IsRTL()) {
- x = width() - x -
- (data().favicon.isNull() ? kFaviconSize : data().favicon.width());
+ x = width() - x - (data().favicon.isNull()
+ ? kTouchTargetIconSize : data().favicon.width());
}
- int favicon_x = x;
- if (!data().favicon.isNull() && data().favicon.width() != kFaviconSize)
- favicon_x += (data().favicon.width() - kFaviconSize) / 2;
-
if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
ui::ThemeProvider* tp = GetThemeProvider();
SkBitmap frames(*tp->GetBitmapNamed(
- (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
- IDR_THROBBER_WAITING : IDR_THROBBER));
+ (data().network_state == TabRendererData::NETWORK_STATE_WAITING)
+ ? IDR_THROBBER_WAITING : IDR_THROBBER));
int image_size = frames.height();
int image_offset = loading_animation_frame() * image_size;
- canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x, y,
- kTouchTabIconSize, kTouchTabIconSize, false);
+ canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x,
+ y, kTouchTargetIconSize, kTouchTargetIconSize, false);
} else {
canvas->Save();
canvas->ClipRectInt(0, 0, width(), height());
@@ -215,33 +206,16 @@ void TouchTab::PaintIcon(gfx::Canvas* canvas) {
SkBitmap crashed_favicon(*rb.GetBitmapNamed(IDR_SAD_FAVICON));
canvas->DrawBitmapInt(crashed_favicon, 0, 0, crashed_favicon.width(),
crashed_favicon.height(), x, y + favicon_hiding_offset(),
- kTouchTabIconSize, kTouchTabIconSize, true);
+ kTouchTargetIconSize, kTouchTargetIconSize, true);
} else {
if (!data().favicon.isNull()) {
-
- if ((data().favicon.width() == kTouchTabIconSize) &&
- (data().favicon.height() == kTouchTabIconSize)) {
- canvas->DrawBitmapInt(data().favicon, 0, 0,
- data().favicon.width(), data().favicon.height(),
- x, y + favicon_hiding_offset(),
- kTouchTabIconSize, kTouchTabIconSize, true);
- } else {
- // Draw a background around target touch area in case the favicon
- // is smaller than touch area (e.g www.google.com is 16x16 now)
- canvas->DrawRectInt(
- GetThemeProvider()->GetColor(
- ThemeService::COLOR_BUTTON_BACKGROUND),
- x, y, kTouchTabIconSize, kTouchTabIconSize);
-
- // We center the image
- // TODO(saintlou): later request larger image from HistoryService
- canvas->DrawBitmapInt(data().favicon, 0, 0, data().favicon.width(),
- data().favicon.height(),
- x + ((kTouchTabIconSize - data().favicon.width()) / 2),
- y + ((kTouchTabIconSize - data().favicon.height()) / 2) +
- favicon_hiding_offset(),
- data().favicon.width(), data().favicon.height(), true);
- }
+ // We center the image since it might not be square
+ canvas->DrawBitmapInt(data().favicon,
+ 0, 0, data().favicon.width(), data().favicon.height(),
+ x + ((kTouchTargetIconSize - data().favicon.width()) / 2),
+ y + ((kTouchTargetIconSize - data().favicon.height()) / 2) +
+ favicon_hiding_offset(),
+ data().favicon.width(), data().favicon.height(), true);
}
}
canvas->Restore();
@@ -260,7 +234,6 @@ void TouchTab::InitTabResources() {
LoadTabImages();
}
-
// static
void TouchTab::LoadTabImages() {
// We're not letting people override tab images just yet.
diff --git a/chrome/browser/ui/touch/tabs/touch_tab.h b/chrome/browser/ui/touch/tabs/touch_tab.h
index b4ff409..ec458aa 100644
--- a/chrome/browser/ui/touch/tabs/touch_tab.h
+++ b/chrome/browser/ui/touch/tabs/touch_tab.h
@@ -25,6 +25,9 @@ class TouchTab : public BaseTab {
// The menu button's class name.
static const char kViewClassName[];
+ // The size of the favicon touch area.
+ static const int kTouchTargetIconSize = 32;
+
explicit TouchTab(TabController* controller);
virtual ~TouchTab();
@@ -34,6 +37,14 @@ class TouchTab : public BaseTab {
background_offset_ = offset;
}
+ // get and set touch icon
+ void set_touch_icon(const SkBitmap& bitmap) {
+ touch_icon_ = bitmap;
+ }
+ const SkBitmap& touch_icon() const {
+ return touch_icon_;
+ }
+
// Returns the minimum possible size of a single unselected Tab.
static gfx::Size GetMinimumUnselectedSize();
@@ -74,6 +85,9 @@ class TouchTab : public BaseTab {
// The offset used to paint the inactive background image.
gfx::Point background_offset_;
+ // The touch icon found
+ SkBitmap touch_icon_;
+
// 'l' is for left
// 'c' is for center
// 'r' is for right
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.cc b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc
index f051bac..46bfd71 100644
--- a/chrome/browser/ui/touch/tabs/touch_tab_strip.cc
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc
@@ -271,6 +271,11 @@ TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const {
return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index));
}
+// Retrieves the Tab at the specified *model* index.
+TouchTab* TouchTabStrip::GetTouchTabAtModelIndex(int model_index) const {
+ return static_cast<TouchTab*>(GetBaseTabAtModelIndex(model_index));
+}
+
////////////////////////////////////////////////////////////////////////////////
// TouchTabStrip, private:
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.h b/chrome/browser/ui/touch/tabs/touch_tab_strip.h
index 0ab5396..f6dadb3 100644
--- a/chrome/browser/ui/touch/tabs/touch_tab_strip.h
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.h
@@ -66,6 +66,9 @@ class TouchTabStrip : public BaseTabStrip {
// is in terms of tab_data, *not* the model.
TouchTab* GetTabAtTabDataIndex(int tab_data_index) const;
+ // Retrieves the Tab at the specified *model* index.
+ TouchTab* GetTouchTabAtModelIndex(int model_index) const;
+
private:
void Init();
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc
new file mode 100644
index 0000000..185f542
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2011 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/ui/touch/tabs/touch_tab_strip_controller.h"
+
+#include "chrome/browser/extensions/extension_tab_helper.h"
+#include "chrome/browser/favicon/favicon_tab_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/browser/ui/touch/tabs/touch_tab.h"
+#include "chrome/browser/ui/touch/tabs/touch_tab_strip.h"
+#include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
+#include "skia/ext/image_operations.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
+
+namespace {
+
+void CalcTouchIconTargetSize(int* width, int* height) {
+ if (*width > TouchTab::kTouchTargetIconSize ||
+ *height > TouchTab::kTouchTargetIconSize) {
+ // Too big, resize it maintaining the aspect ratio.
+ float aspect_ratio = static_cast<float>(*width) /
+ static_cast<float>(*height);
+ *height = TouchTab::kTouchTargetIconSize;
+ *width = static_cast<int>(aspect_ratio * *height);
+ if (*width > TouchTab::kTouchTargetIconSize) {
+ *width = TouchTab::kTouchTargetIconSize;
+ *height = static_cast<int>(*width / aspect_ratio);
+ }
+ }
+}
+
+GURL GetURLWithoutFragment(const GURL& gurl) {
+ url_canon::Replacements<char> replacements;
+ replacements.ClearUsername();
+ replacements.ClearPassword();
+ replacements.ClearQuery();
+ replacements.ClearRef();
+ return gurl.ReplaceComponents(replacements);
+}
+
+} // namespace
+
+TouchTabStripController::TouchTabStripController(Browser* browser,
+ TabStripModel* model)
+ : BrowserTabStripController(browser, model) {
+}
+
+TouchTabStripController::~TouchTabStripController() {
+}
+
+void TouchTabStripController::TabDetachedAt(TabContentsWrapper* contents,
+ int model_index) {
+ if (consumer_.HasPendingRequests()) {
+ TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index);
+ consumer_.CancelAllRequestsForClientData(touch_tab);
+ }
+}
+
+void TouchTabStripController::TabChangedAt(TabContentsWrapper* contents,
+ int model_index,
+ TabChangeType change_type) {
+ // Clear the large icon if we are loading a different URL in the same tab.
+ if (change_type == LOADING_ONLY) {
+ TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index);
+ if (!touch_tab->touch_icon().isNull()) {
+ GURL existing_tab_url = GetURLWithoutFragment(touch_tab->data().url);
+ GURL page_url = GetURLWithoutFragment(contents->tab_contents()->GetURL());
+ // Reset touch icon if the url are different.
+ if (existing_tab_url != page_url) {
+ touch_tab->set_touch_icon(SkBitmap());
+ consumer_.CancelAllRequestsForClientData(touch_tab);
+ }
+ }
+ }
+
+ // Always call parent's method.
+ BrowserTabStripController::TabChangedAt(contents, model_index, change_type);
+}
+
+void TouchTabStripController::SetTabRendererDataFromModel(
+ TabContents* contents,
+ int model_index,
+ TabRendererData* data,
+ TabStatus tab_status) {
+ // Call parent first.
+ BrowserTabStripController::SetTabRendererDataFromModel(contents, model_index,
+ data, tab_status);
+ if (tab_status == NEW_TAB)
+ return;
+
+ // Use the touch icon if any.
+ TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index);
+ if (!touch_tab->touch_icon().isNull()) {
+ data->favicon = touch_tab->touch_icon();
+ return;
+ }
+
+ // In the case where we do not have a touch icon we scale up the small
+ // favicons (16x16) which originally are coming from NavigationEntry.
+ if (data->favicon.width() == kFaviconSize &&
+ data->favicon.height() == kFaviconSize) {
+ data->favicon = skia::ImageOperations::Resize(data->favicon,
+ skia::ImageOperations::RESIZE_BEST, TouchTab::kTouchTargetIconSize,
+ TouchTab::kTouchTargetIconSize);
+ }
+
+ // Check if we have an outstanding request for this tab.
+ if (consumer_.HasPendingRequests())
+ consumer_.CancelAllRequestsForClientData(touch_tab);
+
+ // Request touch icon.
+ GURL page_url = GetURLWithoutFragment(contents->GetURL());
+ FaviconService* favicon_service = profile()->GetFaviconService(
+ Profile::EXPLICIT_ACCESS);
+ if (favicon_service) {
+ CancelableRequestProvider::Handle h =
+ favicon_service->GetFaviconForURL(
+ page_url,
+ history::TOUCH_ICON | history::TOUCH_PRECOMPOSED_ICON,
+ &consumer_,
+ NewCallback(this, &TouchTabStripController::OnTouchIconAvailable));
+ consumer_.SetClientData(favicon_service, h, touch_tab);
+ }
+}
+
+const TouchTabStrip* TouchTabStripController::tabstrip() const {
+ return static_cast<const TouchTabStrip*>(
+ BrowserTabStripController::tabstrip());
+}
+
+void TouchTabStripController::OnTouchIconAvailable(
+ FaviconService::Handle h,
+ history::FaviconData favicon) {
+ // Abandon the request when there is no valid favicon.
+ if (!favicon.is_valid())
+ return;
+
+ // Retrieve the model_index from the TouchTab pointer received.
+ TouchTab* touch_tab = consumer_.GetClientDataForCurrentRequest();
+ int model_index = tabstrip()->GetModelIndexOfBaseTab(touch_tab);
+ if (!IsValidIndex(model_index))
+ return;
+
+ // Try to decode the favicon, return on failure.
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(favicon.image_data->front(),
+ favicon.image_data->size(),
+ &bitmap);
+ if (bitmap.isNull())
+ return;
+
+ // Rescale output, if needed, and assign to the TouchTab instance.
+ int width = bitmap.width();
+ int height = bitmap.height();
+ if (width == TouchTab::kTouchTargetIconSize &&
+ height == TouchTab::kTouchTargetIconSize) {
+ touch_tab->set_touch_icon(bitmap);
+ } else {
+ CalcTouchIconTargetSize(&width, &height);
+ touch_tab->set_touch_icon(skia::ImageOperations::Resize(bitmap,
+ skia::ImageOperations::RESIZE_BEST, width, height));
+ }
+
+ // Refresh UI since favicon changed.
+ browser()->GetTabContentsAt(model_index)->NotifyNavigationStateChanged(
+ TabContents::INVALIDATE_TAB);
+}
diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h
new file mode 100644
index 0000000..484b079
--- /dev/null
+++ b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 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_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_
+#define CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_
+#pragma once
+
+#include "chrome/browser/favicon/favicon_service.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
+
+class TouchTab;
+class TouchTabStrip;
+
+class TouchTabStripController : public BrowserTabStripController {
+ public:
+ TouchTabStripController(Browser* browser, TabStripModel* model);
+ virtual ~TouchTabStripController();
+
+ virtual void TabDetachedAt(TabContentsWrapper* contents,
+ int model_index) OVERRIDE;
+
+ virtual void TabChangedAt(TabContentsWrapper* contents,
+ int model_index,
+ TabChangeType change_type) OVERRIDE;
+
+ protected:
+ virtual void SetTabRendererDataFromModel(TabContents* contents,
+ int model_index,
+ TabRendererData* data,
+ TabStatus tab_status) OVERRIDE;
+
+ const TouchTabStrip* tabstrip() const;
+
+ private:
+ void OnTouchIconAvailable(FaviconService::Handle h,
+ history::FaviconData favicon);
+
+ // Our consumer for touch icon requests.
+ CancelableRequestConsumerTSimple<TouchTab*> consumer_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchTabStripController);
+};
+
+#endif // CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_