// 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 "base/logging.h" #include "ppapi/cpp/image_data.h" #include "ppapi/cpp/mouse_cursor.h" #include "remoting/client/plugin/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( cursor_shape.data().data()); const int bytes_per_row = size.width() * kBytesPerPixel; uint8* dst_row_data = reinterpret_cast(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