blob: 8f04cfb70469777b09c68b6efbba6207c0e76123 [file] [log] [blame]
/*
* Copyright (C) 2010 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.
*/
#define LOG_TAG "PointerController"
//#define LOG_NDEBUG 0
// Log debug messages about pointer updates
#define DEBUG_POINTER_UPDATES 0
#include "PointerController.h"
#include "MouseCursorController.h"
#include "PointerControllerContext.h"
#include "TouchSpotController.h"
#include <log/log.h>
#include <SkBitmap.h>
#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaint.h>
namespace android {
// --- PointerController ---
std::shared_ptr<PointerController> PointerController::create(
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController) {
// using 'new' to access non-public constructor
std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
new PointerController(policy, looper, spriteController));
/*
* Now we need to hook up the constructed PointerController object to its callbacks.
*
* This must be executed after the constructor but before any other methods on PointerController
* in order to ensure that the fully constructed object is visible on the Looper thread, since
* that may be a different thread than where the PointerController is initially constructed.
*
* Unfortunately, this cannot be done as part of the constructor since we need to hand out
* weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
*/
controller->mContext.setHandlerController(controller);
controller->mContext.setCallbackController(controller);
return controller;
}
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
const sp<SpriteController>& spriteController)
: mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
std::scoped_lock lock(mLock);
mLocked.presentation = Presentation::SPOT;
}
bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
float* outMaxY) const {
return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY);
}
void PointerController::move(float deltaX, float deltaY) {
mCursorController.move(deltaX, deltaY);
}
void PointerController::setButtonState(int32_t buttonState) {
mCursorController.setButtonState(buttonState);
}
int32_t PointerController::getButtonState() const {
return mCursorController.getButtonState();
}
void PointerController::setPosition(float x, float y) {
std::scoped_lock lock(mLock);
mCursorController.setPosition(x, y);
}
void PointerController::getPosition(float* outX, float* outY) const {
mCursorController.getPosition(outX, outY);
}
int32_t PointerController::getDisplayId() const {
return mCursorController.getDisplayId();
}
void PointerController::fade(Transition transition) {
std::scoped_lock lock(mLock);
mCursorController.fade(transition);
}
void PointerController::unfade(Transition transition) {
std::scoped_lock lock(mLock);
mCursorController.unfade(transition);
}
void PointerController::setPresentation(Presentation presentation) {
std::scoped_lock lock(mLock);
if (mLocked.presentation == presentation) {
return;
}
mLocked.presentation = presentation;
if (!mCursorController.isViewportValid()) {
return;
}
if (presentation == Presentation::POINTER) {
mCursorController.getAdditionalMouseResources();
clearSpotsLocked();
}
}
void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
BitSet32 spotIdBits, int32_t displayId) {
std::scoped_lock lock(mLock);
auto it = mLocked.spotControllers.find(displayId);
if (it == mLocked.spotControllers.end()) {
mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
}
mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
}
void PointerController::clearSpots() {
std::scoped_lock lock(mLock);
clearSpotsLocked();
}
void PointerController::clearSpotsLocked() REQUIRES(mLock) {
for (auto& [displayID, spotController] : mLocked.spotControllers) {
spotController.clearSpots();
}
}
void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
mContext.setInactivityTimeout(inactivityTimeout);
}
void PointerController::reloadPointerResources() {
std::scoped_lock lock(mLock);
for (auto& [displayID, spotController] : mLocked.spotControllers) {
spotController.reloadSpotResources();
}
if (mCursorController.resourcesLoaded()) {
bool getAdditionalMouseResources = false;
if (mLocked.presentation == PointerController::Presentation::POINTER) {
getAdditionalMouseResources = true;
}
mCursorController.reloadPointerResources(getAdditionalMouseResources);
}
}
void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
std::scoped_lock lock(mLock);
bool getAdditionalMouseResources = false;
if (mLocked.presentation == PointerController::Presentation::POINTER) {
getAdditionalMouseResources = true;
}
mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
}
void PointerController::updatePointerIcon(int32_t iconId) {
std::scoped_lock lock(mLock);
mCursorController.updatePointerIcon(iconId);
}
void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
std::scoped_lock lock(mLock);
mCursorController.setCustomPointerIcon(icon);
}
void PointerController::doInactivityTimeout() {
fade(Transition::GRADUAL);
}
void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
std::unordered_set<int32_t> displayIdSet;
for (DisplayViewport viewport : viewports) {
displayIdSet.insert(viewport.displayId);
}
std::scoped_lock lock(mLock);
for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
int32_t displayID = it->first;
if (!displayIdSet.count(displayID)) {
/*
* Ensures that an in-progress animation won't dereference
* a null pointer to TouchSpotController.
*/
mContext.removeAnimationCallback(displayID);
it = mLocked.spotControllers.erase(it);
} else {
++it;
}
}
}
} // namespace android