summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-07 18:09:38 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-07 18:09:38 +0000
commit4b5ea27735e55571b5c745e5827fc1e217d97447 (patch)
treecda78aa3bf86fa440525126f8daf2404782450fc
parent18b0832d7e012df21a196777add97c67e4b72cd9 (diff)
downloadchromium_src-4b5ea27735e55571b5c745e5827fc1e217d97447.zip
chromium_src-4b5ea27735e55571b5c745e5827fc1e217d97447.tar.gz
chromium_src-4b5ea27735e55571b5c745e5827fc1e217d97447.tar.bz2
Add new widget API to Pepper to replace the old theming API. The implementation is a copy of the WebKit code, I will figure out how to reuse it soon.
Review URL: http://codereview.chromium.org/2011004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46710 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_renderer.gypi7
-rw-r--r--chrome/renderer/pepper_scrollbar_widget.cc633
-rw-r--r--chrome/renderer/pepper_scrollbar_widget.h221
-rw-r--r--chrome/renderer/pepper_scrollbar_widget_linux.cc244
-rw-r--r--chrome/renderer/pepper_scrollbar_widget_mac.mm34
-rw-r--r--chrome/renderer/pepper_scrollbar_widget_win.cc199
-rw-r--r--chrome/renderer/pepper_widget.cc129
-rw-r--r--chrome/renderer/pepper_widget.h41
-rw-r--r--chrome/renderer/render_view.cc6
-rw-r--r--chrome/renderer/webplugin_delegate_pepper.cc223
-rw-r--r--chrome/renderer/webplugin_delegate_pepper.h11
-rw-r--r--gfx/native_theme_win.cc7
-rw-r--r--gfx/native_theme_win.h3
-rw-r--r--third_party/npapi/bindings/npapi_extensions.h406
-rw-r--r--webkit/glue/plugins/npapi_extension_thunk.cc38
-rw-r--r--webkit/glue/plugins/webplugin_2d_device_delegate.h9
-rw-r--r--webkit/glue/plugins/webplugin_delegate.h1
17 files changed, 1779 insertions, 433 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index b5c9281..854d15e 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -107,6 +107,13 @@
'renderer/paint_aggregator.cc',
'renderer/pepper_devices.cc',
'renderer/pepper_devices.h',
+ 'renderer/pepper_scrollbar_widget.cc',
+ 'renderer/pepper_scrollbar_widget.h',
+ 'renderer/pepper_scrollbar_widget_linux.cc',
+ 'renderer/pepper_scrollbar_widget_mac.mm',
+ 'renderer/pepper_scrollbar_widget_win.cc',
+ 'renderer/pepper_widget.cc',
+ 'renderer/pepper_widget.h',
'renderer/plugin_channel_host.cc',
'renderer/plugin_channel_host.h',
'renderer/print_web_view_helper.cc',
diff --git a/chrome/renderer/pepper_scrollbar_widget.cc b/chrome/renderer/pepper_scrollbar_widget.cc
new file mode 100644
index 0000000..d37ed25
--- /dev/null
+++ b/chrome/renderer/pepper_scrollbar_widget.cc
@@ -0,0 +1,633 @@
+// 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/renderer/pepper_scrollbar_widget.h"
+
+#include "base/basictypes.h"
+#include "base/keyboard_codes.h"
+#include "base/logging.h"
+#include "chrome/renderer/pepper_devices.h"
+#include "skia/ext/platform_canvas.h"
+#include "skia/ext/platform_device.h"
+#include "webkit/glue/plugins/plugin_instance.h"
+
+const int PepperScrollbarWidget::kPixelsPerLine = 40;
+const float PepperScrollbarWidget::kMinFractionToStepWhenPaging = 0.875f;
+#if !defined(OS_MACOSX)
+const int PepperScrollbarWidget::kMaxOverlapBetweenPages = kint32max;
+#endif
+const float PepperScrollbarWidget::kInitialAutoscrollTimerDelay = 0.25f;
+const float PepperScrollbarWidget::kAutoscrollTimerDelay = 0.05f;
+
+
+PepperScrollbarWidget::PepperScrollbarWidget()
+ : vertical_(true),
+ enabled_(true),
+ length_(0),
+ total_length_(0),
+ pixels_per_page_(0),
+ thickness_(0),
+ arrow_length_(0),
+ hovered_part_(-1),
+ pressed_part_(-1),
+ thumb_position_(0),
+ have_mouse_capture_(false),
+ drag_origin_(-1.0),
+ pressed_position_(-1) {
+ GenerateMeasurements();
+}
+
+PepperScrollbarWidget::~PepperScrollbarWidget() {
+ StopTimerIfNeeded();
+}
+
+void PepperScrollbarWidget::Destroy() {
+ delete this;
+}
+
+bool PepperScrollbarWidget::HandleEvent(const NPPepperEvent& event) {
+ bool rv = false;
+ switch (event.type) {
+ case NPEventType_MouseDown:
+ rv = OnMouseDown(event);
+ break;
+ case NPEventType_MouseUp:
+ rv = OnMouseUp(event);
+ break;
+ case NPEventType_MouseMove:
+ rv = OnMouseMove(event);
+ break;
+ case NPEventType_MouseEnter:
+ break;
+ case NPEventType_MouseLeave:
+ rv = OnMouseLeave(event);
+ break;
+ case NPEventType_MouseWheel:
+ rv = OnMouseWheel(event);
+ break;
+ case NPEventType_KeyDown:
+ rv = OnKeyDown(event);
+ break;
+ case NPEventType_KeyUp:
+ rv = OnKeyUp(event);
+ break;
+ default:
+ break;
+ }
+
+ if (rv) {
+ dirty_rect_ = dirty_rect_.Union(gfx::Rect(
+ location_,
+ gfx::Size(vertical_ ? thickness_: length_,
+ vertical_ ? length_ : thickness_)));
+ WidgetPropertyChanged(NPWidgetPropertyDirtyRect);
+ }
+
+ return rv;
+}
+
+void PepperScrollbarWidget::GetProperty(
+ NPWidgetProperty property, void* value) {
+ switch (property) {
+ case NPWidgetPropertyDirtyRect: {
+ NPRect* rv = reinterpret_cast<NPRect*>(value);
+ rv->left = dirty_rect_.x();
+ rv->top = dirty_rect_.y();
+ rv->right = dirty_rect_.right();
+ rv->bottom = dirty_rect_.bottom();
+ dirty_rect_ = gfx::Rect();
+ break;
+ }
+ case NPWidgetPropertyScrollbarThickness: {
+ int32* rv = static_cast<int32*>(value);
+ *rv = thickness_;
+ break;
+ }
+ case NPWidgetPropertyScrollbarPosition: {
+ int32* rv = static_cast<int32*>(value);
+ *rv = GetPosition();
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void PepperScrollbarWidget::SetProperty(
+ NPWidgetProperty property, void* value) {
+ switch (property) {
+ case NPWidgetPropertyLocation: {
+ NPRect* r = static_cast<NPRect*>(value);
+ gfx::Point location(r->left, r->top);
+ gfx::Size size(r->right - r->left, r->bottom - r->top);
+ vertical_ = size.height() > size.width();
+ SetLocation(location,
+ vertical_ ? size.height() : size.width(),
+ total_length_);
+ break;
+ }
+ case NPWidgetPropertyScrollbarPosition: {
+ int32* position = static_cast<int*>(value);
+ ScrollTo(*position);
+ break;
+ }
+ case NPWidgetPropertyScrollbarDocumentSize: {
+ int32* total_length = static_cast<int32*>(value);
+ SetLocation(location_, length_, *total_length);
+ break;
+ }
+ case NPWidgetPropertyScrollbarTickMarks:
+ break;
+ case NPWidgetPropertyScrollbarScrollByLine: {
+ bool* forward = static_cast<bool*>(value);
+ Scroll(!forward, SCROLL_BY_LINE, 0);
+ break;
+ }
+ case NPWidgetPropertyScrollbarScrollByPage: {
+ bool* forward = static_cast<bool*>(value);
+ Scroll(!forward, SCROLL_BY_PAGE, 0);
+ break;
+ }
+ case NPWidgetPropertyScrollbarScrollByDocument: {
+ bool* forward = static_cast<bool*>(value);
+ Scroll(!forward, SCROLL_BY_DOCUMENT, 0);
+ break;
+ }
+ case NPWidgetPropertyScrollbarScrollByPixels: {
+ int32 pixels = *static_cast<int32*>(value);
+ bool forward = pixels >= 0;
+ if (pixels < 0)
+ pixels *= -1;
+ Scroll(!forward, SCROLL_BY_PIXELS, pixels);
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void PepperScrollbarWidget::SetLocation(
+ const gfx::Point& location, int length, int total_length) {
+ location_ = location;
+ length_ = length;
+ total_length_ = total_length;
+
+ // As a result of zooming out, the thumb's current position might need to be
+ // updated.
+ if (thumb_position_ > MaximumThumbPosition())
+ SetPosition(static_cast<float>(MaximumThumbPosition()), true);
+
+ pixels_per_page_ = std::max<int>(std::max<int>(
+ static_cast<int>(length_ * kMinFractionToStepWhenPaging),
+ length_ - kMaxOverlapBetweenPages), 1);
+
+
+ // did this above tho inside setpositoin...
+ dirty_rect_ = dirty_rect_.Union(gfx::Rect(
+ location_,
+ gfx::Size(vertical_ ? thickness_: length_,
+ vertical_ ? length_ : thickness_)));
+ WidgetPropertyChanged(NPWidgetPropertyDirtyRect);
+}
+
+gfx::Rect PepperScrollbarWidget::GetLocation() const {
+ return gfx::Rect(location_.x(),
+ location_.y(),
+ vertical_ ? thickness_ : length_,
+ vertical_ ? length_ : thickness_);
+}
+
+int PepperScrollbarWidget::GetPosition() const {
+ return static_cast<int>(thumb_position_ * (total_length_ - length_) /
+ MaximumThumbPosition());
+}
+
+bool PepperScrollbarWidget::OnMouseDown(const NPPepperEvent& event) {
+ if (event.u.mouse.button == NPMouseButton_Right)
+ return false;
+
+ gfx::Point location(event.u.mouse.x, event.u.mouse.y);
+ int pressed_part = HitTest(location);
+ if (pressed_part == -1)
+ return false;
+
+ have_mouse_capture_ = true;
+
+ pressed_part_ = pressed_part;
+ int pressed_position = ThumbPosition(location);
+ if (IsThumb(pressed_part_)) {
+ pressed_position_ = pressed_position;
+ drag_origin_ = thumb_position_;
+ return true;
+ } else if (IsTrackbar(pressed_part_) && ShouldCenterOnThumb(event)) {
+ hovered_part_ = pressed_part_ = vertical_ ?
+ VERTICAL_THUMB : HORIZONTAL_THUMB;
+ drag_origin_ = thumb_position_;
+ // Need to mark the middle of the thumb as the pressed position so that when
+ // it's moved, the delta will be from the current pixel position of the
+ // thumb to its new position.
+ pressed_position_ = static_cast<int>(thumb_position_) + ThumbLength() / 2;
+ MoveThumb(pressed_position);
+ return true;
+ }
+
+ pressed_position_ = pressed_position;
+ DCHECK(IsArrow(pressed_part_) || IsTrackbar(pressed_part_));
+
+ AutoScroll(kInitialAutoscrollTimerDelay);
+
+ return true;
+}
+
+bool PepperScrollbarWidget::OnMouseUp(const NPPepperEvent& event) {
+ if (event.u.mouse.button != NPMouseButton_Left)
+ return false;
+
+ pressed_part_ = -1;
+ pressed_position_ = -1;
+ drag_origin_ = -1.0;
+ StopTimerIfNeeded();
+
+ gfx::Point location(event.u.mouse.x, event.u.mouse.y);
+ return HitTest(location) != -1;
+}
+
+bool PepperScrollbarWidget::OnMouseMove(const NPPepperEvent& event) {
+ gfx::Point location(event.u.mouse.x, event.u.mouse.y);
+ if (IsThumb(pressed_part_)) {
+ if (ShouldSnapBack(location)) {
+ SetPosition(drag_origin_, true);
+ } else {
+ MoveThumb(ThumbPosition(location));
+ }
+ return true;
+ }
+
+ if (pressed_part_ != -1)
+ pressed_position_ = ThumbPosition(location);
+
+ int part = HitTest(location);
+ if (part != hovered_part_) {
+ if (pressed_part_ != -1) {
+ if (part == pressed_part_) {
+ // The mouse just moved back over the pressed part. Need to start the
+ // timers again.
+ StartTimerIfNeeded(kAutoscrollTimerDelay);
+ } else if (hovered_part_ == pressed_part_) {
+ // The mouse is leaving the pressed part. Stop the timer.
+ StopTimerIfNeeded();
+ }
+ }
+
+ hovered_part_ = part;
+ return true;
+ }
+
+ return false;
+}
+
+bool PepperScrollbarWidget::OnMouseLeave(const NPPepperEvent& event) {
+ hovered_part_ = -1;
+ return have_mouse_capture_;
+}
+
+bool PepperScrollbarWidget::OnMouseWheel(const NPPepperEvent& event) {
+ // TODO(jabdelmalek): handle middle clicking and moving the mouse diagonaly,
+ // which would give both deltaX and deltaY.
+ int delta = static_cast<int>(
+ vertical_ ? event.u.wheel.deltaY : event.u.wheel.deltaX);
+ // Delta is negative for down/right.
+ bool backwards = delta > 0;
+ if (delta < 0)
+ delta = -delta;
+ if (delta != 0) {
+ if (event.u.wheel.scrollByPage) {
+ Scroll(backwards, SCROLL_BY_PAGE, 0);
+ } else {
+ Scroll(backwards, SCROLL_BY_PIXELS, delta);
+ }
+ }
+
+ return delta != 0;
+}
+
+bool PepperScrollbarWidget::OnKeyDown(const NPPepperEvent& event) {
+ bool rv = true;
+ int key = event.u.key.normalizedKeyCode;
+ if (vertical_ && key == base::VKEY_UP ||
+ !vertical_ && key == base::VKEY_LEFT) {
+ Scroll(true, SCROLL_BY_LINE, 0);
+ } else if (vertical_ && key == base::VKEY_DOWN ||
+ !vertical_ && key == base::VKEY_RIGHT) {
+ Scroll(false, SCROLL_BY_LINE, 0);
+ } else if (key == base::VKEY_HOME) {
+ Scroll(true, SCROLL_BY_DOCUMENT, 0);
+ } else if (key == base::VKEY_END) {
+ Scroll(false, SCROLL_BY_DOCUMENT, 0);
+ } else if (key == base::VKEY_PRIOR) {
+ Scroll(true, SCROLL_BY_PAGE, 0);
+ } else if (key == base::VKEY_NEXT) {
+ Scroll(false, SCROLL_BY_PAGE, 0);
+ } else {
+ rv = false;
+ }
+
+ return rv;
+}
+
+bool PepperScrollbarWidget::OnKeyUp(const NPPepperEvent& event) {
+ return false;
+}
+
+int PepperScrollbarWidget::HitTest(const gfx::Point& location) const {
+ if (BackArrowRect().Contains(location)) {
+ return vertical_ ? UP_ARROW : LEFT_ARROW;
+ } else if (ForwardArrowRect().Contains(location)) {
+ return vertical_ ? DOWN_ARROW : RIGHT_ARROW;
+ } else if (ThumbRect().Contains(location)) {
+ return vertical_ ? VERTICAL_THUMB : HORIZONTAL_THUMB;
+ } else if (BackTrackRect().Contains(location)) {
+ return vertical_ ? VERTICAL_TRACK : HORIZONTAL_TRACK;
+ } else if (ForwardTrackRect().Contains(location)) {
+ return vertical_ ? VERTICAL_TRACK : HORIZONTAL_TRACK;
+ }
+
+ return -1;
+}
+
+int PepperScrollbarWidget::ThumbPosition(const gfx::Point& location) const {
+ int position;
+ if (vertical_) {
+ position = location.y() - location_.y() - arrow_length_;
+ } else {
+ position = location.x() - location_.x() - arrow_length_;
+ }
+
+ return position;
+}
+
+void PepperScrollbarWidget::MoveThumb(int new_position) {
+ float delta = static_cast<float>(new_position - pressed_position_);
+ if (delta > MaximumThumbPosition() - thumb_position_) {
+ // Don't want to go beyond max pos.
+ delta = MaximumThumbPosition() - thumb_position_;
+ } else if (delta < -1 * thumb_position_) {
+ // Don't want to go below 0.
+ delta = - 1 * thumb_position_;
+ }
+
+ SetPosition(thumb_position_ + delta, true);
+}
+
+void PepperScrollbarWidget::SetPosition(float position, bool notify_client) {
+ float old_thumb_position = thumb_position_;
+ thumb_position_ = position;
+ if (IsThumb(pressed_part_)) {
+ pressed_position_ =
+ pressed_position_ + static_cast<int>(position - old_thumb_position);
+ }
+
+ if (notify_client)
+ WidgetPropertyChanged(NPWidgetPropertyScrollbarPosition);
+
+ dirty_rect_ = dirty_rect_.Union(gfx::Rect(
+ location_,
+ gfx::Size(vertical_ ? thickness_: length_,
+ vertical_ ? length_ : thickness_)));
+ WidgetPropertyChanged(NPWidgetPropertyDirtyRect);
+}
+
+void PepperScrollbarWidget::OnTimerFired() {
+ AutoScroll(kAutoscrollTimerDelay);
+}
+
+void PepperScrollbarWidget::AutoScroll(float delay) {
+ if (pressed_part_ == -1 || IsThumb(pressed_part_)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (DidThumbCatchUpWithMouse())
+ return;
+
+ ScrollGranularity granularity =
+ IsArrow(pressed_part_) ? SCROLL_BY_LINE : SCROLL_BY_PAGE;
+ Scroll(IsBackscrolling(), granularity, 0);
+
+ StartTimerIfNeeded(delay);
+}
+
+void PepperScrollbarWidget::Scroll(bool backwards,
+ ScrollGranularity granularity,
+ int pixels) {
+ float new_position;
+ if (granularity == SCROLL_BY_LINE || granularity == SCROLL_BY_PAGE) {
+ int delta =
+ granularity == SCROLL_BY_LINE ? kPixelsPerLine : pixels_per_page_;
+ if (backwards)
+ delta *= -1;
+
+ // delta is in document pixels. We want to convert to scrollbar pixels.
+ new_position = thumb_position_ + ThumbPixelsFromDocumentPixels(delta);
+ } else if (granularity == SCROLL_BY_PIXELS) {
+ if (backwards)
+ pixels *= -1;
+ new_position = thumb_position_ + ThumbPixelsFromDocumentPixels(pixels);
+ } else {
+ DCHECK(granularity == SCROLL_BY_DOCUMENT);
+ new_position =
+ backwards ? 0.0f : static_cast<float>(MaximumThumbPosition());
+ }
+
+ SetPosition(std::max<float>(std::min<float>(
+ new_position, static_cast<float>(MaximumThumbPosition())), 0.0), true);
+}
+
+void PepperScrollbarWidget::ScrollTo(int position) {
+ if (position > (total_length_ - length_))
+ position = total_length_ - length_;
+ float thumb_position =
+ static_cast<float>(position) * MaximumThumbPosition() /
+ (total_length_ - length_);
+ SetPosition(thumb_position, false);
+}
+
+void PepperScrollbarWidget::StartTimerIfNeeded(float delay) {
+ if (IsThumb(pressed_part_))
+ return;
+
+ if (DidThumbCatchUpWithMouse())
+ return;
+
+ if (IsBackscrolling()) {
+ if (thumb_position_ == 0)
+ return; // Already at beginning.
+ } else {
+ if (static_cast<int>(thumb_position_) == MaximumThumbPosition())
+ return; // Already at end.
+ }
+
+ DCHECK(!timer_.IsRunning());
+ timer_.Start(
+ base::TimeDelta::FromMilliseconds(static_cast<int64>(1000 * delay)),
+ this,
+ &PepperScrollbarWidget::OnTimerFired);
+}
+
+void PepperScrollbarWidget::StopTimerIfNeeded() {
+ if (!timer_.IsRunning())
+ return;
+
+ timer_.Stop();
+}
+
+gfx::Rect PepperScrollbarWidget::BackArrowRect() const {
+ int width = vertical_ ? thickness_ : arrow_length_;
+ int height = vertical_ ? arrow_length_ : thickness_;
+ return gfx::Rect(location_.x(), location_.y(), width, height);
+}
+
+gfx::Rect PepperScrollbarWidget::ForwardArrowRect() const {
+ int x = location_.x();
+ int y = location_.y();
+ if (vertical_) {
+ y += length_ - arrow_length_;
+ } else {
+ x += length_ - arrow_length_;
+ }
+ int width = vertical_ ? thickness_ : arrow_length_;
+ int height = vertical_ ? arrow_length_ : thickness_;
+ return gfx::Rect(x, y, width, height);
+}
+
+gfx::Rect PepperScrollbarWidget::BackTrackRect() const {
+ int x = location_.x();
+ int y = location_.y();
+ if (vertical_) {
+ y += arrow_length_;
+ } else {
+ x += arrow_length_;
+ }
+ int length = static_cast<int>(thumb_position_) + ThumbLength() / 2;
+ int width = vertical_ ? thickness_ : length;
+ int height = vertical_ ? length : thickness_;
+ return gfx::Rect(x, y, width, height);
+}
+
+gfx::Rect PepperScrollbarWidget::ForwardTrackRect() const {
+ int track_begin_offset =
+ arrow_length_ + static_cast<int>(thumb_position_) + ThumbLength() / 2;
+ int track_length =
+ TrackLength() - ThumbLength() / 2 - static_cast<int>(thumb_position_);
+ int x = location_.x();
+ int y = location_.y();
+ if (vertical_) {
+ y += track_begin_offset;
+ } else {
+ x += track_begin_offset;
+ }
+ int width = vertical_ ? thickness_ : track_length;
+ int height = vertical_ ? track_length : thickness_;
+ return gfx::Rect(x, y, width, height);
+}
+
+gfx::Rect PepperScrollbarWidget::TrackRect() const {
+ int x = location_.x();
+ int y = location_.y();
+ if (vertical_) {
+ y += arrow_length_;
+ } else {
+ x += arrow_length_;
+ }
+ int width = vertical_ ? thickness_ : TrackLength();
+ int height = vertical_ ? TrackLength() : thickness_;
+ return gfx::Rect(x, y, width, height);
+}
+
+gfx::Rect PepperScrollbarWidget::ThumbRect() const {
+ int thumb_begin_offset = arrow_length_ + static_cast<int>(thumb_position_);
+ int x = location_.x();
+ int y = location_.y();
+ if (vertical_) {
+ y += thumb_begin_offset;
+ } else {
+ x += thumb_begin_offset;
+ }
+ int width = vertical_ ? thickness_ : ThumbLength();
+ int height = vertical_ ? ThumbLength() : thickness_;
+ return gfx::Rect(x, y, width, height);
+}
+
+bool PepperScrollbarWidget::IsBackTrackPressed() const {
+ return pressed_position_ >= 0 &&
+ pressed_position_ < static_cast<int>(thumb_position_);
+}
+
+bool PepperScrollbarWidget::DidThumbCatchUpWithMouse() {
+ if (IsTrackbar(pressed_part_) && IsThumbUnderMouse()) {
+ hovered_part_ = vertical_ ?
+ VERTICAL_THUMB : HORIZONTAL_THUMB;
+ return true;
+ }
+
+ return false;
+}
+
+bool PepperScrollbarWidget::IsThumbUnderMouse() const {
+ int thumb_start = static_cast<int>(thumb_position_);
+ int thumb_end = thumb_start + ThumbLength();
+ return pressed_position_ >= thumb_start &&
+ pressed_position_ < thumb_end;
+}
+
+bool PepperScrollbarWidget::IsBackscrolling() const {
+ return pressed_part_ == UP_ARROW ||
+ pressed_part_ == LEFT_ARROW ||
+ ((pressed_part_ == VERTICAL_TRACK ||
+ pressed_part_ == HORIZONTAL_TRACK) &&
+ IsBackTrackPressed());
+}
+
+int PepperScrollbarWidget::TrackLength() const {
+ int rv = length_ - 2 * arrow_length_;
+ if (rv < 0)
+ rv = 0; // In case there isn't space after we draw the arrows.
+ return rv;
+}
+
+int PepperScrollbarWidget::ThumbLength() const {
+ float proportion = static_cast<float>(length_) / total_length_;
+ int track_length = TrackLength();
+ int length = static_cast<int>(proportion * track_length);
+ length = std::max(length, MinimumThumbLength());
+ if (length > track_length)
+ length = 0; // In case there's no space for the thumb.
+ return length;
+}
+
+int PepperScrollbarWidget::MaximumThumbPosition() const {
+ return TrackLength() - ThumbLength();
+}
+
+float PepperScrollbarWidget::ThumbPixelsFromDocumentPixels(int pixels) const {
+ return static_cast<float>(pixels) * MaximumThumbPosition() /
+ (total_length_ - length_);
+}
+
+bool PepperScrollbarWidget::IsArrow(int part) {
+ return part == DOWN_ARROW ||
+ part == LEFT_ARROW ||
+ part == RIGHT_ARROW ||
+ part == UP_ARROW;
+}
+
+bool PepperScrollbarWidget::IsTrackbar(int part) {
+ return part == HORIZONTAL_TRACK || part == VERTICAL_TRACK;
+}
+
+bool PepperScrollbarWidget::IsThumb(int part) {
+ return part == HORIZONTAL_THUMB || part == VERTICAL_THUMB;
+}
diff --git a/chrome/renderer/pepper_scrollbar_widget.h b/chrome/renderer/pepper_scrollbar_widget.h
new file mode 100644
index 0000000..a762bb8
--- /dev/null
+++ b/chrome/renderer/pepper_scrollbar_widget.h
@@ -0,0 +1,221 @@
+// 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_RENDERER_PEPPER_SCROLLBAR_WIDGET_H_
+#define CHROME_RENDERER_PEPPER_SCROLLBAR_WIDGET_H_
+
+#include "base/timer.h"
+#include "build/build_config.h"
+#include "gfx/point.h"
+#include "gfx/rect.h"
+#include "chrome/renderer/pepper_widget.h"
+
+// An implementation of a horizontal/vertical scrollbar.
+// TODO(jam): this code is copied from WebKit/Chromium, use WebCore::Scrollbar
+// instead.
+class PepperScrollbarWidget : public PepperWidget {
+ public:
+ PepperScrollbarWidget();
+ ~PepperScrollbarWidget();
+
+ virtual void Destroy();
+ virtual void Paint(Graphics2DDeviceContext* context, const NPRect& dirty);
+ virtual bool HandleEvent(const NPPepperEvent& event);
+ virtual void GetProperty(NPWidgetProperty property, void* value);
+ virtual void SetProperty(NPWidgetProperty property, void* value);
+
+#if defined(OS_LINUX)
+ static void SetScrollbarColors(unsigned inactive_color,
+ unsigned active_color,
+ unsigned track_color);
+#endif
+
+ private:
+ enum ScrollGranularity {
+ SCROLL_BY_LINE,
+ SCROLL_BY_PAGE,
+ SCROLL_BY_DOCUMENT,
+ SCROLL_BY_PIXELS,
+ };
+
+ enum Part {
+ DOWN_ARROW,
+ LEFT_ARROW,
+ RIGHT_ARROW,
+ UP_ARROW,
+ HORIZONTAL_THUMB,
+ VERTICAL_THUMB,
+ HORIZONTAL_TRACK,
+ VERTICAL_TRACK,
+ };
+
+#if defined(OS_WIN)
+ int GetThemeState(Part part) const;
+ int GetThemeArrowState(Part part) const;
+ int GetClassicThemeState(Part part) const;
+ bool IsVistaOrNewer() const;
+#endif
+
+ // Length is the size in pixels of the scroll bar, while total_length is the
+ // length of the scrollable document.
+ void SetLocation(const gfx::Point& location, int length, int total_length);
+ gfx::Rect GetLocation() const;
+
+ // Returns the offset into the scrollbar document.
+ int GetPosition() const;
+
+ // Called when the timer is fired.
+ void OnTimerFired();
+
+ // Scroll the document by the given amount. pixels is only used when the
+ // granularity is SCROLL_BY_PIXELS.
+ void Scroll(bool backwards, ScrollGranularity granularity, int pixels);
+
+ // Scroll to the given location in document pixels.
+ void ScrollTo(int position);
+
+ // Calculate one-time measurements on the components of the scroll bar.
+ void GenerateMeasurements();
+
+ // Mouse/keyboard event handlers.
+ bool OnMouseDown(const NPPepperEvent& event);
+ bool OnMouseUp(const NPPepperEvent& event);
+ bool OnMouseMove(const NPPepperEvent& event);
+ bool OnMouseLeave(const NPPepperEvent& event);
+ bool OnMouseWheel(const NPPepperEvent& event);
+ bool OnKeyDown(const NPPepperEvent& event);
+ bool OnKeyUp(const NPPepperEvent& event);
+
+ // If the given location is over a part, return its id, otherwise -1.
+ int HitTest(const gfx::Point& location) const;
+
+ // When dragging the thumb, on some platforms if the user moves the mouse too
+ // far then the thumb snaps back to its original location.
+ bool ShouldSnapBack(const gfx::Point& location) const;
+
+ // Returns true if we should center the thumb on the track.
+ bool ShouldCenterOnThumb(const NPPepperEvent& event) const;
+
+ // Given a coordinate, returns the position as an offset from the beginning of
+ // the track.
+ int ThumbPosition(const gfx::Point& location) const;
+
+ // Moves the thumb and sets its location to the given position.
+ void MoveThumb(int new_position);
+
+ // Sets the position and optionally calls the client to inform them of a new
+ // position.
+ void SetPosition(float position, bool notify_client);
+
+ // Handle scrolling when the mouse is pressed over the track/arrow.
+ void AutoScroll(float delay);
+
+ // If the mouse is pressed over an arrow or track area, starts a timer so that
+ // we scroll another time.
+ void StartTimerIfNeeded(float delay);
+
+ // Cancel the timer if it's running.
+ void StopTimerIfNeeded();
+
+ // Getters for location and size of arrows, thumb, and track.
+ gfx::Rect BackArrowRect() const; // Up/left arrow.
+ gfx::Rect ForwardArrowRect() const; // Down/right arrow.
+ gfx::Rect BackTrackRect() const; // Track before the thumb.
+ gfx::Rect ForwardTrackRect() const; // Track after the thumb.
+ gfx::Rect TrackRect() const; // Entire track.
+ gfx::Rect ThumbRect() const; // Thumb.
+
+ // Returns true if the back part of the track is pressed. Returning false
+ // does not necessarily mean the forward part is pressed.
+ bool IsBackTrackPressed() const;
+
+ // Returns true if the the trackbar was pressed and the thumb has moved enough
+ // that it's now over the pressed position.
+ bool DidThumbCatchUpWithMouse();
+
+ // Returns true if the thumb is under the mouse.
+ bool IsThumbUnderMouse() const;
+
+ // Returns true if the up/left/back track are pressed.
+ bool IsBackscrolling() const;
+
+ // How many pixels is the track length (i.e. without the arrows).
+ int TrackLength() const;
+
+ // The length of the thumb in pixels.
+ int ThumbLength() const;
+
+ // Minimium number of pixels for the thumb.
+ int MinimumThumbLength() const;
+
+ // Maximum offst of the thumb in pixels from the beginning of the track.
+ int MaximumThumbPosition() const;
+
+ // Converts between pixels in the document to pixels of the thumb position.
+ float ThumbPixelsFromDocumentPixels(int pixels) const;
+
+ // Helpers for mapping between theme part IDs and their functionality.
+ static bool IsArrow(int part);
+ static bool IsTrackbar(int part);
+ static bool IsThumb(int part);
+
+ bool vertical_;
+ bool enabled_;
+ gfx::Point location_;
+ // Length of the scroll bar.
+ int length_;
+ // Length of the document being scrolled.
+ int total_length_;
+ // Calculated value, based on the length of the scrollbar and document, of how
+ // many pixels to advance when the user clicks on the trackbar.
+ int pixels_per_page_;
+
+ // Values we calculated on construction.
+ // How wide/high a vertical/horizontal scrollbar is.
+ int thickness_;
+ int arrow_length_;
+
+ // -1 if no parts are hovered or pressed. Otherwise a value from Part.
+ int hovered_part_;
+ int pressed_part_;
+
+ // How many pixels from the beginning of the track the thumb starts.
+ // This is a float because in case of a very large document, clicking the
+ // arrow button might not be enough to advance the thumb by one pixel. If
+ // this was an int, then clicking it repeatedly wouldn't move the thumb.
+ float thumb_position_;
+
+ // True if we have mouse capture.
+ bool have_mouse_capture_;
+ // If we have mouse capture and the user clicked on a trackbar, where they
+ // started their click relative to the beginning of the track.
+ float drag_origin_;
+ // The current offset relative to the beginning of the track of the last
+ // mouse down. drag_origin_ isn't enough because when the user is dragging
+ // the thumb, we get events even when they stop moving the mouse, and so we
+ // need to know if the mouse moved since the last time that we moved the
+ // thumb.
+ int pressed_position_;
+
+ // Used when holding down arrows or tracks.
+ base::OneShotTimer<PepperScrollbarWidget> timer_;
+
+ gfx::Rect dirty_rect_;
+
+ // How many pixels to advance in the document when pressing the arrows.
+ static const int kPixelsPerLine;
+
+ // Used to calculate how many pixels to advance in the document when clicking
+ // the trackbar.
+ static const int kMaxOverlapBetweenPages;
+ static const float kMinFractionToStepWhenPaging;
+
+ // Used when holding down arrows/track.
+ static const float kInitialAutoscrollTimerDelay;
+ static const float kAutoscrollTimerDelay;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperScrollbarWidget);
+};
+
+#endif // CHROME_RENDERER_PEPPER_SCROLLBAR_WIDGET_H_
diff --git a/chrome/renderer/pepper_scrollbar_widget_linux.cc b/chrome/renderer/pepper_scrollbar_widget_linux.cc
new file mode 100644
index 0000000..3468383
--- /dev/null
+++ b/chrome/renderer/pepper_scrollbar_widget_linux.cc
@@ -0,0 +1,244 @@
+// 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/renderer/pepper_scrollbar_widget.h"
+
+#include "base/logging.h"
+#include "chrome/renderer/pepper_devices.h"
+#include "skia/ext/platform_canvas.h"
+
+namespace {
+
+unsigned int g_scrollbar_width = 15;
+unsigned int g_thumb_inactive_color = 0xf0ebe5;
+unsigned int g_thumb_active_color = 0xfaf8f5;
+unsigned int g_track_color = 0xe3ddd8;
+
+SkScalar Clamp(SkScalar value,
+ SkScalar min,
+ SkScalar max) {
+ return std::min(std::max(value, min), max);
+}
+
+SkColor SaturateAndBrighten(SkScalar* hsv,
+ SkScalar saturate_amount,
+ SkScalar brighten_amount) {
+ SkScalar color[3];
+ color[0] = hsv[0];
+ color[1] = Clamp(hsv[1] + saturate_amount, 0.0, 1.0);
+ color[2] = Clamp(hsv[2] + brighten_amount, 0.0, 1.0);
+ return SkHSVToColor(color);
+}
+
+SkColor OutlineColor(SkScalar* hsv1, SkScalar* hsv2) {
+ // GTK Theme engines have way too much control over the layout of
+ // the scrollbar. We might be able to more closely approximate its
+ // look-and-feel, if we sent whole images instead of just colors
+ // from the browser to the renderer. But even then, some themes
+ // would just break.
+ //
+ // So, instead, we don't even try to 100% replicate the look of
+ // the native scrollbar. We render our own version, but we make
+ // sure to pick colors that blend in nicely with the system GTK
+ // theme. In most cases, we can just sample a couple of pixels
+ // from the system scrollbar and use those colors to draw our
+ // scrollbar.
+ //
+ // This works fine for the track color and the overall thumb
+ // color. But it fails spectacularly for the outline color used
+ // around the thumb piece. Not all themes have a clearly defined
+ // outline. For some of them it is partially transparent, and for
+ // others the thickness is very unpredictable.
+ //
+ // So, instead of trying to approximate the system theme, we
+ // instead try to compute a reasonable looking choice based on the
+ // known color of the track and the thumb piece. This is difficult
+ // when trying to deal both with high- and low-contrast themes,
+ // and both with positive and inverted themes.
+ //
+ // The following code has been tested to look OK with all of the
+ // default GTK themes.
+ SkScalar min_diff = Clamp((hsv1[1] + hsv2[1]) * 1.2, 0.2, 0.5);
+ SkScalar diff = Clamp(fabs(hsv1[2] - hsv2[2]) / 2, min_diff, 0.5);
+
+ if (hsv1[2] + hsv2[2] > 1.0)
+ diff = -diff;
+
+ return SaturateAndBrighten(hsv2, -0.2, diff);
+}
+
+
+void DrawVertLine(SkCanvas* canvas,
+ int x,
+ int y1,
+ int y2,
+ const SkPaint& paint) {
+ SkIRect skrect;
+ skrect.set(x, y1, x + 1, y2 + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+void DrawHorizLine(SkCanvas* canvas,
+ int x1,
+ int x2,
+ int y,
+ const SkPaint& paint) {
+ SkIRect skrect;
+ skrect.set(x1, y, x2 + 1, y + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+void DrawBox(SkCanvas* canvas,
+ const gfx::Rect& rect,
+ const SkPaint& paint) {
+ const int right = rect.x() + rect.width() - 1;
+ const int bottom = rect.y() + rect.height() - 1;
+ DrawHorizLine(canvas, rect.x(), right, rect.y(), paint);
+ DrawVertLine(canvas, right, rect.y(), bottom, paint);
+ DrawHorizLine(canvas, rect.x(), right, bottom, paint);
+ DrawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
+}
+
+void PaintTrack(skia::PlatformCanvas* canvas,
+ const gfx::Rect& rect) {
+ SkPaint paint;
+ SkIRect skrect;
+
+ skrect.set(rect.x(), rect.y(), rect.right(), rect.bottom());
+ SkScalar track_hsv[3];
+ SkColorToHSV(g_track_color, track_hsv);
+ paint.setColor(SaturateAndBrighten(track_hsv, 0, 0));
+ canvas->drawIRect(skrect, paint);
+
+ SkScalar thumb_hsv[3];
+ SkColorToHSV(g_thumb_inactive_color, thumb_hsv);
+
+ paint.setColor(OutlineColor(track_hsv, thumb_hsv));
+ DrawBox(canvas, rect, paint);
+}
+
+void PaintThumb(skia::PlatformCanvas* canvas,
+ bool vertical,
+ bool hovered,
+ const gfx::Rect& rect) {
+ const int midx = rect.x() + rect.width() / 2;
+ const int midy = rect.y() + rect.height() / 2;
+
+ SkScalar thumb[3];
+ SkColorToHSV(hovered ? g_thumb_active_color : g_thumb_inactive_color, thumb);
+
+ SkPaint paint;
+ paint.setColor(SaturateAndBrighten(thumb, 0, 0.02));
+
+ SkIRect skrect;
+ if (vertical)
+ skrect.set(rect.x(), rect.y(), midx + 1, rect.y() + rect.height());
+ else
+ skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), midy + 1);
+
+ canvas->drawIRect(skrect, paint);
+
+ paint.setColor(SaturateAndBrighten(thumb, 0, -0.02));
+
+ if (vertical) {
+ skrect.set(
+ midx + 1, rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
+ } else {
+ skrect.set(
+ rect.x(), midy + 1, rect.x() + rect.width(), rect.y() + rect.height());
+ }
+
+ canvas->drawIRect(skrect, paint);
+
+ SkScalar track[3];
+ SkColorToHSV(g_track_color, track);
+ paint.setColor(OutlineColor(track, thumb));
+ DrawBox(canvas, rect, paint);
+
+ if (rect.height() > 10 && rect.width() > 10) {
+ const int grippy_half_width = 2;
+ const int inter_grippy_offset = 3;
+ if (vertical) {
+ DrawHorizLine(canvas,
+ midx - grippy_half_width,
+ midx + grippy_half_width,
+ midy - inter_grippy_offset,
+ paint);
+ DrawHorizLine(canvas,
+ midx - grippy_half_width,
+ midx + grippy_half_width,
+ midy,
+ paint);
+ DrawHorizLine(canvas,
+ midx - grippy_half_width,
+ midx + grippy_half_width,
+ midy + inter_grippy_offset,
+ paint);
+ } else {
+ DrawVertLine(canvas,
+ midx - inter_grippy_offset,
+ midy - grippy_half_width,
+ midy + grippy_half_width,
+ paint);
+ DrawVertLine(canvas,
+ midx,
+ midy - grippy_half_width,
+ midy + grippy_half_width,
+ paint);
+ DrawVertLine(canvas,
+ midx + inter_grippy_offset,
+ midy - grippy_half_width,
+ midy + grippy_half_width,
+ paint);
+ }
+ }
+}
+
+
+} // annonymous namespace
+
+void PepperScrollbarWidget::Paint(Graphics2DDeviceContext* context,
+ const NPRect& dirty) {
+ skia::PlatformCanvas* canvas = context->canvas();
+
+ // Beginning track.
+ PaintTrack(canvas, BackTrackRect());
+
+ // End track.
+ PaintTrack(canvas, ForwardTrackRect());
+
+ // Thumb.
+ PaintThumb(canvas, vertical_, IsThumb(hovered_part_), ThumbRect());
+
+ canvas->endPlatformPaint();
+}
+
+void PepperScrollbarWidget::GenerateMeasurements() {
+ // TODO(port)
+ thickness_ = g_scrollbar_width;
+ arrow_length_ = 0; // On Linux, we don't use buttons.
+}
+
+bool PepperScrollbarWidget::ShouldSnapBack(const gfx::Point& location) const {
+ return false;
+}
+
+bool PepperScrollbarWidget::ShouldCenterOnThumb(
+ const NPPepperEvent& event) const {
+ return (event.u.mouse.button == NPMouseButton_Left &&
+ event.u.mouse.modifier & NPEventModifier_ShiftKey) ||
+ event.u.mouse.button == NPMouseButton_Middle;
+}
+
+void PepperScrollbarWidget::SetScrollbarColors(unsigned inactive_color,
+ unsigned active_color,
+ unsigned track_color) {
+ g_thumb_inactive_color = inactive_color;
+ g_thumb_active_color = active_color;
+ g_track_color = track_color;
+}
+
+int PepperScrollbarWidget::MinimumThumbLength() const {
+ return 2 * g_scrollbar_width; // This matches Firefox on Linux.
+}
diff --git a/chrome/renderer/pepper_scrollbar_widget_mac.mm b/chrome/renderer/pepper_scrollbar_widget_mac.mm
new file mode 100644
index 0000000..0e73ab6
--- /dev/null
+++ b/chrome/renderer/pepper_scrollbar_widget_mac.mm
@@ -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/renderer/pepper_scrollbar_widget.h"
+
+const int PepperScrollbarWidget::kMaxOverlapBetweenPages = 40;
+
+void PepperScrollbarWidget::Paint(Graphics2DDeviceContext* context,
+ const NPRect& dirty) {
+ // TODO(port)
+}
+
+void PepperScrollbarWidget::GenerateMeasurements() {
+ // TODO(port)
+ thickness_ = 0;
+ arrow_length_ = 0;
+}
+
+bool PepperScrollbarWidget::ShouldSnapBack(const gfx::Point& location) const {
+ return false;
+}
+
+bool PepperScrollbarWidget::ShouldCenterOnThumb(
+ const NPPepperEvent& event) const {
+ // TODO: to do this properly on Mac, the AppleScrollerPagingBehavior
+ // preference needs to be checked. See ScrollbarThemeChromiumMac.mm.
+ return event.u.mouse.button == NPMouseButton_Left &&
+ event.u.mouse.modifier & NPEventModifier_AltKey;
+}
+
+int PepperScrollbarWidget::MinimumThumbLength() const {
+ return thickness_;
+}
diff --git a/chrome/renderer/pepper_scrollbar_widget_win.cc b/chrome/renderer/pepper_scrollbar_widget_win.cc
new file mode 100644
index 0000000..ddfdcf1
--- /dev/null
+++ b/chrome/renderer/pepper_scrollbar_widget_win.cc
@@ -0,0 +1,199 @@
+// 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 <vsstyle.h>
+
+#include "chrome/renderer/pepper_scrollbar_widget.h"
+
+#include "base/logging.h"
+#include "base/win_util.h"
+#include "gfx/native_theme_win.h"
+#include "chrome/renderer/pepper_devices.h"
+#include "skia/ext/platform_canvas.h"
+#include "skia/ext/platform_device.h"
+
+
+void PepperScrollbarWidget::Paint(Graphics2DDeviceContext* context,
+ const NPRect& dirty) {
+ skia::PlatformCanvas* canvas = context->canvas();
+ HDC dc = canvas->beginPlatformPaint();
+
+ Part part;
+ int part_id;
+
+ // Up/Left arrow.
+ part = vertical_ ? UP_ARROW : LEFT_ARROW;
+ part_id = vertical_ ? DFCS_SCROLLUP : DFCS_SCROLLLEFT;
+ gfx::NativeTheme::instance()->PaintScrollbarArrow(
+ dc, GetThemeArrowState(part), part_id | GetClassicThemeState(part),
+ &BackArrowRect().ToRECT());
+
+ // Down/Right arrow.
+ part = vertical_ ? DOWN_ARROW : RIGHT_ARROW;
+ part_id = vertical_ ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT;
+ gfx::NativeTheme::instance()->PaintScrollbarArrow(
+ dc, GetThemeArrowState(part), part_id | GetClassicThemeState(part),
+ &ForwardArrowRect().ToRECT());
+
+ // Beginning track.
+ part = vertical_ ? VERTICAL_TRACK : HORIZONTAL_TRACK;
+ part_id = vertical_ ? SBP_UPPERTRACKVERT : SBP_UPPERTRACKHORZ;
+ gfx::Rect align_rect(location_, gfx::Size());
+ gfx::NativeTheme::instance()->PaintScrollbarTrack(
+ dc, part_id, GetThemeState(part), GetClassicThemeState(part),
+ &BackTrackRect().ToRECT(), &align_rect.ToRECT(), canvas);
+
+ // End track.
+ part_id = vertical_ ? SBP_LOWERTRACKVERT : SBP_LOWERTRACKHORZ;
+ gfx::NativeTheme::instance()->PaintScrollbarTrack(
+ dc, part_id, GetThemeState(part), GetClassicThemeState(part),
+ &ForwardTrackRect().ToRECT(), &align_rect.ToRECT(), canvas);
+
+ // Thumb.
+ part = vertical_ ? VERTICAL_THUMB : HORIZONTAL_THUMB;
+ part_id = vertical_ ? SBP_THUMBBTNVERT : SBP_THUMBBTNHORZ;
+ gfx::NativeTheme::instance()->PaintScrollbarThumb(
+ dc, part_id, GetThemeState(part), GetClassicThemeState(part),
+ &ThumbRect().ToRECT());
+
+ // Gripper.
+ part_id = vertical_ ? SBP_GRIPPERVERT : SBP_GRIPPERHORZ;
+ gfx::NativeTheme::instance()->PaintScrollbarThumb(
+ dc, part_id, GetThemeState(part), GetClassicThemeState(part),
+ &ThumbRect().ToRECT());
+
+ if (gfx::NativeTheme::instance()->IsClassicTheme(
+ gfx::NativeTheme::SCROLLBAR)) {
+ // Make the pixels opaque for the themed controls to appear correctly.
+ canvas->getTopPlatformDevice().makeOpaque(
+ location_.x(), location_.y(), vertical_ ? thickness_ : length_,
+ vertical_ ? length_ : thickness_);
+ }
+
+ canvas->endPlatformPaint();
+}
+
+int PepperScrollbarWidget::GetThemeState(Part part) const {
+ // When dragging the thumb, draw thumb pressed and other segments normal
+ // regardless of where the cursor actually is. See also four places in
+ // getThemeArrowState().
+ if (IsThumb(pressed_part_)) {
+ if (IsThumb(part))
+ return SCRBS_PRESSED;
+ return IsVistaOrNewer() ? SCRBS_HOVER : SCRBS_NORMAL;
+ }
+ if (!enabled_)
+ return SCRBS_DISABLED;
+ if (hovered_part_ != part || IsTrackbar(part)) {
+ return (hovered_part_ == -1 || !IsVistaOrNewer()) ?
+ SCRBS_NORMAL : SCRBS_HOVER;
+ }
+ if (pressed_part_ == -1)
+ return SCRBS_HOT;
+ return (pressed_part_ == part) ? SCRBS_PRESSED : SCRBS_NORMAL;
+}
+
+int PepperScrollbarWidget::GetThemeArrowState(Part part) const {
+ if (part == LEFT_ARROW || part == UP_ARROW) {
+ if (!vertical_) {
+ if (IsThumb(pressed_part_))
+ return !IsVistaOrNewer() ? ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ if (!enabled_)
+ return ABS_LEFTDISABLED;
+ if (hovered_part_ != part) {
+ return ((hovered_part_ == -1) || !IsVistaOrNewer()) ?
+ ABS_LEFTNORMAL : ABS_LEFTHOVER;
+ }
+ if (pressed_part_ == -1)
+ return ABS_LEFTHOT;
+ return (pressed_part_ == part) ? ABS_LEFTPRESSED : ABS_LEFTNORMAL;
+ }
+ if (IsThumb(pressed_part_))
+ return !IsVistaOrNewer() ? ABS_UPNORMAL : ABS_UPHOVER;
+ if (!enabled_)
+ return ABS_UPDISABLED;
+ if (hovered_part_ != part) {
+ return ((hovered_part_ == -1) || !IsVistaOrNewer()) ?
+ ABS_UPNORMAL : ABS_UPHOVER;
+ }
+ if (pressed_part_ == -1)
+ return ABS_UPHOT;
+ return (pressed_part_ == part) ? ABS_UPPRESSED : ABS_UPNORMAL;
+ }
+ if (!vertical_) {
+ if (IsThumb(pressed_part_))
+ return !IsVistaOrNewer() ? ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ if (!enabled_)
+ return ABS_RIGHTDISABLED;
+ if (hovered_part_ != part) {
+ return ((hovered_part_ == -1) || !IsVistaOrNewer()) ?
+ ABS_RIGHTNORMAL : ABS_RIGHTHOVER;
+ }
+ if (pressed_part_ == -1)
+ return ABS_RIGHTHOT;
+ return (pressed_part_ == part) ? ABS_RIGHTPRESSED : ABS_RIGHTNORMAL;
+ }
+ if (IsThumb(pressed_part_))
+ return !IsVistaOrNewer() ? ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ if (!enabled_)
+ return ABS_DOWNDISABLED;
+ if (hovered_part_ != part) {
+ return ((hovered_part_ == -1) || !IsVistaOrNewer()) ?
+ ABS_DOWNNORMAL : ABS_DOWNHOVER;
+ }
+ if (pressed_part_ == -1)
+ return ABS_DOWNHOT;
+ return (pressed_part_ == part) ? ABS_DOWNPRESSED : ABS_DOWNNORMAL;
+}
+
+int PepperScrollbarWidget::GetClassicThemeState(Part part) const {
+ // When dragging the thumb, draw the buttons normal even when hovered.
+ if (IsThumb(pressed_part_))
+ return 0;
+ if (!enabled_)
+ return DFCS_INACTIVE;
+ if (hovered_part_ != part || IsTrackbar(part))
+ return 0;
+ if (pressed_part_ == -1)
+ return DFCS_HOT;
+ return (pressed_part_ == part) ? (DFCS_PUSHED | DFCS_FLAT) : 0;
+}
+
+bool PepperScrollbarWidget::IsVistaOrNewer() const {
+ return win_util::GetWinVersion() >= win_util::WINVERSION_VISTA;
+}
+
+void PepperScrollbarWidget::GenerateMeasurements() {
+ thickness_ = GetSystemMetrics(SM_CXVSCROLL);
+ arrow_length_ = GetSystemMetrics(SM_CYVSCROLL);
+}
+
+bool PepperScrollbarWidget::ShouldSnapBack(const gfx::Point& location) const {
+ static const int kOffEndMultiplier = 3;
+ static const int kOffSideMultiplier = 8;
+
+ // Find the rect within which we shouldn't snap, by expanding the track rect
+ // in both dimensions.
+ gfx::Rect rect = TrackRect();
+ int x_diff =
+ (vertical_ ? kOffSideMultiplier : kOffEndMultiplier) * thickness_;
+ int y_diff =
+ (vertical_ ? kOffEndMultiplier : kOffSideMultiplier) * thickness_;
+ rect.set_x(rect.x() - x_diff);
+ rect.set_width(rect.width() + 2 * x_diff);
+ rect.set_y(rect.y() - y_diff);
+ rect.set_height(rect.height() + 2 * y_diff);
+
+ return !rect.Contains(location);
+}
+
+bool PepperScrollbarWidget::ShouldCenterOnThumb(
+ const NPPepperEvent& event) const {
+ return event.u.mouse.button == NPMouseButton_Left &&
+ event.u.mouse.modifier & NPEventModifier_ShiftKey;
+}
+
+int PepperScrollbarWidget::MinimumThumbLength() const {
+ return thickness_;
+}
diff --git a/chrome/renderer/pepper_widget.cc b/chrome/renderer/pepper_widget.cc
new file mode 100644
index 0000000..5fa2fc5
--- /dev/null
+++ b/chrome/renderer/pepper_widget.cc
@@ -0,0 +1,129 @@
+// 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/renderer/pepper_widget.h"
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "chrome/renderer/pepper_scrollbar_widget.h"
+#include "chrome/renderer/webplugin_delegate_pepper.h"
+#include "webkit/glue/plugins/plugin_instance.h"
+#include "webkit/glue/plugins/webplugin.h"
+#include "webkit/glue/plugins/webplugin_delegate.h"
+
+static int g_next_id;
+typedef base::hash_map<int, PepperWidget*> WidgetMap;
+static base::LazyInstance<WidgetMap> g_widgets(base::LINKER_INITIALIZED);
+
+NPError NPCreateWidget(NPP instance, NPWidgetType type, NPWidgetID* id) {
+ PepperWidget* widget;
+ switch(type) {
+ case NPWidgetTypeScrollbar:
+ widget = new PepperScrollbarWidget();
+ break;
+ default:
+ return NPERR_INVALID_PARAM;
+ }
+
+ *id = ++g_next_id;
+ widget->Init(instance, *id);
+ return NPERR_NO_ERROR;
+}
+
+NPError NPDestroyWidget(NPP instance, NPWidgetID id) {
+ WidgetMap::iterator iter = g_widgets.Get().find(id);
+ if (iter == g_widgets.Get().end())
+ return NPERR_INVALID_PARAM;
+
+ iter->second->Destroy();
+ return NPERR_NO_ERROR;
+}
+
+NPError NPPaintWidget(NPP instance,
+ NPWidgetID id,
+ NPDeviceContext2D* context,
+ NPRect* dirty) {
+ WidgetMap::iterator iter = g_widgets.Get().find(id);
+ if (iter == g_widgets.Get().end())
+ return NPERR_INVALID_PARAM;
+
+ NPAPI::PluginInstance* plugin =
+ static_cast<NPAPI::PluginInstance*>(instance->ndata);
+ WebPluginDelegatePepper* delegate =
+ static_cast<WebPluginDelegatePepper*>(plugin->webplugin()->delegate());
+ Graphics2DDeviceContext* gdc = delegate->GetGraphicsContext(context);
+ iter->second->Paint(gdc, *dirty);
+ return NPERR_NO_ERROR;
+}
+
+bool NPHandleWidgetEvent(NPP instance, NPWidgetID id, NPPepperEvent* event) {
+ WidgetMap::iterator iter = g_widgets.Get().find(id);
+ if (iter == g_widgets.Get().end())
+ return false;
+
+ return iter->second->HandleEvent(*event);
+}
+
+NPError NPGetWidgetProperty(NPP instance,
+ NPWidgetID id,
+ NPWidgetProperty property,
+ void* value) {
+ WidgetMap::iterator iter = g_widgets.Get().find(id);
+ if (iter == g_widgets.Get().end())
+ return NPERR_INVALID_PARAM;
+
+ iter->second->GetProperty(property, value);
+ return NPERR_NO_ERROR;
+}
+
+NPError NPSetWidgetProperty(NPP instance,
+ NPWidgetID id,
+ NPWidgetProperty property,
+ void* value) {
+ WidgetMap::iterator iter = g_widgets.Get().find(id);
+ if (iter == g_widgets.Get().end())
+ return NPERR_INVALID_PARAM;
+
+ iter->second->SetProperty(property, value);
+ return NPERR_NO_ERROR;
+}
+
+NPWidgetExtensions g_widget_extensions = {
+ NPCreateWidget,
+ NPDestroyWidget,
+ NPPaintWidget,
+ NPHandleWidgetEvent,
+ NPGetWidgetProperty,
+ NPSetWidgetProperty
+};
+
+// static
+NPWidgetExtensions* PepperWidget::GetWidgetExtensions() {
+ return &g_widget_extensions;
+}
+
+PepperWidget::PepperWidget() : instance_(NULL), id_(0) {
+}
+
+PepperWidget::~PepperWidget() {
+ if (id_)
+ g_widgets.Get().erase(id_);
+}
+
+void PepperWidget::Init(NPP instance, int id) {
+ instance_ = instance;
+ id_ = id;
+ g_widgets.Get()[id] = this;
+}
+
+void PepperWidget::WidgetPropertyChanged(NPWidgetProperty property) {
+ NPAPI::PluginInstance* instance =
+ static_cast<NPAPI::PluginInstance*>(instance_->ndata);
+ NPPExtensions* extensions = NULL;
+ instance->NPP_GetValue(NPPVPepperExtensions, &extensions);
+ if (!extensions)
+ return;
+
+ extensions->widgetPropertyChanged(instance_, id_, property);
+}
diff --git a/chrome/renderer/pepper_widget.h b/chrome/renderer/pepper_widget.h
new file mode 100644
index 0000000..1cc84f6
--- /dev/null
+++ b/chrome/renderer/pepper_widget.h
@@ -0,0 +1,41 @@
+// 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_RENDERER_PEPPER_WIDGET_H_
+#define CHROME_RENDERER_PEPPER_WIDGET_H_
+
+#include "base/basictypes.h"
+#include "third_party/npapi/bindings/npapi_extensions.h"
+
+class Graphics2DDeviceContext;
+
+// Every class that implements a Pepper widget derives from this.
+class PepperWidget {
+ public:
+ static NPWidgetExtensions* GetWidgetExtensions();
+
+ PepperWidget();
+ void Init(NPP instance, int id);
+
+ // Called as a result of the corresponding Pepper functions.
+ virtual void Destroy() = 0;
+ virtual void Paint(Graphics2DDeviceContext* context, const NPRect& dirty) = 0;
+ virtual bool HandleEvent(const NPPepperEvent& event) = 0;
+ virtual void GetProperty(NPWidgetProperty property, void* value) = 0;
+ virtual void SetProperty(NPWidgetProperty property, void* value) = 0;
+
+ protected:
+ ~PepperWidget();
+
+ // Tells the plugin that a property changed.
+ void WidgetPropertyChanged(NPWidgetProperty property);
+
+ private:
+ NPP instance_;
+ int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperWidget);
+};
+
+#endif // CHROME_RENDERER_PEPPER_WIDGET_H_
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 2aea82a..f2bd227 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -49,6 +49,7 @@
#include "chrome/renderer/media/ipc_video_renderer.h"
#include "chrome/renderer/navigation_state.h"
#include "chrome/renderer/notification_provider.h"
+#include "chrome/renderer/pepper_scrollbar_widget.h"
#include "chrome/renderer/plugin_channel_host.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/renderer/render_process.h"
@@ -3874,6 +3875,11 @@ void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) {
WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
+ PepperScrollbarWidget::SetScrollbarColors(
+ renderer_prefs.thumb_inactive_color,
+ renderer_prefs.thumb_active_color,
+ renderer_prefs.track_color);
+
if (webview()) {
webview()->setScrollbarColors(
renderer_prefs.thumb_inactive_color,
diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc
index 64d1828..683382d 100644
--- a/chrome/renderer/webplugin_delegate_pepper.cc
+++ b/chrome/renderer/webplugin_delegate_pepper.cc
@@ -4,11 +4,6 @@
#define PEPPER_APIS_ENABLED 1
-#include "build/build_config.h"
-#if defined(OS_WIN)
-#include <vsstyle.h>
-#endif
-
#include "chrome/renderer/webplugin_delegate_pepper.h"
#include <string>
@@ -28,17 +23,14 @@
#include "base/stats_counters.h"
#include "base/string_util.h"
#include "base/time.h"
-#if defined(OS_WIN)
-#include "base/win_util.h"
-#endif
#include "chrome/common/render_messages.h"
+#include "chrome/renderer/pepper_widget.h"
#include "chrome/renderer/render_thread.h"
#include "chrome/renderer/webplugin_delegate_proxy.h"
#include "gfx/blit.h"
#if defined(OS_WIN)
#include "gfx/codec/jpeg_codec.h"
#include "gfx/gdi_util.h"
-#include "gfx/native_theme_win.h"
#include "skia/ext/vector_platform_device.h"
#endif
#include "third_party/npapi/bindings/npapi_extensions.h"
@@ -79,55 +71,6 @@ struct Device3DImpl {
const int32 kDefaultCommandBufferSize = 1024 * 1024;
-#if defined(OS_WIN)
-struct ScrollbarThemeMapping {
- NPThemeItem item;
- NPThemeState state;
- int state_id; // Used by uxtheme.
-};
-static const ScrollbarThemeMapping scrollbar_mappings[] = {
- { NPThemeItemScrollbarDownArrow, NPThemeStateDisabled, ABS_DOWNDISABLED},
- { NPThemeItemScrollbarDownArrow, NPThemeStateHot, ABS_DOWNHOT},
- { NPThemeItemScrollbarDownArrow, NPThemeStateHover, ABS_DOWNHOVER},
- { NPThemeItemScrollbarDownArrow, NPThemeStateNormal, ABS_DOWNNORMAL},
- { NPThemeItemScrollbarDownArrow, NPThemeStatePressed, ABS_DOWNPRESSED},
- { NPThemeItemScrollbarLeftArrow, NPThemeStateDisabled, ABS_LEFTDISABLED},
- { NPThemeItemScrollbarLeftArrow, NPThemeStateHot, ABS_LEFTHOT},
- { NPThemeItemScrollbarLeftArrow, NPThemeStateHover, ABS_LEFTHOVER},
- { NPThemeItemScrollbarLeftArrow, NPThemeStateNormal, ABS_LEFTNORMAL},
- { NPThemeItemScrollbarLeftArrow, NPThemeStatePressed, ABS_LEFTPRESSED},
- { NPThemeItemScrollbarRightArrow, NPThemeStateDisabled, ABS_RIGHTDISABLED},
- { NPThemeItemScrollbarRightArrow, NPThemeStateHot, ABS_RIGHTHOT},
- { NPThemeItemScrollbarRightArrow, NPThemeStateHover, ABS_RIGHTHOVER},
- { NPThemeItemScrollbarRightArrow, NPThemeStateNormal, ABS_RIGHTNORMAL},
- { NPThemeItemScrollbarRightArrow, NPThemeStatePressed, ABS_RIGHTPRESSED},
- { NPThemeItemScrollbarUpArrow, NPThemeStateDisabled, ABS_UPDISABLED},
- { NPThemeItemScrollbarUpArrow, NPThemeStateHot, ABS_UPHOT},
- { NPThemeItemScrollbarUpArrow, NPThemeStateHover, ABS_UPHOVER},
- { NPThemeItemScrollbarUpArrow, NPThemeStateNormal, ABS_UPNORMAL},
- { NPThemeItemScrollbarUpArrow, NPThemeStatePressed, ABS_UPPRESSED},
-};
-
-int GetStateIdFromNPState(int state) {
- switch (state) {
- case NPThemeStateDisabled:
- return SCRBS_DISABLED;
- case NPThemeStateHot:
- return SCRBS_HOT;
- case NPThemeStateHover:
- return SCRBS_HOVER;
- case NPThemeStateNormal:
- return SCRBS_NORMAL;
- case NPThemeStatePressed:
- return SCRBS_PRESSED;
- default:
- return -1;
- };
-}
-#else
- // TODO(port)
-#endif
-
} // namespace
WebPluginDelegatePepper* WebPluginDelegatePepper::Create(
@@ -387,13 +330,6 @@ void WebPluginDelegatePepper::SelectedFindResultChanged(int index) {
find_identifier_, index + 1, WebKit::WebRect());
}
-void WebPluginDelegatePepper::Zoom(int factor) {
- NPPExtensions* extensions = NULL;
- instance()->NPP_GetValue(NPPVPepperExtensions, &extensions);
- if (extensions && extensions->zoom)
- extensions->zoom(instance()->npp(), factor);
-}
-
bool WebPluginDelegatePepper::ChooseFile(const char* mime_types,
int mode,
NPChooseFileCallback callback,
@@ -426,6 +362,17 @@ bool WebPluginDelegatePepper::ChooseFile(const char* mime_types,
return render_view_->ScheduleFileChooser(ipc_params, this);
}
+NPWidgetExtensions* WebPluginDelegatePepper::GetWidgetExtensions() {
+ return PepperWidget::GetWidgetExtensions();
+}
+
+void WebPluginDelegatePepper::Zoom(int factor) {
+ NPPExtensions* extensions = NULL;
+ instance()->NPP_GetValue(NPPVPepperExtensions, &extensions);
+ if (extensions && extensions->zoom)
+ extensions->zoom(instance()->npp(), factor);
+}
+
NPError WebPluginDelegatePepper::Device2DQueryCapability(int32 capability,
int32* value) {
return NPERR_GENERIC_ERROR;
@@ -473,8 +420,7 @@ NPError WebPluginDelegatePepper::Device2DGetStateContext(
if (state == NPExtensionsReservedStateSharedMemory) {
if (!context)
return NPERR_INVALID_PARAM;
- Graphics2DDeviceContext* ctx = graphic2d_contexts_.Lookup(
- reinterpret_cast<intptr_t>(context->reserved));
+ Graphics2DDeviceContext* ctx = GetGraphicsContext(context);
if (!ctx)
return NPERR_INVALID_PARAM;
*value = reinterpret_cast<intptr_t>(ctx->transport_dib());
@@ -526,144 +472,10 @@ NPError WebPluginDelegatePepper::Device2DDestroyContext(
return NPERR_NO_ERROR;
}
-NPError WebPluginDelegatePepper::Device2DThemeGetSize(NPThemeItem item,
- int* width,
- int* height) {
-#if defined(OS_WIN)
- switch (item) {
- case NPThemeItemScrollbarDownArrow:
- case NPThemeItemScrollbarUpArrow:
- *width = GetSystemMetrics(SM_CXVSCROLL);
- *height = GetSystemMetrics(SM_CYVSCROLL);
- break;
- case NPThemeItemScrollbarLeftArrow:
- case NPThemeItemScrollbarRightArrow:
- *width = GetSystemMetrics(SM_CXHSCROLL);
- *height = GetSystemMetrics(SM_CYHSCROLL);
- break;
- case NPThemeItemScrollbarHorizontalThumb:
- *width = GetSystemMetrics(SM_CXHTHUMB);
- *height = *width; // Make the min size a square.
- break;
- case NPThemeItemScrollbarVerticalThumb:
- *height = GetSystemMetrics(SM_CYVTHUMB);
- *width = *height; // Make the min size a square.
- break;
- case NPThemeItemScrollbarHoriztonalTrack:
- *height = GetSystemMetrics(SM_CYHSCROLL);
- *width = 0;
- break;
- case NPThemeItemScrollbarVerticalTrack:
- *width = GetSystemMetrics(SM_CXVSCROLL);
- *height = 0;
- break;
- default:
- return NPERR_GENERIC_ERROR;
- }
- return NPERR_NO_ERROR;
-#else
- NOTIMPLEMENTED();
- return NPERR_GENERIC_ERROR;
-#endif
-}
-
-NPError WebPluginDelegatePepper::Device2DThemePaint(NPDeviceContext2D* context,
- NPThemeParams* params) {
- if (!context)
- return NPERR_INVALID_PARAM;
-
- Graphics2DDeviceContext* ctx = graphic2d_contexts_.Lookup(
+Graphics2DDeviceContext* WebPluginDelegatePepper::GetGraphicsContext(
+ NPDeviceContext2D* context) {
+ return graphic2d_contexts_.Lookup(
reinterpret_cast<intptr_t>(context->reserved));
- if (!ctx)
- return NPERR_INVALID_PARAM;
-
- NPError rv = NPERR_GENERIC_ERROR;
- gfx::Rect rect(params->location.left,
- params->location.top,
- params->location.right - params->location.left,
- params->location.bottom - params->location.top);
- skia::PlatformCanvas* canvas = ctx->canvas();
-
-#if defined(OS_WIN)
- int state = -1;
- int part = -1;
- int classic_state = 0;
- skia::PlatformDevice::PlatformSurface surface = canvas->beginPlatformPaint();
-#endif
-
- switch (params->item) {
- case NPThemeItemScrollbarDownArrow:
- case NPThemeItemScrollbarLeftArrow:
- case NPThemeItemScrollbarRightArrow:
- case NPThemeItemScrollbarUpArrow: {
- int state_to_use = params->state;
- if (state_to_use == NPThemeStateHover
-#if defined(OS_WIN)
- && win_util::GetWinVersion() < win_util::WINVERSION_VISTA
-#endif
- ) {
- state_to_use = NPThemeStateHover;
- }
-
-#if defined(OS_WIN)
- for (size_t i = 0; i < arraysize(scrollbar_mappings); ++i) {
- if (scrollbar_mappings[i].item == params->item &&
- scrollbar_mappings[i].state == state_to_use) {
- state = scrollbar_mappings[i].state_id;
- gfx::NativeTheme::instance()->PaintScrollbarArrow(
- surface, state, classic_state, &rect.ToRECT());
- rv = NPERR_NO_ERROR;
- break;
- }
- }
-#else
- // TODO(port)
-#endif
- break;
- }
- case NPThemeItemScrollbarHorizontalThumb:
- case NPThemeItemScrollbarVerticalThumb:
-#if defined(OS_WIN)
- // First draw the thumb, then the gripper.
- part = params->item == NPThemeItemScrollbarHorizontalThumb ?
- SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
- state = GetStateIdFromNPState(params->state);
- gfx::NativeTheme::instance()->PaintScrollbarThumb(
- surface, part, state, classic_state, &rect.ToRECT());
-
- part = params->item == NPThemeItemScrollbarHorizontalThumb ?
- SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
- gfx::NativeTheme::instance()->PaintScrollbarThumb(
- surface, part, state, classic_state, &rect.ToRECT());
- rv = NPERR_NO_ERROR;
-#else
- // TODO(port)
-#endif
- break;
- case NPThemeItemScrollbarHoriztonalTrack:
- case NPThemeItemScrollbarVerticalTrack: {
-#if defined(OS_WIN)
- part = params->item == NPThemeItemScrollbarHoriztonalTrack ?
- SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
- state = GetStateIdFromNPState(params->state);
- RECT align;
- align.left = align.right = params->align.x;
- align.top = align.bottom = params->align.y;
- gfx::NativeTheme::instance()->PaintScrollbarTrack(
- surface, part, state, classic_state, &rect.ToRECT(), &align, canvas);
- rv = NPERR_NO_ERROR;
-#else
- // TODO(port)
- NOTIMPLEMENTED();
-#endif
- break;
- }
- default:
- NOTREACHED();
- }
-
- canvas->endPlatformPaint();
- return rv;
}
NPError WebPluginDelegatePepper::Device3DQueryCapability(int32 capability,
@@ -1344,7 +1156,8 @@ void WebPluginDelegatePepper::Paint(WebKit::WebCanvas* canvas,
// Flip the transform
CGContextSaveGState(canvas);
- float window_height = static_cast<float>(CGBitmapContextGetHeight(canvas));
+ float window_height =
+ static_cast<float>(CGBitmapContextGetHeight(canvas));
CGContextTranslateCTM(canvas, 0, window_height);
CGContextScaleCTM(canvas, 1.0, -1.0);
diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h
index 9ca3858..7f861fc 100644
--- a/chrome/renderer/webplugin_delegate_pepper.h
+++ b/chrome/renderer/webplugin_delegate_pepper.h
@@ -88,11 +88,13 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate,
virtual void StopFind();
virtual void NumberOfFindResultsChanged(int total, bool final_result);
virtual void SelectedFindResultChanged(int index);
- virtual void Zoom(int factor);
virtual bool ChooseFile(const char* mime_types,
int mode,
NPChooseFileCallback callback,
void* user_data);
+ virtual NPWidgetExtensions* GetWidgetExtensions();
+
+ virtual void Zoom(int factor);
// WebPlugin2DDeviceDelegate implementation.
virtual NPError Device2DQueryCapability(int32 capability, int32* value);
@@ -112,11 +114,6 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate,
NPDeviceFlushContextCallbackPtr callback,
void* user_data);
virtual NPError Device2DDestroyContext(NPDeviceContext2D* context);
- virtual NPError Device2DThemeGetSize(NPThemeItem item,
- int* width,
- int* height);
- virtual NPError Device2DThemePaint(NPDeviceContext2D* context,
- NPThemeParams* params);
// WebPlugin3DDeviceDelegate implementation.
virtual NPError Device3DQueryCapability(int32 capability, int32* value);
@@ -200,6 +197,8 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate,
void RenderViewInitiatedPaint();
void RenderViewFlushedPaint();
+ Graphics2DDeviceContext* GetGraphicsContext(NPDeviceContext2D* context);
+
private:
WebPluginDelegatePepper(
const base::WeakPtr<RenderView>& render_view,
diff --git a/gfx/native_theme_win.cc b/gfx/native_theme_win.cc
index 87024d3..ec70b2f 100644
--- a/gfx/native_theme_win.cc
+++ b/gfx/native_theme_win.cc
@@ -659,6 +659,13 @@ void NativeTheme::CloseHandles() const
}
}
+bool NativeTheme::IsClassicTheme(ThemeName name) const {
+ if (!theme_dll_)
+ return true;
+
+ return !GetThemeHandle(name);
+}
+
HANDLE NativeTheme::GetThemeHandle(ThemeName theme_name) const
{
if (!open_theme_ || theme_name < 0 || theme_name >= LAST)
diff --git a/gfx/native_theme_win.h b/gfx/native_theme_win.h
index 504ce46..8dd320b 100644
--- a/gfx/native_theme_win.h
+++ b/gfx/native_theme_win.h
@@ -254,6 +254,9 @@ class NativeTheme {
// for a theme change.
void CloseHandles() const;
+ // Returns true if classic theme is in use.
+ bool IsClassicTheme(ThemeName name) const;
+
// Gets our singleton instance.
static const NativeTheme* instance();
diff --git a/third_party/npapi/bindings/npapi_extensions.h b/third_party/npapi/bindings/npapi_extensions.h
index 940a7b5..bdc0dd0 100644
--- a/third_party/npapi/bindings/npapi_extensions.h
+++ b/third_party/npapi/bindings/npapi_extensions.h
@@ -27,42 +27,142 @@ typedef void NPUserData;
/* unique id for each device interface */
typedef int32 NPDeviceID;
-typedef struct _NPPoint {
- uint16 x;
- uint16 y;
-} NPPoint;
+/* Events -------------------------------------------------------------------*/
typedef enum {
- NPThemeItemScrollbarDownArrow = 0,
- NPThemeItemScrollbarLeftArrow = 1,
- NPThemeItemScrollbarRightArrow = 2,
- NPThemeItemScrollbarUpArrow = 3,
- NPThemeItemScrollbarHorizontalThumb = 4,
- NPThemeItemScrollbarVerticalThumb = 5,
- NPThemeItemScrollbarHoriztonalTrack = 6,
- NPThemeItemScrollbarVerticalTrack = 7
-} NPThemeItem;
+ NPMouseButton_None = -1,
+ NPMouseButton_Left = 0,
+ NPMouseButton_Middle = 1,
+ NPMouseButton_Right = 2
+} NPMouseButtons;
typedef enum {
- NPThemeStateDisabled = 0,
- // Mouse is over this item.
- NPThemeStateHot = 1,
- // Mouse is over another part of this component. This is only used on Windows
- // Vista and above. The plugin should pass it in, and the host will convert
- // it to NPThemeStateNormal if on other platforms or on Windows XP.
- NPThemeStateHover = 2,
- NPThemeStateNormal = 3,
- NPThemeStatePressed = 4
-} NPThemeState;
-
-typedef struct _NPThemeParams {
- NPThemeItem item;
- NPThemeState state;
- NPRect location;
- // Used for scroll bar tracks, needed for classic theme in Windows which draws
- // a checkered pattern.
- NPPoint align;
-} NPThemeParams;
+ NPEventType_Undefined = -1,
+ NPEventType_MouseDown = 0,
+ NPEventType_MouseUp = 1,
+ NPEventType_MouseMove = 2,
+ NPEventType_MouseEnter = 3,
+ NPEventType_MouseLeave = 4,
+ NPEventType_MouseWheel = 5,
+ NPEventType_RawKeyDown = 6,
+ NPEventType_KeyDown = 7,
+ NPEventType_KeyUp = 8,
+ NPEventType_Char = 9,
+ NPEventType_Minimize = 10,
+ NPEventType_Focus = 11,
+ NPEventType_Device = 12
+} NPEventTypes;
+
+typedef enum {
+ NPEventModifier_ShiftKey = 1 << 0,
+ NPEventModifier_ControlKey = 1 << 1,
+ NPEventModifier_AltKey = 1 << 2,
+ NPEventModifier_MetaKey = 1 << 3,
+ NPEventModifier_IsKeyPad = 1 << 4,
+ NPEventModifier_IsAutoRepeat = 1 << 5,
+ NPEventModifier_LeftButtonDown = 1 << 6,
+ NPEventModifier_MiddleButtonDown = 1 << 7,
+ NPEventModifier_RightButtonDown = 1 << 8
+} NPEventModifiers;
+
+typedef struct _NPKeyEvent
+{
+ uint32 modifier;
+ uint32 normalizedKeyCode;
+} NPKeyEvent;
+
+typedef struct _NPCharacterEvent
+{
+ uint32 modifier;
+ uint16 text[4];
+ uint16 unmodifiedText[4];
+} NPCharacterEvent;
+
+typedef struct _NPMouseEvent
+{
+ uint32 modifier;
+ int32 button;
+ int32 x;
+ int32 y;
+ int32 clickCount;
+} NPMouseEvent;
+
+typedef struct _NPMouseWheelEvent
+{
+ uint32 modifier;
+ float deltaX;
+ float deltaY;
+ float wheelTicksX;
+ float wheelTicksY;
+ uint32 scrollByPage;
+} NPMouseWheelEvent;
+
+typedef struct _NPDeviceEvent {
+ uint32 device_uid;
+ uint32 subtype;
+ /* uint8 generic[0]; */
+} NPDeviceEvent;
+
+typedef struct _NPMinimizeEvent {
+ int32 value;
+} NPMinimizeEvent;
+
+typedef struct _NPFocusEvent {
+ int32 value;
+} NPFocusEvent;
+
+typedef struct _NPPepperEvent
+{
+ uint32 size;
+ int32 type;
+ double timeStampSeconds;
+ union {
+ NPKeyEvent key;
+ NPCharacterEvent character;
+ NPMouseEvent mouse;
+ NPMouseWheelEvent wheel;
+ NPMinimizeEvent minimize;
+ NPFocusEvent focus;
+ NPDeviceEvent device;
+ } u;
+} NPPepperEvent;
+
+/* 2D -----------------------------------------------------------------------*/
+
+#define NPPepper2DDevice 1
+
+typedef struct _NPDeviceContext2DConfig {
+} NPDeviceContext2DConfig;
+
+typedef struct _NPDeviceContext2D
+{
+ /* Internal value used by the browser to identify this device. */
+ void* reserved;
+
+ /* A pointer to the pixel data. This data is 8-bit values in BGRA order in
+ * memory. Each row will start |stride| bytes after the previous one.
+ *
+ * THIS DATA USES PREMULTIPLIED ALPHA. This means that each color channel has
+ * been multiplied with the corresponding alpha, which makes compositing
+ * easier. If any color channels have a value greater than the alpha value,
+ * you'll likely get crazy colors and weird artifacts. */
+ void* region;
+
+ /* Length of each row of pixels in bytes. This may be larger than width * 4
+ * if there is padding at the end of each row to help with alignment. */
+ int32 stride;
+
+ /* The dirty region that the plugin has painted into the buffer. This
+ * will be initialized to the size of the plugin image in
+ * initializeContextPtr. The plugin can change the values to only
+ * update portions of the image. */
+ struct {
+ int32 left;
+ int32 top;
+ int32 right;
+ int32 bottom;
+ } dirty;
+} NPDeviceContext2D;
typedef struct _NPDeviceBuffer {
void* ptr;
@@ -134,19 +234,6 @@ typedef NPError (*NPDeviceMapBufferPtr)(
NPDeviceContext* context,
int32 id,
NPDeviceBuffer* buffer);
-/* Gets the size of the given theme component. For variable sized items like */
-/* vertical scrollbar tracks, the width will be the required width of the */
-/* track while the height will be the minimum height. */
-typedef NPError (*NPDeviceThemeGetSize)(
- NPP instance,
- NPThemeItem item,
- int* width,
- int* height);
-/* Draw a themed item (i.e. scrollbar arrow). */
-typedef NPError (*NPDeviceThemePaint)(
- NPP instance,
- NPDeviceContext* context,
- NPThemeParams* params);
/* forward decl typdef structs */
@@ -303,8 +390,6 @@ struct NPDevice {
NPDeviceCreateBufferPtr createBuffer;
NPDeviceDestroyBufferPtr destroyBuffer;
NPDeviceMapBufferPtr mapBuffer;
- NPDeviceThemeGetSize themeGetSize;
- NPDeviceThemePaint themePaint;
/* Experimental device API */
NPDeviceGetNumConfigsPtr getNumConfigs;
@@ -342,6 +427,88 @@ typedef void (*NPSelectedFindResultChangedPtr)(
NPP instance,
int index);
+/* Theming -----------------------------------------------------------------*/
+typedef int32 NPWidgetID;
+
+typedef enum {
+ NPWidgetTypeScrollbar = 0,
+} NPWidgetType;
+
+typedef struct _NPTickMarks {
+ uint32 count;
+ uint32* tickmarks;
+} NPTickMarks;
+
+typedef enum {
+ NPWidgetPropertyLocation = 0, // Set only. variable is NPRect*.
+ NPWidgetPropertyDirtyRect = 1, // Get only. variable is NPRec*t.
+ NPWidgetPropertyScrollbarThickness = 2, // Get only. variable is int32*.
+ NPWidgetPropertyScrollbarPosition = 3, // variable is int32*.
+ NPWidgetPropertyScrollbarDocumentSize = 4, // Set only. variable is int32*.
+ // Set only. variable is NPTickMarks*.
+ NPWidgetPropertyScrollbarTickMarks = 5,
+ // Set only. variable is bool* (true for forward, false for backward).
+ NPWidgetPropertyScrollbarScrollByLine = 6,
+ // Set only. variable is bool* (true for forward, false for backward).
+ NPWidgetPropertyScrollbarScrollByPage = 7,
+ // Set only. variable is bool* (true for forward, false for backward).
+ NPWidgetPropertyScrollbarScrollByDocument = 8,
+ // Set only. variable is int32* (positive forward, negative backward).
+ NPWidgetPropertyScrollbarScrollByPixels = 9,
+} NPWidgetProperty;
+
+// Creates a widget. If it returns NPERR_NO_ERROR then id will contain a unique
+// identifer for the widget that's used for the next functions.
+typedef NPError (*NPCreateWidgetPtr) (
+ NPP instance,
+ NPWidgetType type,
+ NPWidgetID* id);
+
+// Destroys a widget.
+typedef NPError (*NPDestroyWidgetPtr) (
+ NPP instance,
+ NPWidgetID id);
+
+// Paint the dirty rectangle of the given widget into context.
+typedef NPError (*NPPaintWidgetPtr) (
+ NPP instance,
+ NPWidgetID id,
+ NPDeviceContext2D* context,
+ NPRect* dirty);
+
+// Pass in a pepper event to a plugin. It'll return true iff it uses it.
+typedef bool (*NPHandleWidgetEventPtr) (
+ NPP instance,
+ NPWidgetID id,
+ NPPepperEvent* event);
+
+// Gets a property of the widget. "value" varies depending on the variable.
+typedef NPError (*NPGetWidgetPropertyPtr) (
+ NPP instance,
+ NPWidgetID id,
+ NPWidgetProperty property,
+ void* value);
+
+// Sets a property of the widget.
+typedef NPError (*NPSetWidgetPropertyPtr) (
+ NPP instance,
+ NPWidgetID id,
+ NPWidgetProperty property,
+ void* value);
+
+typedef struct _NPWidgetExtensions {
+ NPCreateWidgetPtr createWidget;
+ NPDestroyWidgetPtr destroyWidget;
+ NPPaintWidgetPtr paintWidget;
+ NPHandleWidgetEventPtr handleWidgetEvent;
+ NPGetWidgetPropertyPtr getWidgetProperty;
+ NPSetWidgetPropertyPtr setWidgetProperty;
+} NPWidgetExtensions;
+
+typedef NPWidgetExtensions* (*NPGetWidgetExtensionsPtr)(
+ NPP instance);
+
+
/* Supports opening files anywhere on the system after prompting the user to
* pick one.
*
@@ -410,145 +577,10 @@ struct NPNExtensions {
NPSelectedFindResultChangedPtr selectedFindResultChanged;
/* File I/O extensions */
NPChooseFilePtr chooseFile;
+ /* Widget */
+ NPGetWidgetExtensionsPtr getWidgetExtensions;
};
-/* Events -------------------------------------------------------------------*/
-
-typedef enum {
- NPMouseButton_None = -1,
- NPMouseButton_Left = 0,
- NPMouseButton_Middle = 1,
- NPMouseButton_Right = 2
-} NPMouseButtons;
-
-typedef enum {
- NPEventType_Undefined = -1,
- NPEventType_MouseDown = 0,
- NPEventType_MouseUp = 1,
- NPEventType_MouseMove = 2,
- NPEventType_MouseEnter = 3,
- NPEventType_MouseLeave = 4,
- NPEventType_MouseWheel = 5,
- NPEventType_RawKeyDown = 6,
- NPEventType_KeyDown = 7,
- NPEventType_KeyUp = 8,
- NPEventType_Char = 9,
- NPEventType_Minimize = 10,
- NPEventType_Focus = 11,
- NPEventType_Device = 12
-} NPEventTypes;
-
-typedef enum {
- NPEventModifier_ShiftKey = 1 << 0,
- NPEventModifier_ControlKey = 1 << 1,
- NPEventModifier_AltKey = 1 << 2,
- NPEventModifier_MetaKey = 1 << 3,
- NPEventModifier_IsKeyPad = 1 << 4,
- NPEventModifier_IsAutoRepeat = 1 << 5,
- NPEventModifier_LeftButtonDown = 1 << 6,
- NPEventModifier_MiddleButtonDown = 1 << 7,
- NPEventModifier_RightButtonDown = 1 << 8
-} NPEventModifiers;
-
-typedef struct _NPKeyEvent
-{
- uint32 modifier;
- uint32 normalizedKeyCode;
-} NPKeyEvent;
-
-typedef struct _NPCharacterEvent
-{
- uint32 modifier;
- uint16 text[4];
- uint16 unmodifiedText[4];
-} NPCharacterEvent;
-
-typedef struct _NPMouseEvent
-{
- uint32 modifier;
- int32 button;
- int32 x;
- int32 y;
- int32 clickCount;
-} NPMouseEvent;
-
-typedef struct _NPMouseWheelEvent
-{
- uint32 modifier;
- float deltaX;
- float deltaY;
- float wheelTicksX;
- float wheelTicksY;
- uint32 scrollByPage;
-} NPMouseWheelEvent;
-
-typedef struct _NPDeviceEvent {
- uint32 device_uid;
- uint32 subtype;
- /* uint8 generic[0]; */
-} NPDeviceEvent;
-
-typedef struct _NPMinimizeEvent {
- int32 value;
-} NPMinimizeEvent;
-
-typedef struct _NPFocusEvent {
- int32 value;
-} NPFocusEvent;
-
-typedef struct _NPPepperEvent
-{
- uint32 size;
- int32 type;
- double timeStampSeconds;
- union {
- NPKeyEvent key;
- NPCharacterEvent character;
- NPMouseEvent mouse;
- NPMouseWheelEvent wheel;
- NPMinimizeEvent minimize;
- NPFocusEvent focus;
- NPDeviceEvent device;
- } u;
-} NPPepperEvent;
-
-/* 2D -----------------------------------------------------------------------*/
-
-#define NPPepper2DDevice 1
-
-typedef struct _NPDeviceContext2DConfig {
-} NPDeviceContext2DConfig;
-
-typedef struct _NPDeviceContext2D
-{
- /* Internal value used by the browser to identify this device. */
- void* reserved;
-
- /* A pointer to the pixel data. This data is 8-bit values in BGRA order in
- * memory. Each row will start |stride| bytes after the previous one.
- *
- * THIS DATA USES PREMULTIPLIED ALPHA. This means that each color channel has
- * been multiplied with the corresponding alpha, which makes compositing
- * easier. If any color channels have a value greater than the alpha value,
- * you'll likely get crazy colors and weird artifacts. */
- void* region;
-
- /* Length of each row of pixels in bytes. This may be larger than width * 4
- * if there is padding at the end of each row to help with alignment. */
- int32 stride;
-
- /* The dirty region that the plugin has painted into the buffer. This
- * will be initialized to the size of the plugin image in
- * initializeContextPtr. The plugin can change the values to only
- * update portions of the image. */
- struct {
- int32 left;
- int32 top;
- int32 right;
- int32 bottom;
- } dirty;
-} NPDeviceContext2D;
-
/* 3D -----------------------------------------------------------------------*/
#define NPPepper3DDevice 2
@@ -855,10 +887,16 @@ typedef NPError (*NPPZoomPtr) (
NPP instance,
int factor);
+typedef NPError (*NPPWidgetPropertyChangedPtr) (
+ NPP instance,
+ NPWidgetID id,
+ NPWidgetProperty property);
+
typedef struct _NPPExtensions {
NPPGetPrintExtensionsPtr getPrintExtensions;
NPPGetFindExtensionsPtr getFindExtensions;
NPPZoomPtr zoom;
+ NPPWidgetPropertyChangedPtr widgetPropertyChanged;
} NPPExtensions;
#endif /* _NP_EXTENSIONS_H_ */
diff --git a/webkit/glue/plugins/npapi_extension_thunk.cc b/webkit/glue/plugins/npapi_extension_thunk.cc
index 100beef..9a84cf4 100644
--- a/webkit/glue/plugins/npapi_extension_thunk.cc
+++ b/webkit/glue/plugins/npapi_extension_thunk.cc
@@ -137,29 +137,6 @@ static NPError Device2DMapBuffer(NPP id,
return NPERR_GENERIC_ERROR;
}
-static NPError Device2DThemeGetSize(NPP id,
- NPThemeItem item,
- int* width,
- int* height) {
- scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id);
- if (plugin) {
- return plugin->webplugin()->delegate()->Device2DThemeGetSize(
- item, width, height);
- }
- return NPERR_GENERIC_ERROR;
-}
-
-static NPError Device2DThemePaint(NPP id,
- NPDeviceContext* context,
- NPThemeParams* params) {
- scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id);
- if (plugin) {
- return plugin->webplugin()->delegate()->Device2DThemePaint(
- static_cast<NPDeviceContext2D*>(context), params);
- }
- return NPERR_GENERIC_ERROR;
-}
-
// 3D device API ---------------------------------------------------------------
static NPError Device3DQueryCapability(NPP id, int32 capability, int32* value) {
@@ -441,8 +418,6 @@ static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) {
Device2DCreateBuffer,
Device2DDestroyBuffer,
Device2DMapBuffer,
- Device2DThemeGetSize,
- Device2DThemePaint,
NULL,
NULL,
NULL,
@@ -460,8 +435,6 @@ static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) {
Device3DCreateBuffer,
Device3DDestroyBuffer,
Device3DMapBuffer,
- NULL,
- NULL,
Device3DGetNumConfigs,
Device3DGetConfigAttribs,
Device3DCreateContext,
@@ -484,8 +457,6 @@ static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) {
NULL,
NULL,
NULL,
- NULL,
- NULL,
};
switch (device_id) {
@@ -536,6 +507,14 @@ static void SelectedFindResultChanged(NPP id, int index) {
plugin->webplugin()->delegate()->SelectedFindResultChanged(index);
}
+static NPWidgetExtensions* GetWidgetExtensions(NPP id) {
+ scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id);
+ if (!plugin)
+ return NULL;
+
+ return plugin->webplugin()->delegate()->GetWidgetExtensions();
+}
+
namespace NPAPI {
NPError GetPepperExtensionsFunctions(void* value) {
@@ -545,6 +524,7 @@ NPError GetPepperExtensionsFunctions(void* value) {
&NumberOfFindResultsChanged,
&SelectedFindResultChanged,
&ChooseFile,
+ &GetWidgetExtensions,
};
// Return a pointer to the canonical function table.
diff --git a/webkit/glue/plugins/webplugin_2d_device_delegate.h b/webkit/glue/plugins/webplugin_2d_device_delegate.h
index b622d20..69bd53a 100644
--- a/webkit/glue/plugins/webplugin_2d_device_delegate.h
+++ b/webkit/glue/plugins/webplugin_2d_device_delegate.h
@@ -46,15 +46,6 @@ class WebPlugin2DDeviceDelegate {
virtual NPError Device2DDestroyContext(NPDeviceContext2D* context) {
return NPERR_GENERIC_ERROR;
}
- virtual NPError Device2DThemeGetSize(NPThemeItem item,
- int* width,
- int* height) {
- return NPERR_GENERIC_ERROR;
- }
- virtual NPError Device2DThemePaint(NPDeviceContext2D* context,
- NPThemeParams* params) {
- return NPERR_GENERIC_ERROR;
- }
protected:
WebPlugin2DDeviceDelegate() {}
diff --git a/webkit/glue/plugins/webplugin_delegate.h b/webkit/glue/plugins/webplugin_delegate.h
index 6b15839..981ef0f 100644
--- a/webkit/glue/plugins/webplugin_delegate.h
+++ b/webkit/glue/plugins/webplugin_delegate.h
@@ -150,6 +150,7 @@ class WebPluginDelegate : public WebPlugin2DDeviceDelegate,
virtual void StopFind() {}
virtual void NumberOfFindResultsChanged(int total, bool final_result) {}
virtual void SelectedFindResultChanged(int index) {}
+ virtual NPWidgetExtensions* GetWidgetExtensions() { return NULL; }
// Used for zooming of full page plugins. 0 means reset, while -1 means zoom
// out and +1 means zoom in.