blob: 2e1a919cf9fcbfe2752192eb5382acec4a94f500 [file] [log] [blame]
// Copyright 2014 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 "remoting/client/plugin/pepper_cursor_setter.h"
#include <stdint.h>
#include "base/logging.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/mouse_cursor.h"
#include "remoting/client/empty_cursor_filter.h"
#include "remoting/proto/control.pb.h"
namespace remoting {
PepperCursorSetter::PepperCursorSetter(const pp::InstanceHandle& instance)
: instance_(instance), delegate_stub_(nullptr) {
}
PepperCursorSetter::~PepperCursorSetter() {}
void PepperCursorSetter::SetCursorShape(
const protocol::CursorShapeInfo& cursor_shape) {
if (SetInstanceCursor(cursor_shape)) {
// PPAPI cursor was set successfully, so clear delegate cursor, if any.
if (delegate_stub_) {
delegate_stub_->SetCursorShape(EmptyCursorShape());
}
} else if (delegate_stub_) {
// Clear PPAPI cursor and fall-back to rendering cursor via delegate.
pp::MouseCursor::SetCursor(instance_, PP_MOUSECURSOR_TYPE_NONE);
delegate_stub_->SetCursorShape(cursor_shape);
} else {
// TODO(wez): Fall-back to cropping & re-trying the cursor iff there is no
// delegate and the cursor is >32x32?
DLOG(FATAL) << "Failed to set PPAPI cursor, and no delegate provided.";
}
}
bool PepperCursorSetter::SetInstanceCursor(
const protocol::CursorShapeInfo& cursor_shape) {
// If the cursor is empty then tell PPAPI there is no cursor.
if (IsCursorShapeEmpty(cursor_shape)) {
pp::MouseCursor::SetCursor(instance_, PP_MOUSECURSOR_TYPE_NONE);
return true;
}
// pp::MouseCursor requires image to be in the native format.
if (pp::ImageData::GetNativeImageDataFormat() !=
PP_IMAGEDATAFORMAT_BGRA_PREMUL) {
LOG(WARNING) << "Unable to set cursor shape - native image format is not"
" premultiplied BGRA";
return false;
}
// Create a new ImageData to pass to SetCursor().
pp::Size size(cursor_shape.width(), cursor_shape.height());
pp::Point hotspot(cursor_shape.hotspot_x(), cursor_shape.hotspot_y());
pp::ImageData image(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
if (image.is_null()) {
LOG(WARNING) << "Unable to create cursor image";
return false;
}
// Fill the pixel data and pass the cursor to PPAPI to set.
const int kBytesPerPixel = sizeof(uint32_t);
const uint32_t* src_row_data = reinterpret_cast<const uint32_t*>(
cursor_shape.data().data());
const int bytes_per_row = size.width() * kBytesPerPixel;
uint8_t* dst_row_data = reinterpret_cast<uint8_t*>(image.data());
for (int row = 0; row < size.height(); row++) {
memcpy(dst_row_data, src_row_data, bytes_per_row);
src_row_data += size.width();
dst_row_data += image.stride();
}
return pp::MouseCursor::SetCursor(
instance_, PP_MOUSECURSOR_TYPE_CUSTOM, image, hotspot);
}
} // namespace remoting