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



commit b9a50140d14ca1b6f8df21938751450a8866050d
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 | 464 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 269 insertions(+), 195 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index dc403ef82b..9073f89861 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,47 @@ 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._nudgedItem = 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 +317,216 @@ 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.source;
+        const [item, dragLocation] = this.getDropTarget(x, y);
+
+        // Dragging over invalid parts of the grid cancels the timeout
+        if (!item ||
+            item === source ||
+            dragLocation === IconGrid.DragLocation.ON_ICON) {
+            this._removeDelayedMove();
+            this._removeNudge();
+            return;
+        }
+
+        const [page, position] = this._grid.getItemPosition(item);
+
+        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._removeNudge();
+                    this._targetDropPosition = null;
+                    this._delayedMoveId = 0;
+                    return GLib.SOURCE_REMOVE;
+                });
+
+            this._nudgeItem(item, dragLocation);
+        }
+    }
+
+    _removeDelayedMove() {
+        if (this._delayedMoveId > 0) {
+            GLib.source_remove(this._delayedMoveId);
+            this._delayedMoveId = 0;
+        }
+        this._targetDropPosition = null;
+    }
+
+    _nudgeItem(item, dragLocation) {
+        if (this._nudgedItem)
+            this._removeNudge();
+
+        const params = {
+            duration: DELAYED_MOVE_TIMEOUT,
+            mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+        };
+
+        const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
+        const nudgeOffset = item.width / 4;
+        if (dragLocation === IconGrid.DragLocation.START_EDGE)
+            params.translation_x = nudgeOffset * (rtl ? -1 : 1);
+        else if (dragLocation === IconGrid.DragLocation.END_EDGE)
+            params.translation_x = -nudgeOffset * (rtl ? -1 : 1);
+
+        item.ease(params);
+        this._nudgedItem = item;
+    }
+
+    _removeNudge() {
+        if (!this._nudgedItem)
+            return;
+
+        this._nudgedItem.ease({
+            translation_x: 0,
+            duration: DELAYED_MOVE_TIMEOUT,
+            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+        });
+        this._nudgedItem = 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();
+        this._removeNudge();
+    }
+
+    _onDragCancelled() {
+        // Restore all icon positions, since they may have reflowed
+        // to different pages
+        for (const item of this._orderedItems) {
+            const [page, position] = this._getItemPosition(item);
+            this.moveItem(item, page, position);
+        }
+    }
+
+    _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;
 
@@ -612,7 +864,6 @@ class AppDisplay extends BaseAppView {
             y_expand: true,
         });
 
-        this._grid._delegate = this;
         this._pageManager = new PageManager();
 
         this._scrollView.add_style_class_name('all-apps');
@@ -633,11 +884,6 @@ class AppDisplay extends BaseAppView {
         this._displayingDialog = false;
         this._currentDialogDestroyId = 0;
 
-        this._lastOvershootY = -1;
-        this._lastOvershootTimeoutId = 0;
-        this._delayedMoveId = 0;
-        this._targetDropPosition = null;
-        this._nudgedItem = null;
         this._placeholder = null;
 
         Main.overview.connect('hidden', () => this.goToPage(0));
@@ -654,12 +900,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();
@@ -676,7 +916,7 @@ class AppDisplay extends BaseAppView {
     }
 
     _onDestroy() {
-        this._removeDelayedMove();
+        super._onDestroy();
 
         if (this._scrollTimeoutId !== 0) {
             GLib.source_remove(this._scrollTimeoutId);
@@ -940,146 +1180,20 @@ class AppDisplay extends BaseAppView {
         });
     }
 
-    _removeDelayedMove() {
-        if (this._delayedMoveId > 0) {
-            GLib.source_remove(this._delayedMoveId);
-            this._delayedMoveId = 0;
-        }
-        this._targetDropPosition = null;
-    }
-
-    _nudgeItem(item, dragLocation) {
-        if (this._nudgedItem)
-            this._removeNudge();
-
-        const params = {
-            duration: DELAYED_MOVE_TIMEOUT,
-            mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
-        };
-
-        const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
-        const nudgeOffset = item.width / 4;
-        if (dragLocation === IconGrid.DragLocation.START_EDGE)
-            params.translation_x = nudgeOffset * (rtl ? -1 : 1);
-        else if (dragLocation === IconGrid.DragLocation.END_EDGE)
-            params.translation_x = -nudgeOffset * (rtl ? -1 : 1);
-
-        item.ease(params);
-        this._nudgedItem = item;
-    }
-
-    _removeNudge() {
-        if (!this._nudgedItem)
-            return;
-
-        this._nudgedItem.ease({
-            translation_x: 0,
-            duration: DELAYED_MOVE_TIMEOUT,
-            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
-        });
-        this._nudgedItem = 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 [item, dragLocation] = this.getDropTarget(x, y);
-
-        // Dragging over invalid parts of the grid cancels the timeout
-        if (!item ||
-            item === source ||
-            dragLocation === IconGrid.DragLocation.ON_ICON) {
-            this._removeDelayedMove();
-            this._removeNudge();
-            return;
-        }
-
-        const [page, position] = this._grid.getItemPosition(item);
-
-        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._removeNudge();
-                    this._targetDropPosition = null;
-                    this._delayedMoveId = 0;
-                    return GLib.SOURCE_REMOVE;
-                });
-
-            this._nudgeItem(item, dragLocation);
-        }
-    }
+        const clonedEvent = {
+            x: dragEvent.x,
+            y: dragEvent.y,
+            dragActor: dragEvent.dragActor,
+            source: this._placeholder ? this._placeholder : dragEvent.source,
+            targetActor: dragEvent.targetActor,
+        };
 
-    _resetOvershoot() {
-        if (this._lastOvershootTimeoutId)
-            GLib.source_remove(this._lastOvershootTimeoutId);
-        this._lastOvershootTimeoutId = 0;
-        this._lastOvershootY = -1;
+        super._maybeMoveItem(clonedEvent);
     }
 
-    _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);
-
-        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(_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
@@ -1090,70 +1204,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();
-        this._removeNudge();
+        super._onDragEnd();
         this._removePlaceholder();
     }
 
-    _onDragCancelled(_overview, source) {
+    _onDragCancelled(overview, source) {
         const view = _getViewFromIcon(source);
 
         if (view instanceof FolderView)
             return;
 
-        // Restore all icon positions, since they may have reflowed
-        // to different pages
-        for (const item of this._orderedItems) {
-            const [page, position] = this._getItemPosition(item);
-            this.moveItem(item, page, position);
-        }
-    }
-
-    _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]