diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index a1eb2256a..83fd57745 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -339,6 +339,9 @@ var AllView = class AllView extends BaseAppView { Main.queueDeferredWork(this._redisplayWorkId); }); + Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this)); + Main.overview.connect('item-drag-end', this._onDragEnd.bind(this)); + this._nEventBlockerInhibits = 0; } @@ -675,6 +678,58 @@ var AllView = class AllView extends BaseAppView { this.folderIcons[i].adaptToSize(availWidth, availHeight); } + _handleDragOvershoot(dragEvent) { + let [gridX, gridY] = this.actor.get_transformed_position(); + let [gridWidth, gridHeight] = this.actor.get_transformed_size(); + let gridBottom = gridY + gridHeight; + + // Within the grid boundaries, or already animating + if (dragEvent.y > gridY && dragEvent.y < gridBottom || + Tweener.isTweening(this._adjustment)) { + return; + } + + // Moving above the grid + let currentY = this._adjustment.value; + if (dragEvent.y <= gridY && currentY > 0) { + this.goToPage(this._grid.currentPage - 1); + return; + } + + // Moving below the grid + let maxY = this._adjustment.upper - this._adjustment.page_size; + if (dragEvent.y >= gridBottom && currentY < maxY) { + this.goToPage(this._grid.currentPage + 1); + return; + } + } + + _onDragBegin() { + this._dragMonitor = { + dragMotion: this._onDragMotion.bind(this) + }; + DND.addDragMonitor(this._dragMonitor); + } + + _onDragMotion(dragEvent) { + let appIcon = dragEvent.source; + + // Handle the drag overshoot. When dragging to above the + // icon grid, move to the page above; when dragging below, + // move to the page below. + if (appIcon.view == this) + this._handleDragOvershoot(dragEvent); + + return DND.DragMotionResult.CONTINUE; + } + + _onDragEnd() { + if (this._dragMonitor) { + DND.removeDragMonitor(this._dragMonitor); + this._dragMonitor = null; + } + } + inhibitEventBlocker() { this._nEventBlockerInhibits++; this._eventBlocker.visible = this._nEventBlockerInhibits == 0;