From 3e6bcbb486e38877b672627ad33923b2e6aef277 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Sun, 30 Jun 2019 17:15:37 +0500 Subject: [PATCH] appDisplay: Use SwipeTracker Replace existing panning and touchpad scrolling by SwipeTracker. Since SwipeTracker only references one actor, redirect scroll events from page indicators to the main scroll view. Change programmatic scroll animation to use easeOutCubic interpolator to match the gesture. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/826 --- js/ui/appDisplay.js | 111 +++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 64 deletions(-) diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 0156877e8..da8f56219 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -13,6 +13,7 @@ const Main = imports.ui.main; const PageIndicators = imports.ui.pageIndicators; const PopupMenu = imports.ui.popupMenu; const Search = imports.ui.search; +const SwipeTracker = imports.ui.swipeTracker; const Params = imports.misc.params; const Util = imports.misc.util; const SystemActions = imports.misc.systemActions; @@ -327,7 +328,9 @@ var AllView = GObject.registerClass({ (indicators, pageIndex) => { this.goToPage(pageIndex); }); - this._pageIndicators.connect('scroll-event', this._onScroll.bind(this)); + this._pageIndicators.connect('scroll-event', (actor, event) => { + this._scrollView.event(event, false); + }); this.add_actor(this._pageIndicators); this._folderIcons = []; @@ -353,13 +356,12 @@ var AllView = GObject.registerClass({ this._scrollView.connect('scroll-event', this._onScroll.bind(this)); - let panAction = new Clutter.PanAction({ interpolate: false }); - panAction.connect('pan', this._onPan.bind(this)); - panAction.connect('gesture-cancel', this._onPanEnd.bind(this)); - panAction.connect('gesture-end', this._onPanEnd.bind(this)); - this._panAction = panAction; - this._scrollView.add_action(panAction); - this._panning = false; + this._swipeTracker = new SwipeTracker.SwipeTracker( + this._scrollView, Shell.ActionMode.OVERVIEW); + this._swipeTracker.connect('begin', this._swipeBegin.bind(this)); + this._swipeTracker.connect('update', this._swipeUpdate.bind(this)); + this._swipeTracker.connect('end', this._swipeEnd.bind(this)); + this._clickAction = new Clutter.ClickAction(); this._clickAction.connect('clicked', () => { if (!this._currentPopup) @@ -424,6 +426,7 @@ var AllView = GObject.registerClass({ this._keyPressEventId = global.stage.connect('key-press-event', this._onKeyPressEvent.bind(this)); + this._swipeTracker.enabled = true; super.vfunc_map(); } @@ -432,6 +435,7 @@ var AllView = GObject.registerClass({ global.stage.disconnect(this._keyPressEventId); this._keyPressEventId = 0; } + this._swipeTracker.enabled = false; super.vfunc_unmap(); } @@ -577,7 +581,7 @@ var AllView = GObject.registerClass({ return this._grid.getPageY(this._grid.currentPage); } - goToPage(pageNumber) { + goToPage(pageNumber, animate = true) { pageNumber = clamp(pageNumber, 0, this._grid.nPages() - 1); if (this._grid.currentPage == pageNumber && this._displayingPopup && this._currentPopup) @@ -592,42 +596,16 @@ var AllView = GObject.registerClass({ return; } - let velocity; - if (!this._panning) - velocity = 0; - else - velocity = Math.abs(this._panAction.get_velocity(0)[2]); - // Tween the change between pages. - // If velocity is not specified (i.e. scrolling with mouse wheel), - // use the same speed regardless of original position - // if velocity is specified, it's in pixels per milliseconds - let diffToPage = this._diffToPage(pageNumber); - let childBox = this._scrollView.get_allocation_box(); - let totalHeight = childBox.y2 - childBox.y1; - let time; - // Only take the velocity into account on page changes, otherwise - // return smoothly to the current page using the default velocity - if (this._grid.currentPage != pageNumber) { - let minVelocity = totalHeight / PAGE_SWITCH_TIME; - velocity = Math.max(minVelocity, velocity); - time = diffToPage / velocity; - } else { - time = PAGE_SWITCH_TIME * diffToPage / totalHeight; - } - // When changing more than one page, make sure to not take - // longer than PAGE_SWITCH_TIME - time = Math.min(time, PAGE_SWITCH_TIME); + if (this._grid.currentPage === pageNumber) + return; this._grid.currentPage = pageNumber; - this._adjustment.ease(this._grid.getPageY(pageNumber), { - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: time, - }); - } - _diffToPage(pageNumber) { - let currentScrollPosition = this._adjustment.value; - return Math.abs(currentScrollPosition - this._grid.getPageY(pageNumber)); + // Tween the change between pages. + this._adjustment.ease(this._grid.getPageY(this._grid.currentPage), { + mode: Clutter.AnimationMode.EASE_OUT_CUBIC, + duration: animate ? PAGE_SWITCH_TIME : 0, + }); } openSpaceForPopup(item, side, nRows) { @@ -650,6 +628,9 @@ var AllView = GObject.registerClass({ if (this._displayingPopup || !this._scrollView.reactive) return Clutter.EVENT_STOP; + if (this._swipeTracker.canHandleScrollEvent(event)) + return Clutter.EVENT_PROPAGATE; + if (!this._canScroll) return Clutter.EVENT_STOP; @@ -673,34 +654,36 @@ var AllView = GObject.registerClass({ return Clutter.EVENT_STOP; } - _onPan(action) { - if (this._displayingPopup) - return false; - this._panning = true; - this._clickAction.release(); - let [dist_, dx_, dy] = action.get_motion_delta(0); - let adjustment = this._adjustment; - adjustment.value -= (dy / this._scrollView.height) * adjustment.page_size; - return false; - } - - _onPanEnd(action) { - if (this._displayingPopup) + _swipeBegin(tracker, monitor) { + if (monitor !== Main.layoutManager.primaryIndex) return; - let pageHeight = this._grid.getPageHeight(); + let adjustment = this._adjustment; + adjustment.remove_transition('value'); - // Calculate the scroll value we'd be at, which is our current - // scroll plus any velocity the user had when they released - // their finger. + let progress = adjustment.value / adjustment.page_size; + let points = Array.from({ length: this._grid.nPages() }, (v, i) => i); - let velocity = -action.get_velocity(0)[2]; - let endPanValue = this._adjustment.value + velocity; + tracker.confirmSwipe(this._scrollView.height, + points, progress, Math.round(progress)); + } - let closestPage = Math.round(endPanValue / pageHeight); - this.goToPage(closestPage); + _swipeUpdate(tracker, progress) { + let adjustment = this._adjustment; + adjustment.value = progress * adjustment.page_size; + } - this._panning = false; + _swipeEnd(tracker, duration, endProgress) { + let adjustment = this._adjustment; + let value = endProgress * adjustment.page_size; + + adjustment.ease(value, { + mode: Clutter.AnimationMode.EASE_OUT_CUBIC, + duration, + onComplete: () => { + this.goToPage(endProgress, false); + }, + }); } _onKeyPressEvent(actor, event) {