diff options
author | 2012-09-08 18:05:28 -0700 | |
---|---|---|
committer | 2012-09-08 18:12:57 -0700 | |
commit | d728bf514f257670fcb9aa22c6eaf97626072c93 (patch) | |
tree | dedf4c8771ab1e1b618ea0d75e5f8328b0bfe83a | |
parent | 631938f26dbc89e7e9530bb85d9f37706dba59f3 (diff) |
Make display manager tell input system about viewports.
The window manager is no longer responsible for telling the
input system about the display viewport.
Change-Id: I932882bae55decef55f25093bb2a7ebac1620bb1
18 files changed, 419 insertions, 213 deletions
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 6d63998cc93e..513dc1334185 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -203,34 +203,18 @@ static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, // --- InputReaderConfiguration --- -bool InputReaderConfiguration::getDisplayInfo(int32_t displayId, bool external, - int32_t* width, int32_t* height, int32_t* orientation) const { - if (displayId == 0) { - const DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay; - if (info.width > 0 && info.height > 0) { - if (width) { - *width = info.width; - } - if (height) { - *height = info.height; - } - if (orientation) { - *orientation = info.orientation; - } - return true; - } +bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const { + const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay; + if (viewport.displayId >= 0) { + *outViewport = viewport; + return true; } return false; } -void InputReaderConfiguration::setDisplayInfo(int32_t displayId, bool external, - int32_t width, int32_t height, int32_t orientation) { - if (displayId == 0) { - DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay; - info.width = width; - info.height = height; - info.orientation = orientation; - } +void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) { + DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay; + v = viewport; } @@ -2001,9 +1985,11 @@ void KeyboardInputMapper::configure(nsecs_t when, } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) { - if (!config->getDisplayInfo(mParameters.associatedDisplayId, - false /*external*/, NULL, NULL, &mOrientation)) { + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { + DisplayViewport v; + if (config->getDisplayInfo(false /*external*/, &v)) { + mOrientation = v.orientation; + } else { mOrientation = DISPLAY_ORIENTATION_0; } } else { @@ -2017,16 +2003,16 @@ void KeyboardInputMapper::configureParameters() { getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = -1; + mParameters.hasAssociatedDisplay = false; if (mParameters.orientationAware) { - mParameters.associatedDisplayId = 0; + mParameters.hasAssociatedDisplay = true; } } void KeyboardInputMapper::dumpParameters(String8& dump) { dump.append(INDENT3 "Parameters:\n"); - dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n", - mParameters.associatedDisplayId); + dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", + toString(mParameters.hasAssociatedDisplay)); dump.appendFormat(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); } @@ -2086,7 +2072,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, if (down) { // Rotate key codes according to orientation if needed. - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) { + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { keyCode = rotateKeyCode(keyCode, mOrientation); } @@ -2317,9 +2303,11 @@ void CursorInputMapper::configure(nsecs_t when, } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) { - if (!config->getDisplayInfo(mParameters.associatedDisplayId, - false /*external*/, NULL, NULL, &mOrientation)) { + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) { + DisplayViewport v; + if (config->getDisplayInfo(false /*external*/, &v)) { + mOrientation = v.orientation; + } else { mOrientation = DISPLAY_ORIENTATION_0; } } else { @@ -2344,16 +2332,16 @@ void CursorInputMapper::configureParameters() { getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = -1; + mParameters.hasAssociatedDisplay = false; if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) { - mParameters.associatedDisplayId = 0; + mParameters.hasAssociatedDisplay = true; } } void CursorInputMapper::dumpParameters(String8& dump) { dump.append(INDENT3 "Parameters:\n"); - dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n", - mParameters.associatedDisplayId); + dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n", + toString(mParameters.hasAssociatedDisplay)); switch (mParameters.mode) { case Parameters::MODE_POINTER: @@ -2420,7 +2408,7 @@ void CursorInputMapper::sync(nsecs_t when) { bool moved = deltaX != 0 || deltaY != 0; // Rotate delta according to orientation if needed. - if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0 + if (mParameters.orientationAware && mParameters.hasAssociatedDisplay && (deltaX != 0.0f || deltaY != 0.0f)) { rotateDelta(mOrientation, &deltaX, &deltaY); } @@ -2782,15 +2770,15 @@ void TouchInputMapper::configureParameters() { getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"), mParameters.orientationAware); - mParameters.associatedDisplayId = -1; + mParameters.hasAssociatedDisplay = false; mParameters.associatedDisplayIsExternal = false; if (mParameters.orientationAware || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) { + mParameters.hasAssociatedDisplay = true; mParameters.associatedDisplayIsExternal = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN && getDevice()->isExternal(); - mParameters.associatedDisplayId = 0; } } @@ -2822,8 +2810,9 @@ void TouchInputMapper::dumpParameters(String8& dump) { ALOG_ASSERT(false); } - dump.appendFormat(INDENT4 "AssociatedDisplay: id=%d, isExternal=%s\n", - mParameters.associatedDisplayId, toString(mParameters.associatedDisplayIsExternal)); + dump.appendFormat(INDENT4 "AssociatedDisplay: present=%s, isExternal=%s\n", + toString(mParameters.hasAssociatedDisplay), + toString(mParameters.associatedDisplayIsExternal)); dump.appendFormat(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); } @@ -2861,7 +2850,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mSource |= AINPUT_SOURCE_STYLUS; } } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN - && mParameters.associatedDisplayId >= 0) { + && mParameters.hasAssociatedDisplay) { mSource = AINPUT_SOURCE_TOUCHSCREEN; mDeviceMode = DEVICE_MODE_DIRECT; if (hasStylus()) { @@ -2881,15 +2870,13 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } // Get associated display dimensions. - if (mParameters.associatedDisplayId >= 0) { - if (!mConfig.getDisplayInfo(mParameters.associatedDisplayId, - mParameters.associatedDisplayIsExternal, - &mAssociatedDisplayWidth, &mAssociatedDisplayHeight, - &mAssociatedDisplayOrientation)) { + if (mParameters.hasAssociatedDisplay) { + if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, + &mAssociatedDisplayViewport)) { ALOGI(INDENT "Touch device '%s' could not query the properties of its associated " - "display %d. The device will be inoperable until the display size " + "display. The device will be inoperable until the display size " "becomes available.", - getDeviceName().string(), mParameters.associatedDisplayId); + getDeviceName().string()); mDeviceMode = DEVICE_MODE_DISABLED; return; } @@ -2898,10 +2885,16 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { // Configure dimensions. int32_t width, height, orientation; if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) { - width = mAssociatedDisplayWidth; - height = mAssociatedDisplayHeight; + width = mAssociatedDisplayViewport.logicalRight - mAssociatedDisplayViewport.logicalLeft; + height = mAssociatedDisplayViewport.logicalBottom - mAssociatedDisplayViewport.logicalTop; + if (mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_90 + || mAssociatedDisplayViewport.orientation == DISPLAY_ORIENTATION_270) { + int32_t temp = height; + height = width; + width = temp; + } orientation = mParameters.orientationAware ? - mAssociatedDisplayOrientation : DISPLAY_ORIENTATION_0; + mAssociatedDisplayViewport.orientation : DISPLAY_ORIENTATION_0; } else { width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; @@ -3163,8 +3156,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1; int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1; float rawDiagonal = hypotf(rawWidth, rawHeight); - float displayDiagonal = hypotf(mAssociatedDisplayWidth, - mAssociatedDisplayHeight); + float displayDiagonal = hypotf(width, height); // Scale movements such that one whole swipe of the touch pad covers a // given area relative to the diagonal size of the display when no acceleration diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 6c06986ee73f..e345a5fb6278 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -24,7 +24,6 @@ #include <androidfw/Input.h> #include <androidfw/VelocityControl.h> #include <androidfw/VelocityTracker.h> -#include <ui/DisplayInfo.h> #include <utils/KeyedVector.h> #include <utils/threads.h> #include <utils/Timers.h> @@ -48,6 +47,45 @@ namespace android { class InputDevice; class InputMapper; +/* + * Describes how coordinates are mapped on a physical display. + * See com.android.server.display.DisplayViewport. + */ +struct DisplayViewport { + int32_t displayId; // -1 if invalid + int32_t orientation; + int32_t logicalLeft; + int32_t logicalTop; + int32_t logicalRight; + int32_t logicalBottom; + int32_t physicalLeft; + int32_t physicalTop; + int32_t physicalRight; + int32_t physicalBottom; + + DisplayViewport() : + displayId(-1), orientation(DISPLAY_ORIENTATION_0), + logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), + physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0) { + } + + bool operator==(const DisplayViewport& other) const { + return displayId == other.displayId + && orientation == other.orientation + && logicalLeft == other.logicalLeft + && logicalTop == other.logicalTop + && logicalRight == other.logicalRight + && logicalBottom == other.logicalBottom + && physicalLeft == other.physicalLeft + && physicalTop == other.physicalTop + && physicalRight == other.physicalRight + && physicalBottom == other.physicalBottom; + } + + bool operator!=(const DisplayViewport& other) const { + return !(*this == other); + } +}; /* * Input reader configuration. @@ -180,25 +218,12 @@ struct InputReaderConfiguration { pointerGestureZoomSpeedRatio(0.3f), showTouches(false) { } - bool getDisplayInfo(int32_t displayId, bool external, - int32_t* width, int32_t* height, int32_t* orientation) const; - - void setDisplayInfo(int32_t displayId, bool external, - int32_t width, int32_t height, int32_t orientation); + bool getDisplayInfo(bool external, DisplayViewport* outViewport) const; + void setDisplayInfo(bool external, const DisplayViewport& viewport); private: - struct DisplayInfo { - int32_t width; - int32_t height; - int32_t orientation; - - DisplayInfo() : - width(-1), height(-1), orientation(DISPLAY_ORIENTATION_0) { - } - }; - - DisplayInfo mInternalDisplay; - DisplayInfo mExternalDisplay; + DisplayViewport mInternalDisplay; + DisplayViewport mExternalDisplay; }; @@ -992,7 +1017,7 @@ private: // Immutable configuration parameters. struct Parameters { - int32_t associatedDisplayId; + bool hasAssociatedDisplay; bool orientationAware; } mParameters; @@ -1042,7 +1067,7 @@ private: }; Mode mode; - int32_t associatedDisplayId; + bool hasAssociatedDisplay; bool orientationAware; } mParameters; @@ -1143,7 +1168,7 @@ protected: }; DeviceType deviceType; - int32_t associatedDisplayId; + bool hasAssociatedDisplay; bool associatedDisplayIsExternal; bool orientationAware; @@ -1277,10 +1302,8 @@ private: int32_t mSurfaceWidth; int32_t mSurfaceHeight; - // The associated display orientation and width and height set by configureSurface(). - int32_t mAssociatedDisplayOrientation; - int32_t mAssociatedDisplayWidth; - int32_t mAssociatedDisplayHeight; + // The associated display viewport set by configureSurface(). + DisplayViewport mAssociatedDisplayViewport; // Translation and scaling factors, orientation-independent. float mXScale; diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp index fc828a6afee7..9af521b7aba2 100644 --- a/services/input/PointerController.cpp +++ b/services/input/PointerController.cpp @@ -307,9 +307,17 @@ void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout } } -void PointerController::setDisplaySize(int32_t width, int32_t height) { +void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) { AutoMutex _l(mLock); + // Adjust to use the display's unrotated coordinate frame. + if (orientation == DISPLAY_ORIENTATION_90 + || orientation == DISPLAY_ORIENTATION_270) { + int32_t temp = height; + height = width; + width = temp; + } + if (mLocked.displayWidth != width || mLocked.displayHeight != height) { mLocked.displayWidth = width; mLocked.displayHeight = height; @@ -324,12 +332,7 @@ void PointerController::setDisplaySize(int32_t width, int32_t height) { } fadeOutAndReleaseAllSpotsLocked(); - updatePointerLocked(); } -} - -void PointerController::setDisplayOrientation(int32_t orientation) { - AutoMutex _l(mLock); if (mLocked.displayOrientation != orientation) { // Apply offsets to convert from the pixel top-left corner position to the pixel center. @@ -380,9 +383,9 @@ void PointerController::setDisplayOrientation(int32_t orientation) { mLocked.pointerX = x - 0.5f; mLocked.pointerY = y - 0.5f; mLocked.displayOrientation = orientation; - - updatePointerLocked(); } + + updatePointerLocked(); } void PointerController::setPointerIcon(const SpriteIcon& icon) { diff --git a/services/input/PointerController.h b/services/input/PointerController.h index 4c307c4a5ead..fd68b61b5ae7 100644 --- a/services/input/PointerController.h +++ b/services/input/PointerController.h @@ -170,8 +170,7 @@ public: const uint32_t* spotIdToIndex, BitSet32 spotIdBits); virtual void clearSpots(); - void setDisplaySize(int32_t width, int32_t height); - void setDisplayOrientation(int32_t orientation); + void setDisplayViewport(int32_t width, int32_t height, int32_t orientation); void setPointerIcon(const SpriteIcon& icon); void setInactivityTimeout(InactivityTimeout inactivityTimeout); diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index abda10bc4c08..03516af0ca53 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -138,8 +138,21 @@ public: void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) { // Set the size of both the internal and external display at the same time. - mConfig.setDisplayInfo(displayId, false /*external*/, width, height, orientation); - mConfig.setDisplayInfo(displayId, true /*external*/, width, height, orientation); + bool isRotated = (orientation == DISPLAY_ORIENTATION_90 + || orientation == DISPLAY_ORIENTATION_270); + DisplayViewport v; + v.displayId = displayId; + v.orientation = orientation; + v.logicalLeft = 0; + v.logicalTop = 0; + v.logicalRight = isRotated ? height : width; + v.logicalBottom = isRotated ? width : height; + v.physicalLeft = 0; + v.physicalTop = 0; + v.physicalRight = isRotated ? height : width; + v.physicalBottom = isRotated ? width : height; + mConfig.setDisplayInfo(false /*external*/, v); + mConfig.setDisplayInfo(true /*external*/, v); } void addExcludedDeviceName(const String8& deviceName) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 1aad9b39b638..c28afb236115 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -304,6 +304,7 @@ class ServerThread extends Thread { ActivityManagerService.self().setWindowManager(wm); display.setWindowManager(wm); + display.setInputManager(inputManager); // Skip Bluetooth if we have an emulator kernel // TODO: Use a more reliable check to see if this product should diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java index 995c553347b7..8eeefb484d2a 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -132,14 +132,17 @@ abstract class DisplayDevice { || mCurrentDisplayRect == null || !mCurrentDisplayRect.equals(displayRect)) { mCurrentOrientation = orientation; + if (mCurrentLayerStackRect == null) { mCurrentLayerStackRect = new Rect(); } mCurrentLayerStackRect.set(layerStackRect); + if (mCurrentDisplayRect == null) { mCurrentDisplayRect = new Rect(); } mCurrentDisplayRect.set(displayRect); + Surface.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect); } @@ -156,6 +159,26 @@ abstract class DisplayDevice { } /** + * Populates the specified viewport object with orientation, + * physical and logical rects based on the display's current projection. + */ + public final void populateViewportLocked(DisplayViewport viewport) { + viewport.orientation = mCurrentOrientation; + + if (mCurrentLayerStackRect != null) { + viewport.logicalFrame.set(mCurrentLayerStackRect); + } else { + viewport.logicalFrame.setEmpty(); + } + + if (mCurrentDisplayRect != null) { + viewport.physicalFrame.set(mCurrentDisplayRect); + } else { + viewport.physicalFrame.setEmpty(); + } + } + + /** * Dumps the local state of the display device. * Does not need to dump the display device info because that is already dumped elsewhere. */ diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java index c90a1c601f87..7c57694042a5 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -43,6 +43,21 @@ final class DisplayDeviceInfo { public static final int FLAG_SUPPORTS_ROTATION = 1 << 2; /** + * Touch attachment: Display does not receive touch. + */ + public static final int TOUCH_NONE = 0; + + /** + * Touch attachment: Touch input is via the internal interface. + */ + public static final int TOUCH_INTERNAL = 1; + + /** + * Touch attachment: Touch input is via an external interface, such as USB. + */ + public static final int TOUCH_EXTERNAL = 2; + + /** * Gets the name of the display device, which may be derived from * EDID or other sources. The name may be displayed to the user. */ @@ -90,6 +105,11 @@ final class DisplayDeviceInfo { */ public int flags; + /** + * The touch attachment, per {@link DisplayViewport#touch}. + */ + public int touch; + public void setAssumedDensityForExternalDisplay(int width, int height) { densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080; // Technically, these values should be smaller than the apparent density @@ -112,7 +132,8 @@ final class DisplayDeviceInfo { && densityDpi == other.densityDpi && xDpi == other.xDpi && yDpi == other.yDpi - && flags == other.flags; + && flags == other.flags + && touch == other.touch; } @Override @@ -129,6 +150,7 @@ final class DisplayDeviceInfo { xDpi = other.xDpi; yDpi = other.yDpi; flags = other.flags; + touch = other.touch; } // For debugging purposes @@ -136,7 +158,20 @@ final class DisplayDeviceInfo { public String toString() { return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, " + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi" - + flagsToString(flags) + "}"; + + ", touch " + touchToString(touch) + flagsToString(flags) + "}"; + } + + private static String touchToString(int touch) { + switch (touch) { + case TOUCH_NONE: + return "NONE"; + case TOUCH_INTERNAL: + return "INTERNAL"; + case TOUCH_EXTERNAL: + return "EXTERNAL"; + default: + return Integer.toString(touch); + } } private static String flagsToString(int flags) { diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 41a0c09d8bb1..e11d45475668 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -96,6 +96,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; private static final int MSG_DELIVER_DISPLAY_EVENT = 3; private static final int MSG_REQUEST_TRAVERSAL = 4; + private static final int MSG_UPDATE_VIEWPORT = 5; private final Context mContext; private final boolean mHeadless; @@ -103,6 +104,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { private final Handler mUiHandler; private final DisplayAdapterListener mDisplayAdapterListener; private WindowManagerFuncs mWindowManagerFuncs; + private InputManagerFuncs mInputManagerFuncs; // The synchronization root for the display manager. // This lock guards most of the display manager's state. @@ -141,6 +143,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // The Wifi display adapter, or null if not registered. private WifiDisplayAdapter mWifiDisplayAdapter; + // Viewports of the default display and the display that should receive touch + // input from an external source. Used by the input system. + private final DisplayViewport mDefaultViewport = new DisplayViewport(); + private final DisplayViewport mExternalTouchViewport = new DisplayViewport(); + // Temporary callback list, used when sending display events to applications. // May be used outside of the lock but only on the handler thread. private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); @@ -148,6 +155,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // Temporary display info, used for comparing display configurations. private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); + // Temporary viewports, used when sending new viewport information to the + // input system. May be used outside of the lock but only on the handler thread. + private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); + private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); + public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) { mContext = context; mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); @@ -183,7 +195,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } /** - * Called during initialization to associated the display manager with the + * Called during initialization to associate the display manager with the * window manager. */ public void setWindowManager(WindowManagerFuncs windowManagerFuncs) { @@ -194,6 +206,17 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } /** + * Called during initialization to associate the display manager with the + * input manager. + */ + public void setInputManager(InputManagerFuncs inputManagerFuncs) { + synchronized (mSyncRoot) { + mInputManagerFuncs = inputManagerFuncs; + scheduleTraversalLocked(); + } + } + + /** * Called when the system is ready to go. */ public void systemReady(boolean safeMode, boolean onlyCore) { @@ -487,7 +510,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { final int displayId = assignDisplayIdLocked(isDefault); final int layerStack = assignLayerStackLocked(displayId); - LogicalDisplay display = new LogicalDisplay(layerStack, device); + LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); display.updateLocked(mDisplayDevices); if (!display.isValidLocked()) { // This should never happen currently. @@ -548,6 +571,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } mRemovedDisplayDevices.clear(); + // Clear all viewports before configuring displays so that we can keep + // track of which ones we have configured. + clearViewportsLocked(); + // Configure each display device. final int count = mDisplayDevices.size(); for (int i = 0; i < count; i++) { @@ -555,6 +582,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { configureDisplayInTransactionLocked(device); device.performTraversalInTransactionLocked(); } + + // Tell the input system about these new viewports. + if (mInputManagerFuncs != null) { + mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); + } } /** @@ -577,7 +609,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { scheduleTraversalLocked(); } } + } + private void clearViewportsLocked() { + mDefaultViewport.valid = false; + mExternalTouchViewport.valid = false; } private void configureDisplayInTransactionLocked(DisplayDevice device) { @@ -593,11 +629,30 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // Apply the logical display configuration to the display device. if (display == null) { // TODO: no logical display for the device, blank it - Slog.d(TAG, "Missing logical display to use for physical display device: " + Slog.w(TAG, "Missing logical display to use for physical display device: " + device.getDisplayDeviceInfoLocked()); + return; } else { display.configureDisplayInTransactionLocked(device); } + + // Update the viewports if needed. + DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); + if (!mDefaultViewport.valid + && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { + setViewportLocked(mDefaultViewport, display, device); + } + if (!mExternalTouchViewport.valid + && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { + setViewportLocked(mExternalTouchViewport, display, device); + } + } + + private static void setViewportLocked(DisplayViewport viewport, + LogicalDisplay display, DisplayDevice device) { + viewport.valid = true; + viewport.displayId = display.getDisplayIdLocked(); + device.populateViewportLocked(viewport); } private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { @@ -690,6 +745,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub { pw.println(" Display " + displayId + ":"); display.dumpLocked(ipw); } + + pw.println(); + pw.println("Default viewport: " + mDefaultViewport); + pw.println("External touch viewport: " + mExternalTouchViewport); } } @@ -714,6 +773,18 @@ public final class DisplayManagerService extends IDisplayManager.Stub { void requestTraversal(); } + /** + * Private interface to the input manager. + */ + public interface InputManagerFuncs { + /** + * Sets information about the displays as needed by the input system. + * The input system should copy this information if required. + */ + void setDisplayViewports(DisplayViewport defaultViewport, + DisplayViewport externalTouchViewport); + } + private final class DisplayManagerHandler extends Handler { public DisplayManagerHandler(Looper looper) { super(looper, null, true /*async*/); @@ -737,6 +808,16 @@ public final class DisplayManagerService extends IDisplayManager.Stub { case MSG_REQUEST_TRAVERSAL: mWindowManagerFuncs.requestTraversal(); break; + + case MSG_UPDATE_VIEWPORT: { + synchronized (mSyncRoot) { + mTempDefaultViewport.copyFrom(mDefaultViewport); + mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); + } + mInputManagerFuncs.setDisplayViewports( + mTempDefaultViewport, mTempExternalTouchViewport); + break; + } } } } diff --git a/services/java/com/android/server/display/DisplayViewport.java b/services/java/com/android/server/display/DisplayViewport.java new file mode 100644 index 000000000000..ed4016d2b280 --- /dev/null +++ b/services/java/com/android/server/display/DisplayViewport.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 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. + */ + +package com.android.server.display; + +import android.graphics.Rect; + +/** + * Describes how the pixels of physical display device reflects the content of + * a logical display. + * <p> + * This information is used by the input system to translate touch input from + * physical display coordinates into logical display coordinates. + * </p> + */ +public final class DisplayViewport { + // True if this viewport is valid. + public boolean valid; + + // The logical display id. + public int displayId; + + // The rotation applied to the physical coordinate system. + public int orientation; + + // The portion of the logical display that are presented on this physical display. + public final Rect logicalFrame = new Rect(); + + // The portion of the (rotated) physical display that shows the logical display contents. + // The relation between logical and physical frame defines how the coordinate system + // should be scaled or translated after rotation. + public final Rect physicalFrame = new Rect(); + + public void copyFrom(DisplayViewport viewport) { + valid = viewport.valid; + displayId = viewport.displayId; + orientation = viewport.orientation; + logicalFrame.set(viewport.logicalFrame); + physicalFrame.set(viewport.physicalFrame); + } + + // For debugging purposes. + @Override + public String toString() { + return "DisplayViewport{valid=" + valid + + ", displayId=" + displayId + + ", orientation=" + orientation + + ", logicalFrame=" + logicalFrame + + ", physicalFrame=" + physicalFrame + + "}"; + } +} diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java index 3aaacf162dc0..7629db61371c 100644 --- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java +++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java @@ -61,6 +61,7 @@ final class HeadlessDisplayAdapter extends DisplayAdapter { mInfo.yDpi = 160; mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY | DisplayDeviceInfo.FLAG_SECURE; + mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; } return mInfo; } diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java index 4962753e10f1..80c860ba88f4 100644 --- a/services/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/java/com/android/server/display/LocalDisplayAdapter.java @@ -129,10 +129,12 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); mInfo.xDpi = mPhys.xDpi; mInfo.yDpi = mPhys.yDpi; + mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; } else { mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_hdmi_display_name); mInfo.flags = DisplayDeviceInfo.FLAG_SECURE; + mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); } } diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java index e0f63ddb9f00..2e752603360f 100644 --- a/services/java/com/android/server/display/LogicalDisplay.java +++ b/services/java/com/android/server/display/LogicalDisplay.java @@ -54,6 +54,7 @@ import libcore.util.Objects; final class LogicalDisplay { private final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); + private final int mDisplayId; private final int mLayerStack; private DisplayInfo mOverrideDisplayInfo; // set by the window manager private DisplayInfo mInfo; @@ -70,12 +71,22 @@ final class LogicalDisplay { private final Rect mTempLayerStackRect = new Rect(); private final Rect mTempDisplayRect = new Rect(); - public LogicalDisplay(int layerStack, DisplayDevice primaryDisplayDevice) { + public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) { + mDisplayId = displayId; mLayerStack = layerStack; mPrimaryDisplayDevice = primaryDisplayDevice; } /** + * Gets the logical display id of this logical display. + * + * @return The logical display id. + */ + public int getDisplayIdLocked() { + return mDisplayId; + } + + /** * Gets the primary display device associated with this logical display. * * @return The primary display device. diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java index e2d30590188f..9b0e534c5ed1 100644 --- a/services/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java @@ -228,6 +228,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.xDpi = mDensityDpi; mInfo.yDpi = mDensityDpi; mInfo.flags = DisplayDeviceInfo.FLAG_SECURE; + mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; } return mInfo; } diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index abf0d27d223e..ca500c0a2b0b 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -324,6 +324,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mInfo.height = mHeight; mInfo.refreshRate = mRefreshRate; mInfo.flags = mFlags; + mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); } return mInfo; diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index fd4f5fc92f92..95655a56b661 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -19,6 +19,8 @@ package com.android.server.input; import com.android.internal.R; import com.android.internal.util.XmlUtils; import com.android.server.Watchdog; +import com.android.server.display.DisplayManagerService; +import com.android.server.display.DisplayViewport; import org.xmlpull.v1.XmlPullParser; @@ -90,7 +92,8 @@ import libcore.util.Objects; /* * Wraps the C++ InputManager and provides its callbacks. */ -public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor { +public class InputManagerService extends IInputManager.Stub + implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs { static final String TAG = "InputManager"; static final boolean DEBUG = false; @@ -143,11 +146,11 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. private static native int nativeInit(InputManagerService service, Context context, MessageQueue messageQueue); private static native void nativeStart(int ptr); - private static native void nativeSetDisplaySize(int ptr, int displayId, - int width, int height, int externalWidth, int externalHeight); - private static native void nativeSetDisplayOrientation(int ptr, int displayId, - int rotation, int externalRotation); - + private static native void nativeSetDisplayViewport(int ptr, boolean external, + int displayId, int rotation, + int logicalLeft, int logicalTop, int logicalRight, int logicalBottom, + int physicalLeft, int physicalTop, int physicalRight, int physicalBottom); + private static native int nativeGetScanCodeState(int ptr, int deviceId, int sourceMask, int scanCode); private static native int nativeGetKeyCodeState(int ptr, @@ -282,28 +285,27 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. nativeReloadDeviceAliases(mPtr); } - public void setDisplaySize(int displayId, int width, int height) { - if (width <= 0 || height <= 0) { - throw new IllegalArgumentException("Invalid display id or dimensions."); + @Override + public void setDisplayViewports(DisplayViewport defaultViewport, + DisplayViewport externalTouchViewport) { + if (defaultViewport.valid) { + setDisplayViewport(false, defaultViewport); } - - if (DEBUG) { - Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height); + + if (externalTouchViewport.valid) { + setDisplayViewport(true, externalTouchViewport); + } else if (defaultViewport.valid) { + setDisplayViewport(true, defaultViewport); } - // FIXME: external size is deprecated - nativeSetDisplaySize(mPtr, displayId, width, height, 1280, 720); } - public void setDisplayOrientation(int displayId, int rotation) { - if (rotation < Surface.ROTATION_0 || rotation > Surface.ROTATION_270) { - throw new IllegalArgumentException("Invalid rotation."); - } - - if (DEBUG) { - Slog.d(TAG, "Setting display #" + displayId + " orientation to rotation " + rotation); - } - // FIXME: external rotation is deprecated - nativeSetDisplayOrientation(mPtr, displayId, rotation, Surface.ROTATION_0); + private void setDisplayViewport(boolean external, DisplayViewport viewport) { + nativeSetDisplayViewport(mPtr, external, + viewport.displayId, viewport.orientation, + viewport.logicalFrame.left, viewport.logicalFrame.top, + viewport.logicalFrame.right, viewport.logicalFrame.bottom, + viewport.physicalFrame.left, viewport.physicalFrame.top, + viewport.physicalFrame.right, viewport.physicalFrame.bottom); } /** diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 18e793d59e06..cdca8bc7b4d0 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -5947,7 +5947,6 @@ public class WindowManagerService extends IWindowManager.Stub mWaitingForConfig = true; getDefaultDisplayContent().layoutNeeded = true; startFreezingDisplayLocked(inTransaction); - mInputManager.setDisplayOrientation(0, rotation); // We need to update our screen size information to match the new // rotation. Note that this is redundant with the later call to @@ -7121,10 +7120,6 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.appWidth, displayInfo.appHeight); final DisplayContent displayContent = getDefaultDisplayContent(); - mInputManager.setDisplaySize(displayContent.getDisplayId(), - displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight); - mInputManager.setDisplayOrientation(displayContent.getDisplayId(), - mDefaultDisplay.getRotation()); mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight, displayContent.mInitialDisplayDensity); } diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 495d4abd0e83..5e36bf8316d7 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -164,9 +164,7 @@ public: void dump(String8& dump); - void setDisplaySize(int32_t displayId, int32_t width, int32_t height, - int32_t externalWidth, int32_t externalHeight); - void setDisplayOrientation(int32_t displayId, int32_t orientation, int32_t externalOrientation); + void setDisplayViewport(bool external, const DisplayViewport& viewport); status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, const sp<InputWindowHandle>& inputWindowHandle, bool monitor); @@ -223,10 +221,8 @@ private: Mutex mLock; struct Locked { // Display size information. - int32_t displayWidth, displayHeight; // -1 when not initialized - int32_t displayOrientation; - int32_t displayExternalWidth, displayExternalHeight; // -1 when not initialized - int32_t displayExternalOrientation; + DisplayViewport internalViewport; + DisplayViewport externalViewport; // System UI visibility. int32_t systemUiVisibility; @@ -274,13 +270,6 @@ NativeInputManager::NativeInputManager(jobject contextObj, { AutoMutex _l(mLock); - mLocked.displayWidth = -1; - mLocked.displayHeight = -1; - mLocked.displayOrientation = DISPLAY_ORIENTATION_0; - mLocked.displayExternalWidth = -1; - mLocked.displayExternalHeight = -1; - mLocked.displayExternalOrientation = DISPLAY_ORIENTATION_0; - mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; mLocked.pointerSpeed = 0; mLocked.pointerGesturesEnabled = true; @@ -316,57 +305,26 @@ bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const c return false; } -void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height, - int32_t externalWidth, int32_t externalHeight) { +void NativeInputManager::setDisplayViewport(bool external, const DisplayViewport& viewport) { bool changed = false; - if (displayId == 0) { - AutoMutex _l(mLock); - - if (mLocked.displayWidth != width || mLocked.displayHeight != height) { - changed = true; - mLocked.displayWidth = width; - mLocked.displayHeight = height; - - sp<PointerController> controller = mLocked.pointerController.promote(); - if (controller != NULL) { - controller->setDisplaySize(width, height); - } - } - - if (mLocked.displayExternalWidth != externalWidth - || mLocked.displayExternalHeight != externalHeight) { - changed = true; - mLocked.displayExternalWidth = externalWidth; - mLocked.displayExternalHeight = externalHeight; - } - } - - if (changed) { - mInputManager->getReader()->requestRefreshConfiguration( - InputReaderConfiguration::CHANGE_DISPLAY_INFO); - } -} - -void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation, - int32_t externalOrientation) { - bool changed = false; - if (displayId == 0) { + { AutoMutex _l(mLock); - if (mLocked.displayOrientation != orientation) { + DisplayViewport& v = external ? mLocked.externalViewport : mLocked.internalViewport; + if (v != viewport) { changed = true; - mLocked.displayOrientation = orientation; - - sp<PointerController> controller = mLocked.pointerController.promote(); - if (controller != NULL) { - controller->setDisplayOrientation(orientation); + v = viewport; + + if (!external) { + sp<PointerController> controller = mLocked.pointerController.promote(); + if (controller != NULL) { + controller->setDisplayViewport( + viewport.logicalRight - viewport.logicalLeft, + viewport.logicalBottom - viewport.logicalTop, + viewport.orientation); + } } } - - if (mLocked.displayExternalOrientation != externalOrientation) { - changed = true; - mLocked.displayExternalOrientation = externalOrientation; - } } if (changed) { @@ -448,11 +406,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon outConfig->showTouches = mLocked.showTouches; - outConfig->setDisplayInfo(0, false /*external*/, - mLocked.displayWidth, mLocked.displayHeight, mLocked.displayOrientation); - outConfig->setDisplayInfo(0, true /*external*/, - mLocked.displayExternalWidth, mLocked.displayExternalHeight, - mLocked.displayExternalOrientation); + outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport); + outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport); } // release lock } @@ -466,8 +421,11 @@ sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32 controller = new PointerController(this, mLooper, mLocked.spriteController); mLocked.pointerController = controller; - controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight); - controller->setDisplayOrientation(mLocked.displayOrientation); + DisplayViewport& v = mLocked.internalViewport; + controller->setDisplayViewport( + v.logicalRight - v.logicalLeft, + v.logicalBottom - v.logicalTop, + v.orientation); JNIEnv* env = jniEnv(); jobject pointerIconObj = env->CallObjectMethod(mServiceObj, @@ -1032,22 +990,24 @@ static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { } } -static void nativeSetDisplaySize(JNIEnv* env, jclass clazz, jint ptr, - jint displayId, jint width, jint height, jint externalWidth, jint externalHeight) { - NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); - - // XXX we could get this from the SurfaceFlinger directly instead of requiring it - // to be passed in like this, not sure which is better but leaving it like this - // keeps the window manager in direct control of when display transitions propagate down - // to the input dispatcher - im->setDisplaySize(displayId, width, height, externalWidth, externalHeight); -} - -static void nativeSetDisplayOrientation(JNIEnv* env, jclass clazz, - jint ptr, jint displayId, jint orientation, jint externalOrientation) { +static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external, + jint displayId, jint orientation, + jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, + jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); - im->setDisplayOrientation(displayId, orientation, externalOrientation); + DisplayViewport v; + v.displayId = displayId; + v.orientation = orientation; + v.logicalLeft = logicalLeft; + v.logicalTop = logicalTop; + v.logicalRight = logicalRight; + v.logicalBottom = logicalBottom; + v.physicalLeft = physicalLeft; + v.physicalTop = physicalTop; + v.physicalRight = physicalRight; + v.physicalBottom = physicalBottom; + im->setDisplayViewport(external, v); } static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz, @@ -1328,10 +1288,8 @@ static JNINativeMethod gInputManagerMethods[] = { (void*) nativeInit }, { "nativeStart", "(I)V", (void*) nativeStart }, - { "nativeSetDisplaySize", "(IIIIII)V", - (void*) nativeSetDisplaySize }, - { "nativeSetDisplayOrientation", "(IIII)V", - (void*) nativeSetDisplayOrientation }, + { "nativeSetDisplayViewport", "(IZIIIIIIIIII)V", + (void*) nativeSetDisplayViewport }, { "nativeGetScanCodeState", "(IIII)I", (void*) nativeGetScanCodeState }, { "nativeGetKeyCodeState", "(IIII)I", |