1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/ppb_scrollbar_impl.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/renderer/pepper/common.h"
11 #include "content/renderer/pepper/event_conversion.h"
12 #include "content/renderer/pepper/host_globals.h"
13 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14 #include "content/renderer/pepper/plugin_module.h"
15 #include "content/renderer/pepper/ppb_image_data_impl.h"
16 #include "ppapi/c/dev/ppp_scrollbar_dev.h"
17 #include "ppapi/thunk/thunk.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "third_party/WebKit/public/platform/WebCanvas.h"
20 #include "third_party/WebKit/public/platform/WebRect.h"
21 #include "third_party/WebKit/public/platform/WebVector.h"
22 #include "third_party/WebKit/public/web/WebInputEvent.h"
23 #include "third_party/WebKit/public/web/WebPluginScrollbar.h"
26 #include "base/win/windows_version.h"
29 using ppapi::thunk::PPB_Scrollbar_API
;
30 using WebKit::WebInputEvent
;
31 using WebKit::WebRect
;
32 using WebKit::WebScrollbar
;
33 using WebKit::WebPluginScrollbar
;
38 PP_Resource
PPB_Scrollbar_Impl::Create(PP_Instance instance
,
40 scoped_refptr
<PPB_Scrollbar_Impl
> scrollbar(
41 new PPB_Scrollbar_Impl(instance
));
42 scrollbar
->Init(vertical
);
43 return scrollbar
->GetReference();
46 PPB_Scrollbar_Impl::PPB_Scrollbar_Impl(PP_Instance instance
)
47 : PPB_Widget_Impl(instance
),
48 weak_ptr_factory_(this) {
51 PPB_Scrollbar_Impl::~PPB_Scrollbar_Impl() {
54 void PPB_Scrollbar_Impl::Init(bool vertical
) {
55 PepperPluginInstanceImpl
* plugin_instance
=
56 HostGlobals::Get()->GetInstance(pp_instance());
59 scrollbar_
.reset(WebPluginScrollbar::createForPlugin(
60 vertical
? WebScrollbar::Vertical
: WebScrollbar::Horizontal
,
61 plugin_instance
->container(),
62 static_cast<WebKit::WebPluginScrollbarClient
*>(this)));
65 PPB_Scrollbar_API
* PPB_Scrollbar_Impl::AsPPB_Scrollbar_API() {
69 void PPB_Scrollbar_Impl::InstanceWasDeleted() {
73 uint32_t PPB_Scrollbar_Impl::GetThickness() {
74 return WebPluginScrollbar::defaultThickness();
77 bool PPB_Scrollbar_Impl::IsOverlay() {
78 return scrollbar_
->isOverlay();
81 uint32_t PPB_Scrollbar_Impl::GetValue() {
82 return scrollbar_
->value();
85 void PPB_Scrollbar_Impl::SetValue(uint32_t value
) {
87 scrollbar_
->setValue(value
);
90 void PPB_Scrollbar_Impl::SetDocumentSize(uint32_t size
) {
92 scrollbar_
->setDocumentSize(size
);
95 void PPB_Scrollbar_Impl::SetTickMarks(const PP_Rect
* tick_marks
,
99 tickmarks_
.resize(count
);
100 for (uint32 i
= 0; i
< count
; ++i
) {
101 tickmarks_
[i
] = WebRect(tick_marks
[i
].point
.x
,
102 tick_marks
[i
].point
.y
,
103 tick_marks
[i
].size
.width
,
104 tick_marks
[i
].size
.height
);;
106 PP_Rect rect
= location();
110 void PPB_Scrollbar_Impl::ScrollBy(PP_ScrollBy_Dev unit
, int32_t multiplier
) {
114 WebScrollbar::ScrollDirection direction
= multiplier
>= 0 ?
115 WebScrollbar::ScrollForward
: WebScrollbar::ScrollBackward
;
116 float fmultiplier
= 1.0;
118 WebScrollbar::ScrollGranularity granularity
;
119 if (unit
== PP_SCROLLBY_LINE
) {
120 granularity
= WebScrollbar::ScrollByLine
;
121 } else if (unit
== PP_SCROLLBY_PAGE
) {
122 granularity
= WebScrollbar::ScrollByPage
;
123 } else if (unit
== PP_SCROLLBY_DOCUMENT
) {
124 granularity
= WebScrollbar::ScrollByDocument
;
126 granularity
= WebScrollbar::ScrollByPixel
;
127 fmultiplier
= static_cast<float>(multiplier
);
131 scrollbar_
->scroll(direction
, granularity
, fmultiplier
);
134 PP_Bool
PPB_Scrollbar_Impl::PaintInternal(const gfx::Rect
& rect
,
135 PPB_ImageData_Impl
* image
) {
136 ImageDataAutoMapper
mapper(image
);
137 skia::PlatformCanvas
* canvas
= image
->GetPlatformCanvas();
138 if (!canvas
|| !scrollbar_
)
141 canvas
->scale(scale(), scale());
142 scrollbar_
->paint(canvas
, rect
);
146 if (base::win::GetVersion() == base::win::VERSION_XP
)
147 skia::MakeOpaque(canvas
, rect
.x(), rect
.y(), rect
.width(), rect
.height());
153 PP_Bool
PPB_Scrollbar_Impl::HandleEventInternal(
154 const ppapi::InputEventData
& data
) {
155 scoped_ptr
<WebInputEvent
> web_input_event(CreateWebInputEvent(data
));
156 if (!web_input_event
.get() || !scrollbar_
)
159 return PP_FromBool(scrollbar_
->handleInputEvent(*web_input_event
.get()));
162 void PPB_Scrollbar_Impl::SetLocationInternal(const PP_Rect
* location
) {
165 scrollbar_
->setLocation(WebRect(location
->point
.x
,
167 location
->size
.width
,
168 location
->size
.height
));
171 void PPB_Scrollbar_Impl::valueChanged(WebKit::WebPluginScrollbar
* scrollbar
) {
172 PluginModule
* plugin_module
=
173 HostGlobals::Get()->GetInstance(pp_instance())->module();
177 const PPP_Scrollbar_Dev
* ppp_scrollbar
=
178 static_cast<const PPP_Scrollbar_Dev
*>(plugin_module
->GetPluginInterface(
179 PPP_SCROLLBAR_DEV_INTERFACE
));
180 if (!ppp_scrollbar
) {
181 // Try the old version. This is ok because the old interface is a subset of
182 // the new one, and ValueChanged didn't change.
184 static_cast<const PPP_Scrollbar_Dev
*>(plugin_module
->GetPluginInterface(
185 PPP_SCROLLBAR_DEV_INTERFACE_0_2
));
189 ppp_scrollbar
->ValueChanged(pp_instance(), pp_resource(),
190 scrollbar_
->value());
193 void PPB_Scrollbar_Impl::overlayChanged(WebPluginScrollbar
* scrollbar
) {
194 PluginModule
* plugin_module
=
195 HostGlobals::Get()->GetInstance(pp_instance())->module();
199 const PPP_Scrollbar_Dev
* ppp_scrollbar
=
200 static_cast<const PPP_Scrollbar_Dev
*>(plugin_module
->GetPluginInterface(
201 PPP_SCROLLBAR_DEV_INTERFACE
));
204 ppp_scrollbar
->OverlayChanged(pp_instance(), pp_resource(),
205 PP_FromBool(IsOverlay()));
208 void PPB_Scrollbar_Impl::invalidateScrollbarRect(
209 WebKit::WebPluginScrollbar
* scrollbar
,
210 const WebKit::WebRect
& rect
) {
211 gfx::Rect
gfx_rect(rect
.x
,
215 dirty_
.Union(gfx_rect
);
216 // Can't call into the client to tell them about the invalidate right away,
217 // since the PPB_Scrollbar_Impl code is still in the middle of updating its
219 // Note: we use a WeakPtrFactory here so that a lingering callback can not
220 // modify the lifetime of this object. Otherwise, WebKit::WebPluginScrollbar
221 // could outlive WebKit::WebPluginContainer, which is against its contract.
222 base::MessageLoop::current()->PostTask(
224 base::Bind(&PPB_Scrollbar_Impl::NotifyInvalidate
,
225 weak_ptr_factory_
.GetWeakPtr()));
228 void PPB_Scrollbar_Impl::getTickmarks(
229 WebKit::WebPluginScrollbar
* scrollbar
,
230 WebKit::WebVector
<WebKit::WebRect
>* tick_marks
) const {
231 if (tickmarks_
.empty()) {
232 WebRect
* rects
= NULL
;
233 tick_marks
->assign(rects
, 0);
235 tick_marks
->assign(&tickmarks_
[0], tickmarks_
.size());
239 void PPB_Scrollbar_Impl::NotifyInvalidate() {
240 if (dirty_
.IsEmpty())
243 pp_rect
.point
.x
= dirty_
.x();
244 pp_rect
.point
.y
= dirty_
.y();
245 pp_rect
.size
.width
= dirty_
.width();
246 pp_rect
.size
.height
= dirty_
.height();
247 dirty_
= gfx::Rect();
248 Invalidate(&pp_rect
);
251 } // namespace content