viewSelector: don't process key presses from capture-event
Rather than connecting to stage::capture-event and then trying to guess whether or not a given key-press should be handled by us or not, handle the end-search-on-Escape case from entry::key-press-event (since it only makes sense when the entry is focused anyway) and the start-search-on-printable-key case from stage::key-press-event (which will only get the events that no other actor wanted for itself). Similarly, do exit-overview-on-Escape and switch-panes cases from stage::key-press-event, rather than viewSelector.actor::key-press-event, so that they will work correctly even if the keyboard focus is somewhere else. (Also fix a longstanding bug in the pane-switching code, which was supposed to be disabled when a search was active, but was checking a non-existent variable.) https://bugzilla.gnome.org/show_bug.cgi?id=642502
This commit is contained in:
parent
3755783d41
commit
d5735496af
@ -513,7 +513,7 @@ Overview.prototype = {
|
|||||||
if (this._shown)
|
if (this._shown)
|
||||||
return;
|
return;
|
||||||
// Do this manually instead of using _syncInputMode, to handle failure
|
// Do this manually instead of using _syncInputMode, to handle failure
|
||||||
if (!Main.pushModal(this.viewSelector.actor))
|
if (!Main.pushModal(this._group))
|
||||||
return;
|
return;
|
||||||
this._modal = true;
|
this._modal = true;
|
||||||
this._animateVisible();
|
this._animateVisible();
|
||||||
|
@ -80,19 +80,17 @@ ViewTab.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function SearchTab(focusBase) {
|
function SearchTab() {
|
||||||
this._init(focusBase);
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchTab.prototype = {
|
SearchTab.prototype = {
|
||||||
__proto__: BaseTab.prototype,
|
__proto__: BaseTab.prototype,
|
||||||
|
|
||||||
_init: function(focusBase) {
|
_init: function() {
|
||||||
this._searchActive = false;
|
this.active = false;
|
||||||
this._searchPending = false;
|
this._searchPending = false;
|
||||||
this._keyPressId = 0;
|
|
||||||
this._searchTimeoutId = 0;
|
this._searchTimeoutId = 0;
|
||||||
this._focusBase = focusBase;
|
|
||||||
|
|
||||||
this._searchSystem = new Search.SearchSystem();
|
this._searchSystem = new Search.SearchSystem();
|
||||||
this._openSearchSystem = new Search.OpenSearchSystem();
|
this._openSearchSystem = new Search.OpenSearchSystem();
|
||||||
@ -105,6 +103,7 @@ SearchTab.prototype = {
|
|||||||
hint_text: _("Type to search..."),
|
hint_text: _("Type to search..."),
|
||||||
track_hover: true });
|
track_hover: true });
|
||||||
this._text = this._entry.clutter_text;
|
this._text = this._entry.clutter_text;
|
||||||
|
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
||||||
|
|
||||||
this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
|
this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
|
||||||
icon_name: 'edit-find',
|
icon_name: 'edit-find',
|
||||||
@ -142,29 +141,16 @@ SearchTab.prototype = {
|
|||||||
this._capturedEventId = 0;
|
this._capturedEventId = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
|
||||||
BaseTab.prototype.show.call(this);
|
|
||||||
|
|
||||||
if (this._keyPressId == 0)
|
|
||||||
this._keyPressId = this._text.connect('key-press-event',
|
|
||||||
Lang.bind(this, this._onKeyPress));
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function() {
|
hide: function() {
|
||||||
BaseTab.prototype.hide.call(this);
|
BaseTab.prototype.hide.call(this);
|
||||||
|
|
||||||
if (this._keyPressId > 0) {
|
|
||||||
this._text.disconnect(this._keyPressId);
|
|
||||||
this._keyPressId = 0;
|
|
||||||
}
|
|
||||||
this._reset();
|
this._reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
_reset: function () {
|
_reset: function () {
|
||||||
this._text.text = '';
|
this._text.text = '';
|
||||||
|
|
||||||
// Return focus to the viewSelector
|
global.stage.set_key_focus(null);
|
||||||
global.stage.set_key_focus(this._focusBase);
|
|
||||||
|
|
||||||
this._text.set_cursor_visible(true);
|
this._text.set_cursor_visible(true);
|
||||||
this._text.set_selection(0, 0);
|
this._text.set_selection(0, 0);
|
||||||
@ -172,10 +158,7 @@ SearchTab.prototype = {
|
|||||||
|
|
||||||
_updateCursorVisibility: function() {
|
_updateCursorVisibility: function() {
|
||||||
let focus = global.stage.get_key_focus();
|
let focus = global.stage.get_key_focus();
|
||||||
if (focus == this._focusBase || focus == this._text)
|
this._text.set_cursor_visible(focus == this._text);
|
||||||
this._text.set_cursor_visible(true);
|
|
||||||
else
|
|
||||||
this._text.set_cursor_visible(false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMapped: function() {
|
_onMapped: function() {
|
||||||
@ -198,19 +181,24 @@ SearchTab.prototype = {
|
|||||||
this._searchResults.createProviderMeta(provider);
|
this._searchResults.createProviderMeta(provider);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
startSearch: function(event) {
|
||||||
|
global.stage.set_key_focus(this._text);
|
||||||
|
this._text.event(event, false);
|
||||||
|
},
|
||||||
|
|
||||||
// the entry does not show the hint
|
// the entry does not show the hint
|
||||||
_isActivated: function() {
|
_isActivated: function() {
|
||||||
return this._text.text == this._entry.get_text();
|
return this._text.text == this._entry.get_text();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onTextChanged: function (se, prop) {
|
_onTextChanged: function (se, prop) {
|
||||||
let searchPreviouslyActive = this._searchActive;
|
let searchPreviouslyActive = this.active;
|
||||||
this._searchActive = this._entry.get_text() != '';
|
this.active = this._entry.get_text() != '';
|
||||||
this._searchPending = this._searchActive && !searchPreviouslyActive;
|
this._searchPending = this.active && !searchPreviouslyActive;
|
||||||
if (this._searchPending) {
|
if (this._searchPending) {
|
||||||
this._searchResults.startingSearch();
|
this._searchResults.startingSearch();
|
||||||
}
|
}
|
||||||
if (this._searchActive) {
|
if (this.active) {
|
||||||
this._entry.set_secondary_icon(this._activeIcon);
|
this._entry.set_secondary_icon(this._activeIcon);
|
||||||
|
|
||||||
if (this._iconClickedId == 0) {
|
if (this._iconClickedId == 0) {
|
||||||
@ -228,7 +216,7 @@ SearchTab.prototype = {
|
|||||||
this._entry.set_secondary_icon(this._inactiveIcon);
|
this._entry.set_secondary_icon(this._inactiveIcon);
|
||||||
this.emit('search-cancelled');
|
this.emit('search-cancelled');
|
||||||
}
|
}
|
||||||
if (!this._searchActive) {
|
if (!this.active) {
|
||||||
if (this._searchTimeoutId > 0) {
|
if (this._searchTimeoutId > 0) {
|
||||||
Mainloop.source_remove(this._searchTimeoutId);
|
Mainloop.source_remove(this._searchTimeoutId);
|
||||||
this._searchTimeoutId = 0;
|
this._searchTimeoutId = 0;
|
||||||
@ -243,63 +231,35 @@ SearchTab.prototype = {
|
|||||||
_onKeyPress: function(entry, event) {
|
_onKeyPress: function(entry, event) {
|
||||||
let symbol = event.get_key_symbol();
|
let symbol = event.get_key_symbol();
|
||||||
if (symbol == Clutter.Up) {
|
if (symbol == Clutter.Up) {
|
||||||
if (!this._searchActive)
|
if (!this.active)
|
||||||
return true;
|
return true;
|
||||||
this._searchResults.selectUp(false);
|
this._searchResults.selectUp(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (symbol == Clutter.Down) {
|
} else if (symbol == Clutter.Down) {
|
||||||
if (!this._searchActive)
|
if (!this.active)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
this._searchResults.selectDown(false);
|
this._searchResults.selectDown(false);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (symbol == Clutter.Escape) {
|
||||||
|
if (this._isActivated()) {
|
||||||
|
this._reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onCapturedEvent: function(actor, event) {
|
_onCapturedEvent: function(actor, event) {
|
||||||
let source = event.get_source();
|
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||||
|
let source = event.get_source();
|
||||||
switch (event.type()) {
|
if (source != this._text && this._text.text == '') {
|
||||||
case Clutter.EventType.BUTTON_PRESS:
|
|
||||||
// the user clicked outside after activating the entry, but
|
// the user clicked outside after activating the entry, but
|
||||||
// with no search term entered - cancel the search
|
// with no search term entered - cancel the search
|
||||||
if (source != this._text && this._text.text == '')
|
this._reset();
|
||||||
this._reset();
|
}
|
||||||
break;
|
|
||||||
case Clutter.EventType.KEY_PRESS:
|
|
||||||
// If some "special" actor grabbed the focus (run
|
|
||||||
// dialog, looking glass); we don't want to interfere
|
|
||||||
// with that
|
|
||||||
let focus = global.stage.get_key_focus();
|
|
||||||
if (focus != this._focusBase && focus != this._text)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let sym = event.get_key_symbol();
|
|
||||||
|
|
||||||
// If we have an active search, Escape cancels it - if we
|
|
||||||
// haven't, the key is ignored
|
|
||||||
if (sym == Clutter.Escape)
|
|
||||||
if (this._isActivated()) {
|
|
||||||
this._reset();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore non-printable keys
|
|
||||||
if (!Clutter.keysym_to_unicode(sym))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Search started - move the key focus to the entry and
|
|
||||||
// "repeat" the event
|
|
||||||
if (!this._isActivated()) {
|
|
||||||
global.stage.set_key_focus(this._text);
|
|
||||||
this._text.event(event, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -323,8 +283,6 @@ ViewSelector.prototype = {
|
|||||||
_init : function() {
|
_init : function() {
|
||||||
this.actor = new St.BoxLayout({ name: 'viewSelector',
|
this.actor = new St.BoxLayout({ name: 'viewSelector',
|
||||||
vertical: true });
|
vertical: true });
|
||||||
this.actor.connect('key-press-event',
|
|
||||||
Lang.bind(this, this._onKeyPress));
|
|
||||||
|
|
||||||
// The tab bar is located at the top of the view selector and
|
// The tab bar is located at the top of the view selector and
|
||||||
// holds both "normal" tab labels and the search entry. The former
|
// holds both "normal" tab labels and the search entry. The former
|
||||||
@ -358,7 +316,7 @@ ViewSelector.prototype = {
|
|||||||
this._tabs = [];
|
this._tabs = [];
|
||||||
this._activeTab = null;
|
this._activeTab = null;
|
||||||
|
|
||||||
this._searchTab = new SearchTab(this.actor);
|
this._searchTab = new SearchTab();
|
||||||
this._searchArea.set_child(this._searchTab.title);
|
this._searchArea.set_child(this._searchTab.title);
|
||||||
this._addTab(this._searchTab);
|
this._addTab(this._searchTab);
|
||||||
|
|
||||||
@ -369,10 +327,22 @@ ViewSelector.prototype = {
|
|||||||
|
|
||||||
Main.overview.connect('item-drag-begin',
|
Main.overview.connect('item-drag-begin',
|
||||||
Lang.bind(this, this._switchDefaultTab));
|
Lang.bind(this, this._switchDefaultTab));
|
||||||
Main.overview.connect('showing',
|
|
||||||
Lang.bind(this, this._switchDefaultTab));
|
this._stageKeyPressId = 0;
|
||||||
Main.overview.connect('hiding',
|
Main.overview.connect('showing', Lang.bind(this,
|
||||||
Lang.bind(this, this._switchDefaultTab));
|
function () {
|
||||||
|
this._switchDefaultTab();
|
||||||
|
this._stageKeyPressId = global.stage.connect('key-press-event',
|
||||||
|
Lang.bind(this, this._onStageKeyPress));
|
||||||
|
}));
|
||||||
|
Main.overview.connect('hiding', Lang.bind(this,
|
||||||
|
function () {
|
||||||
|
this._switchDefaultTab();
|
||||||
|
if (this._stageKeyPressId != 0) {
|
||||||
|
global.stage.disconnect(this._stageKeyPressId);
|
||||||
|
this._stageKeyPressId = 0;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// Public constraints which may be used to tie actors' height or
|
// Public constraints which may be used to tie actors' height or
|
||||||
// vertical position to the current tab's content; as the content's
|
// vertical position to the current tab's content; as the content's
|
||||||
@ -527,22 +497,25 @@ ViewSelector.prototype = {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_onKeyPress: function(actor, event) {
|
_onStageKeyPress: function(actor, event) {
|
||||||
let modifiers = Shell.get_event_state(event);
|
let modifiers = Shell.get_event_state(event);
|
||||||
let symbol = event.get_key_symbol();
|
let symbol = event.get_key_symbol();
|
||||||
|
|
||||||
if (symbol == Clutter.Escape) {
|
if (symbol == Clutter.Escape) {
|
||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
return true;
|
return true;
|
||||||
} else if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
|
} else if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
|
||||||
if (symbol == Clutter.Page_Up) {
|
if (symbol == Clutter.Page_Up) {
|
||||||
if (!this._searchActive)
|
if (!this._searchTab.active)
|
||||||
this._prevTab();
|
this._prevTab();
|
||||||
return true;
|
return true;
|
||||||
} else if (symbol == Clutter.Page_Down) {
|
} else if (symbol == Clutter.Page_Down) {
|
||||||
if (!this._searchActive)
|
if (!this._searchTab.active)
|
||||||
this._nextTab();
|
this._nextTab();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (Clutter.keysym_to_unicode(symbol)) {
|
||||||
|
this._searchTab.startSearch(event);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user