Compare commits

...

24 Commits

Author SHA1 Message Date
raresvis
de814752d6 search.js: Vertically center the provider icon 2017-07-05 01:00:49 +03:00
raresvis
c36f006b88 update sass 2017-07-05 00:56:41 +03:00
raresvis
bf884ae9ea search.js: Apply the bold style in real time 2017-07-05 00:32:16 +03:00
raresvis
7bbff9d0c0 search.js: Propagate searchResultsView down the hierarchy 2017-07-05 00:32:09 +03:00
Florian Müllner
04ad2b24d8 util: Wrap g_regex_escape_string() 2017-07-04 22:34:18 +03:00
raresvis
4ffbec5b75 search.js: Increase maximum number of visible list search results 2017-07-04 22:34:18 +03:00
raresvis
d35f2d375b gnome-shell.css: Make search result description semitransparent 2017-07-04 22:34:18 +03:00
raresvis
235d4b244d gnome-shell.css: Use standard font size for the search-result-title class 2017-07-04 22:34:18 +03:00
raresvis
9a007058ae search.js: Replace the gradient separator with a simple line 2017-07-04 22:34:18 +03:00
raresvis
985e53a04e search.js: Tweak the sizes of search results icons
Just a small tweak of icon sizes. This patch could be easily
included in any of the two bigger patches.
2017-07-04 22:34:18 +03:00
raresvis
aed6d466cb search.js: Refactor providerIcon into providerInfo
In order to match the current mockups, the providerIcon
class needed to include both the name of the provider
and the label that informs the user about how many more
search results are available for that specific provider.
The latter replaces the plus sign icon that has been
used so far.

https://bugzilla.gnome.org/show_bug.cgi?id=749957
2017-07-04 22:34:14 +03:00
raresvis
c62e3614d5 search.js: Make the results take more horizontal space
In order to make gnome-shell search functionality fit on
smaller screens, like those of devices, search results
need to take advantage of more horizontal space so that
any extra space can be used efficiently.

In order to do so, change the layout of the ListSearchResult
class from a vertical one, to a horizontal one and also
decrease the padding of the list-search-result-content css
class.

https://bugzilla.gnome.org/show_bug.cgi?id=749957
2017-07-01 02:53:25 +03:00
raresvis
8dae0b5767 update sass 2017-07-01 02:24:57 +03:00
Michael Catanzaro
a00a186772 authPrompt: Remove stray tab character 2017-06-29 18:16:32 -05:00
Ray Strode
e3330b638a Revert "gdmUtil: Fix auth prompt drawing over user list"
This reverts commit 875a1d6159.

(this was pushed accidentally, isn't the right patch, and lacks
 a bug reference)
2017-06-28 13:16:22 -04:00
Ray Strode
bdc15d680a Revert "data: install process-working.svg to filesystem"
This reverts commit 0e922eee36.

(this was pushed accidentally, and is meant to be a downstream
 only patch)
2017-06-28 13:16:02 -04:00
Michael Catanzaro
82e20f94f4 authPrompt: Reorder import
5b339c8371 put this in the wrong place.
2017-06-28 02:35:46 -05:00
Mario Sanchez Prada
5221744d1d workspace: Reset source IDs to zero after removing them
There were some source IDs that were not being reset to zero when
removing the associated sources, resulting on some critical errors
being dumped when _realRecalculateWindowPositions() got called
after that point, via _delayedWindowRepositioning().
2017-06-27 10:10:40 +01:00
Michael Catanzaro
293d1697fe Fix a typo 2017-06-26 13:47:19 -05:00
Ray Strode
9c8a470934 objectManager: handle proxies coming and going
Ever since commit b8e29ae8c7
(I think), start up is littered with this message:

 Gjs-WARNING **: JS ERROR: could not get remote objects for service
 org.gnome.SettingsDaemon.Smartcard path

since gnome-shell is now started before gnome-settings-daemon.

This commit addresses the problem by making the object manager code
not try to autostart its proxy, and instead wait for it to appear.

https://bugzilla.gnome.org/show_bug.cgi?id=772589
2017-06-22 14:31:19 -04:00
Ray Strode
9c4e875de4 objectManager: handle object manager sending empty array
If the service implementing the object manager returns
a 0 length array we currently throw an exception.

This commit fixes that.

https://bugzilla.gnome.org/show_bug.cgi?id=780403
2017-06-22 14:31:19 -04:00
Ray Strode
0e922eee36 data: install process-working.svg to filesystem
This helps prevent unlock failure on inplace upgrades between
7.3 and 7.4
2017-06-22 14:31:19 -04:00
Ray Strode
875a1d6159 gdmUtil: Fix auth prompt drawing over user list
If the user fails to enter their password then hits escape, we
jump back to the user list, then ask again for a password in a
garbled screen. this commit fixes that by guarding against the retry
if the fail counter is reset.
2017-06-22 14:31:19 -04:00
Florian Müllner
e995730a4d style: Fix nesting of elements
.login-dialog-user-selection-box is the enclosing element, not between
.login-dialog-not-listed-button and .login-dialog-not-listed-label.

https://bugzilla.gnome.org/show_bug.cgi?id=784040
2017-06-22 02:06:34 +02:00
11 changed files with 226 additions and 81 deletions

View File

@@ -1180,14 +1180,19 @@ StScrollBar {
.list-search-result-content {
spacing: 12px;
padding: 12px; }
padding: 2px; }
.list-search-result-title {
font-size: 1.5em;
color: #e2e2df; }
.list-search-result-provider {
color: #e2e2df;
margin-top: 0.24em; }
.list-search-result-description {
color: #cacac4; }
color: #cacac4;
margin-left: 30px; }
.search-provider-icon {
padding: 15px; }
@@ -1704,11 +1709,12 @@ StScrollBar {
.login-dialog-user-selection-box {
padding: 100px 0px; }
.login-dialog-user-selection-box .login-dialog-not-listed-label {
padding-left: 2px; }
.login-dialog-not-listed-button:focus .login-dialog-user-selection-box .login-dialog-not-listed-label,
.login-dialog-not-listed-button:hover .login-dialog-user-selection-box .login-dialog-not-listed-label {
color: #eeeeec; }
.login-dialog-not-listed-label {
padding-left: 2px; }
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label,
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
color: #eeeeec; }
.login-dialog-not-listed-label {
font-size: 90%;

View File

@@ -1171,23 +1171,30 @@ StScrollBar {
.list-search-results {
spacing: 3px; }
.list-search-provider-details {
spacing: 3px;
width: 150px;
margin-left: 30px; }
.search-section-separator {
-gradient-height: 1px;
-gradient-start: rgba(255, 255, 255, 0);
-gradient-end: rgba(255, 255, 255, 0.1);
-margin-horizontal: 1.5em;
height: 1px; }
height: 2px;
background-color: rgba(255, 255, 255, 0.2); }
.list-search-result-content {
spacing: 12px;
padding: 12px; }
padding: 2px; }
.list-search-result-title {
font-size: 1.5em;
color: #e2e2df; }
.list-search-result-provider {
color: #e2e2df;
margin-top: 0.24em;
}
.list-search-result-description {
color: #cacac4; }
color: rgba(202, 202, 196, 0.5);
margin-left: 30px; }
.search-provider-icon {
padding: 15px; }
@@ -1704,11 +1711,12 @@ StScrollBar {
.login-dialog-user-selection-box {
padding: 100px 0px; }
.login-dialog-user-selection-box .login-dialog-not-listed-label {
padding-left: 2px; }
.login-dialog-not-listed-button:focus .login-dialog-user-selection-box .login-dialog-not-listed-label,
.login-dialog-not-listed-button:hover .login-dialog-user-selection-box .login-dialog-not-listed-label {
color: #eeeeec; }
.login-dialog-not-listed-label {
padding-left: 2px; }
.login-dialog-not-listed-button:focus .login-dialog-not-listed-label,
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
color: #eeeeec; }
.login-dialog-not-listed-label {
font-size: 90%;

View File

@@ -3,6 +3,7 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Signals = imports.signals;
const St = imports.gi.St;
@@ -13,7 +14,6 @@ const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const Pango = imports.gi.Pango;
const DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
const DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
@@ -263,7 +263,7 @@ const AuthPrompt = new Lang.Class({
_onVerificationComplete: function() {
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
this.cancelButton.reactive = false;
},
_onReset: function() {

View File

@@ -138,7 +138,7 @@ const ShellUserVerifier = new Lang.Class({
// We check for smartcards right away, since an inserted smartcard
// at startup should result in immediately initiating authentication.
// This is different than fingeprint readers, where we only check them
// This is different than fingerprint readers, where we only check them
// after a user has been picked.
this._checkForSmartcard();

View File

@@ -46,7 +46,7 @@ const ObjectManager = new Lang.Class({
g_interface_info: ObjectManagerInfo,
g_name: this._serviceName,
g_object_path: this._managerPath,
g_flags: Gio.DBusProxyFlags.NONE });
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
this._interfaceInfos = {};
this._objects = {};
@@ -65,6 +65,9 @@ const ObjectManager = new Lang.Class({
},
_tryToCompleteLoad: function() {
if (this._numLoadInhibitors == 0)
return;
this._numLoadInhibitors--;
if (this._numLoadInhibitors == 0) {
if (this._onLoaded)
@@ -86,7 +89,7 @@ const ObjectManager = new Lang.Class({
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.NONE });
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
@@ -181,6 +184,18 @@ const ObjectManager = new Lang.Class({
return;
}
this._managerProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
if (this._managerProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
}));
if (this._managerProxy.g_name_owner)
this._onNameAppeared();
},
_onNameAppeared: function() {
this._managerProxy.GetManagedObjectsRemote(Lang.bind(this, function(result, error) {
if (!result) {
if (error) {
@@ -193,6 +208,11 @@ const ObjectManager = new Lang.Class({
let [objects] = result;
if (!objects) {
this._tryToCompleteLoad();
return;
}
let objectPaths = Object.keys(objects);
for (let i = 0; i < objectPaths.length; i++) {
let objectPath = objectPaths[i];
@@ -213,6 +233,21 @@ const ObjectManager = new Lang.Class({
}));
},
_onNameVanished: function() {
let objectPaths = Object.keys(this._objects);
for (let i = 0; i < objectPaths.length; i++) {
let object = this._objects[objectPaths];
let interfaceNames = Object.keys(object);
for (let j = 0; i < interfaceNames.length; i++) {
let interfaceName = interfaceNames[i];
if (object[interfaceName])
this._removeInterface(objectPath, interfaceName);
}
}
},
_registerInterfaces: function(interfaces) {
for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);

View File

@@ -1131,7 +1131,7 @@ const AppSearchProvider = new Lang.Class({
this.getInitialResultSet(terms, callback, cancellable);
},
createResultObject: function (resultMeta) {
createResultObject: function (resultMeta, searchResultsView) {
let app = this._appSys.lookup_app(resultMeta['id']);
return new AppIcon(app);
}

View File

@@ -22,7 +22,7 @@ const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_LIST_SEARCH_RESULTS_ROWS = 5;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const MaxWidthBin = new Lang.Class({
@@ -48,9 +48,10 @@ const MaxWidthBin = new Lang.Class({
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo) {
_init: function(provider, metaInfo, searchResultsView) {
this.provider = provider;
this.metaInfo = metaInfo;
this._searchResultsView = searchResultsView;
this.actor = new St.Button({ reactive: true,
can_focus: true,
@@ -72,10 +73,10 @@ const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
ICON_SIZE: 24,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
_init: function(provider, metaInfo, searchResultsView) {
this.parent(provider, metaInfo, searchResultsView);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
@@ -90,7 +91,7 @@ const ListSearchResult = new Lang.Class({
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
let details = new St.BoxLayout({ vertical: false });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
@@ -101,17 +102,38 @@ const ListSearchResult = new Lang.Class({
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
y_align: St.Align.MIDDLE });
this.actor.label_actor = title;
this._descriptionLabel =
new St.Label({
style_class: 'list-search-result-description' });
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
this._highlightTerms();
details.add(this._descriptionLabel, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
}
this._termsChangedSignal =
this._searchResultsView.connect(
'terms-changed',
Lang.bind(this, this._highlightTerms));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
_highlightTerms: function() {
if (!this.metaInfo['description'] || !this._descriptionLabel || !this._searchResultsView)
return;
this._descriptionLabel.clutter_text.set_markup(this._searchResultsView.highlightTerms(this.metaInfo['description']));
},
_onDestroy: function() {
this._searchResultsView.disconnect(this._termsChangedSignal);
}
});
@@ -119,8 +141,8 @@ const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
_init: function(provider, metaInfo, searchResultsView) {
this.parent(provider, metaInfo, searchResultsView);
this.actor.style_class = 'grid-search-result';
@@ -135,8 +157,9 @@ const GridSearchResult = new Lang.Class({
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
_init: function(provider, searchResultsView) {
this.provider = provider;
this._searchResultsView = searchResultsView;
this._terms = [];
@@ -147,8 +170,8 @@ const SearchResultsBase = new Lang.Class({
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
let separator = new St.DrawingArea({ style_class: 'search-section-separator' });
this.actor.add(separator);
this._resultDisplays = {};
@@ -164,7 +187,8 @@ const SearchResultsBase = new Lang.Class({
_createResultDisplay: function(meta) {
if (this.provider.createResultObject)
return this.provider.createResultObject(meta);
return this.provider.createResultObject(meta,
this._searchResultsView);
return null;
},
@@ -188,7 +212,7 @@ const SearchResultsBase = new Lang.Class({
Main.overview.toggle();
},
_setMoreIconVisible: function(visible) {
_setMoreLabelVisible: function(visible, moreNumber) {
},
_ensureResultActors: function(results, callback) {
@@ -231,7 +255,6 @@ const SearchResultsBase = new Lang.Class({
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
@@ -256,7 +279,8 @@ const SearchResultsBase = new Lang.Class({
results.forEach(Lang.bind(this, function(resultId) {
this._addItem(this._resultDisplays[resultId]);
}));
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this._setMoreLabelVisible(hasMoreResults && this.provider.canLaunchSearch,
providerResults.length - results.length);
this.actor.show();
callback();
}));
@@ -268,20 +292,20 @@ const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
_init: function(provider, searchResultsView) {
this.parent(provider, searchResultsView);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
this.providerInfo = new ProviderInfo(provider);
this.providerInfo.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerInfo.connect('clicked', Lang.bind(this,
function() {
this.providerIcon.animateLaunch();
this.providerInfo.animateLaunch();
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
this._container.add(this.providerInfo, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
@@ -293,8 +317,8 @@ const ListSearchResults = new Lang.Class({
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = visible;
_setMoreLabelVisible: function(visible, moreNumber) {
this.providerInfo.setMoreVisible(visible, moreNumber);
},
_getMaxDisplayedResults: function() {
@@ -306,7 +330,8 @@ const ListSearchResults = new Lang.Class({
},
_createResultDisplay: function(meta) {
return this.parent(meta) || new ListSearchResult(this.provider, meta);
return this.parent(meta, this._searchResultsView) ||
new ListSearchResult(this.provider, meta, this._searchResultsView);
},
_addItem: function(display) {
@@ -326,14 +351,14 @@ const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider, parentContainer) {
this.parent(provider);
_init: function(provider, searchResultsView) {
this.parent(provider, searchResultsView);
// We need to use the parent container to know how much results we can show.
// None of the actors in this class can be used for that, since the main actor
// goes hidden when no results are displayed, and then it lost its allocation.
// Then on the next use of _getMaxDisplayedResults allocation is 0, en therefore
// it doesn't show any result although we have some.
this._parentContainer = parentContainer;
this._parentContainer = searchResultsView.actor;
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
@@ -354,7 +379,8 @@ const GridSearchResults = new Lang.Class({
},
_createResultDisplay: function(meta) {
return this.parent(meta) || new GridSearchResult(this.provider, meta);
return this.parent(meta, this._searchResultsView) ||
new GridSearchResult(this.provider, meta, this._searchResultsView);
},
_addItem: function(display) {
@@ -418,6 +444,8 @@ const SearchResults = new Lang.Class({
this._providers = [];
this._searchTermRegex = null;
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders));
@@ -537,6 +565,14 @@ const SearchResults = new Lang.Class({
if (this._searchTimeoutId == 0)
this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._onSearchTimeout));
let escapedSearchTerms = this._terms.map(
(currentTerm, index, array) =>
{ return Shell.util_regex_escape(currentTerm) });
this._searchTermRegex =
new RegExp(`(${escapedSearchTerms.join('|')})`, 'gi');
this.emit('terms-changed');
},
_onPan: function(action) {
@@ -556,9 +592,9 @@ const SearchResults = new Lang.Class({
let providerDisplay;
if (provider.appInfo)
providerDisplay = new ListSearchResults(provider);
providerDisplay = new ListSearchResults(provider, this);
else
providerDisplay = new GridSearchResults(provider, this.actor);
providerDisplay = new GridSearchResults(provider, this);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
providerDisplay.actor.hide();
@@ -675,14 +711,22 @@ const SearchResults = new Lang.Class({
} else {
result.actor.remove_style_pseudo_class('selected');
}
},
highlightTerms: function(description) {
if (!description)
return '';
return description.replace(this._searchTermRegex, '<b>$1</b>');
}
});
Signals.addSignalMethods(SearchResults.prototype);
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
const ProviderInfo = new Lang.Class({
Name: 'ProviderInfo',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
PROVIDER_ICON_SIZE: 32,
_init: function(provider) {
this.provider = provider;
@@ -692,22 +736,45 @@ const ProviderIcon = new Lang.Class({
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._content = new St.BoxLayout({ vertical: false });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
this._providerDetails = new St.BoxLayout({
style_class: 'list-search-provider-details',
vertical: true });
let providerNameLabel = new St.Label({
style_class: 'list-search-result-provider',
text: provider.appInfo.get_name() });
this._remainingResultsLabel = new St.Label({
style_class: 'list-search-result-title' });
this._providerDetails.add(providerNameLabel,
{ x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._providerDetails.add(this._remainingResultsLabel,
{ x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content.add(icon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this._content.add(this._providerDetails, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
},
animateLaunch: function() {
@@ -715,5 +782,11 @@ const ProviderIcon = new Lang.Class({
let app = appSys.lookup_app(this.provider.appInfo.get_id());
if (app.state == Shell.AppState.STOPPED)
IconGrid.zoomOutActor(this._content);
},
setMoreVisible: function(visible, resultsCount) {
this._remainingResultsLabel.visible = visible;
this._remainingResultsLabel.clutter_text.set_markup(
_("%d more").format(resultsCount));
}
});

View File

@@ -1793,14 +1793,20 @@ const Workspace = new Lang.Class({
global.screen.disconnect(this._windowEnteredMonitorId);
global.screen.disconnect(this._windowLeftMonitorId);
if (this._repositionWindowsId > 0)
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
if (this._positionWindowsId > 0)
if (this._positionWindowsId > 0) {
Meta.later_remove(this._positionWindowsId);
this._positionWindowsId = 0;
}
if (this._actualGeometryLater > 0)
if (this._actualGeometryLater > 0) {
Meta.later_remove(this._actualGeometryLater);
this._actualGeometryLater = 0;
}
this._windows = [];
},

View File

@@ -240,6 +240,21 @@ shell_util_translate_time_string (const char *str)
return res;
}
/**
* shell_util_regex_escape:
* @str: a UTF-8 string to escape
*
* A wrapper around g_regex_escape_string() that takes its argument as
* \0-terminated string rather than a byte-array the confuses gjs.
*
* Returns: @str with all regex-special characters escaped
*/
char *
shell_util_regex_escape (const char *str)
{
return g_regex_escape_string (str, -1);
}
/**
* shell_write_string_to_stream:
* @stream: a #GOutputStream

View File

@@ -24,6 +24,8 @@ char *shell_util_format_date (const char *format,
gint64 time_ms);
const char *shell_util_translate_time_string (const char *str);
char *shell_util_regex_escape (const char *str);
gboolean shell_write_string_to_stream (GOutputStream *stream,
const char *str,
GError **error);