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/event_conversion.h"
11 #include "content/renderer/pepper/host_globals.h"
12 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
13 #include "content/renderer/pepper/plugin_module.h"
14 #include "content/renderer/pepper/ppb_image_data_impl.h"
15 #include "ppapi/c/dev/ppp_scrollbar_dev.h"
16 #include "ppapi/c/pp_bool.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 blink::WebInputEvent
;
32 using blink::WebScrollbar
;
33 using blink::WebPluginScrollbar
;
38 PP_Resource
PPB_Scrollbar_Impl::Create(PP_Instance instance
, bool vertical
) {
39 scoped_refptr
<PPB_Scrollbar_Impl
> scrollbar(new PPB_Scrollbar_Impl(instance
));
40 scrollbar
->Init(vertical
);
41 return scrollbar
->GetReference();
44 PPB_Scrollbar_Impl::PPB_Scrollbar_Impl(PP_Instance instance
)
45 : PPB_Widget_Impl(instance
), weak_ptr_factory_(this) {}
47 PPB_Scrollbar_Impl::~PPB_Scrollbar_Impl() {}
49 void PPB_Scrollbar_Impl::Init(bool vertical
) {
50 PepperPluginInstanceImpl
* plugin_instance
=
51 HostGlobals::Get()->GetInstance(pp_instance());
54 scrollbar_
.reset(WebPluginScrollbar::createForPlugin(
55 vertical
? WebScrollbar::Vertical
: WebScrollbar::Horizontal
,
56 plugin_instance
->container(),
57 static_cast<blink::WebPluginScrollbarClient
*>(this)));
60 PPB_Scrollbar_API
* PPB_Scrollbar_Impl::AsPPB_Scrollbar_API() { return this; }
62 void PPB_Scrollbar_Impl::InstanceWasDeleted() { scrollbar_
.reset(); }
64 uint32_t PPB_Scrollbar_Impl::GetThickness() {
65 return WebPluginScrollbar::defaultThickness();
68 bool PPB_Scrollbar_Impl::IsOverlay() { return scrollbar_
->isOverlay(); }
70 uint32_t PPB_Scrollbar_Impl::GetValue() { return scrollbar_
->value(); }
72 void PPB_Scrollbar_Impl::SetValue(uint32_t value
) {
74 scrollbar_
->setValue(value
);
77 void PPB_Scrollbar_Impl::SetDocumentSize(uint32_t size
) {
79 scrollbar_
->setDocumentSize(size
);
82 void PPB_Scrollbar_Impl::SetTickMarks(const PP_Rect
* tick_marks
,
86 tickmarks_
.resize(count
);
87 for (uint32 i
= 0; i
< count
; ++i
) {
88 tickmarks_
[i
] = WebRect(tick_marks
[i
].point
.x
,
89 tick_marks
[i
].point
.y
,
90 tick_marks
[i
].size
.width
,
91 tick_marks
[i
].size
.height
);
94 PP_Rect rect
= location();
98 void PPB_Scrollbar_Impl::ScrollBy(PP_ScrollBy_Dev unit
, int32_t multiplier
) {
102 WebScrollbar::ScrollDirection direction
= multiplier
>= 0
103 ? WebScrollbar::ScrollForward
104 : WebScrollbar::ScrollBackward
;
105 float fmultiplier
= 1.0;
107 WebScrollbar::ScrollGranularity granularity
;
108 if (unit
== PP_SCROLLBY_LINE
) {
109 granularity
= WebScrollbar::ScrollByLine
;
110 } else if (unit
== PP_SCROLLBY_PAGE
) {
111 granularity
= WebScrollbar::ScrollByPage
;
112 } else if (unit
== PP_SCROLLBY_DOCUMENT
) {
113 granularity
= WebScrollbar::ScrollByDocument
;
115 granularity
= WebScrollbar::ScrollByPixel
;
116 fmultiplier
= static_cast<float>(multiplier
);
120 scrollbar_
->scroll(direction
, granularity
, fmultiplier
);
123 PP_Bool
PPB_Scrollbar_Impl::PaintInternal(const gfx::Rect
& rect
,
124 PPB_ImageData_Impl
* image
) {
125 ImageDataAutoMapper
mapper(image
);
126 skia::PlatformCanvas
* canvas
= image
->GetPlatformCanvas();
127 if (!canvas
|| !scrollbar_
)
130 canvas
->scale(scale(), scale());
131 scrollbar_
->paint(canvas
, rect
);
135 if (base::win::GetVersion() == base::win::VERSION_XP
)
136 skia::MakeOpaque(canvas
, rect
.x(), rect
.y(), rect
.width(), rect
.height());
142 PP_Bool
PPB_Scrollbar_Impl::HandleEventInternal(
143 const ppapi::InputEventData
& data
) {
144 scoped_ptr
<WebInputEvent
> web_input_event(CreateWebInputEvent(data
));
145 if (!web_input_event
.get() || !scrollbar_
)
148 return PP_FromBool(scrollbar_
->handleInputEvent(*web_input_event
.get()));
151 void PPB_Scrollbar_Impl::SetLocationInternal(const PP_Rect
* location
) {
154 scrollbar_
->setLocation(WebRect(location
->point
.x
,
156 location
->size
.width
,
157 location
->size
.height
));
160 void PPB_Scrollbar_Impl::valueChanged(blink::WebPluginScrollbar
* scrollbar
) {
161 PluginModule
* plugin_module
=
162 HostGlobals::Get()->GetInstance(pp_instance())->module();
166 const PPP_Scrollbar_Dev
* ppp_scrollbar
=
167 static_cast<const PPP_Scrollbar_Dev
*>(
168 plugin_module
->GetPluginInterface(PPP_SCROLLBAR_DEV_INTERFACE
));
169 if (!ppp_scrollbar
) {
170 // Try the old version. This is ok because the old interface is a subset of
171 // the new one, and ValueChanged didn't change.
172 ppp_scrollbar
= static_cast<const PPP_Scrollbar_Dev
*>(
173 plugin_module
->GetPluginInterface(PPP_SCROLLBAR_DEV_INTERFACE_0_2
));
177 ppp_scrollbar
->ValueChanged(
178 pp_instance(), pp_resource(), scrollbar_
->value());
181 void PPB_Scrollbar_Impl::overlayChanged(WebPluginScrollbar
* scrollbar
) {
182 PluginModule
* plugin_module
=
183 HostGlobals::Get()->GetInstance(pp_instance())->module();
187 const PPP_Scrollbar_Dev
* ppp_scrollbar
=
188 static_cast<const PPP_Scrollbar_Dev
*>(
189 plugin_module
->GetPluginInterface(PPP_SCROLLBAR_DEV_INTERFACE
));
192 ppp_scrollbar
->OverlayChanged(
193 pp_instance(), pp_resource(), PP_FromBool(IsOverlay()));
196 void PPB_Scrollbar_Impl::invalidateScrollbarRect(
197 blink::WebPluginScrollbar
* scrollbar
,
198 const blink::WebRect
& rect
) {
199 gfx::Rect
gfx_rect(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
200 dirty_
.Union(gfx_rect
);
201 // Can't call into the client to tell them about the invalidate right away,
202 // since the PPB_Scrollbar_Impl code is still in the middle of updating its
204 // Note: we use a WeakPtrFactory here so that a lingering callback can not
205 // modify the lifetime of this object. Otherwise, blink::WebPluginScrollbar
206 // could outlive blink::WebPluginContainer, which is against its contract.
207 base::MessageLoop::current()->PostTask(
209 base::Bind(&PPB_Scrollbar_Impl::NotifyInvalidate
,
210 weak_ptr_factory_
.GetWeakPtr()));
213 void PPB_Scrollbar_Impl::getTickmarks(
214 blink::WebPluginScrollbar
* scrollbar
,
215 blink::WebVector
<blink::WebRect
>* tick_marks
) const {
216 if (tickmarks_
.empty()) {
217 WebRect
* rects
= NULL
;
218 tick_marks
->assign(rects
, 0);
220 tick_marks
->assign(&tickmarks_
[0], tickmarks_
.size());
224 void PPB_Scrollbar_Impl::NotifyInvalidate() {
225 if (dirty_
.IsEmpty())
228 pp_rect
.point
.x
= dirty_
.x();
229 pp_rect
.point
.y
= dirty_
.y();
230 pp_rect
.size
.width
= dirty_
.width();
231 pp_rect
.size
.height
= dirty_
.height();
232 dirty_
= gfx::Rect();
233 Invalidate(&pp_rect
);
236 } // namespace content