summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Sack <asac@linaro.org>2011-05-23 19:36:18 +0200
committerAlexander Sack <asac@linaro.org>2011-05-23 19:36:18 +0200
commit097190e725a5ed16ca0284824b951f4caf1f3bee (patch)
treea5b6ee221a17b805f506570e4fd0adc3fee05a2f
parent69ae4c09824fd810e61a5b82b0d82c866e5a2c6b (diff)
parentd84e4a7899680479f961c2f0585873a0a5439d4b (diff)
downloadbase-dev_toolchain_preview.tar.gz
Merge branch 'linaro_android_2.3.3' into dev_toolchain_previewdev_toolchain_preview
-rw-r--r--core/java/android/view/IWindowManager.aidl3
-rw-r--r--core/java/android/view/MotionEvent.java10
-rw-r--r--core/java/android/view/ViewRoot.java18
-rw-r--r--include/ui/EventHub.h3
-rw-r--r--include/ui/InputReader.h51
-rw-r--r--libs/ui/EventHub.cpp5
-rw-r--r--libs/ui/InputDispatcher.cpp10
-rw-r--r--libs/ui/InputReader.cpp230
-rw-r--r--services/java/com/android/server/WindowManagerService.java80
9 files changed, 401 insertions, 9 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index d4dd05c19adc..b125ec018ef9 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -51,6 +51,9 @@ interface IWindowManager
IWindowSession openSession(in IInputMethodClient client,
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
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index c2fec968172c..279a10a63c06 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -781,6 +781,16 @@ public final class MotionEvent extends InputEvent implements Parcelable {
return mDataSamples[mLastDataSampleIndex + SAMPLE_Y] + mYOffset;
}
+ /** @hide */
+ public final float getXOffset() {
+ return mXOffset;
+ }
+
+ /** @hide */
+ public final float getYOffset() {
+ return mYOffset;
+ }
+
/**
* {@link #getPressure(int)} for the first pointer index (may be an
* arbitrary pointer identifier).
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index c58207ee9999..f4e0bb7b1d11 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -215,6 +215,8 @@ public final class ViewRoot extends Handler implements ViewParent,
final ViewConfiguration mViewConfiguration;
+ static IWindowManager wm;
+
/**
* see {@link #playSoundEffect(int)}
*/
@@ -227,9 +229,8 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
mTranslator.translateEventInScreenToAppWindow(event);
}
+ boolean isMouse = ((event.getSource() & InputDevice.SOURCE_MOUSE) ^ InputDevice.SOURCE_MOUSE) == 0;
boolean handled;
if (mView != null && mAdded) {
@@ -2837,7 +2839,15 @@ public final class ViewRoot extends Handler implements ViewParent,
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);
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d78e35fbfa6c..958754125d37 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -119,6 +119,9 @@ enum {
/* The input device has switches. */
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+
+ /* The input device is a mouse. */
+ INPUT_DEVICE_CLASS_MOUSE = 0x00000100,
};
/*
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 7568ba72329a..cf93fb0aba33 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -504,6 +504,57 @@ private:
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,
+ FIELD_BTN_RIGHT = 8,
+ FIELD_BTN_MIDDLE = 16
+ };
+
+ uint32_t fields;
+
+ bool btnMouse;
+ bool btnRight;
+ bool btnMiddle;
+ 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:
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 41daa9ca0dbc..5f920a73d4ee 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -719,7 +719,10 @@ int EventHub::openDevice(const char *deviceName) {
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;
}
}
}
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 421ad663f8fd..90c85425dc8c 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -731,17 +731,19 @@ bool InputDispatcher::dispatchMotionLocked(
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);
}
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 83b382b9a7b0..df0174a86269 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -340,6 +340,11 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui
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));
@@ -1227,6 +1232,231 @@ int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scan
}
+// --- 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 mouse 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 now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
+ // we need to ensure that we report the up/down promptly.
+ sync(rawEvent->when);
+ break;
+ case BTN_RIGHT:
+ // Back Button
+ mAccumulator.fields |= Accumulator::FIELD_BTN_RIGHT;
+ mAccumulator.btnRight = rawEvent->value != 0;
+ sync(rawEvent->when);
+ break;
+ case BTN_MIDDLE:
+ // Menu Button
+ mAccumulator.fields |= Accumulator::FIELD_BTN_MIDDLE;
+ mAccumulator.btnMiddle = rawEvent->value != 0;
+ sync(rawEvent->when);
+ 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);
+
+ if (fields & Accumulator::FIELD_BTN_RIGHT) {
+ getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_DPAD, 0,
+ mAccumulator.btnRight ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, 0x4 /*Keycode*/, 0x18 /*Scancode*/, mContext->getGlobalMetaState(), when);
+ }
+
+ if (fields & Accumulator::FIELD_BTN_MIDDLE) {
+ getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_DPAD, 0,
+ mAccumulator.btnMiddle ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ AKEY_EVENT_FLAG_FROM_SYSTEM, 0x52 /*Keycode*/, 0x19/*Scancode*/, mContext->getGlobalMetaState(), when);
+ }
+
+ 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;
+ }
+
+ // Rotate motion based on display orientation if needed.
+ // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
+
+ 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;
+ }
+}
+
+
// --- TouchInputMapper ---
TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index efd0bb49dc1b..9e9d55a4db93 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -60,6 +60,7 @@ import android.content.res.Configuration;
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 @@ public class WindowManagerService extends IWindowManager.Stub
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,30 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ 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
@@ -8497,6 +8529,54 @@ public class WindowManagerService extends IWindowManager.Stub
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();