diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-07 18:09:38 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-07 18:09:38 +0000 |
commit | 4b5ea27735e55571b5c745e5827fc1e217d97447 (patch) | |
tree | cda78aa3bf86fa440525126f8daf2404782450fc | |
parent | 18b0832d7e012df21a196777add97c67e4b72cd9 (diff) | |
download | chromium_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.gypi | 7 | ||||
-rw-r--r-- | chrome/renderer/pepper_scrollbar_widget.cc | 633 | ||||
-rw-r--r-- | chrome/renderer/pepper_scrollbar_widget.h | 221 | ||||
-rw-r--r-- | chrome/renderer/pepper_scrollbar_widget_linux.cc | 244 | ||||
-rw-r--r-- | chrome/renderer/pepper_scrollbar_widget_mac.mm | 34 | ||||
-rw-r--r-- | chrome/renderer/pepper_scrollbar_widget_win.cc | 199 | ||||
-rw-r--r-- | chrome/renderer/pepper_widget.cc | 129 | ||||
-rw-r--r-- | chrome/renderer/pepper_widget.h | 41 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 6 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 223 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 11 | ||||
-rw-r--r-- | gfx/native_theme_win.cc | 7 | ||||
-rw-r--r-- | gfx/native_theme_win.h | 3 | ||||
-rw-r--r-- | third_party/npapi/bindings/npapi_extensions.h | 406 | ||||
-rw-r--r-- | webkit/glue/plugins/npapi_extension_thunk.cc | 38 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_2d_device_delegate.h | 9 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate.h | 1 |
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. |