From 858a82fcdd7a0fdd2f3255284129a9a8034050e1 Mon Sep 17 00:00:00 2001 From: Marina Zhurakhinskaya Date: Mon, 29 Jun 2009 15:08:48 -0400 Subject: [PATCH] Use a separate icon image as a drag actor instead of using the clone of the icon Clutter no longer allows using a clone of an actor that is not a part of the scene graph. This is what used to happen when we created a clone for the icon of the item that was being dragged, and then closed the More panes with the original item, removing the icon from the scene graph. This was also when happened when the user hit Esc while dragging, which prompted the overlay to close, removing the original icon from the scene graph. Rename getIcon() methods to createIcon() to better reflect on the fact that a new icon is created each time the method is called (we do use cache in some cases). Remove a stray log message in overlay.js Fixes http://bugzilla.gnome.org/show_bug.cgi?id=585490 and http://bugzilla.gnome.org/show_bug.cgi?id=585489 --- js/misc/appInfo.js | 2 +- js/misc/docInfo.js | 2 +- js/ui/appDisplay.js | 13 +++++++----- js/ui/docDisplay.js | 10 ++++++--- js/ui/genericDisplay.js | 47 ++++++++++++----------------------------- js/ui/overlay.js | 1 - js/ui/widget.js | 4 ++-- 7 files changed, 33 insertions(+), 46 deletions(-) diff --git a/js/misc/appInfo.js b/js/misc/appInfo.js index 67554f352..4b6dde673 100644 --- a/js/misc/appInfo.js +++ b/js/misc/appInfo.js @@ -27,7 +27,7 @@ AppInfo.prototype = { this._gicon = this._gAppInfo.get_icon(); }, - getIcon : function(size) { + createIcon : function(size) { if (this._gicon) return Shell.TextureCache.get_default().load_gicon(this._gicon, size); else diff --git a/js/misc/docInfo.js b/js/misc/docInfo.js index 8ac02f6bf..c590dccea 100644 --- a/js/misc/docInfo.js +++ b/js/misc/docInfo.js @@ -21,7 +21,7 @@ DocInfo.prototype = { this.mimeType = recentInfo.get_mime_type(); }, - getIcon : function(size) { + createIcon : function(size) { let icon = new Clutter.Texture(); let iconPixbuf; diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index aa3495f76..084f8183a 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -41,8 +41,7 @@ AppDisplayItem.prototype = { GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth); this._appInfo = appInfo; - this._setItemInfo(appInfo.name, appInfo.description, - appInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE)); + this._setItemInfo(appInfo.name, appInfo.description); }, //// Public method overrides //// @@ -54,6 +53,11 @@ AppDisplayItem.prototype = { //// Protected method overrides //// + // Returns an icon for the item. + _createIcon : function() { + return this._appInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE); + }, + // Ensures the preview icon is created. _ensurePreviewIconCreated : function() { if (!this._showPreview || this._previewIcon) @@ -447,7 +451,7 @@ WellDisplayItem.prototype = { let draggable = DND.makeDraggable(this.actor); - this._icon = appInfo.getIcon(APP_ICON_SIZE); + this._icon = appInfo.createIcon(APP_ICON_SIZE); this.actor.append(this._icon, Big.BoxPackFlags.NONE); @@ -475,8 +479,7 @@ WellDisplayItem.prototype = { // Draggable interface - FIXME deduplicate with GenericDisplay getDragActor: function(stageX, stageY) { - this.dragActor = new Clutter.Clone({ source: this._icon }); - [this.dragActor.width, this.dragActor.height] = this._icon.get_transformed_size(); + this.dragActor = this.appInfo.createIcon(APP_ICON_SIZE); // If the user dragged from the icon itself, then position // the dragActor over the original icon. Otherwise center it diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js index 2ea28208c..e727de328 100644 --- a/js/ui/docDisplay.js +++ b/js/ui/docDisplay.js @@ -27,8 +27,7 @@ DocDisplayItem.prototype = { GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth); this._docInfo = docInfo; - this._setItemInfo(docInfo.name, "", - docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE)); + this._setItemInfo(docInfo.name, ""); }, //// Public methods //// @@ -42,10 +41,15 @@ DocDisplayItem.prototype = { //// Protected method overrides //// + // Returns an icon for the item. + _createIcon : function() { + return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE); + }, + // Ensures the preview icon is created. _ensurePreviewIconCreated : function() { if (!this._previewIcon) - this._previewIcon = this._docInfo.getIcon(GenericDisplay.PREVIEW_ICON_SIZE); + this._previewIcon = this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE); }, // Creates and returns a large preview icon, but only if this._docInfo is an image file diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index e70e42758..9d9c328c2 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -126,8 +126,7 @@ GenericDisplayItem.prototype = { // Returns a cloned texture of the item's icon to represent the item as it // is being dragged. getDragActor: function(stageX, stageY) { - this.dragActor = new Clutter.Clone({ source: this._icon }); - [this.dragActor.width, this.dragActor.height] = this._icon.get_transformed_size(); + this.dragActor = this._createIcon(); // If the user dragged from the icon itself, then position // the dragActor over the original icon. Otherwise center it @@ -142,8 +141,10 @@ GenericDisplayItem.prototype = { return this.dragActor; }, - // Returns the original icon that is being used as a source for the cloned texture - // that represents the item as it is being dragged. + // Returns the item icon, a separate copy of which is used to + // represent the item as it is being dragged. This is used to + // determine a snap-back location for the drag icon if it does + // not get accepted by any drop target. getDragActorSource: function() { return this._icon; }, @@ -238,9 +239,8 @@ GenericDisplayItem.prototype = { * * nameText - name of the item * descriptionText - short description of the item - * iconActor - ClutterTexture containing the icon image which should be ITEM_DISPLAY_ICON_SIZE size */ - _setItemInfo: function(nameText, descriptionText, iconActor) { + _setItemInfo: function(nameText, descriptionText) { if (this._name != null) { // this also removes this._name from the parent container, // so we don't need to call this.actor.remove_actor(this._name) directly @@ -263,7 +263,7 @@ GenericDisplayItem.prototype = { this._previewIcon = null; } - this._icon = iconActor; + this._icon = this._createIcon(); this.actor.add_actor(this._icon); let textWidth = this._availableWidth - (ITEM_DISPLAY_ICON_SIZE + 4) - INFORMATION_BUTTON_SIZE - ITEM_DISPLAY_PADDING_RIGHT; @@ -294,6 +294,11 @@ GenericDisplayItem.prototype = { //// Pure virtual protected methods //// + // Returns an icon for the item. + _createIcon: function() { + throw new Error("Not implemented"); + }, + // Ensures the preview icon is created. _ensurePreviewIconCreated: function() { throw new Error("Not implemented"); @@ -588,32 +593,8 @@ GenericDisplay.prototype = { this.selectUp(); } - if (displayItem.dragActor) { - // The user might be handling a dragActor when the list of items - // changes (for example, if the dragging caused us to transition - // from an expanded overlay view to the regular view). So we need - // to keep the item around so that the drag and drop action initiated - // by the user can be completed. However, we remove the item from the list. - // - // For some reason, just removing the displayItem.actor - // is not enough to get displayItem._icon.visible - // to return false, so we hide the display item and - // all its children first. (We check displayItem._icon.visible - // when deciding if a dragActor has a place to snap back to - // in case the drop was not accepted by any actor.) - displayItem.actor.hide_all(); - this._grid.remove_actor(displayItem.actor); - // We should not destroy the item up-front, because that would also - // destroy the icon that was used to clone the image for the drag actor. - // We destroy it once the dragActor is destroyed instead. - displayItem.dragActor.connect('destroy', - function(item) { - displayItem.destroy(); - }); - - } else { - displayItem.destroy(); - } + displayItem.destroy(); + delete this._displayedItems[itemId]; this._displayedItemsCount--; }, diff --git a/js/ui/overlay.js b/js/ui/overlay.js index 03078ff95..e6a96f9b7 100644 --- a/js/ui/overlay.js +++ b/js/ui/overlay.js @@ -762,7 +762,6 @@ Overlay.prototype = { // the item on any workspace. handleDragOver : function(source, actor, x, y, time) { if (source instanceof GenericDisplay.GenericDisplayItem) { - log("unsetting more mode"); this._dash.unsetMoreMode(); return true; } diff --git a/js/ui/widget.js b/js/ui/widget.js index a49db3117..8a0644f8e 100644 --- a/js/ui/widget.js +++ b/js/ui/widget.js @@ -182,7 +182,7 @@ LauncherWidget.prototype = { spacing: ITEM_SPACING, reactive: true }); item._info = info; - item.append(info.getIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE); + item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE); item.append(new Clutter.Text({ color: ITEM_NAME_COLOR, font_name: "Sans 14px", ellipsize: Pango.EllipsizeMode.END, @@ -203,7 +203,7 @@ LauncherWidget.prototype = { padding: ITEM_PADDING, reactive: true }); item._info = info; - item.append(info.getIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING), + item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING), Big.BoxPackFlags.NONE); this.collapsedActor.append(item, Big.BoxPackFlags.NONE);