Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
//
|
|
|
|
// Copyright 2010 The Android Open Source Project
|
|
|
|
//
|
|
|
|
// Provides a pipe-based transport for native events in the NDK.
|
|
|
|
//
|
|
|
|
#define LOG_TAG "Input"
|
|
|
|
|
|
|
|
//#define LOG_NDEBUG 0
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
#define DEBUG_PROBE 0
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2010-12-02 21:50:46 +00:00
|
|
|
#include <ctype.h>
|
2010-11-30 01:37:49 +00:00
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
#include <ui/Input.h>
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_ANDROID_OS
|
|
|
|
#include <binder/Parcel.h>
|
|
|
|
|
|
|
|
#include "SkPoint.h"
|
|
|
|
#include "SkMatrix.h"
|
|
|
|
#include "SkScalar.h"
|
|
|
|
#endif
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
namespace android {
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
static const char* CONFIGURATION_FILE_DIR[] = {
|
|
|
|
"idc/",
|
|
|
|
"keylayout/",
|
|
|
|
"keychars/",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char* CONFIGURATION_FILE_EXTENSION[] = {
|
|
|
|
".idc",
|
|
|
|
".kl",
|
|
|
|
".kcm",
|
|
|
|
};
|
|
|
|
|
2010-12-02 21:50:46 +00:00
|
|
|
static bool isValidNameChar(char ch) {
|
|
|
|
return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
|
|
|
|
}
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
static void appendInputDeviceConfigurationFileRelativePath(String8& path,
|
|
|
|
const String8& name, InputDeviceConfigurationFileType type) {
|
|
|
|
path.append(CONFIGURATION_FILE_DIR[type]);
|
|
|
|
for (size_t i = 0; i < name.length(); i++) {
|
|
|
|
char ch = name[i];
|
2010-12-02 21:50:46 +00:00
|
|
|
if (!isValidNameChar(ch)) {
|
2010-11-30 01:37:49 +00:00
|
|
|
ch = '_';
|
|
|
|
}
|
|
|
|
path.append(&ch, 1);
|
|
|
|
}
|
|
|
|
path.append(CONFIGURATION_FILE_EXTENSION[type]);
|
|
|
|
}
|
|
|
|
|
2010-12-02 21:50:46 +00:00
|
|
|
String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
|
|
|
|
const InputDeviceIdentifier& deviceIdentifier,
|
|
|
|
InputDeviceConfigurationFileType type) {
|
|
|
|
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
|
|
|
|
if (deviceIdentifier.version != 0) {
|
|
|
|
// Try vendor product version.
|
|
|
|
String8 versionPath(getInputDeviceConfigurationFilePathByName(
|
|
|
|
String8::format("Vendor_%04x_Product_%04x_Version_%04x",
|
|
|
|
deviceIdentifier.vendor, deviceIdentifier.product,
|
|
|
|
deviceIdentifier.version),
|
|
|
|
type));
|
|
|
|
if (!versionPath.isEmpty()) {
|
|
|
|
return versionPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try vendor product.
|
|
|
|
String8 productPath(getInputDeviceConfigurationFilePathByName(
|
|
|
|
String8::format("Vendor_%04x_Product_%04x",
|
|
|
|
deviceIdentifier.vendor, deviceIdentifier.product),
|
|
|
|
type));
|
|
|
|
if (!productPath.isEmpty()) {
|
|
|
|
return productPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try device name.
|
|
|
|
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
String8 getInputDeviceConfigurationFilePathByName(
|
2010-11-30 01:37:49 +00:00
|
|
|
const String8& name, InputDeviceConfigurationFileType type) {
|
|
|
|
// Search system repository.
|
|
|
|
String8 path;
|
|
|
|
path.setTo(getenv("ANDROID_ROOT"));
|
|
|
|
path.append("/usr/");
|
|
|
|
appendInputDeviceConfigurationFileRelativePath(path, name, type);
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
LOGD("Probing for system provided input device configuration file: path='%s'", path.string());
|
|
|
|
#endif
|
|
|
|
if (!access(path.string(), R_OK)) {
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
LOGD("Found");
|
|
|
|
#endif
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search user repository.
|
|
|
|
// TODO Should only look here if not in safe mode.
|
|
|
|
path.setTo(getenv("ANDROID_DATA"));
|
|
|
|
path.append("/system/devices/");
|
|
|
|
appendInputDeviceConfigurationFileRelativePath(path, name, type);
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
LOGD("Probing for system user input device configuration file: path='%s'", path.string());
|
|
|
|
#endif
|
|
|
|
if (!access(path.string(), R_OK)) {
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
LOGD("Found");
|
|
|
|
#endif
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not found.
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
LOGD("Probe failed to find input device configuration file: name='%s', type=%d",
|
|
|
|
name.string(), type);
|
|
|
|
#endif
|
|
|
|
return String8();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- InputEvent ---
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
|
2010-07-15 01:48:53 +00:00
|
|
|
void InputEvent::initialize(int32_t deviceId, int32_t source) {
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
mDeviceId = deviceId;
|
2010-07-15 01:48:53 +00:00
|
|
|
mSource = source;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
}
|
|
|
|
|
2010-07-16 00:44:53 +00:00
|
|
|
void InputEvent::initialize(const InputEvent& from) {
|
|
|
|
mDeviceId = from.mDeviceId;
|
|
|
|
mSource = from.mSource;
|
|
|
|
}
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
// --- KeyEvent ---
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
|
2010-06-30 02:20:40 +00:00
|
|
|
bool KeyEvent::hasDefaultAction(int32_t keyCode) {
|
|
|
|
switch (keyCode) {
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_HOME:
|
|
|
|
case AKEYCODE_BACK:
|
|
|
|
case AKEYCODE_CALL:
|
|
|
|
case AKEYCODE_ENDCALL:
|
|
|
|
case AKEYCODE_VOLUME_UP:
|
|
|
|
case AKEYCODE_VOLUME_DOWN:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_VOLUME_MUTE:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_POWER:
|
|
|
|
case AKEYCODE_CAMERA:
|
|
|
|
case AKEYCODE_HEADSETHOOK:
|
|
|
|
case AKEYCODE_MENU:
|
|
|
|
case AKEYCODE_NOTIFICATION:
|
|
|
|
case AKEYCODE_FOCUS:
|
|
|
|
case AKEYCODE_SEARCH:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_MEDIA_PLAY:
|
|
|
|
case AKEYCODE_MEDIA_PAUSE:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
|
|
|
case AKEYCODE_MEDIA_STOP:
|
|
|
|
case AKEYCODE_MEDIA_NEXT:
|
|
|
|
case AKEYCODE_MEDIA_PREVIOUS:
|
|
|
|
case AKEYCODE_MEDIA_REWIND:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_MEDIA_RECORD:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MEDIA_FAST_FORWARD:
|
|
|
|
case AKEYCODE_MUTE:
|
2010-06-30 02:20:40 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KeyEvent::hasDefaultAction() const {
|
|
|
|
return hasDefaultAction(getKeyCode());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KeyEvent::isSystemKey(int32_t keyCode) {
|
|
|
|
switch (keyCode) {
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MENU:
|
|
|
|
case AKEYCODE_SOFT_RIGHT:
|
|
|
|
case AKEYCODE_HOME:
|
|
|
|
case AKEYCODE_BACK:
|
|
|
|
case AKEYCODE_CALL:
|
|
|
|
case AKEYCODE_ENDCALL:
|
|
|
|
case AKEYCODE_VOLUME_UP:
|
|
|
|
case AKEYCODE_VOLUME_DOWN:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_VOLUME_MUTE:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MUTE:
|
|
|
|
case AKEYCODE_POWER:
|
|
|
|
case AKEYCODE_HEADSETHOOK:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_MEDIA_PLAY:
|
|
|
|
case AKEYCODE_MEDIA_PAUSE:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
|
|
|
case AKEYCODE_MEDIA_STOP:
|
|
|
|
case AKEYCODE_MEDIA_NEXT:
|
|
|
|
case AKEYCODE_MEDIA_PREVIOUS:
|
|
|
|
case AKEYCODE_MEDIA_REWIND:
|
2010-11-01 22:24:01 +00:00
|
|
|
case AKEYCODE_MEDIA_RECORD:
|
2010-06-30 23:10:35 +00:00
|
|
|
case AKEYCODE_MEDIA_FAST_FORWARD:
|
|
|
|
case AKEYCODE_CAMERA:
|
|
|
|
case AKEYCODE_FOCUS:
|
|
|
|
case AKEYCODE_SEARCH:
|
2010-06-30 02:20:40 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KeyEvent::isSystemKey() const {
|
|
|
|
return isSystemKey(getKeyCode());
|
|
|
|
}
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
void KeyEvent::initialize(
|
|
|
|
int32_t deviceId,
|
2010-07-15 01:48:53 +00:00
|
|
|
int32_t source,
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
int32_t action,
|
|
|
|
int32_t flags,
|
|
|
|
int32_t keyCode,
|
|
|
|
int32_t scanCode,
|
|
|
|
int32_t metaState,
|
|
|
|
int32_t repeatCount,
|
|
|
|
nsecs_t downTime,
|
|
|
|
nsecs_t eventTime) {
|
2010-07-15 01:48:53 +00:00
|
|
|
InputEvent::initialize(deviceId, source);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
mAction = action;
|
|
|
|
mFlags = flags;
|
|
|
|
mKeyCode = keyCode;
|
|
|
|
mScanCode = scanCode;
|
|
|
|
mMetaState = metaState;
|
|
|
|
mRepeatCount = repeatCount;
|
|
|
|
mDownTime = downTime;
|
|
|
|
mEventTime = eventTime;
|
|
|
|
}
|
|
|
|
|
2010-07-16 00:44:53 +00:00
|
|
|
void KeyEvent::initialize(const KeyEvent& from) {
|
|
|
|
InputEvent::initialize(from);
|
|
|
|
mAction = from.mAction;
|
|
|
|
mFlags = from.mFlags;
|
|
|
|
mKeyCode = from.mKeyCode;
|
|
|
|
mScanCode = from.mScanCode;
|
|
|
|
mMetaState = from.mMetaState;
|
|
|
|
mRepeatCount = from.mRepeatCount;
|
|
|
|
mDownTime = from.mDownTime;
|
|
|
|
mEventTime = from.mEventTime;
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
|
|
|
|
// --- PointerCoords ---
|
|
|
|
|
|
|
|
#ifdef HAVE_ANDROID_OS
|
|
|
|
status_t PointerCoords::readFromParcel(Parcel* parcel) {
|
|
|
|
bits = parcel->readInt32();
|
|
|
|
|
|
|
|
uint32_t count = __builtin_popcount(bits);
|
|
|
|
if (count > MAX_AXES) {
|
|
|
|
return BAD_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
values[i] = parcel->readInt32();
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t PointerCoords::writeToParcel(Parcel* parcel) const {
|
|
|
|
parcel->writeInt32(bits);
|
|
|
|
|
|
|
|
uint32_t count = __builtin_popcount(bits);
|
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
parcel->writeInt32(values[i]);
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void PointerCoords::tooManyAxes(int axis) {
|
|
|
|
LOGW("Could not set value for axis %d because the PointerCoords structure is full and "
|
|
|
|
"cannot contain more than %d axis values.", axis, int(MAX_AXES));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
// --- MotionEvent ---
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
|
|
|
|
void MotionEvent::initialize(
|
|
|
|
int32_t deviceId,
|
2010-07-15 01:48:53 +00:00
|
|
|
int32_t source,
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
int32_t action,
|
2010-09-02 00:01:00 +00:00
|
|
|
int32_t flags,
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
int32_t edgeFlags,
|
|
|
|
int32_t metaState,
|
2010-06-16 08:53:36 +00:00
|
|
|
float xOffset,
|
|
|
|
float yOffset,
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
float xPrecision,
|
|
|
|
float yPrecision,
|
|
|
|
nsecs_t downTime,
|
|
|
|
nsecs_t eventTime,
|
|
|
|
size_t pointerCount,
|
|
|
|
const int32_t* pointerIds,
|
|
|
|
const PointerCoords* pointerCoords) {
|
2010-07-15 01:48:53 +00:00
|
|
|
InputEvent::initialize(deviceId, source);
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
mAction = action;
|
2010-09-02 00:01:00 +00:00
|
|
|
mFlags = flags;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
mEdgeFlags = edgeFlags;
|
|
|
|
mMetaState = metaState;
|
2010-06-16 08:53:36 +00:00
|
|
|
mXOffset = xOffset;
|
|
|
|
mYOffset = yOffset;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
mXPrecision = xPrecision;
|
|
|
|
mYPrecision = yPrecision;
|
|
|
|
mDownTime = downTime;
|
|
|
|
mPointerIds.clear();
|
|
|
|
mPointerIds.appendArray(pointerIds, pointerCount);
|
|
|
|
mSampleEventTimes.clear();
|
|
|
|
mSamplePointerCoords.clear();
|
|
|
|
addSample(eventTime, pointerCoords);
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
|
|
|
|
InputEvent::initialize(other->mDeviceId, other->mSource);
|
|
|
|
mAction = other->mAction;
|
|
|
|
mFlags = other->mFlags;
|
|
|
|
mEdgeFlags = other->mEdgeFlags;
|
|
|
|
mMetaState = other->mMetaState;
|
|
|
|
mXOffset = other->mXOffset;
|
|
|
|
mYOffset = other->mYOffset;
|
|
|
|
mXPrecision = other->mXPrecision;
|
|
|
|
mYPrecision = other->mYPrecision;
|
|
|
|
mDownTime = other->mDownTime;
|
|
|
|
mPointerIds = other->mPointerIds;
|
|
|
|
|
|
|
|
if (keepHistory) {
|
|
|
|
mSampleEventTimes = other->mSampleEventTimes;
|
|
|
|
mSamplePointerCoords = other->mSamplePointerCoords;
|
|
|
|
} else {
|
|
|
|
mSampleEventTimes.clear();
|
|
|
|
mSampleEventTimes.push(other->getEventTime());
|
|
|
|
mSamplePointerCoords.clear();
|
|
|
|
size_t pointerCount = other->getPointerCount();
|
|
|
|
size_t historySize = other->getHistorySize();
|
|
|
|
mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
|
|
|
|
+ (historySize * pointerCount), pointerCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
void MotionEvent::addSample(
|
|
|
|
int64_t eventTime,
|
|
|
|
const PointerCoords* pointerCoords) {
|
|
|
|
mSampleEventTimes.push(eventTime);
|
|
|
|
mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
|
|
|
|
return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
|
|
|
|
return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
|
|
|
|
float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
|
|
|
|
switch (axis) {
|
2011-02-17 21:01:34 +00:00
|
|
|
case AMOTION_EVENT_AXIS_X:
|
2011-02-15 01:03:18 +00:00
|
|
|
value += mXOffset;
|
|
|
|
break;
|
2011-02-17 21:01:34 +00:00
|
|
|
case AMOTION_EVENT_AXIS_Y:
|
2011-02-15 01:03:18 +00:00
|
|
|
value += mYOffset;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
|
|
|
|
size_t pointerIndex, size_t historicalIndex) const {
|
|
|
|
return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
|
|
|
|
size_t historicalIndex) const {
|
|
|
|
return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
|
|
|
|
size_t historicalIndex) const {
|
|
|
|
float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
|
|
|
|
switch (axis) {
|
2011-02-17 21:01:34 +00:00
|
|
|
case AMOTION_EVENT_AXIS_X:
|
2011-02-15 01:03:18 +00:00
|
|
|
value += mXOffset;
|
|
|
|
break;
|
2011-02-17 21:01:34 +00:00
|
|
|
case AMOTION_EVENT_AXIS_Y:
|
2011-02-15 01:03:18 +00:00
|
|
|
value += mYOffset;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
void MotionEvent::offsetLocation(float xOffset, float yOffset) {
|
2010-06-16 08:53:36 +00:00
|
|
|
mXOffset += xOffset;
|
|
|
|
mYOffset += yOffset;
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
|
|
|
|
float* value = c.editAxisValue(axis);
|
|
|
|
if (value) {
|
|
|
|
*value *= scaleFactor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MotionEvent::scale(float scaleFactor) {
|
|
|
|
mXOffset *= scaleFactor;
|
|
|
|
mYOffset *= scaleFactor;
|
|
|
|
mXPrecision *= scaleFactor;
|
|
|
|
mYPrecision *= scaleFactor;
|
|
|
|
|
|
|
|
size_t numSamples = mSamplePointerCoords.size();
|
|
|
|
for (size_t i = 0; i < numSamples; i++) {
|
|
|
|
PointerCoords& c = mSamplePointerCoords.editItemAt(i);
|
|
|
|
// No need to scale pressure or size since they are normalized.
|
|
|
|
// No need to scale orientation since it is meaningless to do so.
|
2011-02-17 21:01:34 +00:00
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_X, scaleFactor);
|
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_Y, scaleFactor);
|
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
|
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
|
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
|
|
|
|
scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
|
2011-02-15 01:03:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_ANDROID_OS
|
|
|
|
static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
|
|
|
|
// Construct and transform a vector oriented at the specified clockwise angle from vertical.
|
|
|
|
// Coordinate system: down is increasing Y, right is increasing X.
|
|
|
|
SkPoint vector;
|
|
|
|
vector.fX = SkFloatToScalar(sinf(angleRadians));
|
|
|
|
vector.fY = SkFloatToScalar(-cosf(angleRadians));
|
|
|
|
matrix->mapVectors(& vector, 1);
|
|
|
|
|
|
|
|
// Derive the transformed vector's clockwise angle from vertical.
|
|
|
|
float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
|
|
|
|
if (result < - M_PI_2) {
|
|
|
|
result += M_PI;
|
|
|
|
} else if (result > M_PI_2) {
|
|
|
|
result -= M_PI;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MotionEvent::transform(const SkMatrix* matrix) {
|
|
|
|
float oldXOffset = mXOffset;
|
|
|
|
float oldYOffset = mYOffset;
|
|
|
|
|
|
|
|
// The tricky part of this implementation is to preserve the value of
|
|
|
|
// rawX and rawY. So we apply the transformation to the first point
|
|
|
|
// then derive an appropriate new X/Y offset that will preserve rawX and rawY.
|
|
|
|
SkPoint point;
|
|
|
|
float rawX = getRawX(0);
|
|
|
|
float rawY = getRawY(0);
|
|
|
|
matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
|
|
|
|
& point);
|
|
|
|
float newX = SkScalarToFloat(point.fX);
|
|
|
|
float newY = SkScalarToFloat(point.fY);
|
|
|
|
float newXOffset = newX - rawX;
|
|
|
|
float newYOffset = newY - rawY;
|
|
|
|
|
|
|
|
mXOffset = newXOffset;
|
|
|
|
mYOffset = newYOffset;
|
|
|
|
|
|
|
|
// Apply the transformation to all samples.
|
|
|
|
size_t numSamples = mSamplePointerCoords.size();
|
|
|
|
for (size_t i = 0; i < numSamples; i++) {
|
|
|
|
PointerCoords& c = mSamplePointerCoords.editItemAt(i);
|
2011-02-17 21:01:34 +00:00
|
|
|
float* xPtr = c.editAxisValue(AMOTION_EVENT_AXIS_X);
|
|
|
|
float* yPtr = c.editAxisValue(AMOTION_EVENT_AXIS_Y);
|
2011-02-15 01:03:18 +00:00
|
|
|
if (xPtr && yPtr) {
|
|
|
|
float x = *xPtr + oldXOffset;
|
|
|
|
float y = *yPtr + oldYOffset;
|
|
|
|
matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point);
|
|
|
|
*xPtr = SkScalarToFloat(point.fX) - newXOffset;
|
|
|
|
*yPtr = SkScalarToFloat(point.fY) - newYOffset;
|
|
|
|
}
|
|
|
|
|
2011-02-17 21:01:34 +00:00
|
|
|
float* orientationPtr = c.editAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
|
2011-02-15 01:03:18 +00:00
|
|
|
if (orientationPtr) {
|
|
|
|
*orientationPtr = transformAngle(matrix, *orientationPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t MotionEvent::readFromParcel(Parcel* parcel) {
|
|
|
|
size_t pointerCount = parcel->readInt32();
|
|
|
|
size_t sampleCount = parcel->readInt32();
|
|
|
|
if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
|
|
|
|
return BAD_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
mDeviceId = parcel->readInt32();
|
|
|
|
mSource = parcel->readInt32();
|
|
|
|
mAction = parcel->readInt32();
|
|
|
|
mFlags = parcel->readInt32();
|
|
|
|
mEdgeFlags = parcel->readInt32();
|
|
|
|
mMetaState = parcel->readInt32();
|
|
|
|
mXOffset = parcel->readFloat();
|
|
|
|
mYOffset = parcel->readFloat();
|
|
|
|
mXPrecision = parcel->readFloat();
|
|
|
|
mYPrecision = parcel->readFloat();
|
|
|
|
mDownTime = parcel->readInt64();
|
|
|
|
|
|
|
|
mPointerIds.clear();
|
|
|
|
mPointerIds.setCapacity(pointerCount);
|
|
|
|
mSampleEventTimes.clear();
|
|
|
|
mSampleEventTimes.setCapacity(sampleCount);
|
|
|
|
mSamplePointerCoords.clear();
|
|
|
|
mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < pointerCount; i++) {
|
|
|
|
mPointerIds.push(parcel->readInt32());
|
|
|
|
}
|
|
|
|
|
|
|
|
while (sampleCount-- > 0) {
|
|
|
|
mSampleEventTimes.push(parcel->readInt64());
|
|
|
|
for (size_t i = 0; i < pointerCount; i++) {
|
|
|
|
mSamplePointerCoords.push();
|
|
|
|
status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
|
2011-02-17 21:01:34 +00:00
|
|
|
if (status) {
|
2011-02-15 01:03:18 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t MotionEvent::writeToParcel(Parcel* parcel) const {
|
|
|
|
size_t pointerCount = mPointerIds.size();
|
|
|
|
size_t sampleCount = mSampleEventTimes.size();
|
|
|
|
|
|
|
|
parcel->writeInt32(pointerCount);
|
|
|
|
parcel->writeInt32(sampleCount);
|
|
|
|
|
|
|
|
parcel->writeInt32(mDeviceId);
|
|
|
|
parcel->writeInt32(mSource);
|
|
|
|
parcel->writeInt32(mAction);
|
|
|
|
parcel->writeInt32(mFlags);
|
|
|
|
parcel->writeInt32(mEdgeFlags);
|
|
|
|
parcel->writeInt32(mMetaState);
|
|
|
|
parcel->writeFloat(mXOffset);
|
|
|
|
parcel->writeFloat(mYOffset);
|
|
|
|
parcel->writeFloat(mXPrecision);
|
|
|
|
parcel->writeFloat(mYPrecision);
|
|
|
|
parcel->writeInt64(mDownTime);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < pointerCount; i++) {
|
|
|
|
parcel->writeInt32(mPointerIds.itemAt(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
const PointerCoords* pc = mSamplePointerCoords.array();
|
|
|
|
for (size_t h = 0; h < sampleCount; h++) {
|
|
|
|
parcel->writeInt64(mSampleEventTimes.itemAt(h));
|
|
|
|
for (size_t i = 0; i < pointerCount; i++) {
|
|
|
|
status_t status = (pc++)->writeToParcel(parcel);
|
2011-02-17 21:01:34 +00:00
|
|
|
if (status) {
|
2011-02-15 01:03:18 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2010-11-30 01:37:49 +00:00
|
|
|
// --- InputDeviceInfo ---
|
2010-07-24 04:28:06 +00:00
|
|
|
|
|
|
|
InputDeviceInfo::InputDeviceInfo() {
|
|
|
|
initialize(-1, String8("uninitialized device info"));
|
|
|
|
}
|
|
|
|
|
|
|
|
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
|
|
|
|
mId(other.mId), mName(other.mName), mSources(other.mSources),
|
|
|
|
mKeyboardType(other.mKeyboardType),
|
|
|
|
mMotionRanges(other.mMotionRanges) {
|
|
|
|
}
|
|
|
|
|
|
|
|
InputDeviceInfo::~InputDeviceInfo() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputDeviceInfo::initialize(int32_t id, const String8& name) {
|
|
|
|
mId = id;
|
|
|
|
mName = name;
|
|
|
|
mSources = 0;
|
|
|
|
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
|
|
|
|
mMotionRanges.clear();
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t axis) const {
|
|
|
|
ssize_t index = mMotionRanges.indexOfKey(axis);
|
2010-07-24 04:28:06 +00:00
|
|
|
return index >= 0 ? & mMotionRanges.valueAt(index) : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputDeviceInfo::addSource(uint32_t source) {
|
|
|
|
mSources |= source;
|
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
void InputDeviceInfo::addMotionRange(int32_t axis, float min, float max,
|
2010-07-24 04:28:06 +00:00
|
|
|
float flat, float fuzz) {
|
|
|
|
MotionRange range = { min, max, flat, fuzz };
|
2011-02-15 01:03:18 +00:00
|
|
|
addMotionRange(axis, range);
|
2010-07-24 04:28:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-15 01:03:18 +00:00
|
|
|
void InputDeviceInfo::addMotionRange(int32_t axis, const MotionRange& range) {
|
|
|
|
mMotionRanges.add(axis, range);
|
2010-07-24 04:28:06 +00:00
|
|
|
}
|
|
|
|
|
Native input dispatch rewrite work in progress.
The old dispatch mechanism has been left in place and continues to
be used by default for now. To enable native input dispatch,
edit the ENABLE_NATIVE_DISPATCH constant in WindowManagerPolicy.
Includes part of the new input event NDK API. Some details TBD.
To wire up input dispatch, as the ViewRoot adds a window to the
window session it receives an InputChannel object as an output
argument. The InputChannel encapsulates the file descriptors for a
shared memory region and two pipe end-points. The ViewRoot then
provides the InputChannel to the InputQueue. Behind the
scenes, InputQueue simply attaches handlers to the native PollLoop object
that underlies the MessageQueue. This way MessageQueue doesn't need
to know anything about input dispatch per-se, it just exposes (in native
code) a PollLoop that other components can use to monitor file descriptor
state changes.
There can be zero or more targets for any given input event. Each
input target is specified by its input channel and some parameters
including flags, an X/Y coordinate offset, and the dispatch timeout.
An input target can request either synchronous dispatch (for foreground apps)
or asynchronous dispatch (fire-and-forget for wallpapers and "outside"
targets). Currently, finding the appropriate input targets for an event
requires a call back into the WindowManagerServer from native code.
In the future this will be refactored to avoid most of these callbacks
except as required to handle pending focus transitions.
End-to-end event dispatch mostly works!
To do: event injection, rate limiting, ANRs, testing, optimization, etc.
Change-Id: I8c36b2b9e0a2d27392040ecda0f51b636456de25
2010-04-23 01:58:52 +00:00
|
|
|
} // namespace android
|