mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1249915 - Add ability to synthesize native touch events on Fennec for mochitests. r=snorp
MozReview-Commit-ID: Dit8QhqJSYc
This commit is contained in:
parent
6fb25463b4
commit
650f50e205
@ -23,6 +23,8 @@ import android.graphics.RectF;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -106,6 +108,8 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
*/
|
||||
private volatile boolean mContentDocumentIsDisplayed;
|
||||
|
||||
private SynthesizedEventState mPointerState;
|
||||
|
||||
public GeckoLayerClient(Context context, LayerView view, EventDispatcher eventDispatcher) {
|
||||
// we can fill these in with dummy values because they are always written
|
||||
// to before being read
|
||||
@ -709,6 +713,141 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
layersUpdated, paintSyncId);
|
||||
}
|
||||
|
||||
class PointerInfo {
|
||||
public int pointerId;
|
||||
public int screenX;
|
||||
public int screenY;
|
||||
public double pressure;
|
||||
public int orientation;
|
||||
|
||||
public MotionEvent.PointerCoords getCoords() {
|
||||
MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
|
||||
coords.orientation = orientation;
|
||||
coords.pressure = (float)pressure;
|
||||
coords.x = screenX;
|
||||
coords.y = screenY;
|
||||
return coords;
|
||||
}
|
||||
}
|
||||
|
||||
class SynthesizedEventState {
|
||||
public final ArrayList<PointerInfo> pointers;
|
||||
public long downTime;
|
||||
|
||||
SynthesizedEventState() {
|
||||
pointers = new ArrayList<PointerInfo>();
|
||||
}
|
||||
|
||||
int getPointerIndex(int pointerId) {
|
||||
for (int i = 0; i < pointers.size(); i++) {
|
||||
if (pointers.get(i).pointerId == pointerId) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int addPointer(int pointerId) {
|
||||
PointerInfo info = new PointerInfo();
|
||||
info.pointerId = pointerId;
|
||||
pointers.add(info);
|
||||
return pointers.size() - 1;
|
||||
}
|
||||
|
||||
int[] getPointerIds() {
|
||||
int[] ids = new int[pointers.size()];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
ids[i] = pointers.get(i).pointerId;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
MotionEvent.PointerCoords[] getPointerCoords() {
|
||||
MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointers.size()];
|
||||
for (int i = 0; i < coords.length; i++) {
|
||||
coords[i] = pointers.get(i).getCoords();
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public void synthesizeNativeTouchPoint(int pointerId, int eventType, int screenX,
|
||||
int screenY, double pressure, int orientation)
|
||||
{
|
||||
if (mPointerState == null) {
|
||||
mPointerState = new SynthesizedEventState();
|
||||
}
|
||||
|
||||
// Find the pointer if it already exists
|
||||
int pointerIndex = mPointerState.getPointerIndex(pointerId);
|
||||
|
||||
// Event-specific handling
|
||||
switch (eventType) {
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (pointerIndex < 0) {
|
||||
Log.d(LOGTAG, "Requested synthesis of a pointer-up for a pointer that doesn't exist!");
|
||||
return;
|
||||
}
|
||||
if (mPointerState.pointers.size() == 1) {
|
||||
// Last pointer is going up
|
||||
eventType = MotionEvent.ACTION_UP;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (pointerIndex < 0) {
|
||||
Log.d(LOGTAG, "Requested synthesis of a pointer-cancel for a pointer that doesn't exist!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (pointerIndex < 0) {
|
||||
// Adding a new pointer
|
||||
pointerIndex = mPointerState.addPointer(pointerId);
|
||||
if (pointerIndex == 0) {
|
||||
// first pointer
|
||||
eventType = MotionEvent.ACTION_DOWN;
|
||||
mPointerState.downTime = SystemClock.uptimeMillis();
|
||||
}
|
||||
} else {
|
||||
// We're moving an existing pointer
|
||||
eventType = MotionEvent.ACTION_MOVE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the pointer with the new info
|
||||
PointerInfo info = mPointerState.pointers.get(pointerIndex);
|
||||
info.screenX = screenX;
|
||||
info.screenY = screenY;
|
||||
info.pressure = pressure;
|
||||
info.orientation = orientation;
|
||||
|
||||
// Dispatch the event
|
||||
int action = (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
|
||||
action &= MotionEvent.ACTION_POINTER_INDEX_MASK;
|
||||
action |= (eventType & MotionEvent.ACTION_MASK);
|
||||
final MotionEvent event = MotionEvent.obtain(mPointerState.downTime,
|
||||
SystemClock.uptimeMillis(), action, mPointerState.pointers.size(),
|
||||
mPointerState.getPointerIds(), mPointerState.getPointerCoords(),
|
||||
0, 0, 0, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
|
||||
mView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
event.offsetLocation(0, mView.getSurfaceTranslation());
|
||||
mView.dispatchTouchEvent(event);
|
||||
}
|
||||
});
|
||||
|
||||
// Forget about removed pointers
|
||||
if (eventType == MotionEvent.ACTION_POINTER_UP ||
|
||||
eventType == MotionEvent.ACTION_UP ||
|
||||
eventType == MotionEvent.ACTION_CANCEL)
|
||||
{
|
||||
mPointerState.pointers.remove(pointerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(allowMultithread = true)
|
||||
public LayerRenderer.Frame createFrame() {
|
||||
// Create the shaders and textures if necessary.
|
||||
|
@ -1437,6 +1437,14 @@ auto GeckoLayerClient::SyncViewportInfo(int32_t a0, int32_t a1, int32_t a2, int3
|
||||
return mozilla::jni::Method<SyncViewportInfo_t>::Call(GeckoLayerClient::mCtx, nullptr, a0, a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
|
||||
constexpr char GeckoLayerClient::SynthesizeNativeTouchPoint_t::name[];
|
||||
constexpr char GeckoLayerClient::SynthesizeNativeTouchPoint_t::signature[];
|
||||
|
||||
auto GeckoLayerClient::SynthesizeNativeTouchPoint(int32_t a0, int32_t a1, int32_t a2, int32_t a3, double a4, int32_t a5) const -> void
|
||||
{
|
||||
return mozilla::jni::Method<SynthesizeNativeTouchPoint_t>::Call(GeckoLayerClient::mCtx, nullptr, a0, a1, a2, a3, a4, a5);
|
||||
}
|
||||
|
||||
template<> const char mozilla::jni::Context<ImmutableViewportMetrics, jobject>::name[] =
|
||||
"org/mozilla/gecko/gfx/ImmutableViewportMetrics";
|
||||
|
||||
|
@ -3370,6 +3370,27 @@ public:
|
||||
|
||||
auto SyncViewportInfo(int32_t, int32_t, int32_t, int32_t, float, bool, int32_t) const -> mozilla::jni::Object::LocalRef;
|
||||
|
||||
struct SynthesizeNativeTouchPoint_t {
|
||||
typedef GeckoLayerClient Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
double,
|
||||
int32_t> Args;
|
||||
static constexpr char name[] = "synthesizeNativeTouchPoint";
|
||||
static constexpr char signature[] =
|
||||
"(IIIIDI)V";
|
||||
static const bool isStatic = false;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
};
|
||||
|
||||
auto SynthesizeNativeTouchPoint(int32_t, int32_t, int32_t, int32_t, double, int32_t) const -> void;
|
||||
|
||||
static const bool isMultithreaded = true;
|
||||
|
||||
};
|
||||
|
@ -3263,6 +3263,45 @@ nsWindow::GetIMEUpdatePreference()
|
||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||
TouchPointerState aPointerState,
|
||||
ScreenIntPoint aPointerScreenPoint,
|
||||
double aPointerPressure,
|
||||
uint32_t aPointerOrientation,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
mozilla::widget::AutoObserverNotifier notifier(aObserver, "touchpoint");
|
||||
|
||||
int eventType;
|
||||
switch (aPointerState) {
|
||||
case TOUCH_CONTACT:
|
||||
// This could be a ACTION_DOWN or ACTION_MOVE depending on the
|
||||
// existing state; it is mapped to the right thing in Java.
|
||||
eventType = sdk::MotionEvent::ACTION_POINTER_DOWN;
|
||||
break;
|
||||
case TOUCH_REMOVE:
|
||||
// This could be turned into a ACTION_UP in Java
|
||||
eventType = sdk::MotionEvent::ACTION_POINTER_UP;
|
||||
break;
|
||||
case TOUCH_CANCEL:
|
||||
eventType = sdk::MotionEvent::ACTION_CANCEL;
|
||||
break;
|
||||
case TOUCH_HOVER: // not supported for now
|
||||
default:
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mGLControllerSupport);
|
||||
GeckoLayerClient::LocalRef client = mGLControllerSupport->GetLayerClient();
|
||||
client->SynthesizeNativeTouchPoint(aPointerId, eventType,
|
||||
aPointerScreenPoint.x, aPointerScreenPoint.y, aPointerPressure,
|
||||
aPointerOrientation);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager,
|
||||
LayoutDeviceIntRect aRect)
|
||||
|
@ -186,6 +186,13 @@ public:
|
||||
const FrameMetrics::ViewID& aViewId,
|
||||
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
|
||||
|
||||
nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||
TouchPointerState aPointerState,
|
||||
ScreenIntPoint aPointerScreenPoint,
|
||||
double aPointerPressure,
|
||||
uint32_t aPointerOrientation,
|
||||
nsIObserver* aObserver) override;
|
||||
|
||||
protected:
|
||||
void BringToFront();
|
||||
nsWindow *FindTopLevel();
|
||||
|
Loading…
Reference in New Issue
Block a user