Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6dbfdd3 authored by Jeff Brown's avatar Jeff Brown Committed by Jeff Brown
Browse files

Add a sprite controller. (DO NOT MERGE)

Refactored PointerController to extract the surface management
code to a new component called a SpriteController so that it can
be used to move finger tracking spots around the screen as well.
The SpriteController is designed to fully decouple the client from
any latency introduced by surface transactions and drawing.
All sprite updates are performed asynchronously on the Looper using
a copy of the sprite state.

Added a stub SpotController implementation for touch pad UX.
It will be implemented in a subsequent patch.

Fixed a little bug in pointer orientation changes when entering
DISPLAY_ORIENTATION_90 the x offset was clobbered.

Change-Id: I6d59d80df9af61e93af50290e7776337d10c9d5a
parent 5ced76a1
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ LOCAL_SRC_FILES:= \
    InputManager.cpp \
    InputReader.cpp \
    InputWindow.cpp \
    PointerController.cpp
    PointerController.cpp \
    SpotController.cpp \
    SpriteController.cpp

LOCAL_SHARED_LIBRARIES := \
    libcutils \
+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "EventHub.h"
#include "InputDispatcher.h"
#include "PointerController.h"
#include "SpotController.h"

#include <ui/Input.h>
#include <ui/DisplayInfo.h>
@@ -89,6 +90,9 @@ public:

    /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;

    /* Gets a spot controller associated with the specified touch pad device. */
    virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId) = 0;
};


+19 −193
Original line number Diff line number Diff line
@@ -49,8 +49,11 @@ static const nsecs_t FADE_FRAME_INTERVAL = 1000000000LL / 60;
static const float FADE_DECAY_PER_FRAME = float(FADE_FRAME_INTERVAL) / FADE_DURATION;


PointerController::PointerController(const sp<Looper>& looper, int32_t pointerLayer) :
        mLooper(looper), mPointerLayer(pointerLayer) {
PointerController::PointerController(const sp<Looper>& looper,
        const sp<SpriteController>& spriteController) :
        mLooper(looper), mSpriteController(spriteController) {
    mHandler = new WeakMessageHandler(this);

    AutoMutex _l(mLock);

    mLocked.displayWidth = -1;
@@ -61,34 +64,20 @@ PointerController::PointerController(const sp<Looper>& looper, int32_t pointerLa
    mLocked.pointerY = 0;
    mLocked.buttonState = 0;

    mLocked.iconBitmap = NULL;
    mLocked.iconHotSpotX = 0;
    mLocked.iconHotSpotY = 0;

    mLocked.fadeAlpha = 1;
    mLocked.inactivityFadeDelay = INACTIVITY_FADE_DELAY_NORMAL;

    mLocked.wantVisible = false;
    mLocked.visible = false;
    mLocked.drawn = false;

    mHandler = new WeakMessageHandler(this);
    mLocked.sprite = mSpriteController->createSprite();
}

PointerController::~PointerController() {
    mLooper->removeMessages(mHandler);

    if (mSurfaceControl != NULL) {
        mSurfaceControl->clear();
        mSurfaceControl.clear();
    }

    if (mSurfaceComposerClient != NULL) {
        mSurfaceComposerClient->dispose();
        mSurfaceComposerClient.clear();
    }
    AutoMutex _l(mLock);

    delete mLocked.iconBitmap;
    mLocked.sprite.clear();
}

bool PointerController::getBounds(float* outMinX, float* outMinY,
@@ -214,75 +203,11 @@ void PointerController::setInactivityFadeDelay(InactivityFadeDelay inactivityFad
}

void PointerController::updateLocked() {
    bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap;

    if (wantVisibleAndHavePointerIcon) {
        // Want the pointer to be visible.
        // Ensure the surface is created and drawn.
        if (!createSurfaceIfNeededLocked() || !drawPointerIfNeededLocked()) {
            return;
        }
    } else {
        // Don't want the pointer to be visible.
        // If it is not visible then we are done.
        if (mSurfaceControl == NULL || !mLocked.visible) {
            return;
        }
    }

    status_t status = mSurfaceComposerClient->openTransaction();
    if (status) {
        LOGE("Error opening surface transaction to update pointer surface.");
        return;
    }

    if (wantVisibleAndHavePointerIcon) {
        status = mSurfaceControl->setPosition(
                mLocked.pointerX - mLocked.iconHotSpotX,
                mLocked.pointerY - mLocked.iconHotSpotY);
        if (status) {
            LOGE("Error %d moving pointer surface.", status);
            goto CloseTransaction;
        }

        status = mSurfaceControl->setAlpha(mLocked.fadeAlpha);
        if (status) {
            LOGE("Error %d setting pointer surface alpha.", status);
            goto CloseTransaction;
        }

        if (!mLocked.visible) {
            status = mSurfaceControl->setLayer(mPointerLayer);
            if (status) {
                LOGE("Error %d setting pointer surface layer.", status);
                goto CloseTransaction;
            }

            status = mSurfaceControl->show(mPointerLayer);
            if (status) {
                LOGE("Error %d showing pointer surface.", status);
                goto CloseTransaction;
            }

            mLocked.visible = true;
        }
    } else {
        if (mLocked.visible) {
            status = mSurfaceControl->hide();
            if (status) {
                LOGE("Error %d hiding pointer surface.", status);
                goto CloseTransaction;
            }

            mLocked.visible = false;
        }
    }

CloseTransaction:
    status = mSurfaceComposerClient->closeTransaction();
    if (status) {
        LOGE("Error closing surface transaction to update pointer surface.");
    }
    mLocked.sprite->openTransaction();
    mLocked.sprite->setPosition(mLocked.pointerX, mLocked.pointerY);
    mLocked.sprite->setAlpha(mLocked.fadeAlpha);
    mLocked.sprite->setVisible(mLocked.visible);
    mLocked.sprite->closeTransaction();
}

void PointerController::setDisplaySize(int32_t width, int32_t height) {
@@ -339,7 +264,7 @@ void PointerController::setDisplayOrientation(int32_t orientation) {
        case DISPLAY_ORIENTATION_90:
            temp = x;
            x = y;
            y = mLocked.displayWidth - x;
            y = mLocked.displayWidth - temp;
            break;
        case DISPLAY_ORIENTATION_180:
            x = mLocked.displayWidth - x;
@@ -365,106 +290,7 @@ void PointerController::setDisplayOrientation(int32_t orientation) {
void PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) {
    AutoMutex _l(mLock);

    if (mLocked.iconBitmap) {
        delete mLocked.iconBitmap;
        mLocked.iconBitmap = NULL;
    }

    if (bitmap) {
        mLocked.iconBitmap = new SkBitmap();
        bitmap->copyTo(mLocked.iconBitmap, SkBitmap::kARGB_8888_Config);
    }

    mLocked.iconHotSpotX = hotSpotX;
    mLocked.iconHotSpotY = hotSpotY;
    mLocked.drawn = false;
}

bool PointerController::createSurfaceIfNeededLocked() {
    if (!mLocked.iconBitmap) {
        // If we don't have a pointer icon, then no point allocating a surface now.
        return false;
    }

    if (mSurfaceComposerClient == NULL) {
        mSurfaceComposerClient = new SurfaceComposerClient();
    }

    if (mSurfaceControl == NULL) {
        mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(),
                String8("Pointer Icon"), 0,
                mLocked.iconBitmap->width(), mLocked.iconBitmap->height(),
                PIXEL_FORMAT_RGBA_8888);
        if (mSurfaceControl == NULL) {
            LOGE("Error creating pointer surface.");
            return false;
        }
    }
    return true;
}

bool PointerController::drawPointerIfNeededLocked() {
    if (!mLocked.drawn) {
        if (!mLocked.iconBitmap) {
            return false;
        }

        if (!resizeSurfaceLocked(mLocked.iconBitmap->width(), mLocked.iconBitmap->height())) {
            return false;
        }

        sp<Surface> surface = mSurfaceControl->getSurface();

        Surface::SurfaceInfo surfaceInfo;
        status_t status = surface->lock(&surfaceInfo);
        if (status) {
            LOGE("Error %d locking pointer surface before drawing.", status);
            return false;
        }

        SkBitmap surfaceBitmap;
        ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
        surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, surfaceInfo.w, surfaceInfo.h, bpr);
        surfaceBitmap.setPixels(surfaceInfo.bits);

        SkCanvas surfaceCanvas;
        surfaceCanvas.setBitmapDevice(surfaceBitmap);

        SkPaint paint;
        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        surfaceCanvas.drawBitmap(*mLocked.iconBitmap, 0, 0, &paint);

        status = surface->unlockAndPost();
        if (status) {
            LOGE("Error %d unlocking pointer surface after drawing.", status);
            return false;
        }
    }

    mLocked.drawn = true;
    return true;
}

bool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) {
    status_t status = mSurfaceComposerClient->openTransaction();
    if (status) {
        LOGE("Error opening surface transaction to resize pointer surface.");
        return false;
    }

    status = mSurfaceControl->setSize(width, height);
    if (status) {
        LOGE("Error %d setting pointer surface size.", status);
        return false;
    }

    status = mSurfaceComposerClient->closeTransaction();
    if (status) {
        LOGE("Error closing surface transaction to resize pointer surface.");
        return false;
    }

    return true;
    mLocked.sprite->setBitmap(bitmap, hotSpotX, hotSpotY);
}

void PointerController::handleMessage(const Message& message) {
@@ -481,7 +307,7 @@ bool PointerController::unfadeBeforeUpdateLocked() {
    sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());

    if (isFadingLocked()) {
        mLocked.wantVisible = true;
        mLocked.visible = true;
        mLocked.fadeAlpha = 1;
        return true; // update required to effect the unfade
    }
@@ -501,11 +327,11 @@ void PointerController::startInactivityFadeDelayLocked() {
}

void PointerController::fadeStepLocked() {
    if (mLocked.wantVisible) {
    if (mLocked.visible) {
        mLocked.fadeAlpha -= FADE_DECAY_PER_FRAME;
        if (mLocked.fadeAlpha < 0) {
            mLocked.fadeAlpha = 0;
            mLocked.wantVisible = false;
            mLocked.visible = false;
        } else {
            sendFadeStepMessageDelayedLocked(FADE_FRAME_INTERVAL);
        }
@@ -514,7 +340,7 @@ void PointerController::fadeStepLocked() {
}

bool PointerController::isFadingLocked() {
    return !mLocked.wantVisible || mLocked.fadeAlpha != 1;
    return !mLocked.visible || mLocked.fadeAlpha != 1;
}

nsecs_t PointerController::getInactivityFadeDelayTimeLocked() {
+7 −19
Original line number Diff line number Diff line
@@ -17,16 +17,14 @@
#ifndef _UI_POINTER_CONTROLLER_H
#define _UI_POINTER_CONTROLLER_H

#include "SpriteController.h"

#include <ui/DisplayInfo.h>
#include <ui/Input.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
#include <utils/String8.h>

#include <surfaceflinger/Surface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/ISurfaceComposer.h>

#include <SkBitmap.h>

namespace android {
@@ -86,7 +84,7 @@ public:
        INACTIVITY_FADE_DELAY_SHORT = 1,
    };

    PointerController(const sp<Looper>& looper, int32_t pointerLayer);
    PointerController(const sp<Looper>& looper, const sp<SpriteController>& spriteController);

    virtual bool getBounds(float* outMinX, float* outMinY,
            float* outMaxX, float* outMaxY) const;
@@ -111,9 +109,8 @@ private:
    mutable Mutex mLock;

    sp<Looper> mLooper;
    int32_t mPointerLayer;
    sp<SurfaceComposerClient> mSurfaceComposerClient;
    sp<SurfaceControl> mSurfaceControl;
    sp<SpriteController> mSpriteController;
    sp<WeakMessageHandler> mHandler;

    struct Locked {
        int32_t displayWidth;
@@ -124,26 +121,17 @@ private:
        float pointerY;
        uint32_t buttonState;

        SkBitmap* iconBitmap;
        float iconHotSpotX;
        float iconHotSpotY;

        float fadeAlpha;
        InactivityFadeDelay inactivityFadeDelay;

        bool wantVisible;
        bool visible;
        bool drawn;
    } mLocked;

    sp<WeakMessageHandler> mHandler;
        sp<Sprite> sprite;
    } mLocked;

    bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
    void setPositionLocked(float x, float y);
    void updateLocked();
    bool createSurfaceIfNeededLocked();
    bool drawPointerIfNeededLocked();
    bool resizeSurfaceLocked(int32_t width, int32_t height);

    void handleMessage(const Message& message);
    bool unfadeBeforeUpdateLocked();
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 "SpotController"

//#define LOG_NDEBUG 0

// Log debug messages about spot updates
#define DEBUG_SPOT_UPDATES 0

#include "SpotController.h"

#include <cutils/log.h>

namespace android {

// --- SpotController ---

SpotController::SpotController(const sp<Looper>& looper,
        const sp<SpriteController>& spriteController) :
        mLooper(looper), mSpriteController(spriteController) {
    mHandler = new WeakMessageHandler(this);
}

SpotController::~SpotController() {
    mLooper->removeMessages(mHandler);
}

void SpotController:: handleMessage(const Message& message) {
}

} // namespace android
Loading