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.os.SystemClock;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -106,6 +108,8 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
|||||||
*/
|
*/
|
||||||
private volatile boolean mContentDocumentIsDisplayed;
|
private volatile boolean mContentDocumentIsDisplayed;
|
||||||
|
|
||||||
|
private SynthesizedEventState mPointerState;
|
||||||
|
|
||||||
public GeckoLayerClient(Context context, LayerView view, EventDispatcher eventDispatcher) {
|
public GeckoLayerClient(Context context, LayerView view, EventDispatcher eventDispatcher) {
|
||||||
// we can fill these in with dummy values because they are always written
|
// we can fill these in with dummy values because they are always written
|
||||||
// to before being read
|
// to before being read
|
||||||
@ -709,6 +713,141 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
|||||||
layersUpdated, paintSyncId);
|
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)
|
@WrapForJNI(allowMultithread = true)
|
||||||
public LayerRenderer.Frame createFrame() {
|
public LayerRenderer.Frame createFrame() {
|
||||||
// Create the shaders and textures if necessary.
|
// 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);
|
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[] =
|
template<> const char mozilla::jni::Context<ImmutableViewportMetrics, jobject>::name[] =
|
||||||
"org/mozilla/gecko/gfx/ImmutableViewportMetrics";
|
"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;
|
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;
|
static const bool isMultithreaded = true;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -3263,6 +3263,45 @@ nsWindow::GetIMEUpdatePreference()
|
|||||||
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
|
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
|
void
|
||||||
nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager,
|
nsWindow::DrawWindowUnderlay(LayerManagerComposite* aManager,
|
||||||
LayoutDeviceIntRect aRect)
|
LayoutDeviceIntRect aRect)
|
||||||
|
@ -186,6 +186,13 @@ public:
|
|||||||
const FrameMetrics::ViewID& aViewId,
|
const FrameMetrics::ViewID& aViewId,
|
||||||
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
|
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
|
||||||
|
|
||||||
|
nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
|
||||||
|
TouchPointerState aPointerState,
|
||||||
|
ScreenIntPoint aPointerScreenPoint,
|
||||||
|
double aPointerPressure,
|
||||||
|
uint32_t aPointerOrientation,
|
||||||
|
nsIObserver* aObserver) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BringToFront();
|
void BringToFront();
|
||||||
nsWindow *FindTopLevel();
|
nsWindow *FindTopLevel();
|
||||||
|
Loading…
Reference in New Issue
Block a user