Add cursor type and hotspot to surface metadata.
Also bootstrap unit tests for PointerController. Need to mark 3 functions of SpriteController virtual so their behaviors can be overridden. Bug: 130822623 Test: SurfaceFlinger can get cursor type and hotspot. Change-Id: I739cd03214364144bb4e22a166ecc7abfd3492fe
This commit is contained in:
@@ -497,11 +497,8 @@ static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
|
||||
|
||||
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
|
||||
|
||||
std::vector<uint8_t> byteData(parcel->dataSize());
|
||||
memcpy(byteData.data(), parcel->data(), parcel->dataSize());
|
||||
|
||||
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
|
||||
transaction->setMetadata(ctrl, id, std::move(byteData));
|
||||
transaction->setMetadata(ctrl, id, *parcel);
|
||||
}
|
||||
|
||||
static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,
|
||||
|
||||
@@ -20,6 +20,7 @@ cc_library_shared {
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libbinder",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libutils",
|
||||
|
||||
@@ -245,7 +245,8 @@ void SpriteController::doUpdateSprites() {
|
||||
if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
|
||||
|| (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
|
||||
| DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
|
||||
| DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID))))) {
|
||||
| DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID
|
||||
| DIRTY_ICON_STYLE))))) {
|
||||
needApplyTransaction = true;
|
||||
|
||||
if (wantSurfaceVisibleAndDrawn
|
||||
@@ -274,6 +275,21 @@ void SpriteController::doUpdateSprites() {
|
||||
update.state.transformationMatrix.dtdy);
|
||||
}
|
||||
|
||||
if (wantSurfaceVisibleAndDrawn
|
||||
&& (becomingVisible
|
||||
|| (update.state.dirty & (DIRTY_HOTSPOT | DIRTY_ICON_STYLE)))) {
|
||||
Parcel p;
|
||||
p.writeInt32(update.state.icon.style);
|
||||
p.writeFloat(update.state.icon.hotSpotX);
|
||||
p.writeFloat(update.state.icon.hotSpotY);
|
||||
|
||||
// Pass cursor metadata in the sprite surface so that when Android is running as a
|
||||
// client OS (e.g. ARC++) the host OS can get the requested cursor metadata and
|
||||
// update mouse cursor in the host OS.
|
||||
t.setMetadata(
|
||||
update.state.surfaceControl, METADATA_MOUSE_CURSOR, p);
|
||||
}
|
||||
|
||||
int32_t surfaceLayer = mOverlayLayer + update.state.layer;
|
||||
if (wantSurfaceVisibleAndDrawn
|
||||
&& (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
|
||||
@@ -397,9 +413,14 @@ void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) {
|
||||
} else {
|
||||
dirty = DIRTY_BITMAP;
|
||||
}
|
||||
|
||||
if (mLocked.state.icon.style != icon.style) {
|
||||
mLocked.state.icon.style = icon.style;
|
||||
dirty |= DIRTY_ICON_STYLE;
|
||||
}
|
||||
} else if (mLocked.state.icon.isValid()) {
|
||||
mLocked.state.icon.bitmap.reset();
|
||||
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
|
||||
dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE;
|
||||
} else {
|
||||
return; // setting to invalid icon and already invalid so nothing to do
|
||||
}
|
||||
|
||||
@@ -55,11 +55,12 @@ struct SpriteTransformationMatrix {
|
||||
* Icon that a sprite displays, including its hotspot.
|
||||
*/
|
||||
struct SpriteIcon {
|
||||
inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
|
||||
inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
|
||||
bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
|
||||
inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
|
||||
inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
|
||||
bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
|
||||
|
||||
SkBitmap bitmap;
|
||||
int32_t style;
|
||||
float hotSpotX;
|
||||
float hotSpotY;
|
||||
|
||||
@@ -69,11 +70,12 @@ struct SpriteIcon {
|
||||
bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(),
|
||||
0, 0);
|
||||
}
|
||||
return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
|
||||
return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY);
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
bitmap.reset();
|
||||
style = 0;
|
||||
hotSpotX = 0;
|
||||
hotSpotY = 0;
|
||||
}
|
||||
@@ -149,15 +151,15 @@ public:
|
||||
SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
|
||||
|
||||
/* Creates a new sprite, initially invisible. */
|
||||
sp<Sprite> createSprite();
|
||||
virtual sp<Sprite> createSprite();
|
||||
|
||||
/* Opens or closes a transaction to perform a batch of sprite updates as part of
|
||||
* a single operation such as setPosition and setAlpha. It is not necessary to
|
||||
* open a transaction when updating a single property.
|
||||
* Calls to openTransaction() nest and must be matched by an equal number
|
||||
* of calls to closeTransaction(). */
|
||||
void openTransaction();
|
||||
void closeTransaction();
|
||||
virtual void openTransaction();
|
||||
virtual void closeTransaction();
|
||||
|
||||
private:
|
||||
enum {
|
||||
@@ -174,6 +176,7 @@ private:
|
||||
DIRTY_VISIBILITY = 1 << 5,
|
||||
DIRTY_HOTSPOT = 1 << 6,
|
||||
DIRTY_DISPLAY_ID = 1 << 7,
|
||||
DIRTY_ICON_STYLE = 1 << 8,
|
||||
};
|
||||
|
||||
/* Describes the state of a sprite.
|
||||
|
||||
7
libs/input/TEST_MAPPING
Normal file
7
libs/input/TEST_MAPPING
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "libinputservice_test"
|
||||
}
|
||||
]
|
||||
}
|
||||
45
libs/input/tests/Android.bp
Normal file
45
libs/input/tests/Android.bp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2019 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
cc_test {
|
||||
name: "libinputservice_test",
|
||||
srcs: [
|
||||
"PointerController_test.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libinputservice",
|
||||
"libgui",
|
||||
"libhwui",
|
||||
"libutils",
|
||||
],
|
||||
static_libs: [
|
||||
"libgmock",
|
||||
"libgtest",
|
||||
],
|
||||
header_libs: [
|
||||
"libbase_headers",
|
||||
"libinputflinger_headers",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/base/libs",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
],
|
||||
}
|
||||
215
libs/input/tests/PointerController_test.cpp
Normal file
215
libs/input/tests/PointerController_test.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mocks/MockSprite.h"
|
||||
#include "mocks/MockSpriteController.h"
|
||||
|
||||
#include <input/PointerController.h>
|
||||
#include <input/SpriteController.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
|
||||
enum TestCursorType {
|
||||
CURSOR_TYPE_DEFAULT = 0,
|
||||
CURSOR_TYPE_HOVER,
|
||||
CURSOR_TYPE_TOUCH,
|
||||
CURSOR_TYPE_ANCHOR,
|
||||
CURSOR_TYPE_ADDITIONAL_1,
|
||||
CURSOR_TYPE_ADDITIONAL_2,
|
||||
CURSOR_TYPE_CUSTOM = -1,
|
||||
};
|
||||
|
||||
using ::testing::AllOf;
|
||||
using ::testing::Field;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Mock;
|
||||
using ::testing::Return;
|
||||
using ::testing::Test;
|
||||
|
||||
std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
|
||||
return std::make_pair(type * 10, type * 10 + 5);
|
||||
}
|
||||
|
||||
class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
|
||||
public:
|
||||
virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) override;
|
||||
virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) override;
|
||||
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
|
||||
std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) override;
|
||||
virtual int32_t getDefaultPointerIconId() override;
|
||||
virtual int32_t getCustomPointerIconId() override;
|
||||
|
||||
private:
|
||||
void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
|
||||
};
|
||||
|
||||
void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
|
||||
loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
|
||||
int32_t) {
|
||||
loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
|
||||
loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
|
||||
loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
|
||||
}
|
||||
|
||||
void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
|
||||
std::map<int32_t, SpriteIcon>* outResources,
|
||||
std::map<int32_t, PointerAnimation>* outAnimationResources,
|
||||
int32_t) {
|
||||
SpriteIcon icon;
|
||||
PointerAnimation anim;
|
||||
|
||||
for (int32_t cursorType : {CURSOR_TYPE_ADDITIONAL_1, CURSOR_TYPE_ADDITIONAL_2}) {
|
||||
loadPointerIconForType(&icon, cursorType);
|
||||
anim.animationFrames.push_back(icon);
|
||||
anim.durationPerFrame = 10;
|
||||
(*outResources)[cursorType] = icon;
|
||||
(*outAnimationResources)[cursorType] = anim;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
|
||||
return CURSOR_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
int32_t MockPointerControllerPolicyInterface::getCustomPointerIconId() {
|
||||
return CURSOR_TYPE_CUSTOM;
|
||||
}
|
||||
|
||||
void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
|
||||
icon->style = type;
|
||||
std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
|
||||
icon->hotSpotX = hotSpot.first;
|
||||
icon->hotSpotY = hotSpot.second;
|
||||
}
|
||||
|
||||
class PointerControllerTest : public Test {
|
||||
protected:
|
||||
PointerControllerTest();
|
||||
~PointerControllerTest();
|
||||
|
||||
sp<MockSprite> mPointerSprite;
|
||||
sp<MockPointerControllerPolicyInterface> mPolicy;
|
||||
sp<MockSpriteController> mSpriteController;
|
||||
sp<PointerController> mPointerController;
|
||||
|
||||
private:
|
||||
void loopThread();
|
||||
|
||||
std::atomic<bool> mRunning = true;
|
||||
class MyLooper : public Looper {
|
||||
public:
|
||||
MyLooper() : Looper(false) {}
|
||||
~MyLooper() = default;
|
||||
};
|
||||
sp<MyLooper> mLooper;
|
||||
std::thread mThread;
|
||||
};
|
||||
|
||||
PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
|
||||
mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
|
||||
|
||||
mSpriteController = new NiceMock<MockSpriteController>(mLooper);
|
||||
mPolicy = new MockPointerControllerPolicyInterface();
|
||||
|
||||
EXPECT_CALL(*mSpriteController, createSprite())
|
||||
.WillOnce(Return(mPointerSprite));
|
||||
|
||||
mPointerController = new PointerController(mPolicy, mLooper, mSpriteController);
|
||||
|
||||
DisplayViewport viewport;
|
||||
viewport.displayId = ADISPLAY_ID_DEFAULT;
|
||||
viewport.logicalRight = 1600;
|
||||
viewport.logicalBottom = 1200;
|
||||
viewport.physicalRight = 800;
|
||||
viewport.physicalBottom = 600;
|
||||
viewport.deviceWidth = 400;
|
||||
viewport.deviceHeight = 300;
|
||||
mPointerController->setDisplayViewport(viewport);
|
||||
}
|
||||
|
||||
PointerControllerTest::~PointerControllerTest() {
|
||||
mRunning.store(false, std::memory_order_relaxed);
|
||||
mThread.join();
|
||||
}
|
||||
|
||||
void PointerControllerTest::loopThread() {
|
||||
Looper::setForThread(mLooper);
|
||||
|
||||
while (mRunning.load(std::memory_order_relaxed)) {
|
||||
mLooper->pollOnce(100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
|
||||
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
|
||||
|
||||
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
|
||||
EXPECT_CALL(*mPointerSprite, setVisible(true));
|
||||
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
|
||||
EXPECT_CALL(*mPointerSprite, setIcon(
|
||||
AllOf(
|
||||
Field(&SpriteIcon::style, CURSOR_TYPE_DEFAULT),
|
||||
Field(&SpriteIcon::hotSpotX, hotspot.first),
|
||||
Field(&SpriteIcon::hotSpotY, hotspot.second))));
|
||||
mPointerController->reloadPointerResources();
|
||||
}
|
||||
|
||||
TEST_F(PointerControllerTest, updatePointerIcon) {
|
||||
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
|
||||
|
||||
int32_t type = CURSOR_TYPE_ADDITIONAL_1;
|
||||
std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
|
||||
EXPECT_CALL(*mPointerSprite, setVisible(true));
|
||||
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
|
||||
EXPECT_CALL(*mPointerSprite, setIcon(
|
||||
AllOf(
|
||||
Field(&SpriteIcon::style, type),
|
||||
Field(&SpriteIcon::hotSpotX, hotspot.first),
|
||||
Field(&SpriteIcon::hotSpotY, hotspot.second))));
|
||||
mPointerController->updatePointerIcon(type);
|
||||
}
|
||||
|
||||
TEST_F(PointerControllerTest, setCustomPointerIcon) {
|
||||
mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
|
||||
|
||||
int32_t style = CURSOR_TYPE_CUSTOM;
|
||||
float hotSpotX = 15;
|
||||
float hotSpotY = 20;
|
||||
|
||||
SpriteIcon icon;
|
||||
icon.style = style;
|
||||
icon.hotSpotX = hotSpotX;
|
||||
icon.hotSpotY = hotSpotY;
|
||||
|
||||
EXPECT_CALL(*mPointerSprite, setVisible(true));
|
||||
EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
|
||||
EXPECT_CALL(*mPointerSprite, setIcon(
|
||||
AllOf(
|
||||
Field(&SpriteIcon::style, style),
|
||||
Field(&SpriteIcon::hotSpotX, hotSpotX),
|
||||
Field(&SpriteIcon::hotSpotY, hotSpotY))));
|
||||
mPointerController->setCustomPointerIcon(icon);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
41
libs/input/tests/mocks/MockSprite.h
Normal file
41
libs/input/tests/mocks/MockSprite.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MOCK_SPRITE_H
|
||||
#define _MOCK_SPRITE_H
|
||||
|
||||
#include <input/SpriteController.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class MockSprite : public Sprite {
|
||||
public:
|
||||
virtual ~MockSprite() = default;
|
||||
|
||||
MOCK_METHOD(void, setIcon, (const SpriteIcon& icon), (override));
|
||||
MOCK_METHOD(void, setVisible, (bool), (override));
|
||||
MOCK_METHOD(void, setPosition, (float, float), (override));
|
||||
MOCK_METHOD(void, setLayer, (int32_t), (override));
|
||||
MOCK_METHOD(void, setAlpha, (float), (override));
|
||||
MOCK_METHOD(void, setTransformationMatrix, (const SpriteTransformationMatrix&), (override));
|
||||
MOCK_METHOD(void, setDisplayId, (int32_t), (override));
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _MOCK_SPRITE_H
|
||||
39
libs/input/tests/mocks/MockSpriteController.h
Normal file
39
libs/input/tests/mocks/MockSpriteController.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MOCK_SPRITE_CONTROLLER_H
|
||||
#define _MOCK_SPRITE_CONTROLLER_H
|
||||
|
||||
#include "MockSprite.h"
|
||||
|
||||
#include <input/SpriteController.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class MockSpriteController : public SpriteController {
|
||||
|
||||
public:
|
||||
MockSpriteController(sp<Looper> looper) : SpriteController(looper, 0) {}
|
||||
~MockSpriteController() {}
|
||||
|
||||
MOCK_METHOD(sp<Sprite>, createSprite, (), (override));
|
||||
MOCK_METHOD(void, openTransaction, (), (override));
|
||||
MOCK_METHOD(void, closeTransaction, (), (override));
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _MOCK_SPRITE_CONTROLLER_H
|
||||
@@ -165,6 +165,7 @@ static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextOb
|
||||
outPointerIcon->bitmap.readPixels(bitmapCopy->info(), bitmapCopy->getPixels(),
|
||||
bitmapCopy->rowBytes(), 0, 0);
|
||||
}
|
||||
outSpriteIcon->style = outPointerIcon->style;
|
||||
outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX;
|
||||
outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY;
|
||||
}
|
||||
@@ -1252,7 +1253,8 @@ void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
|
||||
status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
|
||||
displayContext.get(), &pointerIcon);
|
||||
if (!status && !pointerIcon.isNullIcon()) {
|
||||
*icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
|
||||
*icon = SpriteIcon(
|
||||
pointerIcon.bitmap, pointerIcon.style, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
|
||||
} else {
|
||||
*icon = SpriteIcon();
|
||||
}
|
||||
@@ -1293,10 +1295,12 @@ void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIc
|
||||
milliseconds_to_nanoseconds(pointerIcon.durationPerFrame);
|
||||
animationData.animationFrames.reserve(numFrames);
|
||||
animationData.animationFrames.push_back(SpriteIcon(
|
||||
pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY));
|
||||
pointerIcon.bitmap, pointerIcon.style,
|
||||
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
|
||||
for (size_t i = 0; i < numFrames - 1; ++i) {
|
||||
animationData.animationFrames.push_back(SpriteIcon(
|
||||
pointerIcon.bitmapFrames[i], pointerIcon.hotSpotX, pointerIcon.hotSpotY));
|
||||
pointerIcon.bitmapFrames[i], pointerIcon.style,
|
||||
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1711,6 +1715,7 @@ static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
|
||||
pointerIcon.bitmap.readPixels(spriteInfo, spriteIcon.bitmap.getPixels(),
|
||||
spriteIcon.bitmap.rowBytes(), 0, 0);
|
||||
}
|
||||
spriteIcon.style = pointerIcon.style;
|
||||
spriteIcon.hotSpotX = pointerIcon.hotSpotX;
|
||||
spriteIcon.hotSpotY = pointerIcon.hotSpotY;
|
||||
im->setCustomPointerIcon(spriteIcon);
|
||||
|
||||
Reference in New Issue
Block a user