Skip to content

Commit

Permalink
Adding support for horizontal scrolling (touch pad and touch screen)
Browse files Browse the repository at this point in the history
Also, adding support for devices which report fractional scrolling
amounts. E.g. a mouse with a continuous mouse wheel, or a Mac touch
pad. This is currently only supported in lwjgl3. It can probably be
added to android and maybe to gwt.

InputProcessor scrolled method now receives scroll amount for X and
Y. Changed type to float to support devices which report fractional
scroll amounts. Updated InputEvent in scene2d accordingly: added
scrollAmountX, scrollAmountY attributes and corresponding setters and
getters.

Input event queue can receive float scrolling values. Since the queue
stores the events with integers. Scrolling values are stored in fixed
precision format, with 8 bits for the fraction.

Updated backends accordingly: lwjgl, lwjgl3, android and gwt.
  • Loading branch information
Julien Pauty committed Aug 31, 2020
1 parent f1aaeef commit 68638a6
Show file tree
Hide file tree
Showing 18 changed files with 60 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -22,6 +22,7 @@
- API Change: Removed arm abi from SharedLibraryLoader
- API Addition: Added a Lwjgl3ApplicationConfiguration#foregroundFPS option.
- API Change: Utility classes are now final and have a private constructor to prevent instantiation.
- API Change: InputProcessor scrolled method now receives scroll amount for X and Y. Changed type to float to support devices which report fractional scroll amounts. Updated InputEvent in scene2d accordingly: added scrollAmountX, scrollAmountY attributes and corresponding setters and getters.

[1.9.11]
- Update to MobiVM 2.3.8
Expand Down
Expand Up @@ -35,7 +35,8 @@ public boolean onGenericMotion (MotionEvent event, DefaultAndroidInput input) {
final int action = event.getAction() & MotionEvent.ACTION_MASK;

int x = 0, y = 0;
int scrollAmount = 0;
int scrollAmountX = 0;
int scrollAmountY = 0;

long timeStamp = System.nanoTime();
synchronized (input) {
Expand All @@ -44,15 +45,16 @@ public boolean onGenericMotion (MotionEvent event, DefaultAndroidInput input) {
x = (int)event.getX();
y = (int)event.getY();
if ((x != deltaX) || (y != deltaY)) { // Avoid garbage events
postTouchEvent(input, TouchEvent.TOUCH_MOVED, x, y, 0, timeStamp);
postTouchEvent(input, TouchEvent.TOUCH_MOVED, x, y, 0, 0, timeStamp);
deltaX = x;
deltaY = y;
}
break;

case MotionEvent.ACTION_SCROLL:
scrollAmount = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_VSCROLL));
postTouchEvent(input, TouchEvent.TOUCH_SCROLLED, 0, 0, scrollAmount, timeStamp);
scrollAmountY = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_VSCROLL));
scrollAmountX = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_HSCROLL));
postTouchEvent(input, TouchEvent.TOUCH_SCROLLED, 0, 0, scrollAmountX, scrollAmountY, timeStamp);

}
}
Expand All @@ -75,13 +77,14 @@ else if (action == MotionEvent.ACTION_SCROLL)
Gdx.app.log("AndroidMouseHandler", "action " + actionStr);
}

private void postTouchEvent (DefaultAndroidInput input, int type, int x, int y, int scrollAmount, long timeStamp) {
private void postTouchEvent (DefaultAndroidInput input, int type, int x, int y, int scrollAmountX, int scrollAmountY, long timeStamp) {
TouchEvent event = input.usedTouchEvents.obtain();
event.timeStamp = timeStamp;
event.x = x;
event.y = y;
event.type = type;
event.scrollAmount = scrollAmount;
event.scrollAmountX = scrollAmountX;
event.scrollAmountY = scrollAmountY;
input.touchEvents.add(event);
}

Expand Down
Expand Up @@ -77,7 +77,8 @@ static class TouchEvent {
int type;
int x;
int y;
int scrollAmount;
int scrollAmountX;
int scrollAmountY;
int button;
int pointer;
}
Expand Down Expand Up @@ -419,7 +420,7 @@ public void processEvents () {
processor.mouseMoved(e.x, e.y);
break;
case TouchEvent.TOUCH_SCROLLED:
processor.scrolled(e.scrollAmount);
processor.scrolled(e.scrollAmountX,e.scrollAmountY);
}
usedTouchEvents.free(e);
}
Expand Down
Expand Up @@ -367,7 +367,7 @@ public void processEvents () {
processor.mouseMoved(e.x, e.y);
break;
case TouchEvent.TOUCH_SCROLLED:
processor.scrolled(e.scrollAmount);
processor.scrolled(0, e.scrollAmount);
}
usedTouchEvents.free(e);
}
Expand Down
Expand Up @@ -383,7 +383,7 @@ void processEvents () {
processor.mouseMoved(e.x, e.y);
break;
case TouchEvent.TOUCH_SCROLLED:
processor.scrolled(e.scrollAmount);
processor.scrolled(0, e.scrollAmount);
break;
}
usedTouchEvents.free(e);
Expand Down
Expand Up @@ -87,31 +87,10 @@ public void invoke(long window, int codepoint) {
};

private GLFWScrollCallback scrollCallback = new GLFWScrollCallback() {
private long pauseTime = 250000000L; //250ms
private float scrollYRemainder;
private long lastScrollEventTime;
@Override
public void invoke(long window, double scrollX, double scrollY) {
DefaultLwjgl3Input.this.window.getGraphics().requestRendering();
if (scrollYRemainder > 0 && scrollY < 0 || scrollYRemainder < 0 && scrollY > 0 ||
TimeUtils.nanoTime() - lastScrollEventTime > pauseTime ) {
// fire a scroll event immediately:
// - if the scroll direction changes;
// - if the user did not move the wheel for more than 250ms
scrollYRemainder = 0;
int scrollAmount = (int)-Math.signum(scrollY);
eventQueue.scrolled(scrollAmount);
lastScrollEventTime = TimeUtils.nanoTime();
}
else {
scrollYRemainder += scrollY;
while (Math.abs(scrollYRemainder) >= 1) {
int scrollAmount = (int)-Math.signum(scrollY);
eventQueue.scrolled(scrollAmount);
lastScrollEventTime = TimeUtils.nanoTime();
scrollYRemainder += scrollAmount;
}
}
eventQueue.scrolled(-(float)scrollX, -(float)scrollY);
}
};

Expand Down
Expand Up @@ -679,7 +679,7 @@ private void handleEvent (NativeEvent e) {
}
if (e.getType().equals(getMouseWheelEvent())) {
if (processor != null) {
processor.scrolled((int)getMouseWheelVelocity(e));
processor.scrolled(0, (int)getMouseWheelVelocity(e));
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
Expand Down
Expand Up @@ -350,11 +350,11 @@ public OrthoCamController (OrthographicCamera camera) {
}

@Override
public boolean scrolled (int amount) {
worldCamera.zoom += amount * 0.01f;
public boolean scrolled (float amountX, float amountY) {
worldCamera.zoom += amountY * 0.01f;
worldCamera.zoom = MathUtils.clamp(worldCamera.zoom, 0.01f, 5000);
worldCamera.update();
return super.scrolled(amount);
return super.scrolled(amountX,amountY);
}

@Override
Expand Down Expand Up @@ -599,7 +599,7 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion gdx/src/com/badlogic/gdx/InputAdapter.java
Expand Up @@ -50,7 +50,7 @@ public boolean mouseMoved (int screenX, int screenY) {
}

@Override
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
return false;
}
}
9 changes: 5 additions & 4 deletions gdx/src/com/badlogic/gdx/InputEventQueue.java
Expand Up @@ -92,7 +92,7 @@ public void drain () {
localProcessor.mouseMoved(q[i++], q[i++]);
break;
case SCROLLED:
localProcessor.scrolled(q[i++]);
localProcessor.scrolled(q[i++] / 256f, q[i++] / 256f);
break;
default:
throw new RuntimeException();
Expand Down Expand Up @@ -133,7 +133,7 @@ private synchronized int next (int nextType, int i) {
i += 2;
break;
case SCROLLED:
i++;
i += 2;
break;
default:
throw new RuntimeException();
Expand Down Expand Up @@ -218,10 +218,11 @@ public synchronized boolean mouseMoved (int screenX, int screenY) {
return false;
}

public synchronized boolean scrolled (int amount) {
public synchronized boolean scrolled(float amountX, float amountY) {
queue.add(SCROLLED);
queueTime();
queue.add(amount);
queue.add((int)(amountX * 256));
queue.add((int)(amountY * 256));
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions gdx/src/com/badlogic/gdx/InputMultiplexer.java
Expand Up @@ -150,11 +150,11 @@ public boolean mouseMoved (int screenX, int screenY) {
return false;
}

public boolean scrolled (int amount) {
public boolean scrolled (float amountX,float amountY) {
Object[] items = processors.begin();
try {
for (int i = 0, n = processors.size; i < n; i++)
if (((InputProcessor)items[i]).scrolled(amount)) return true;
if (((InputProcessor)items[i]).scrolled(amountX, amountY)) return true;
} finally {
processors.end();
}
Expand Down
5 changes: 3 additions & 2 deletions gdx/src/com/badlogic/gdx/InputProcessor.java
Expand Up @@ -67,7 +67,8 @@ public interface InputProcessor {
public boolean mouseMoved (int screenX, int screenY);

/** Called when the mouse wheel was scrolled. Will not be called on iOS.
* @param amount the scroll amount, -1 or 1 depending on the direction the wheel was scrolled.
* @param amountX the horizontal scroll amount, negative or positive depending on the direction the wheel was scrolled.
* @param amountY the vertical scroll amount, negative or positive depending on the direction the wheel was scrolled.
* @return whether the input was processed. */
public boolean scrolled (int amount);
public boolean scrolled (float amountX, float amountY);
}
Expand Up @@ -203,8 +203,8 @@ public boolean touchDragged (int screenX, int screenY, int pointer) {
}

@Override
public boolean scrolled (int amount) {
return zoom(amount * scrollFactor * translateUnits);
public boolean scrolled (float amountX, float amountY) {
return zoom(amountY * scrollFactor * translateUnits);
}

public boolean zoom (float amount) {
Expand Down
2 changes: 1 addition & 1 deletion gdx/src/com/badlogic/gdx/input/RemoteSender.java
Expand Up @@ -198,7 +198,7 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
return false;
}

Expand Down
22 changes: 15 additions & 7 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java
Expand Up @@ -24,8 +24,8 @@
* @see InputListener */
public class InputEvent extends Event {
private Type type;
private float stageX, stageY;
private int pointer, button, keyCode, scrollAmount;
private float stageX, stageY, scrollAmountX, scrollAmountY;
private int pointer, button, keyCode;
private char character;
private @Null Actor relatedActor;
private boolean touchFocus = true;
Expand Down Expand Up @@ -103,13 +103,21 @@ public void setCharacter (char character) {
this.character = character;
}

/** The amount the mouse was scrolled. Valid for: scrolled. */
public int getScrollAmount () {
return scrollAmount;
/** The amount the mouse was scrolled horizontally. Valid for: scrolled. */
public float getScrollAmountX () {
return scrollAmountX;
}
/** The amount the mouse was scrolled vertically. Valid for: scrolled. */
public float getScrollAmountY () {
return scrollAmountY;
}

public void setScrollAmountX (float scrollAmount) {
this.scrollAmountX = scrollAmount;
}

public void setScrollAmount (int scrollAmount) {
this.scrollAmount = scrollAmount;
public void setScrollAmountY (float scrollAmount) {
this.scrollAmountY = scrollAmount;
}

/** The actor related to the event. Valid for: enter and exit. For enter, this is the actor being exited, or null. For exit,
Expand Down
4 changes: 2 additions & 2 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java
Expand Up @@ -74,7 +74,7 @@ public boolean handle (Event e) {
case mouseMoved:
return mouseMoved(event, tmpCoords.x, tmpCoords.y);
case scrolled:
return scrolled(event, tmpCoords.x, tmpCoords.y, event.getScrollAmount());
return scrolled(event, tmpCoords.x, tmpCoords.y, event.getScrollAmountX(), event.getScrollAmountY());
case enter:
enter(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getRelatedActor());
return false;
Expand Down Expand Up @@ -128,7 +128,7 @@ public void exit (InputEvent event, float x, float y, int pointer, @Null Actor t
}

/** Called when the mouse wheel has been scrolled. When true is returned, the event is {@link Event#handle() handled}. */
public boolean scrolled (InputEvent event, float x, float y, int amount) {
public boolean scrolled (InputEvent event, float x, float y, float amountX, float amountY) {
return false;
}

Expand Down
5 changes: 3 additions & 2 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java
Expand Up @@ -386,15 +386,16 @@ public boolean mouseMoved (int screenX, int screenY) {

/** Applies a mouse scroll event to the stage and returns true if an actor in the scene {@link Event#handle() handled} the
* event. This event only occurs on the desktop. */
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
Actor target = scrollFocus == null ? root : scrollFocus;

screenToStageCoordinates(tempCoords.set(mouseScreenX, mouseScreenY));

InputEvent event = Pools.obtain(InputEvent.class);
event.setStage(this);
event.setType(InputEvent.Type.scrolled);
event.setScrollAmount(amount);
event.setScrollAmountX(amountX);
event.setScrollAmountY(amountY);
event.setStageX(tempCoords.x);
event.setStageY(tempCoords.y);
target.fire(event);
Expand Down
11 changes: 5 additions & 6 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java
Expand Up @@ -214,13 +214,12 @@ public boolean handle (Event event) {
addListener(flickScrollListener);

addListener(new InputListener() {
public boolean scrolled (InputEvent event, float x, float y, int amount) {
public boolean scrolled (InputEvent event, float x, float y, float scrollAmountX, float scrollAmountY) {
setScrollbarsVisible(true);
if (scrollY)
setScrollY(amountY + getMouseWheelY() * amount);
else if (scrollX) //
setScrollX(amountX + getMouseWheelX() * amount);
else
if (scrollY || scrollX) {
setScrollY(amountY + getMouseWheelY() * scrollAmountY);
setScrollX(amountX + getMouseWheelX() * scrollAmountX);
} else
return false;
return true;
}
Expand Down

0 comments on commit 68638a6

Please sign in to comment.