[gnome-shell] App Picker: Prevent drag if favorite-apps is locked.



commit 1da9546c40b9f4480e15e8d830e5702b07a1cd65
Author: Murray Cumming <murrayc murrayc com>
Date:   Tue Jan 27 22:10:45 2015 +0100

    App Picker: Prevent drag if favorite-apps is locked.
    
    Because there's nothing (in single-monitor setups) that could
    take the drop in this case.
    
    * js/ui/appDisplay.js:
      AllView._loadApps(), FrequentView._loadApps(): Pass
      an isDraggable parameter when creating the AppIcons,
      depending on whether the favorite-apps key is locked.
      AppIcon._init(): Check for isDraggable in the params and
      do not create _draggable if it was specified, to prevent a
      drag from starting.
      AppIcon.popupMenu(): Check _draggable before trying to call
      fakeRelease on it.
    * js/ui/dash.js: Dash._createAppItem(): Check AppIcon._draggable
      before trying to connect to its signals.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741325

 js/ui/appDisplay.js |   67 ++++++++++++++++++++++++++++++++++++++-------------
 js/ui/dash.js       |   19 ++++++++------
 2 files changed, 61 insertions(+), 25 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 4ecc7ec..066c44a 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -366,6 +366,8 @@ const AllView = new Lang.Class({
     Extends: BaseAppView,
 
     _init: function() {
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
+
         this.parent({ usePagination: true }, null);
         this._scrollView = new St.ScrollView({ style_class: 'all-apps',
                                                x_expand: true,
@@ -517,9 +519,19 @@ const AllView = new Lang.Class({
             this.folderIcons.push(icon);
         }));
 
+        // Allow dragging of the icon only if the Dash would accept a drop to
+        // change favorite-apps. There are no other possible drop targets from
+        // the app picker, so there's no other need for a drag to start,
+        // at least on single-monitor setups.
+        // This also disables drag-to-launch on multi-monitor setups,
+        // but we hope that is not used much.
+        let favoritesWritable = this._settings.is_writable('favorite-apps');
+
         apps.forEach(Lang.bind(this, function(appId) {
             let app = appSys.lookup_app(appId);
-            let icon = new AppIcon(app);
+
+            let icon = new AppIcon(app,
+                                   { isDraggable: favoritesWritable });
             this.addItem(icon);
         }));
 
@@ -763,6 +775,9 @@ const FrequentView = new Lang.Class({
 
     _init: function() {
         this.parent(null, { fillParent: true });
+
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
+
         this.actor = new St.Widget({ style_class: 'frequent-apps',
                                      layout_manager: new Clutter.BinLayout(),
                                      x_expand: true, y_expand: true });
@@ -799,10 +814,19 @@ const FrequentView = new Lang.Class({
         if(!hasUsefulData)
             return;
 
+        // Allow dragging of the icon only if the Dash would accept a drop to
+        // change favorite-apps. There are no other possible drop targets from
+        // the app picker, so there's no other need for a drag to start,
+        // at least on single-monitor setups.
+        // This also disables drag-to-launch on multi-monitor setups,
+        // but we hope that is not used much.
+        let favoritesWritable = this._settings.is_writable('favorite-apps');
+
         for (let i = 0; i < mostUsed.length; i++) {
             if (!mostUsed[i].get_app_info().should_show())
                 continue;
-            let appIcon = new AppIcon(mostUsed[i]);
+            let appIcon = new AppIcon(mostUsed[i],
+                                      { isDraggable: favoritesWritable });
             this._grid.addItem(appIcon, -1);
         }
     },
@@ -1528,6 +1552,11 @@ const AppIcon = new Lang.Class({
         if (!iconParams)
             iconParams = {};
 
+        // Get the isDraggable property without passing it on to the BaseIcon:
+        let appIconParams = Params.parse(iconParams, { isDraggable: true }, true);
+        let isDraggable = appIconParams['isDraggable'];
+        delete iconParams['isDraggable'];
+
         iconParams['createIcon'] = Lang.bind(this, this._createIcon);
         iconParams['setSizeManually'] = true;
         this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
@@ -1544,20 +1573,22 @@ const AppIcon = new Lang.Class({
         this._menu = null;
         this._menuManager = new PopupMenu.PopupMenuManager(this);
 
-        this._draggable = DND.makeDraggable(this.actor);
-        this._draggable.connect('drag-begin', Lang.bind(this,
-            function () {
-                this._removeMenuTimeout();
-                Main.overview.beginItemDrag(this);
-            }));
-        this._draggable.connect('drag-cancelled', Lang.bind(this,
-            function () {
-                Main.overview.cancelledItemDrag(this);
-            }));
-        this._draggable.connect('drag-end', Lang.bind(this,
-            function () {
-               Main.overview.endItemDrag(this);
-            }));
+        if (isDraggable) {
+            this._draggable = DND.makeDraggable(this.actor);
+            this._draggable.connect('drag-begin', Lang.bind(this,
+                function () {
+                    this._removeMenuTimeout();
+                    Main.overview.beginItemDrag(this);
+                }));
+            this._draggable.connect('drag-cancelled', Lang.bind(this,
+                function () {
+                    Main.overview.cancelledItemDrag(this);
+                }));
+            this._draggable.connect('drag-end', Lang.bind(this,
+                function () {
+                   Main.overview.endItemDrag(this);
+                }));
+        }
 
         this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 
@@ -1645,7 +1676,9 @@ const AppIcon = new Lang.Class({
     popupMenu: function() {
         this._removeMenuTimeout();
         this.actor.fake_release();
-        this._draggable.fakeRelease();
+
+        if (this._draggable)
+            this._draggable.fakeRelease();
 
         if (!this._menu) {
             this._menu = new AppIconMenu(this);
diff --git a/js/ui/dash.js b/js/ui/dash.js
index acf1eb4..146480c 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -535,14 +535,17 @@ const Dash = new Lang.Class({
         let appIcon = new AppDisplay.AppIcon(app,
                                              { setSizeManually: true,
                                                showLabel: false });
-        appIcon._draggable.connect('drag-begin',
-                                   Lang.bind(this, function() {
-                                       appIcon.actor.opacity = 50;
-                                   }));
-        appIcon._draggable.connect('drag-end',
-                                   Lang.bind(this, function() {
-                                       appIcon.actor.opacity = 255;
-                                   }));
+        if (appIcon._draggable) {
+            appIcon._draggable.connect('drag-begin',
+                                       Lang.bind(this, function() {
+                                           appIcon.actor.opacity = 50;
+                                       }));
+            appIcon._draggable.connect('drag-end',
+                                       Lang.bind(this, function() {
+                                           appIcon.actor.opacity = 255;
+                                       }));
+        }
+
         appIcon.connect('menu-state-changed',
                         Lang.bind(this, function(appIcon, opened) {
                             this._itemMenuStateChanged(item, opened);


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