/* * 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 #include #include #include #include #include namespace android { // --- PointerController --- std::shared_ptr PointerController::create( const sp& policy, const sp& looper, const sp& spriteController) { // using 'new' to access non-public constructor std::shared_ptr controller = std::shared_ptr( 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& policy, const sp& looper, const sp& 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& viewports) { std::unordered_set 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