Add tooltip delay to the preview pop-ups.

Showing previews after a delay allows the user to move the mouse around
the screen without triggering constant pop-ups.

Make sure we remove the pop-up when the user hits Escape and redisplay
the pop-up if we are updating the section results due to a change in space
allocated for it.

Rename protected variable _hasPreview to _showPreview in order to not have
the naming conflict with a new private variable _havePointer, which we
name in first person.
This commit is contained in:
Marina Zhurakhinskaya 2009-03-21 10:37:15 -04:00
parent afceea3fe6
commit dcc0f368bd
4 changed files with 67 additions and 28 deletions

View File

@ -106,7 +106,7 @@ AppDisplayItem.prototype = {
// Ensures the preview icon is created. // Ensures the preview icon is created.
_ensurePreviewIconCreated : function() { _ensurePreviewIconCreated : function() {
if (!this._hasPreview || this._previewIcon) if (!this._showPreview || this._previewIcon)
return; return;
let previewIconPath = null; let previewIconPath = null;

View File

@ -88,7 +88,7 @@ DocDisplayItem.prototype = {
// Ensures the preview icon is created. // Ensures the preview icon is created.
_ensurePreviewIconCreated : function() { _ensurePreviewIconCreated : function() {
if (!this._hasPreview || this._previewIcon) if (!this._showPreview || this._previewIcon)
return; return;
this._previewIcon = new Clutter.Texture(); this._previewIcon = new Clutter.Texture();

View File

@ -6,6 +6,7 @@ const Gio = imports.gi.Gio;
const Gdk = imports.gi.Gdk; const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
@ -54,7 +55,9 @@ function GenericDisplayItem(availableWidth) {
GenericDisplayItem.prototype = { GenericDisplayItem.prototype = {
_init: function(availableWidth) { _init: function(availableWidth) {
this._availableWidth = availableWidth; this._availableWidth = availableWidth;
this._hasPreview = false; this._showPreview = false;
this._havePointer = false;
this._previewEventSourceId = null;
this.actor = new Clutter.Group({ reactive: true, this.actor = new Clutter.Group({ reactive: true,
width: availableWidth, width: availableWidth,
@ -117,18 +120,18 @@ GenericDisplayItem.prototype = {
//// Public methods //// //// Public methods ////
// Sets a boolean value that indicates whether the item should display a pop-up preview on mouse over. // Sets a boolean value that indicates whether the item should display a pop-up preview on mouse over.
setHasPreview: function(hasPreview) { setShowPreview: function(showPreview) {
this._hasPreview = hasPreview; this._showPreview = showPreview;
}, },
// Returns a boolean value that indicates whether the item displays a pop-up preview on mouse over. // Returns a boolean value that indicates whether the item displays a pop-up preview on mouse over.
getHasPreview: function() { getShowPreview: function() {
return this._hasPreview; return this._showPreview;
}, },
// Displays the preview for the item. // Displays the preview for the item.
showPreview: function() { showPreview: function() {
if(!this._hasPreview) if(!this._showPreview)
return; return;
this._ensurePreviewCreated(); this._ensurePreviewCreated();
@ -142,14 +145,26 @@ GenericDisplayItem.prototype = {
this._preview.show(); this._preview.show();
}, },
// Hides the preview for the item. // Hides the preview for the item and removes the preview event source so that
// there is no preview scheduled to show up.
hidePreview: function() { hidePreview: function() {
if(!this._hasPreview) if (this._previewEventSourceId) {
return; Mainloop.source_remove(this._previewEventSourceId);
this._previewEventSourceId = null;
}
if (this._preview)
this._preview.hide(); this._preview.hide();
}, },
// Shows a preview when the item was drawn under the mouse pointer.
onDrawnUnderPointer: function() {
this._havePointer = true;
// This code is usually triggered when we just had a different preview showing on the same spot
// and having a delay before showing a new preview looks bad. So we just show it right away.
this.showPreview();
},
// Highlights the item by setting a different background color than the default // Highlights the item by setting a different background color than the default
// if isSelected is true, removes the highlighting otherwise. // if isSelected is true, removes the highlighting otherwise.
markSelected: function(isSelected) { markSelected: function(isSelected) {
@ -250,7 +265,7 @@ GenericDisplayItem.prototype = {
// Ensures the preview actor is created. // Ensures the preview actor is created.
_ensurePreviewCreated: function() { _ensurePreviewCreated: function() {
if (!this._hasPreview || this._preview) if (!this._showPreview || this._preview)
return; return;
this._preview = new Big.Box({ background_color: PREVIEW_BOX_BACKGROUND_COLOR, this._preview = new Big.Box({ background_color: PREVIEW_BOX_BACKGROUND_COLOR,
@ -295,11 +310,22 @@ GenericDisplayItem.prototype = {
// Performs actions on mouse enter event for the item. Currently, shows the preview for the item. // Performs actions on mouse enter event for the item. Currently, shows the preview for the item.
_onEnter: function(actor, event) { _onEnter: function(actor, event) {
this._havePointer = true;
let tooltipTimeout = Gtk.Settings.get_default().gtk_tooltip_timeout;
this._previewEventSourceId = Mainloop.timeout_add(tooltipTimeout,
Lang.bind(this,
function() {
if (this._havePointer) {
this.showPreview(); this.showPreview();
}
this._previewEventSourceId = null;
return false;
}));
}, },
// Performs actions on mouse leave event for the item. Currently, hides the preview for the item. // Performs actions on mouse leave event for the item. Currently, hides the preview for the item.
_onLeave: function(actor, event) { _onLeave: function(actor, event) {
this._havePointer = false;
this.hidePreview(); this.hidePreview();
}, },
@ -308,6 +334,7 @@ GenericDisplayItem.prototype = {
// For some reason, we are not getting leave-event signal when we are dragging an item, // For some reason, we are not getting leave-event signal when we are dragging an item,
// so the preview box stays behind if we didn't have the call here. It makes sense to hide // so the preview box stays behind if we didn't have the call here. It makes sense to hide
// the preview as soon as the item starts being dragged anyway. // the preview as soon as the item starts being dragged anyway.
this._havePointer = false;
this.hidePreview(); this.hidePreview();
} }
}; };
@ -512,6 +539,24 @@ GenericDisplay.prototype = {
} }
this._updateDisplayControl(resetDisplayControl); this._updateDisplayControl(resetDisplayControl);
// We currently redisplay matching items and raise the sideshow as part of two different callbacks.
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
Mainloop.timeout_add(5,
Lang.bind(this,
function() {
// Check if the pointer is over one of the items and display the preview pop-up if it is.
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let global = Shell.Global.get();
let actor = global.stage.get_actor_at_pos(x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor.get_parent());
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}));
}, },
// Creates a display item based on the information associated with itemId // Creates a display item based on the information associated with itemId
@ -526,7 +571,7 @@ GenericDisplay.prototype = {
let itemInfo = this._allItems[itemId]; let itemInfo = this._allItems[itemId];
let displayItem = this._createDisplayItem(itemInfo); let displayItem = this._createDisplayItem(itemInfo);
displayItem.setHasPreview(true); displayItem.setShowPreview(true);
displayItem.connect('activate', function() { displayItem.connect('activate', function() {
me._activatedItem = displayItem; me._activatedItem = displayItem;
@ -608,17 +653,6 @@ GenericDisplay.prototype = {
this._displayMatchedItems(true); this._displayMatchedItems(true);
// Check if the pointer is over one of the items and display the preview pop-up if it is.
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let global = Shell.Global.get();
let actor = global.stage.get_actor_at_pos(x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor.get_parent());
if (item != null) {
item.showPreview();
}
}
this.emit('redisplayed'); this.emit('redisplayed');
}, },

View File

@ -146,6 +146,11 @@ Sideshow.prototype = {
this._searchEntry.connect('key-press-event', function (se, e) { this._searchEntry.connect('key-press-event', function (se, e) {
let symbol = Shell.get_event_key_symbol(e); let symbol = Shell.get_event_key_symbol(e);
if (symbol == Clutter.Escape) { if (symbol == Clutter.Escape) {
// We always want to hide the previews when the user hits Escape.
// If something that should have a preview gets displayed under
// the mouse pointer afterwards the preview will get redisplayed.
me._appDisplay.hidePreview();
me._docDisplay.hidePreview();
// Escape will keep clearing things back to the desktop. First, if // Escape will keep clearing things back to the desktop. First, if
// we have active text, we remove it. // we have active text, we remove it.
if (me._searchEntry.text != '') if (me._searchEntry.text != '')