[gnome-shell/wip/carlosg/app-grid-gestures: 11/11] appDisplay: Improve app grid interaction for touch devices




commit 6fc93b78bc54763c0876951f2425fcfd96f61f00
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Mar 18 19:01:50 2021 +0100

    appDisplay: Improve app grid interaction for touch devices
    
    Currently, handling of touch devices in the app grid is a bit awkward,
    paging by dragging the view can only happen if started from the gaps
    between icons, trying to drag from an icon will trigger DnD, and popping
    up the menu takes over it all.
    
    Instead, have the app grid actions play this game of rock-paper-scissors:
    - Fast swipes on icons trigger scrolling, beats DnD and menu
    - Slower press-and-drag on icons trigger DnD, beats scrolling and menu
    - Long press triggers menu, beats scrolling, is beaten by DnD
    
    This allows quick swipes to handle navigation, while still allowing the
    fine grained operations. DnD, when triggered, dismisses the menu, if
    shown.
    
    This all could probably be nicer with a more stateful gesture framework,
    we're not there yet though.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3849
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1774>

 js/ui/appDisplay.js | 46 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 2086102b4d..39f440127b 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -495,6 +495,11 @@ var BaseAppView = GObject.registerClass({
         if (monitor !== Main.layoutManager.primaryIndex)
             return;
 
+        if (this._dragFocus) {
+            this._dragFocus.cancelActions();
+            this._dragFocus = null;
+        }
+
         const adjustment = this._adjustment;
         adjustment.remove_transition('value');
 
@@ -677,6 +682,8 @@ var BaseAppView = GObject.registerClass({
         };
         DND.addDragMonitor(this._dragMonitor);
         this._slideSidePages(SidePages.PREVIOUS | SidePages.NEXT | SidePages.DND);
+        this._dragFocus = null;
+        this._swipeTracker.enabled = false;
     }
 
     _onDragMotion(dragEvent) {
@@ -713,6 +720,7 @@ var BaseAppView = GObject.registerClass({
         this._resetOvershoot();
         this._slideSidePages(SidePages.NONE);
         delete this._dropPage;
+        this._swipeTracker.enabled = true;
     }
 
     _onDragCancelled() {
@@ -720,6 +728,7 @@ var BaseAppView = GObject.registerClass({
         // will move all items to their original positions
         this._redisplay();
         this._slideSidePages(SidePages.NONE);
+        this._swipeTracker.enabled = true;
     }
 
     _canAccept(source) {
@@ -1331,6 +1340,10 @@ var BaseAppView = GObject.registerClass({
             });
         }
     }
+
+    updateDragFocus(dragFocus) {
+        this._dragFocus = dragFocus;
+    }
 });
 
 var PageManager = GObject.registerClass({
@@ -1522,6 +1535,10 @@ class AppDisplay extends BaseAppView {
             global.settings.is_writable('app-picker-layout');
 
         this._placeholder = new AppIcon(app, { isDraggable });
+        this._placeholder.connect('notify::pressed', () => {
+            if (this._placeholder.pressed)
+                this.updateDragFocus(this._placeholder);
+        });
         this._placeholder.scaleAndFade();
         this._redisplay();
     }
@@ -1597,6 +1614,10 @@ class AppDisplay extends BaseAppView {
                     this._redisplay();
                     this._savePages();
                 });
+                icon.connect('notify::pressed', () => {
+                    if (icon.pressed)
+                        this.updateDragFocus(icon);
+                });
             }
 
             // Don't try to display empty folders
@@ -1630,6 +1651,10 @@ class AppDisplay extends BaseAppView {
                 let app = appSys.lookup_app(appId);
 
                 icon = new AppIcon(app, { isDraggable });
+                icon.connect('notify::pressed', () => {
+                    if (icon.pressed)
+                        this.updateDragFocus(icon);
+                });
             }
 
             appIcons.push(icon);
@@ -1952,7 +1977,8 @@ class AppViewItem extends St.Button {
         this._delegate = this;
 
         if (isDraggable) {
-            this._draggable = DND.makeDraggable(this);
+            this._draggable = DND.makeDraggable(this, { timeoutThreshold: 200 });
+
             this._draggable.connect('drag-begin', this._onDragBegin.bind(this));
             this._draggable.connect('drag-cancelled', this._onDragCancelled.bind(this));
             this._draggable.connect('drag-end', this._onDragEnd.bind(this));
@@ -2131,6 +2157,12 @@ class AppViewItem extends St.Button {
         return true;
     }
 
+    cancelActions() {
+        if (this._draggable)
+            this._draggable.fakeRelease();
+        this.fake_release();
+    }
+
     get id() {
         return this._id;
     }
@@ -3128,6 +3160,8 @@ var AppIcon = GObject.registerClass({
     }
 
     _onDragBegin() {
+        if (this._menu)
+            this._menu.close(true);
         this._removeMenuTimeout();
         super._onDragBegin();
     }
@@ -3205,9 +3239,6 @@ var AppIcon = GObject.registerClass({
         this._removeMenuTimeout();
         this.fake_release();
 
-        if (this._draggable)
-            this._draggable.fakeRelease();
-
         if (!this._menu) {
             this._menu = new AppIconMenu(this, side);
             this._menu.connect('activate-window', (menu, window) => {
@@ -3362,6 +3393,13 @@ var AppIcon = GObject.registerClass({
 
         return view.createFolder(apps);
     }
+
+    cancelActions() {
+        if (this._menu)
+            this._menu.close(true);
+        this._removeMenuTimeout();
+        super.cancelActions();
+    }
 });
 
 var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {


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