PointerController.cpp revision b4ff35df5c04aec71fce7e90a6d6f9ef7180c2ad
1b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown/* 2b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * Copyright (C) 2010 The Android Open Source Project 3b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * 4b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * you may not use this file except in compliance with the License. 6b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * You may obtain a copy of the License at 7b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * 8b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * 10b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * Unless required by applicable law or agreed to in writing, software 11b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * See the License for the specific language governing permissions and 14b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown * limitations under the License. 15b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown */ 16b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 17b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#define LOG_TAG "PointerController" 18b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 19b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown//#define LOG_NDEBUG 0 20b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 21b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown// Log debug messages about pointer updates 22b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#define DEBUG_POINTER_UPDATES 0 23b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 24b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include "PointerController.h" 25b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 26b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <cutils/log.h> 27b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 28b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <SkBitmap.h> 29b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <SkCanvas.h> 30b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <SkColor.h> 31b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <SkPaint.h> 32b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#include <SkXfermode.h> 33b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 34b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownnamespace android { 35b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 36b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown// --- PointerController --- 37b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 38b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff BrownPointerController::PointerController(int32_t pointerLayer) : 39b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mPointerLayer(pointerLayer) { 40b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 41b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 42b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayWidth = -1; 43b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayHeight = -1; 44b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayOrientation = DISPLAY_ORIENTATION_0; 45b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 46b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = 0; 47b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = 0; 48b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.buttonState = 0; 49b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 50b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconBitmap = NULL; 51b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconHotSpotX = 0; 52b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconHotSpotY = 0; 53b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 54b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.wantVisible = false; 55b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.visible = false; 56b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.drawn = false; 57b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 58b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 59b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff BrownPointerController::~PointerController() { 60b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceControl != NULL) { 61b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceControl->clear(); 62b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceControl.clear(); 63b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 64b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 65b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceComposerClient != NULL) { 66b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceComposerClient->dispose(); 67b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceComposerClient.clear(); 68b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 69b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 70b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown delete mLocked.iconBitmap; 71b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 72b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 73b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownbool PointerController::getBounds(float* outMinX, float* outMinY, 74b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown float* outMaxX, float* outMaxY) const { 75b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 76b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 77b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY); 78b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 79b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 80b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownbool PointerController::getBoundsLocked(float* outMinX, float* outMinY, 81b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown float* outMaxX, float* outMaxY) const { 82b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) { 83b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 84b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 85b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 86b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMinX = 0; 87b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMinY = 0; 88b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown switch (mLocked.displayOrientation) { 89b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_90: 90b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_270: 91b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMaxX = mLocked.displayHeight; 92b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMaxY = mLocked.displayWidth; 93b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 94b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown default: 95b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMaxX = mLocked.displayWidth; 96b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outMaxY = mLocked.displayHeight; 97b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 98b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 99b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return true; 100b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 101b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 102b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::move(float deltaX, float deltaY) { 103b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#if DEBUG_POINTER_UPDATES 104b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); 105b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#endif 106b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (deltaX == 0.0f && deltaY == 0.0f) { 107b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return; 108b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 109b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 110b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 111b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 112b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY); 113b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 114b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 115b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setButtonState(uint32_t buttonState) { 116b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#if DEBUG_POINTER_UPDATES 117b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGD("Set button state 0x%08x", buttonState); 118b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#endif 119b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 120b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 121b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mLocked.buttonState != buttonState) { 122b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.buttonState = buttonState; 123b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.wantVisible = true; 124b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown updateLocked(); 125b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 126b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 127b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 128b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownuint32_t PointerController::getButtonState() const { 129b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 130b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 131b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return mLocked.buttonState; 132b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 133b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 134b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setPosition(float x, float y) { 135b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#if DEBUG_POINTER_UPDATES 136b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y); 137b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown#endif 138b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 139b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 140b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown setPositionLocked(x, y); 141b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 142b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 143b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setPositionLocked(float x, float y) { 144b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown float minX, minY, maxX, maxY; 145b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { 146b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (x <= minX) { 147b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = minX; 148b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else if (x >= maxX) { 149b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = maxX; 150b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else { 151b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = x; 152b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 153b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (y <= minY) { 154b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = minY; 155b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else if (y >= maxY) { 156b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = maxY; 157b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else { 158b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = y; 159b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 160b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.wantVisible = true; 161b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown updateLocked(); 162b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 163b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 164b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 165b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::getPosition(float* outX, float* outY) const { 166b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 167b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 168b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outX = mLocked.pointerX; 169b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown *outY = mLocked.pointerY; 170b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 171b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 172b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::updateLocked() { 173b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap; 174b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 175b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (wantVisibleAndHavePointerIcon) { 176b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // Want the pointer to be visible. 177b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // Ensure the surface is created and drawn. 178b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!createSurfaceIfNeededLocked() || !drawPointerIfNeededLocked()) { 179b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return; 180b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 181b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else { 182b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // Don't want the pointer to be visible. 183b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // If it is not visible then we are done. 184b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceControl == NULL || !mLocked.visible) { 185b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return; 186b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 187b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 188b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 189b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status_t status = mSurfaceComposerClient->openTransaction(); 190b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 191b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error opening surface transaction to update pointer surface."); 192b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return; 193b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 194b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 195b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (wantVisibleAndHavePointerIcon) { 196b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceControl->setPosition( 197b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX - mLocked.iconHotSpotX, 198b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY - mLocked.iconHotSpotY); 199b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 200b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d moving pointer surface.", status); 201b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown goto CloseTransaction; 202b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 203b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 204b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!mLocked.visible) { 205b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceControl->setLayer(mPointerLayer); 206b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 207b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d setting pointer surface layer.", status); 208b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown goto CloseTransaction; 209b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 210b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 211b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceControl->show(mPointerLayer); 212b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 213b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d showing pointer surface.", status); 214b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown goto CloseTransaction; 215b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 216b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 217b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.visible = true; 218b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 219b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else { 220b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mLocked.visible) { 221b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceControl->hide(); 222b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 223b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d hiding pointer surface.", status); 224b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown goto CloseTransaction; 225b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 226b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 227b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.visible = false; 228b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 229b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 230b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 231b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff BrownCloseTransaction: 232b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceComposerClient->closeTransaction(); 233b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 234b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error closing surface transaction to update pointer surface."); 235b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 236b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 237b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 238b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setDisplaySize(int32_t width, int32_t height) { 239b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 240b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 241b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mLocked.displayWidth != width || mLocked.displayHeight != height) { 242b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayWidth = width; 243b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayHeight = height; 244b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 245b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown float minX, minY, maxX, maxY; 246b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) { 247b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = (minX + maxX) * 0.5f; 248b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = (minY + maxY) * 0.5f; 249b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } else { 250b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = 0; 251b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = 0; 252b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 253b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 254b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown updateLocked(); 255b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 256b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 257b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 258b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setDisplayOrientation(int32_t orientation) { 259b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 260b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 261b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mLocked.displayOrientation != orientation) { 262b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown float absoluteX, absoluteY; 263b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 264b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // Map from oriented display coordinates to absolute display coordinates. 265b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown switch (mLocked.displayOrientation) { 266b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_90: 267b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteX = mLocked.displayWidth - mLocked.pointerY; 268b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteY = mLocked.pointerX; 269b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 270b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_180: 271b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteX = mLocked.displayWidth - mLocked.pointerX; 272b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteY = mLocked.displayHeight - mLocked.pointerY; 273b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 274b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_270: 275b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteX = mLocked.pointerY; 276b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteY = mLocked.displayHeight - mLocked.pointerX; 277b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 278b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown default: 279b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteX = mLocked.pointerX; 280b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown absoluteY = mLocked.pointerY; 281b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 282b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 283b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 284b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // Map from absolute display coordinates to oriented display coordinates. 285b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown switch (orientation) { 286b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_90: 287b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = absoluteY; 288b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = mLocked.displayWidth - absoluteX; 289b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 290b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_180: 291b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = mLocked.displayWidth - absoluteX; 292b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = mLocked.displayHeight - absoluteY; 293b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 294b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown case DISPLAY_ORIENTATION_270: 295b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = mLocked.displayHeight - absoluteY; 296b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = absoluteX; 297b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 298b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown default: 299b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerX = absoluteX; 300b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.pointerY = absoluteY; 301b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown break; 302b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 303b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 304b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.displayOrientation = orientation; 305b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 306b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown updateLocked(); 307b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 308b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 309b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 310b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownvoid PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) { 311b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown AutoMutex _l(mLock); 312b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 313b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown delete mLocked.iconBitmap; 314b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconBitmap = bitmap ? new SkBitmap(*bitmap) : NULL; 315b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconHotSpotX = hotSpotX; 316b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconHotSpotY = hotSpotY; 317b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.drawn = false; 318b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 319b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 320b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownbool PointerController::createSurfaceIfNeededLocked() { 321b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!mLocked.iconBitmap) { 322b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown // If we don't have a pointer icon, then no point allocating a surface now. 323b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 324b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 325b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 326b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceComposerClient == NULL) { 327b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceComposerClient = new SurfaceComposerClient(); 328b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 329b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 330b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceControl == NULL) { 331b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(), 332b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown String8("Pointer Icon"), 0, 333b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.iconBitmap->width(), mLocked.iconBitmap->height(), 334b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown PIXEL_FORMAT_RGBA_8888); 335b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (mSurfaceControl == NULL) { 336b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error creating pointer surface."); 337b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 338b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 339b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 340b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return true; 341b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 342b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 343b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownbool PointerController::drawPointerIfNeededLocked() { 344b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!mLocked.drawn) { 345b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!mLocked.iconBitmap) { 346b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 347b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 348b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 349b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (!resizeSurfaceLocked(mLocked.iconBitmap->width(), mLocked.iconBitmap->height())) { 350b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 351b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 352b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 353b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown sp<Surface> surface = mSurfaceControl->getSurface(); 354b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 355b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown Surface::SurfaceInfo surfaceInfo; 356b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status_t status = surface->lock(&surfaceInfo); 357b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 358b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d locking pointer surface before drawing.", status); 359b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 360b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 361b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 362b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown SkBitmap surfaceBitmap; 363b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format); 364b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, surfaceInfo.w, surfaceInfo.h, bpr); 365b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown surfaceBitmap.setPixels(surfaceInfo.bits); 366b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 367b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown SkCanvas surfaceCanvas; 368b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown surfaceCanvas.setBitmapDevice(surfaceBitmap); 369b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 370b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown SkPaint paint; 371b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown paint.setXfermodeMode(SkXfermode::kSrc_Mode); 372b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown surfaceCanvas.drawBitmap(*mLocked.iconBitmap, 0, 0, &paint); 373b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 374b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = surface->unlockAndPost(); 375b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 376b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d unlocking pointer surface after drawing.", status); 377b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 378b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 379b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 380b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 381b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown mLocked.drawn = true; 382b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return true; 383b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 384b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 385b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brownbool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) { 386b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status_t status = mSurfaceComposerClient->openTransaction(); 387b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 388b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error opening surface transaction to resize pointer surface."); 389b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 390b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 391b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 392b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceControl->setSize(width, height); 393b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 394b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error %d setting pointer surface size.", status); 395b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 396b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 397b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 398b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown status = mSurfaceComposerClient->closeTransaction(); 399b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown if (status) { 400b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown LOGE("Error closing surface transaction to resize pointer surface."); 401b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return false; 402b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown } 403b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 404b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown return true; 405b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} 406b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown 407b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown} // namespace android 408