Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #13406 from etiennesegonzac/bug-919492-app-to-app-…
Browse files Browse the repository at this point in the history
…edge-gesture

Bug 919492 - Adding edge gestures for app-to-app fast switching. r=alive
  • Loading branch information
etiennesegonzac committed Nov 7, 2013
2 parents 6a194fc + f480d5e commit 55cf586
Show file tree
Hide file tree
Showing 20 changed files with 2,136 additions and 36 deletions.
7 changes: 7 additions & 0 deletions apps/settings/elements/about_more_info_developer.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ <h2 data-l10n-id="debug">Debug</h2>
</label>
<a data-l10n-id="homegesture-enabled">Home gesture enabled</a>
</li>
<li id="edgesgesture">
<label class="pack-checkbox">
<input type="checkbox" name="edgesgesture.enabled"/>
<span></span>
</label>
<a data-l10n-id="edgesgesture-enabled">Edges gesture enabled</a>
</li>
<li>
<label class="pack-checkbox">
<input type="checkbox" name="debug.gaia.enabled"/>
Expand Down
1 change: 1 addition & 0 deletions apps/settings/locales/settings.en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ launch-ftu=Launch first time use
no-ftu=No first time use app found
software-button-enabled=Enable software home button
homegesture-enabled=Home gesture enabled
edgesgesture-enabled=Edges gesture enabled
debug-gaia-enabled=Gaia debug traces

# Device :: Battery
Expand Down
8 changes: 8 additions & 0 deletions apps/system/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@
<script defer src="js/window_manager.js"></script>
<script defer src="js/visibility_manager.js"></script>

<!-- Edge Gestures -->
<script defer src="js/stack_manager.js"></script>
<script defer src="js/sheets_transition.js"></script>
<script defer src="js/edge_swipe_detector.js"></script>
<link rel="stylesheet" type="text/css" href="style/edges/edges.css">

<!-- Entry Sheet -->
<link rel="stylesheet" type="text/css" href="style/entry_sheet/entry_sheet.css">
<script defer src="js/entry_sheet.js"></script>
Expand Down Expand Up @@ -1216,6 +1222,8 @@ <h1 data-l10n-id="deviceMenu">Device menu</h1>
</div>
</div>

<div id="left-panel" class="gesture-panel disabled" data-z-index-level="gesture-panel"></div>
<div id="right-panel" class="gesture-panel disabled" data-z-index-level="gesture-panel"></div>
<div id="bottom-panel" class="gesture-panel" data-z-index-level="gesture-panel"></div>
<div id="software-buttons" data-z-index-level="software-buttons">
<button id="software-home-button"></button>
Expand Down
232 changes: 232 additions & 0 deletions apps/system/js/edge_swipe_detector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
'use strict';

var EdgeSwipeDetector = {
previous: document.getElementById('left-panel'),
next: document.getElementById('right-panel'),
screen: document.getElementById('screen'),

init: function esd_init() {
window.addEventListener('homescreenopening', this);
window.addEventListener('appopen', this);
window.addEventListener('launchapp', this);
window.addEventListener('launchwrapper', this);

['touchstart', 'touchmove', 'touchend'].forEach(function(e) {
this.previous.addEventListener(e, this);
this.next.addEventListener(e, this);
}, this);

SettingsListener.observe('edgesgesture.enabled', false,
this.settingUpdate.bind(this));
},

_settingEnabled: false,

settingUpdate: function esd_settingUpdate(enabled) {
this._settingEnabled = enabled;
this._updateEnabled();
},

_lifecycleEnabled: false,

handleEvent: function esd_handleEvent(e) {
switch (e.type) {
case 'appopen':
this.screen.classList.add('edges');
break;
case 'homescreenopening':
this.screen.classList.remove('edges');
this._lifecycleEnabled = false;
this._updateEnabled();
break;
case 'launchapp':
case 'launchwrapper':
if (!e.detail.stayBackground) {
this._lifecycleEnabled = true;
this._updateEnabled();
}
break;
case 'touchstart':
this._touchStart(e);
break;
case 'touchmove':
this._touchMove(e);
break;
case 'touchend':
this._touchEnd(e);
break;
}
},

_updateEnabled: function esd_updateEnabled() {
var enabled = this._lifecycleEnabled && this._settingEnabled;
this.previous.classList.toggle('disabled', !enabled);
this.next.classList.toggle('disabled', !enabled);
},

_touchStartEvt: null,
_startDate: null,
_startX: null,
_deltaX: null,
_startY: null,
_deltaY: null,
_forwardTimeout: null,

_progress: null,
_winWidth: null,
_direction: null,
_notSwiping: null,

_touchStart: function esd_touchStart(e) {
this._winWidth = window.innerWidth;
this._direction = (e.target == this.next) ? 'rtl' : 'ltr';
this._touchStartEvt = e;
this._startDate = Date.now();

this._iframe = StackManager.getCurrent().iframe;

var touch = e.changedTouches[0];
this._startX = touch.screenX;
this._startY = touch.screenY;
this._deltaX = 0;
this._deltaY = 0;
this._notSwiping = false;

this._clearForwardTimeout();
this._forwardTimeout = setTimeout((function longTouch() {
// Didn't move for a while after the touchstart,
// this isn't a swipe
this._forwardTimeout = null;
this._notSwiping = true;
this._sendTouchEvent(this._touchStartEvt);
}).bind(this), 300);

SheetsTransition.begin(this._direction);
},

_touchMove: function esd_touchMove(e) {
var touch = e.touches[0];
this._deltaX = Math.abs(touch.screenX - this._startX);
this._deltaY = Math.abs(touch.screenY - this._startY);
this._progress = this._deltaX / this._winWidth;

if (this._notSwiping) {
this._sendTouchEvent(e);
return;
}

this._checkIfSwiping(e);

if (this._deltaX > 5) {
this._clearForwardTimeout();
SheetsTransition.moveInDirection(this._direction, this._progress);
}
},

_touchEnd: function esd_touchEnd(e) {
if ((this._deltaX < 5) && (this._deltaY < 5)) {
this._sendTap(e);
this._notSwiping = true;
} else if (this._notSwiping) {
this._sendTouchEvent(e);
}

this._clearForwardTimeout();

var deltaT = Date.now() - this._startDate;
var speed = this._progress / deltaT; // progress / ms
var inertia = speed * 120; // 120 ms of intertia
var adjustedProgress = (this._progress + inertia);

if (adjustedProgress < 0.33 || this._notSwiping) {
SheetsTransition.snapInPlace();
SheetsTransition.end();
return;
}

var direction = this._direction;
if (direction == 'ltr') {
SheetsTransition.snapBack(speed);
} else {
SheetsTransition.snapForward(speed);
}

SheetsTransition.end(function afterTransition() {
if (direction == 'ltr') {
StackManager.goPrev();
} else {
StackManager.goNext();
}
});
},

_clearForwardTimeout: function esd_clearForwardTimeout() {
if (this._forwardTimeout) {
clearTimeout(this._forwardTimeout);
this._forwardTimeout = null;
}
},

_checkIfSwiping: function esd_checkIfSwiping(e) {
if ((this._deltaX * 2 < this._deltaY) &&
(this._deltaY > 5)) {
this._clearForwardTimeout();
this._notSwiping = true;
this._sendTouchEvent(this._touchStartEvt);
this._sendTouchEvent(e);

SheetsTransition.snapInPlace();
SheetsTransition.end();
}
},

_sendTouchEvent: function esd_sendTouchEvent(e) {
this._iframe.sendTouchEvent.apply(null, this._unSynthetizeEvent(e));
},

_sendTap: function esd_sendTap(e) {
var firstTouch = this._touchStartEvt.changedTouches[0];
var lastTouch = e.changedTouches[0];

// If the timeout ended the touchstart was already sent
if (this._forwardTimeout) {
this._sendTouchEvent(this._touchStartEvt);
}
this._iframe.sendMouseEvent('mousedown', firstTouch.pageX,
firstTouch.pageY, 0, 1, 0);

setTimeout((function fakeTap() {
this._sendTouchEvent(e);
this._iframe.sendMouseEvent('mouseup', lastTouch.pageX,
lastTouch.pageY, 0, 1, 0);
}).bind(this), 50);
},

_unSynthetizeEvent: function esd_unSynthetizeEvent(e) {
var type = e.type;
var relevantTouches = (type == 'touchmove') ? e.touches : e.changedTouches;
var identifiers = [];
var xs = [];
var ys = [];
var rxs = [];
var rys = [];
var rs = [];
var fs = [];

for (var i = 0; i < relevantTouches.length; i++) {
var t = relevantTouches[i];

identifiers.push(t.identifier);
xs.push(t.pageX);
ys.push(t.pageY);
rxs.push(t.radiusX);
rys.push(t.radiusY);
rs.push(t.rotationAngle);
fs.push(t.force);
}

return [type, identifiers, xs, ys, rxs, rys, rs, fs, xs.length];
}
};

EdgeSwipeDetector.init();
Loading

1 comment on commit 55cf586

@nullaus
Copy link
Contributor

@nullaus nullaus commented on 55cf586 Nov 7, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 :)

Please sign in to comment.