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