1 // Copyright 2014 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 "remoting/client/plugin/pepper_cursor_setter.h"
7 #include "base/logging.h"
8 #include "ppapi/cpp/image_data.h"
9 #include "ppapi/cpp/mouse_cursor.h"
10 #include "remoting/client/plugin/empty_cursor_filter.h"
11 #include "remoting/proto/control.pb.h"
15 PepperCursorSetter::PepperCursorSetter(const pp::InstanceHandle
& instance
)
16 : instance_(instance
), delegate_stub_(nullptr) {
19 PepperCursorSetter::~PepperCursorSetter() {}
21 void PepperCursorSetter::SetCursorShape(
22 const protocol::CursorShapeInfo
& cursor_shape
) {
23 if (SetInstanceCursor(cursor_shape
)) {
24 // PPAPI cursor was set successfully, so clear delegate cursor, if any.
26 delegate_stub_
->SetCursorShape(EmptyCursorShape());
28 } else if (delegate_stub_
) {
29 // Clear PPAPI cursor and fall-back to rendering cursor via delegate.
30 pp::MouseCursor::SetCursor(instance_
, PP_MOUSECURSOR_TYPE_NONE
);
31 delegate_stub_
->SetCursorShape(cursor_shape
);
33 // TODO(wez): Fall-back to cropping & re-trying the cursor iff there is no
34 // delegate and the cursor is >32x32?
35 DLOG(FATAL
) << "Failed to set PPAPI cursor, and no delegate provided.";
39 bool PepperCursorSetter::SetInstanceCursor(
40 const protocol::CursorShapeInfo
& cursor_shape
) {
41 // If the cursor is empty then tell PPAPI there is no cursor.
42 if (IsCursorShapeEmpty(cursor_shape
)) {
43 pp::MouseCursor::SetCursor(instance_
, PP_MOUSECURSOR_TYPE_NONE
);
47 // pp::MouseCursor requires image to be in the native format.
48 if (pp::ImageData::GetNativeImageDataFormat() !=
49 PP_IMAGEDATAFORMAT_BGRA_PREMUL
) {
50 LOG(WARNING
) << "Unable to set cursor shape - native image format is not"
51 " premultiplied BGRA";
55 // Create a new ImageData to pass to SetCursor().
56 pp::Size
size(cursor_shape
.width(), cursor_shape
.height());
57 pp::Point
hotspot(cursor_shape
.hotspot_x(), cursor_shape
.hotspot_y());
58 pp::ImageData
image(instance_
, PP_IMAGEDATAFORMAT_BGRA_PREMUL
, size
, false);
59 if (image
.is_null()) {
60 LOG(WARNING
) << "Unable to create cursor image";
64 // Fill the pixel data and pass the cursor to PPAPI to set.
65 const int kBytesPerPixel
= sizeof(uint32_t);
66 const uint32_t* src_row_data
= reinterpret_cast<const uint32_t*>(
67 cursor_shape
.data().data());
68 const int bytes_per_row
= size
.width() * kBytesPerPixel
;
69 uint8
* dst_row_data
= reinterpret_cast<uint8
*>(image
.data());
70 for (int row
= 0; row
< size
.height(); row
++) {
71 memcpy(dst_row_data
, src_row_data
, bytes_per_row
);
72 src_row_data
+= size
.width();
73 dst_row_data
+= image
.stride();
76 return pp::MouseCursor::SetCursor(
77 instance_
, PP_MOUSECURSOR_TYPE_CUSTOM
, image
, hotspot
);
80 } // namespace remoting