[gnome-shell/gbsneto/custom-icon-positions: 17/23] appDisplay: Move DnD code to BaseAppView



commit f0e5a00d24d7a2479f36aa017f11937159f8be00
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Jun 24 14:53:12 2020 -0300

    appDisplay: Move DnD code to BaseAppView
    
    This code will be shared with FolderView in the next commit, so
    avoid duplication already and move the to-be-shared code into the
    base class.
    
    Because BaseAppView can handle vertical and horizontal orientations,
    adapt the drag overshoot code to also handle horizontal overshoot.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1284

 js/ui/appDisplay.js | 383 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 227 insertions(+), 156 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 3346c8ffd9..709f2552ad 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -122,6 +122,7 @@ var BaseAppView = GObject.registerClass({
         super._init(params);
 
         this._grid = this._createGrid();
+        this._grid._delegate = this;
         // Standard hack for ClutterBinLayout
         this._grid.x_expand = true;
 
@@ -189,6 +190,46 @@ var BaseAppView = GObject.registerClass({
         this._parentalControlsManager.connect('app-filter-changed', () => {
             this._redisplay();
         });
+
+        // Drag n' Drop
+        this._lastOvershoot = -1;
+        this._lastOvershootTimeoutId = 0;
+        this._delayedMoveId = 0;
+        this._targetDropPosition = null;
+
+        this._dragBeginId =
+            Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
+        this._dragEndId =
+            Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
+        this._dragCancelledId =
+            Main.overview.connect('item-drag-cancelled', this._onDragCancelled.bind(this));
+
+        this.connect('destroy', this._onDestroy.bind(this));
+    }
+
+    _onDestroy() {
+        this._removeDelayedMove();
+
+        if (this._dragBeginId > 0) {
+            Main.overview.disconnect(this._dragBeginId);
+            this._dragBeginId = 0;
+        }
+
+        if (this._dragEndId > 0) {
+            Main.overview.disconnect(this._dragEndId);
+            this._dragEndId = 0;
+        }
+
+        if (this._dragCancelledId > 0) {
+            Main.overview.disconnect(this._dragCancelledId);
+            this._dragCancelledId = 0;
+        }
+
+        if (this._dragMonitor) {
+            DND.removeDragMonitor(this._dragMonitor);
+            this._dragMonitor = null;
+        }
+
     }
 
     _createGrid() {
@@ -275,6 +316,178 @@ var BaseAppView = GObject.registerClass({
         });
     }
 
+    _maybeMoveItem(dragEvent) {
+        const [success, x, y] =
+            this._grid.transform_stage_point(dragEvent.x, dragEvent.y);
+
+        if (!success)
+            return;
+
+        const { source } = dragEvent;
+        const [page, position, dragLocation] =
+            this._getDropTarget(x, y, source);
+        const item = position !== -1
+            ? this._grid.getItemAt(page, position) : null;
+
+
+        // Dragging over invalid parts of the grid cancels the timeout
+        if (item === source ||
+            dragLocation === IconGrid.DragLocation.INVALID ||
+            dragLocation === IconGrid.DragLocation.ON_ICON) {
+            this._removeDelayedMove();
+            return;
+        }
+
+        if (!this._targetDropPosition ||
+            this._targetDropPosition.page !== page ||
+            this._targetDropPosition.position !== position) {
+            // Update the item with a small delay
+            this._removeDelayedMove();
+            this._targetDropPosition = { page, position };
+
+            this._delayedMoveId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
+                DELAYED_MOVE_TIMEOUT, () => {
+                    this._moveItem(source, page, position);
+                    this._targetDropPosition = null;
+                    this._delayedMoveId = 0;
+                    return GLib.SOURCE_REMOVE;
+                });
+        }
+    }
+
+    _removeDelayedMove() {
+        if (this._delayedMoveId > 0) {
+            GLib.source_remove(this._delayedMoveId);
+            this._delayedMoveId = 0;
+        }
+        this._targetDropPosition = null;
+    }
+
+    _resetOvershoot() {
+        if (this._lastOvershootTimeoutId)
+            GLib.source_remove(this._lastOvershootTimeoutId);
+        this._lastOvershootTimeoutId = 0;
+        this._lastOvershoot = -1;
+    }
+
+    _handleDragOvershoot(dragEvent) {
+        const [gridX, gridY] = this.get_transformed_position();
+        const [gridWidth, gridHeight] = this.get_transformed_size();
+
+        const vertical = this._orientation === Clutter.Orientation.VERTICAL;
+        const gridStart = vertical ? gridY : gridX;
+        const gridEnd = vertical
+            ? gridY + gridHeight - OVERSHOOT_THRESHOLD
+            : gridX + gridWidth - OVERSHOOT_THRESHOLD;
+
+        // Already animating
+        if (this._adjustment.get_transition('value') !== null)
+            return;
+
+        // Within the grid boundaries
+        const dragPosition = vertical ? dragEvent.y : dragEvent.x;
+        if (dragPosition > gridStart && dragPosition < gridEnd) {
+            // Check whether we moved out the area of the last switch
+            if (Math.abs(this._lastOvershoot - dragPosition) > OVERSHOOT_THRESHOLD)
+                this._resetOvershoot();
+
+            return;
+        }
+
+        // Still in the area of the previous page switch
+        if (this._lastOvershoot >= 0)
+            return;
+
+        const currentPosition = this._adjustment.value;
+        const maxPosition = this._adjustment.upper - this._adjustment.page_size;
+
+        if (dragPosition <= gridStart && currentPosition > 0)
+            this.goToPage(this._grid.currentPage - 1);
+        else if (dragPosition >= gridEnd && currentPosition < maxPosition)
+            this.goToPage(this._grid.currentPage + 1);
+        else
+            return; // don't go beyond first/last page
+
+        this._lastOvershoot = dragPosition;
+
+        if (this._lastOvershootTimeoutId > 0)
+            GLib.source_remove(this._lastOvershootTimeoutId);
+
+        this._lastOvershootTimeoutId =
+            GLib.timeout_add(GLib.PRIORITY_DEFAULT, OVERSHOOT_TIMEOUT, () => {
+                this._resetOvershoot();
+                this._handleDragOvershoot(dragEvent);
+                return GLib.SOURCE_REMOVE;
+            });
+        GLib.Source.set_name_by_id(this._lastOvershootTimeoutId,
+            '[gnome-shell] this._lastOvershootTimeoutId');
+    }
+
+    _onDragBegin() {
+        this._dragMonitor = {
+            dragMotion: this._onDragMotion.bind(this),
+        };
+        DND.addDragMonitor(this._dragMonitor);
+    }
+
+    _onDragMotion(dragEvent) {
+        if (!(dragEvent.source instanceof AppViewItem))
+            return DND.DragMotionResult.CONTINUE;
+
+        const 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 instanceof AppViewItem)
+            this._handleDragOvershoot(dragEvent);
+
+        this._maybeMoveItem(dragEvent);
+
+        return DND.DragMotionResult.CONTINUE;
+    }
+
+    _onDragEnd() {
+        if (this._dragMonitor) {
+            DND.removeDragMonitor(this._dragMonitor);
+            this._dragMonitor = null;
+        }
+
+        this._resetOvershoot();
+    }
+
+    _onDragCancelled() {
+        // At this point, the positions aren't stored yet, thus _redisplay()
+        // will move all items to their original positions
+        this._redisplay();
+    }
+
+    _canAccept(source) {
+        return source instanceof AppViewItem;
+    }
+
+    handleDragOver(source) {
+        if (!this._canAccept(source))
+            return DND.DragMotionResult.NO_DROP;
+
+        return DND.DragMotionResult.MOVE_DROP;
+    }
+
+    acceptDrop(source) {
+        if (!this._canAccept(source))
+            return false;
+
+        // Dropped before the icon was moved
+        if (this._targetDropPosition) {
+            const { page, position } = this._targetDropPosition;
+
+            this._moveItem(source, page, position);
+            this._removeDelayedMove();
+        }
+
+        return true;
+    }
+
     _addItem(item, page, position) {
         let itemIndex = 0;
 
@@ -646,7 +859,6 @@ class AppDisplay extends BaseAppView {
             y_expand: true,
         });
 
-        this._grid._delegate = this;
         this._pageManager = new PageManager();
 
         this._scrollView.add_style_class_name('all-apps');
@@ -667,10 +879,6 @@ class AppDisplay extends BaseAppView {
         this._displayingDialog = false;
         this._currentDialogDestroyId = 0;
 
-        this._lastOvershootY = -1;
-        this._lastOvershootTimeoutId = 0;
-        this._delayedMoveId = 0;
-        this._targetDropPosition = null;
         this._placeholder = null;
 
         Main.overview.connect('hidden', () => this.goToPage(0));
@@ -687,12 +895,6 @@ class AppDisplay 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));
-        Main.overview.connect('item-drag-cancelled', this._onDragCancelled.bind(this));
-
-        this.connect('destroy', this._onDestroy.bind(this));
-
         this._switcherooNotifyId = global.connect('notify::switcheroo-control',
             () => this._updateDiscreteGpuAvailable());
         this._updateDiscreteGpuAvailable();
@@ -709,7 +911,7 @@ class AppDisplay extends BaseAppView {
     }
 
     _onDestroy() {
-        this._removeDelayedMove();
+        super._onDestroy();
 
         if (this._scrollTimeoutId !== 0) {
             GLib.source_remove(this._scrollTimeoutId);
@@ -975,112 +1177,17 @@ class AppDisplay extends BaseAppView {
         });
     }
 
-    _removeDelayedMove() {
-        if (this._delayedMoveId > 0) {
-            GLib.source_remove(this._delayedMoveId);
-            this._delayedMoveId = 0;
-        }
-        this._targetDropPosition = null;
-    }
-
     _maybeMoveItem(dragEvent) {
-        const [success, x, y] =
-            this._grid.transform_stage_point(dragEvent.x, dragEvent.y);
-
-        if (!success)
-            return;
-
-        const source = this._placeholder ? this._placeholder : dragEvent.source;
-        const [page, position, dragLocation] =
-            this._getDropTarget(x, y, source);
-        const item = position !== -1
-            ? this._grid.getItemAt(page, position) : null;
-
-
-        // Dragging over invalid parts of the grid cancels the timeout
-        if (item === source ||
-            dragLocation === IconGrid.DragLocation.INVALID ||
-            dragLocation === IconGrid.DragLocation.ON_ICON) {
-            this._removeDelayedMove();
-            return;
-        }
-
-        if (!this._targetDropPosition ||
-            this._targetDropPosition.page !== page ||
-            this._targetDropPosition.position !== position) {
-            // Update the item with a small delay
-            this._removeDelayedMove();
-            this._targetDropPosition = { page, position };
-
-            this._delayedMoveId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
-                DELAYED_MOVE_TIMEOUT, () => {
-                    this._moveItem(source, page, position);
-                    this._targetDropPosition = null;
-                    this._delayedMoveId = 0;
-                    return GLib.SOURCE_REMOVE;
-                });
-        }
-    }
-
-    _resetOvershoot() {
-        if (this._lastOvershootTimeoutId)
-            GLib.source_remove(this._lastOvershootTimeoutId);
-        this._lastOvershootTimeoutId = 0;
-        this._lastOvershootY = -1;
-    }
-
-    _handleDragOvershoot(dragEvent) {
-        let [, gridY] = this.get_transformed_position();
-        let [, gridHeight] = this.get_transformed_size();
-        const gridBottom = gridY + gridHeight - OVERSHOOT_THRESHOLD;
-
-        // Already animating
-        if (this._adjustment.get_transition('value') !== null)
-            return;
-
-        // Within the grid boundaries
-        if (dragEvent.y > gridY && dragEvent.y < gridBottom) {
-            // Check whether we moved out the area of the last switch
-            if (Math.abs(this._lastOvershootY - dragEvent.y) > OVERSHOOT_THRESHOLD)
-                this._resetOvershoot();
-
-            return;
-        }
-
-        // Still in the area of the previous page switch
-        if (this._lastOvershootY >= 0)
-            return;
-
-        let currentY = this._adjustment.value;
-        let maxY = this._adjustment.upper - this._adjustment.page_size;
-
-        if (dragEvent.y <= gridY && currentY > 0)
-            this.goToPage(this._grid.currentPage - 1);
-        else if (dragEvent.y >= gridBottom && currentY < maxY)
-            this.goToPage(this._grid.currentPage + 1);
-        else
-            return; // don't go beyond first/last page
-
-        this._lastOvershootY = dragEvent.y;
-
-        if (this._lastOvershootTimeoutId > 0)
-            GLib.source_remove(this._lastOvershootTimeoutId);
+        const clonedEvent = {
+            ...dragEvent,
+            source: this._placeholder ? this._placeholder : dragEvent.source,
+        };
 
-        this._lastOvershootTimeoutId =
-            GLib.timeout_add(GLib.PRIORITY_DEFAULT, OVERSHOOT_TIMEOUT, () => {
-                this._resetOvershoot();
-                this._handleDragOvershoot(dragEvent);
-                return GLib.SOURCE_REMOVE;
-            });
-        GLib.Source.set_name_by_id(this._lastOvershootTimeoutId,
-            '[gnome-shell] this._lastOvershootTimeoutId');
+        super._maybeMoveItem(clonedEvent);
     }
 
-    _onDragBegin(_overview, source) {
-        this._dragMonitor = {
-            dragMotion: this._onDragMotion.bind(this),
-        };
-        DND.addDragMonitor(this._dragMonitor);
+    _onDragBegin(overview, source) {
+        super._onDragBegin(overview, source);
 
         // When dragging from a folder dialog, the dragged app icon doesn't
         // exist in AppDisplay. We work around that by adding a placeholder
@@ -1091,66 +1198,30 @@ class AppDisplay extends BaseAppView {
     }
 
     _onDragMotion(dragEvent) {
-        if (!(dragEvent.source instanceof AppViewItem))
+        if (this._currentDialog)
             return DND.DragMotionResult.CONTINUE;
 
-        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 instanceof AppViewItem)
-            this._handleDragOvershoot(dragEvent);
-
-        this._maybeMoveItem(dragEvent);
-
-        return DND.DragMotionResult.CONTINUE;
+        return super._onDragMotion(dragEvent);
     }
 
     _onDragEnd() {
-        if (this._dragMonitor) {
-            DND.removeDragMonitor(this._dragMonitor);
-            this._dragMonitor = null;
-        }
-
-        this._resetOvershoot();
+        super._onDragEnd();
         this._removePlaceholder();
     }
 
-    _onDragCancelled(_overview, source) {
+    _onDragCancelled(overview, source) {
         const view = _getViewFromIcon(source);
 
         if (view instanceof FolderView)
             return;
 
-        // At this point, the positions aren't stored yet, thus _redisplay()
-        // will move all items to their original positions
-        this._redisplay();
-    }
-
-    _canAccept(source) {
-        return source instanceof AppViewItem;
-    }
-
-    handleDragOver(source) {
-        if (!this._canAccept(source))
-            return DND.DragMotionResult.NO_DROP;
-
-        return DND.DragMotionResult.MOVE_DROP;
+        super._onDragCancelled(overview, source);
     }
 
     acceptDrop(source) {
-        if (!this._canAccept(source))
+        if (!super.acceptDrop(source))
             return false;
 
-        // Dropped before the icon was moved
-        if (this._targetDropPosition) {
-            const { page, position } = this._targetDropPosition;
-
-            this._moveItem(source, page, position);
-            this._removeDelayedMove();
-        }
-
         this._savePages();
 
         let view = _getViewFromIcon(source);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]