注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

时间记录器

记录我的Linux、Android学习之路

 
 
 

日志

 
 

Software cursor with Gingerbread  

2011-08-18 09:16:33|  分类: Android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

android 2.3 USB鼠标 实现 

Here is the patch that we have done at Always Innovating. Works great!

From a721f7e2ab6e680257cc9cb5ecaee6238e615ff2 Mon Sep 17 00:00:00 2001
From: Gregoire Gentil <gregoire@gregoire-laptop.(none)>
Date: Tue, 15 Mar 2011 22:00:26 +0000
Subject: Adding support of cursor on Gingerbread

---
diff --git a/preprocess/gingerbread/patches/cursor.patch b/preprocess/
gingerbread/patches/cursor.patch
new file mode 100644
index 0000000..09c2673
--- a/dev/null
+++ b/preprocess/gingerbread/patches/cursor.patch
@@ -0,0 +1,518 @@
+--- a/frameworks/base/libs/ui/EventHub.cpp     2011-02-23
18:28:26.856910001 -0800
++++ b/frameworks/base/libs/ui/EventHub.cpp     2011-02-23
18:30:09.006909999 -0800
+@@ -719,7 +719,10 @@
+         LOGV("Getting relative controllers...");
+         if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)),
rel_bitmask) >= 0) {
+             if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y,
rel_bitmask)) {
+-                device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
++                if (test_bit(BTN_LEFT, key_bitmask) &&
test_bit(BTN_RIGHT, key_bitmask))
++                    device->classes |= INPUT_DEVICE_CLASS_MOUSE;
++                else
++                    device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
+             }
+         }
+     }
+--- a/frameworks/base/include/ui/EventHub.h    2011-02-23
18:28:18.846910002 -0800
++++ b/frameworks/base/include/ui/EventHub.h    2011-02-25
19:27:08.626910002 -0800
+@@ -119,6 +119,9 @@
+
+     /* The input device has switches. */
+     INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
++
++    /* The input device is a mouse. */
++    INPUT_DEVICE_CLASS_MOUSE         = 0x00000100,
+ };
+
+ /*
+--- a/frameworks/base/libs/ui/InputReader.cpp  2011-02-23
18:43:07.506909997 -0800
++++ b/frameworks/base/libs/ui/InputReader.cpp  2011-02-28
19:12:15.754663005 -0800
+@@ -340,6 +340,11 @@
+         device->addMapper(new TrackballInputMapper(device,
associatedDisplayId));
+     }
+
++    // Mouse-like devices.
++    if (classes & INPUT_DEVICE_CLASS_MOUSE) {
++        device->addMapper(new MouseInputMapper(device,
associatedDisplayId));
++    }
++
+     // Touchscreen-like devices.
+     if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
+         device->addMapper(new MultiTouchInputMapper(device,
associatedDisplayId));
+@@ -3128,6 +3133,207 @@
+ }
+
+
++// --- MouseInputMapper ---
++
++MouseInputMapper::MouseInputMapper(InputDevice* device, int32_t
associatedDisplayId) :
++        InputMapper(device),
mAssociatedDisplayId(associatedDisplayId) {
++    initializeLocked();
++}
++
++MouseInputMapper::~MouseInputMapper() {
++}
++
++uint32_t MouseInputMapper::getSources() {
++    return AINPUT_SOURCE_MOUSE;
++}
++
++void MouseInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
++    InputMapper::populateDeviceInfo(info);
++}
++
++void MouseInputMapper::dump(String8& dump) {
++    { // acquire lock
++        AutoMutex _l(mLock);
++        dump.append(INDENT2 "Mouse Input Mapper:\n");
++        dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n",
mAssociatedDisplayId);
++        dump.appendFormat(INDENT3 "Down: %s\n",
toString(mLocked.down));
++        dump.appendFormat(INDENT3 "DownTime: %lld\n",
mLocked.downTime);
++    } // release lock
++}
++
++void MouseInputMapper::initializeLocked() {
++    mAccumulator.clear();
++
++    mLocked.down = false;
++    mLocked.downTime = 0;
++
++    int32_t screenWidth;
++    int32_t screenHeight;
++    if (mAssociatedDisplayId < 0 || ! getPolicy()-
>getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight,
NULL)) {
++        mAccumulator.absX = 0;
++        mAccumulator.absY = 0;
++    }else{
++        mAccumulator.absX = screenWidth/2;
++        mAccumulator.absY = screenHeight/2;
++    }
++}
++
++void MouseInputMapper::reset() {
++    for (;;) {
++        { // acquire lock
++            AutoMutex _l(mLock);
++
++            if (! mLocked.down) {
++                initializeLocked();
++                break; // done
++            }
++        } // release lock
++
++        // Synthesize trackball button up event on reset.
++        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
++        mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
++        mAccumulator.btnMouse = false;
++        sync(when);
++    }
++
++    InputMapper::reset();
++}
++
++void MouseInputMapper::process(const RawEvent* rawEvent) {
++    switch (rawEvent->type) {
++    case EV_KEY:
++        switch (rawEvent->scanCode) {
++        case BTN_MOUSE:
++            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
++            mAccumulator.btnMouse = rawEvent->value != 0;
++            sync(rawEvent->when);
++            break;
++        case BTN_RIGHT:
++            // Not handled.
++            break;
++        case BTN_MIDDLE:
++            // Not handled.
++            break;
++        }
++        break;
++
++    case EV_REL:
++        switch (rawEvent->scanCode) {
++        case REL_X:
++            mAccumulator.fields |= Accumulator::FIELD_REL_X;
++            mAccumulator.relX = rawEvent->value;
++            break;
++        case REL_Y:
++            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
++            mAccumulator.relY = rawEvent->value;
++            break;
++        }
++        break;
++
++    case EV_SYN:
++        switch (rawEvent->scanCode) {
++        case SYN_REPORT:
++            sync(rawEvent->when);
++            break;
++        }
++        break;
++    }
++}
++
++void MouseInputMapper::sync(nsecs_t when) {
++    uint32_t fields = mAccumulator.fields;
++    if (fields == 0) {
++        return; // no new state changes, so nothing to do
++    }
++
++    int motionEventAction;
++    PointerCoords pointerCoords;
++    nsecs_t downTime;
++    { // acquire lock
++        AutoMutex _l(mLock);
++
++        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
++        if (downChanged) {
++            if (mAccumulator.btnMouse) {
++                mLocked.down = true;
++                mLocked.downTime = when;
++            } else {
++                mLocked.down = false;
++            }
++            motionEventAction = mLocked.down ?
AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
++        } else {
++            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
++        }
++
++        downTime = mLocked.downTime;
++
++        float x = fields & Accumulator::FIELD_REL_X ?
mAccumulator.relX : 0.0f;
++        float y = fields & Accumulator::FIELD_REL_Y ?
mAccumulator.relY : 0.0f;
++
++        int32_t screenWidth;
++        int32_t screenHeight;
++        int32_t orientation;
++        if (mAssociatedDisplayId  < 0 || ! getPolicy()-
>getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight,
&orientation)) {
++            return;
++        }
++
++        float temp;
++        switch (orientation) {
++        case InputReaderPolicyInterface::ROTATION_90:
++            temp = x;
++            x = y;
++            y = - temp;
++            temp = screenHeight;
++            screenHeight = screenWidth;
++            screenWidth = temp;
++            break;
++
++        case InputReaderPolicyInterface::ROTATION_180:
++            x = - x;
++            y = - y;
++            break;
++
++        case InputReaderPolicyInterface::ROTATION_270:
++            temp = x;
++            x = - y;
++            y = temp;
++            temp = screenHeight;
++            screenHeight = screenWidth;
++            screenWidth = temp;
++            break;
++        }
++
++        mAccumulator.absX = (mAccumulator.absX + x) > screenWidth ?
screenWidth -1 : ((mAccumulator.absX + x) < 0 ? 0 : mAccumulator.absX
+ x);
++        mAccumulator.absY = (mAccumulator.absY + y) > screenHeight ?
screenHeight -1 : ((mAccumulator.absY + y) < 0 ? 0 : mAccumulator.absY
+ y);
++        pointerCoords.x = mAccumulator.absX;
++        pointerCoords.y = mAccumulator.absY;
++        pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
++        pointerCoords.size = 0;
++        pointerCoords.touchMajor = 0;
++        pointerCoords.touchMinor = 0;
++        pointerCoords.toolMajor = 0;
++        pointerCoords.toolMinor = 0;
++        pointerCoords.orientation = 0;
++
++    } // release lock
++
++    int32_t metaState = mContext->getGlobalMetaState();
++    int32_t pointerId = 0;
++    getDispatcher()->notifyMotion(when, getDeviceId(),
AINPUT_SOURCE_MOUSE, 0,
++            motionEventAction, 0, metaState,
AMOTION_EVENT_EDGE_FLAG_NONE,
++            1, &pointerId, &pointerCoords, 1, 1, downTime);
++    mAccumulator.clear();
++}
++
++int32_t MouseInputMapper::getScanCodeState(uint32_t sourceMask,
int32_t scanCode) {
++    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
++        return getEventHub()->getScanCodeState(getDeviceId(),
scanCode);
++    } else {
++        return AKEY_STATE_UNKNOWN;
++    }
++}
++
++
+ // --- SingleTouchInputMapper ---
+
+ SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device,
int32_t associatedDisplayId) :
+--- a/frameworks/base/include/ui/InputReader.h 2011-02-23
18:52:36.096910001 -0800
++++ b/frameworks/base/include/ui/InputReader.h 2011-02-28
13:00:02.434663005 -0800
+@@ -489,6 +489,53 @@
+     void sync(nsecs_t when);
+ };
+
++class MouseInputMapper : public InputMapper {
++public:
++    MouseInputMapper(InputDevice* device, int32_t
associatedDisplayId);
++    virtual ~MouseInputMapper();
++
++    virtual uint32_t getSources();
++    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
++    virtual void dump(String8& dump);
++    virtual void reset();
++    virtual void process(const RawEvent* rawEvent);
++
++    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t
scanCode);
++
++private:
++    Mutex mLock;
++
++    int32_t mAssociatedDisplayId;
++
++    struct Accumulator {
++        enum {
++            FIELD_BTN_MOUSE = 1,
++            FIELD_REL_X = 2,
++            FIELD_REL_Y = 4,
++        };
++
++        uint32_t fields;
++
++        bool btnMouse;
++        int32_t relX;
++        int32_t relY;
++        int32_t absX;
++        int32_t absY;
++
++        inline void clear() {
++            fields = 0;
++        }
++    } mAccumulator;
++
++    struct LockedState {
++        bool down;
++        nsecs_t downTime;
++    } mLocked;
++
++    void initializeLocked();
++
++    void sync(nsecs_t when);
++};
+
+ class TouchInputMapper : public InputMapper {
+ public:
+--- a/frameworks/base/libs/ui/InputDispatcher.cpp      2011-02-24
14:02:25.786910001 -0800
++++ b/frameworks/base/libs/ui/InputDispatcher.cpp      2011-02-28
18:03:27.134662999 -0800
+@@ -731,17 +731,19 @@
+         return true;
+     }
+
+-    bool isPointerEvent = entry->source &
AINPUT_SOURCE_CLASS_POINTER;
++    bool isTouchEvent = ! ((entry->source &
AINPUT_SOURCE_TOUCHSCREEN) ^ AINPUT_SOURCE_TOUCHSCREEN);
++    bool isMouseEvent = ! ((entry->source & AINPUT_SOURCE_MOUSE) ^
AINPUT_SOURCE_MOUSE);
++    bool isDownEvent = (entry->action & AMOTION_EVENT_ACTION_MASK)
== AMOTION_EVENT_ACTION_DOWN;
+
+     // Identify targets.
+     if (! mCurrentInputTargetsValid) {
+         int32_t injectionResult;
+-        if (isPointerEvent) {
+-            // Pointer event.  (eg. touchscreen)
++        if (isTouchEvent || (isMouseEvent && (isDownEvent ||
mTouchState.down))) {
++            // Touch-like event.  (eg. touchscreen or mouse drag-n-
drop )
+             injectionResult =
findTouchedWindowTargetsLocked(currentTime,
+                     entry, nextWakeupTime);
+         } else {
+-            // Non touch event.  (eg. trackball)
++            // Non touch event.  (eg. trackball or mouse simple
move)
+             injectionResult =
findFocusedWindowTargetsLocked(currentTime,
+                     entry, nextWakeupTime);
+         }
+--- a/frameworks/base/core/java/android/view/ViewRoot.java     2011-02-23
11:33:20.516910002 -0800
++++ b/frameworks/base/core/java/android/view/ViewRoot.java     2011-02-28
18:16:23.994663005 -0800
+@@ -215,6 +215,8 @@
+
+     final ViewConfiguration mViewConfiguration;
+
++              static IWindowManager wm;
++
+     /**
+      * see {@link #playSoundEffect(int)}
+      */
+@@ -227,9 +229,8 @@
+             if (!mInitialized) {
+                 try {
+                     InputMethodManager imm =
InputMethodManager.getInstance(mainLooper);
+-                    sWindowSession =
IWindowManager.Stub.asInterface(
+-                            ServiceManager.getService("window"))
+-                            .openSession(imm.getClient(),
imm.getInputContext());
++                    wm =
IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
++                    sWindowSession = wm.openSession(imm.getClient(),
imm.getInputContext());
+                     mInitialized = true;
+                 } catch (RemoteException e) {
+                 }
+@@ -2174,6 +2175,7 @@
+             mTranslator.translateEventInScreenToAppWindow(event);
+         }
+
++        boolean isMouse = ((event.getSource() &
InputDevice.SOURCE_MOUSE) ^ InputDevice.SOURCE_MOUSE) == 0;
+         boolean handled;
+         if (mView != null && mAdded) {
+
+@@ -2837,7 +2839,15 @@
+
+     private void dispatchMotion(MotionEvent event, boolean sendDone)
{
+         int source = event.getSource();
+-        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
++        if (((source & InputDevice.SOURCE_MOUSE) ^
InputDevice.SOURCE_MOUSE) == 0) {
++            try{
++                wm.moveMouseSurface((int)event.getX() -
(int)event.getXOffset(),
++                                    (int)event.getY() -
(int)event.getYOffset());
++            }catch (RemoteException e){
++                Log.e(TAG,"RemoteException thrown in
moveMouseSurface");
++            }
++            dispatchPointer(event, sendDone);
++        }else if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0)
{
+             dispatchPointer(event, sendDone);
+         } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) !=
0) {
+             dispatchTrackball(event, sendDone);
+--- a/frameworks/base/services/java/com/android/server/
WindowManagerService.java       2011-02-28 18:24:48.934663006 -0800
++++ b/frameworks/base/services/java/com/android/server/
WindowManagerService.java       2011-02-28 18:38:17.594662998 -0800
+@@ -60,6 +60,7 @@
+ import android.graphics.Canvas;
+ import android.graphics.Matrix;
+ import android.graphics.Paint;
++import android.graphics.Path;
+ import android.graphics.PixelFormat;
+ import android.graphics.Rect;
+ import android.graphics.Region;
+@@ -372,6 +373,13 @@
+     boolean mBlurShown;
+     Watermark mWatermark;
+
++    Surface mMouseSurface;
++    int mShowMouse = 0;
++    private int mMlx;
++    private int mMly;
++    int mMlw;
++    int mMlh;
++
+     int mTransactionSequence = 0;
+
+     final float[] mTmpFloats = new float[9];
+@@ -5400,6 +5408,31 @@
+         }
+     }
+
++              public boolean moveMouseSurface(int x, int y){
++        if (mMouseSurface != null && (x != 0 || y != 0)) {
++        synchronized(mWindowMap) {
++            Surface.openTransaction();
++            WindowState top =
++                (WindowState)mWindows.get(mWindows.size() - 1);
++            try {
++                int mDisplayWidth = mDisplay.getWidth();
++                mMlx = x;
++                mMly = y;
++                mMouseSurface.setPosition(mMlx, mMly);
++                mMouseSurface.setLayer(top.mAnimLayer + 1);
++                if (mShowMouse != 1) {
++                    mMouseSurface.show();
++                    mShowMouse = 1;
++                }
++            } catch ( RuntimeException e) {
++                Slog.e(TAG, "Failure showing mouse surface",e);
++            }
++            Surface.closeTransaction();
++            }
++        }
++                        return true;
++              }
++
+     /**
+      * Injects a keystroke event into the UI.
+      * Even when sync is false, this method may block while waiting
for current
+@@ -8487,6 +8520,54 @@
+             createWatermark = true;
+         }
+
++        if (mMouseSurface == null) {
++            int mMx, mMy, mMw, mMh;
++            Canvas mCanvas;
++            Path mPath = new Path();
++            mMw = 12;
++            mMh = 20;
++            mMx = (mDisplay.getWidth() - mMw) / 2;
++            mMy = (mDisplay.getHeight() - mMh) / 2;
++            try {
++                /*
++                 *First Mouse event, create Surface
++                 */
++                mMouseSurface =
++                    new Surface(mFxSession,
++                                0, -1, mMw, mMh,
++                                PixelFormat.TRANSPARENT,
++                                Surface.FX_SURFACE_NORMAL);
++                mCanvas = mMouseSurface.lockCanvas(null);
++                Paint tPaint = new Paint();
++                tPaint.setStyle(Paint.Style.STROKE);
++                tPaint.setStrokeWidth(2);
++                tPaint.setColor(0xffffffff);
++                mPath.moveTo(0.0f, 0.0f);
++                mPath.lineTo(12.0f, 12.0f);
++                mPath.lineTo(7.0f, 12.0f);
++                mPath.lineTo(11.0f, 20.0f);
++                mPath.lineTo(8.0f, 21.0f);
++                mPath.lineTo(4.0f, 13.0f);
++                mPath.lineTo(0.0f, 17.0f);
++                mPath.close();
++                mCanvas.clipPath(mPath);
++                mCanvas.drawColor(0xff000000);
++                mCanvas.drawPath(mPath, tPaint);
++
++                mMouseSurface.unlockCanvasAndPost(mCanvas);
++                mMouseSurface.openTransaction();
++                mMouseSurface.setSize(mMw, mMh);
++                mMouseSurface.closeTransaction();
++
++            } catch (Exception e) {
++                Slog.e(TAG, "Exception creating mouse surface",e);
++            }
++            mMlx = mMx;
++            mMly = mMy;
++            mMlw = mMw;
++            mMlh = mMh;
++        }
++
+         if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
+
+         Surface.openTransaction();
+--- a/frameworks/base/core/java/android/view/IWindowManager.aidl
2011-02-24 18:01:12.656910000 -0800
++++ b/frameworks/base/core/java/android/view/IWindowManager.aidl
2011-02-28 18:18:05.344663002 -0800
+@@ -52,6 +52,9 @@
+             in IInputContext inputContext);
+     boolean inputMethodClientHasFocus(IInputMethodClient client);
+
++    // Draws the mouse cursor on the screen
++    boolean moveMouseSurface(int dx, int dy);
++
+     // These can only be called when injecting events to your own
window,
+     // or by holding the INJECT_EVENTS permission.  These methods
may block
+     // until pending input events are finished being dispatched even
when 'sync' is false.
+--- a/frameworks/base/core/java/android/view/MotionEvent.java
2011-03-01 09:18:40.494662998 -0800
++++ b/frameworks/base/core/java/android/view/MotionEvent.java
2011-03-01 09:42:35.764663005 -0800
+@@ -781,6 +781,14 @@
+         return mDataSamples[mLastDataSampleIndex + SAMPLE_Y] +
mYOffset;
+     }
+
++    public final float getXOffset() {
++        return mXOffset;
++    }
++
++    public final float getYOffset() {
++        return mYOffset;
++    }
++
+     /**
+      * {@link #getPressure(int)} for the first pointer index (may be
an
+      * arbitrary pointer identifier).
--
cgit v0.8.3

  评论这张
 
阅读(653)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017