Compare commits

..

33 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
a6783692c5 animation: Set size through CSS
Pretty much the same case of the previous commit: we want this size
to be scale-dependant, and using the width and height properties of
ClutterActor doesn't automatically update.

Use CSS to set the width and height.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 14:37:35 -03:00
Georges Basile Stavracas Neto
1c27b68bcc appDisplay: Set the folder icon geometry through CSS
The CSS engine is scale-aware, whereas simply setting the
width and height properties directly isn't.

Use CSS to set the folder icon.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 14:37:35 -03:00
Georges Basile Stavracas Neto
717c05a288 st/theme-node: Use the node's scale factor
Each node stores the scale factor in place when it was created.
Creating nodes with the same style, but with different scale
factors, yields different nodes.

Use the node's scale factor instead of retrieving the context's
one.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 14:37:35 -03:00
Georges Basile Stavracas Neto
e68604b1aa st/theme-node: Consider scale factor when comparing
The CSS engine of St is scale-aware, which means every length
and size it produces is multiplied by the current scale factor.

However, the individual nodes aren't aware of the scale factor
when they compare to each other.

Store and compare the scale factors in the nodes themselves.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1635

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 14:37:35 -03:00
Georges Basile Stavracas Neto
0368ad29e9 st/theme-context: Add a getter for the scale-factor property
Will be used by the next commit to avoid going through the GObject
machinery when retrieving the scale factor.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1176
2020-04-06 14:37:35 -03:00
Jonas Dreßler
b982ce394e shell-app: Use container widget for fallback X11 app icons
Just like StIcon does, we should use a container widget for the fallback
app icon that we get using the cairo surface property. It's needed
because the widget returned by shell_app_create_icon_texture() can be
resized freely, while we want the aspect ratio of the actual texture to
remain the same.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2578


(cherry picked from commit 85846d88f0)
2020-04-06 15:00:05 +00:00
Jonas Dreßler
025647f585 st/theme-context: Also invalidate root node on stylesheet changes
Since commit 6a42d77261 we invalidate the
cached properties for each theme node on stylesheet changes by iterating
over the hashtable of the theme context instead of listening to the
signal in each individual theme node.

That commit forgot one particular node though that's not stored in the
hashtable, but using the `priv->root_node` property instead: The theme
node that belongs to the stage.

So make sure we also invalidate the cached properties of the stage theme
node on stylesheet changes. This fixes various crashes that happened
with extensions providing custom stylesheets (emitting the
"custom-stylesheets-changed" signal on every extension enable/disable),
trying to access an already freed CSS property of the stage.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2584


(cherry picked from commit bc973b80d7)
2020-04-06 14:59:45 +00:00
Florian Müllner
7125b726ad data: Add extension-portal desktop file
Now that the extension preference dialog is opened by a separate
D-Bus service rather than the Extensions app, it can be opened
without a parent window that provides name and icon.

Fix this by adding back a hidden .desktop file.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2562


(cherry picked from commit 6b7c85b079)
2020-04-05 13:48:39 +00:00
Florian Müllner
aebfab7207 extensions-app: Add category in .desktop file
Predefined categories aren't a great way for organizing installed
applications, but they have their use in "stores" like Software
or flathub.

Not listing any category means we fall through the cracks, so
pick the (hopefully) least inappropriate one ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1160


(cherry picked from commit 360f5b1642)
2020-04-05 12:46:11 +00:00
Jonas Dreßler
698bd5b3a9 st/icon: Use a static GIcon for the missing-image icon
Don't create a new GIcon for the "missing-image" texture but simply
create it once statically instead and always use that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1179


(cherry picked from commit 1ca39e8586)
2020-04-04 19:40:10 +00:00
Jonas Dreßler
51e9f19f2f st/icon: Always show empty texture if both gicons are NULL
Commit 7ff7fb5d3b forgot to clear the
`priv->icon_texture` actor when returning from st_icon_update(), which
means we don't always switch to an empty icon if both gicon properties
are set to NULL.

Fix this and destroy the actor before returning early from
st_icon_update().

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1178


(cherry picked from commit 07deda593a)
2020-04-04 19:30:49 +00:00
Rūdolfs Mazurs
6d38a4a7b3 Update Latvian translation 2020-04-04 16:14:40 +00:00
Florian Müllner
dfcc5ffb1e screenShield: Wake up on deactivate()
Usually the screen is woken up before the shield is deactivated, but
it is also possible to unlock the session programmatically via the
org.gnome.ScreenSaver D-Bus API.

The intention is very likely not to unlock a turned off screen in
that case. Nor does it seem like a good idea to change the lock
state without any indication.

Waking up the screen is more likely to meet expectations and is
more reasonable too, so do that.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158


(cherry picked from commit fbe2e30f38)
2020-04-03 15:09:24 +00:00
Florian Müllner
8b80a4cf4d screenShield: Switch lightboxes off before unlock transition
There is no point in animating a transition with fullscreen black
rectangles stacked on top, so switch them off before rather than
after the transition.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1158


(cherry picked from commit fb6ead2881)
2020-04-03 15:08:58 +00:00
Andre Moreira Magalhaes
01e894c028 st/icon: Only load default fallback icon if an icon was set and failed to load
Commit c89d6a633 introduced a default fallback icon that would be displayed in
case the main gicon or the fallback gicon wasn't set or failed to load.

This broke the use case where a StIcon is created but no main icon or
fallback icon are set on purpose, for example the appindicator extension
which always creates a StIcon to represent icons in menu items but the
actual icons are only set if the application provides one, leaving the
menu showing the default fallback ("image-missing") icon for all menu
entries that don't actually have an icon provided by the application.

Fix that by only using the default fallback icon if the provided one
failed to load.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1173

(cherry picked from commit 7ff7fb5d3b)
2020-04-03 17:00:30 +02:00
Florian Müllner
856adfd1f1 extensionUtils: Add openPrefs() convenience method
Opening their own preferences is a reasonable desire for extensions,
so make up for breaking it by adding a convenience method for that
action.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1163

(cherry picked from commit 8030d9ad32)
2020-04-03 17:00:07 +02:00
Florian Müllner
efee3aa749 extensionSystem: Add method for opening extension prefs
Extension that want to expose their own preferences (for example as menu
items) do that by passing their UUID to gnome-shell-extension-prefs.

But since 3.36.1 the app is optional and no longer accepts arguments on
the command line. To adjust, extensions now need to make a D-Bus call
the extensions portal, just like the app and gnome-shell.

We will add a convenience method for that purpose, so it makes
sense to share the existing code. As it's extension-related, the
extension manager looks like the right place ...

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1163

(cherry picked from commit 45bc850715)
2020-04-03 16:58:15 +02:00
Florian Müllner
15e72da648 workspace: Fix chaining up
Gah, accidentally dropped the 'vfunc' prefix :-(

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1172
2020-04-03 15:47:01 +02:00
Florian Müllner
3f8bd1db25 extensions-app: Do not expand headerbar switch
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2563
2020-04-03 15:47:01 +02:00
Florian Müllner
3a863ee341 js: Account for promisified call() method
A promisified method expects the callback parameter to be either
a function (in which case the original method is called normally)
or omitted altogether (in which case a Promise is returned).

The call to open application details in Software does neither and
passes null instead, which will result in a warning (because no
function argument means a promise will be used, but not omitting
the parameter means we end up with too many arguments).

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2551
2020-04-03 02:03:18 +00:00
Florian Müllner
654a7af929 environment: Move g_dbus_connection_call() promisification
Commit 83c6b2ab promisified the method in endSessionDialog, which means
that after the module is imported, every caller will get the promisifed
version. That can be a bit surprising in completely unrelated modules,
so commit 764527c8 (on master) moved the promisification of more common
methods into environment, as that's initialized early and expected to be
shared between anything else.

Do the same for the call() method on the stable branch.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2551
2020-04-03 02:03:18 +00:00
Andre Moreira Magalhaes
8dd9cbac7f app-cache: Fix cache for folder translations
The app-cache code currently stores the folder translations in a hash
that can be accessed via shell_util_get_translated_folder_name().
This hash uses the filename (inc. extension) for the "desktop-directory"
as key which causes an issue when trying to find the translation
on AppDisplay._findBestFolderName() which gets categories (folder names)
from the app info which doesn't contain the ".directory" extension.

Fix that by storing the filename without extension as the hash key for
the cached folder translations.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1168


(cherry picked from commit 343b3351f1)
2020-04-03 00:40:34 +00:00
Jonas Ådahl
331db650dd appDisplay: Don't clear signal handler id before emitting
Otherwise we won't clear the 'view-loaded' handler after it was emitted.

Also move field initialization to the correct place, i.e. the init
function of the base class.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1169


(cherry picked from commit a9df4e7516)
2020-04-02 21:10:30 +00:00
Марко Костић
428d38179d Update Serbian translation 2020-04-02 19:43:03 +00:00
Ibai Oihanguren Sala
fe9708ebd8 Update Basque translation 2020-04-02 16:15:32 +00:00
Jiri Grönroos
8398769321 Update Finnish translation 2020-04-02 09:44:36 +00:00
Marco Trevisan (Treviño)
768c08ba9d main: Don't override DesktopAppInfo desktop if already GNOME
During the shell initialization we call the (deprecated) function to
override the Desktop environment in Gio DesktopAppInfo to make sure that
applications are correctly shown (as per commit b2fbf5a2), however this
might break the cases in which $XDG_CURRENT_DESKTOP is already set and
contains GNOME (given that is now a list).

In Ubuntu this is in fact set to: ubuntu:GNOME.
Now, if an application contains NotShowIn=ubuntu, the key will be ignored by
the shell, and the application is still listed everywhere.

So, override the DesktopAppInfo desktop environment only in the case that
the current desktop is not already GNOME.

At the current date I think we could just safely get rid of this override at
all, but there could be still cases where it still might be useful, like when
running as nested in some other environment, so keeping it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1156


(cherry picked from commit a0def23940)
2020-04-01 03:58:56 +00:00
Danial Behzadi
69426cbfda Update Persian translation 2020-04-01 01:42:46 +00:00
Jonas Ådahl
9f968e7378 appDisplay: Clear animateLater callbacks when unmapping
In some situations we could end up not with lingering 'view-loaded'
handler. This could result in delayed spring animate-in being initiated,
e.g. after a minute after the activities overview was already closed.

Fix this by removing any lingering signal or later handlers when
unmapping.

Fixes: 5c33fe4a0a

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1155


(cherry picked from commit f49b58cf97)
2020-03-31 17:12:35 +00:00
Cheng-Chia Tseng
1ab5e6973a Update Chinese (Taiwan) translation 2020-03-31 16:07:19 +00:00
Fabio Tomat
1dea3341ec Update Friulian translation 2020-03-31 11:14:15 +00:00
Florian Müllner
8fda054dc5 Bump version to 3.36.1
Update NEWS.
2020-03-31 00:27:47 +02:00
Florian Müllner
e989684602 extensions-app/metainfo: Point screenshots to stable branch 2020-03-30 21:32:17 +02:00
103 changed files with 5142 additions and 6939 deletions

View File

@@ -18,7 +18,7 @@ variables:
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: review
variables:
GIT_DEPTH: "100"
@@ -65,7 +65,7 @@ no_template_check:
<<: *only_default
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
@@ -83,7 +83,7 @@ build:
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
@@ -100,7 +100,7 @@ test:
when: on_failure
test-pot:
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: test
before_script:
- ninja -C mutter/build install
@@ -124,7 +124,11 @@ flatpak:
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
FLATPAK_MODULE: "gnome-extensions-app"
APP_ID: "org.gnome.Extensions"
MESON_ARGS: "$SUBPROJECT"
extends: .flatpak
before_script:
- flatpak run --command=$SUBPROJECT/generate-translations.sh
--filesystem=host org.gnome.Sdk//master
<<: *only_default
nightly:

View File

@@ -6,11 +6,6 @@ globs=('*.js' '*.c')
# find source files that contain gettext keywords
files=$(grep -lR ${globs[@]/#/--include=} '\(gettext\|[^I_)]_\)(' $srcdirs)
# filter out excluded files
if [ -f po/POTFILES.skip ]; then
files=$(for f in $files; do ! grep -q ^$f po/POTFILES.skip && echo $f; done)
fi
# find those that aren't listed in POTFILES.in
missing=$(for f in $files; do ! grep -q ^$f po/POTFILES.in && echo $f; done)

58
NEWS
View File

@@ -1,3 +1,61 @@
3.36.1
======
* Improve app folders [Jonas D.; !1011]
* Fix launching ibus daemon [Alynx; !1080]
* Do not shutdown ibus/xsettings on X11 compositor restart [Carlos; #2329]
* Hide hint text in entries when preedit is used [Carlos; !1084]
* Do not load app infos on main thread [Christian; #2282]
* Don't expose FDO Notifications interface on main bus name [Florian; !547]
* Fix icon of mobile broadband connections [Cosimo, Reik; !1097, !1105]
* Fix high-contrast/symbolic icon mix-up [Florian; #2414]
* Don't ellipsize times in world clock [Florian; !1090]
* Only check for extension updates if there are any extensions [Florian; !1100]
* Fix crash when trying to update removed extensions [Florian; #2343]
* Make Extensions app available as flatpak [Florian; !1081, !1106, !1087, !1133]
* Display fractional timezones as hours:minutes [Jonas D.; #2438]
* Fix assigning pad keybindings [Carlos; #2451]
* Handle embedded newlines in lock screen notifications [Florian; #2463]
* Fix OSK layout fallback for unsupported variants [Florian; #2471]
* Do not apply text color to color glyphs (emojis) [Carlos; #850]
* Check "Install pending software updates" by default [Michael; #2427]
* Do not warn about missing GDM on each login [Florian; #2432]
* Fix telepathy chat notifications [Marco; !1112]
* Fix offline updates support in end session dialog [Michael; #2276]
* Fix activating notifications by keyboard [Florian; #2319]
* Remove handling of 'blacklisted' extensions [Florian; !1132]
* Only update extensions if Extensions app is installed [Florian; #2346]
* Improve Norwegian on-screen-keyboard layout [Bjørn; !1073]
* Fix IM support for deleting surrounding text [Takao; !477]
* Fix blur effect with fractional scaling [Jonas D.; !1000]
* Use better location name in weather section [Florian; #2468]
* Fix glitch in sound feedback on volume changes [Florian; !1147]
* Fix on-screen keyboard regressions [Jonas D.; !1142]
* Improve screen-reader support [Luke; #2508, #2517]
* Fix password entry resize on login/lock screen [Florian; #2423]
* Fix crash when opening app picker [Jonas Å.; !1154]
* Misc. bug fixes and cleanups [Florian, Sebastian, Jan, Daniel, Philip, Mario,
Ray, Marco, Jonas D., Carlos, Georges; #2298, #2305, !1078, !1077, #2334,
#2381, !1093, !1098, #2386, !1108, !1109, !1114, !1076, !1072, !1115, !1088,
!1101, #2467, !1121, !1122, #2476, !1123, !1117, !1129, !1113, !1102, !1127,
#2238, !1131, !1135, !1136, !849, #2504, #2371, !1146, !1141, #2510, !1150]
Contributors:
Marco Trevisan (Treviño), Michael Catanzaro, Cosimo Cecchi, Jonas Dreßler,
Takao Fujiwara, Carlos Garnacho, Christian Hergert, Sebastian Keller,
Reik Keutterling, Bjørn Lie, Florian Müllner, Jwtiyar Nariman,
Georges Basile Stavracas Neto, Mario Sanchez Prada, Ray Strode, Jan Tojnar,
Daniel van Vugt, Philip Withnall, Luke Yelavich, Alynx Zhou, Jonas Ådahl
Translators:
Марко Костић [sr], Jordi Mas [ca], sicklylife [ja], Marek Černocký [cs],
Daniel Rusek [cs], Kjartan Maraas [nb], Tim Sabsch [de], Stas Solovey [ru],
Peter Mráz [sk], Rafael Fontenelle [pt_BR], Piotr Drąg [pl],
Milo Casagrande [it], Anders Jonsson [sv], Yuri Chornoivan [uk],
Kukuh Syafaat [id], Guillaume Bernard [fr], Daniel Mustieles [es],
Danial Behzadi [fa], Goran Vidović [hr], Yosef Or Boczko [he],
Emin Tufan Çetin [tr], Wolfgang Stöggl [de], Ibai Oihanguren Sala [eu],
Jwtiyar Nariman [ckb], Aurimas Černius [lt]
3.36.0
======
* Fix off-by-1900 error in date conversions [Florian; !1061]

View File

@@ -1,19 +1,12 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="SetTimeRange">
<arg type="x" name="since" direction="in"/>
<arg type="x" name="until" direction="in"/>
<arg type="b" name="force_reload" direction="in"/>
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<signal name="EventsAddedOrUpdated">
<arg type="a(ssbxxa{sv})" name="events" direction="out"/>
</signal>
<signal name="EventsRemoved">
<arg type="as" name="ids" direction="out"/>
</signal>
<signal name="ClientDisappeared">
<arg type="s" name="source_uid" direction="out"/>
</signal>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>

View File

@@ -153,11 +153,9 @@
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
font-weight: bold;
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
&.calendar-work-day {
color: lighten($fg_color,10%);
font-weight: bold;
}
}
.calendar-other-month-day {

View File

@@ -184,7 +184,7 @@ var AuthPrompt = GObject.registerClass({
});
this._defaultButtonWell.add_constraint(new Clutter.BindConstraint({
source: this.cancelButton,
coordinate: Clutter.BindCoordinate.WIDTH,
coordinate: Clutter.BindCoordinate.SIZE,
}));
this._mainBox.add_child(this._defaultButtonWell);
@@ -424,13 +424,7 @@ var AuthPrompt = GObject.registerClass({
}
updateSensitivity(sensitive) {
if (this._entry.reactive === sensitive)
return;
this._entry.reactive = sensitive;
if (sensitive)
this._entry.grab_key_focus();
}
vfunc_hide() {

View File

@@ -810,13 +810,12 @@ var LoginDialog = GObject.registerClass({
return;
this._logoBin.destroy_all_children();
const [valid, resourceScale] = this._logoBin.get_resource_scale();
if (this._logoFile && valid) {
if (this._logoFile && this._logoBin.resource_scale > 0) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, -1,
scaleFactor,
resourceScale));
this._logoBin.resource_scale));
}
}

View File

@@ -2,7 +2,7 @@
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gdm, Gio, GLib } = imports.gi;
const { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals;
const Batch = imports.gdm.batch;
@@ -12,15 +12,6 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
Gio._promisify(Gdm.Client.prototype,
'open_reauthentication_channel', 'open_reauthentication_channel_finish');
Gio._promisify(Gdm.Client.prototype,
'get_user_verifier', 'get_user_verifier_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification_for_user', 'call_begin_verification_for_user_finish');
Gio._promisify(Gdm.UserVerifierProxy.prototype,
'call_begin_verification', 'call_begin_verification_finish');
var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
@@ -177,12 +168,14 @@ var ShellUserVerifier = class {
this._checkForFingerprintReader();
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
if (userName)
this._openReauthenticationChannel(userName);
else
this._getUserVerifier();
if (userName) {
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
this._client.open_reauthentication_channel(userName, this._cancellable,
this._reauthenticationChannelOpened.bind(this));
} else {
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
}
}
cancel() {
@@ -346,11 +339,10 @@ var ShellUserVerifier = class {
this._verificationFailed(false);
}
async _openReauthenticationChannel(userName) {
_reauthenticationChannelOpened(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = await this._client.open_reauthentication_channel(
userName, this._cancellable);
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@@ -359,7 +351,8 @@ var ShellUserVerifier = class {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
// is no session to reauthenticate. Fall back to performing
// verification from this login session
this._getUserVerifier();
client.get_user_verifier(this._cancellable,
this._userVerifierGot.bind(this));
return;
}
@@ -373,11 +366,10 @@ var ShellUserVerifier = class {
this._hold.release();
}
async _getUserVerifier() {
_userVerifierGot(client, result) {
try {
this._clearUserVerifier();
this._userVerifier =
await this._client.get_user_verifier(this._cancellable);
this._userVerifier = client.get_user_verifier_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
@@ -429,25 +421,35 @@ var ShellUserVerifier = class {
}
}
async _startService(serviceName) {
_startService(serviceName) {
this._hold.acquire();
try {
if (this._userName) {
await this._userVerifier.call_begin_verification_for_user(
serviceName, this._userName, this._cancellable);
} else {
await this._userVerifier.call_begin_verification(
serviceName, this._cancellable);
}
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError(this._userName
? 'Failed to start verification for user'
: 'Failed to start verification', e);
return;
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
});
} else {
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
});
}
this._hold.release();
}
_beginVerification() {

View File

@@ -23,7 +23,6 @@
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
<file>misc/params.js</file>
<file>misc/parentalControlsManager.js</file>
<file>misc/permissionStore.js</file>
<file>misc/smartcardManager.js</file>
<file>misc/systemActions.js</file>
@@ -102,6 +101,7 @@
<file>ui/swipeTracker.js</file>
<file>ui/switcherPopup.js</file>
<file>ui/switchMonitor.js</file>
<file>ui/tweener.js</file>
<file>ui/unlockDialog.js</file>
<file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file>

View File

@@ -6,15 +6,6 @@ const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
Gio._promisify(IBus.Bus.prototype,
'list_engines_async', 'list_engines_async_finish');
Gio._promisify(IBus.Bus.prototype,
'request_name_async', 'request_name_async_finish');
Gio._promisify(IBus.Bus.prototype,
'get_global_engine_async', 'get_global_engine_async_finish');
Gio._promisify(IBus.Bus.prototype,
'set_global_engine_async', 'set_global_engine_async_finish');
// Ensure runtime version matches
_checkIBusVersion(1, 5, 2);
@@ -111,14 +102,16 @@ var IBusManager = class {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._initEngines();
this._initPanelService();
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
this._initPanelService.bind(this));
}
async _initEngines() {
_initEngines(ibus, result) {
try {
const enginesList =
await this._ibus.list_engines_async(-1, this._cancellable);
let enginesList = this._ibus.list_engines_async_finish(result);
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
@@ -133,10 +126,9 @@ var IBusManager = class {
}
}
async _initPanelService() {
_initPanelService(ibus, result) {
try {
await this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable);
this._ibus.request_name_async_finish(result);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
@@ -171,15 +163,19 @@ var IBusManager = class {
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
try {
// If an engine is already active we need to get its properties
const engine =
await this._ibus.get_global_engine_async(-1, this._cancellable);
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
if (!engine)
return;
} catch (e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
this._updateReadiness();
} catch (e) {
}
});
this._updateReadiness();
}
_updateReadiness() {
@@ -227,7 +223,7 @@ var IBusManager = class {
return this._engines.get(id);
}
async setEngine(id, callback) {
setEngine(id, callback) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
@@ -237,16 +233,18 @@ var IBusManager = class {
return;
}
try {
await this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
}
preloadEngines(ids) {

View File

@@ -4,9 +4,6 @@ const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
Gio._promisify(IBus.Bus.prototype,
'create_input_context_async', 'create_input_context_async_finish');
var HIDE_PANEL_TIME = 50;
var InputMethod = GObject.registerClass(
@@ -49,11 +46,15 @@ class InputMethod extends Clutter.InputMethod {
this._currentSource = this._inputSourceManager.currentSource;
}
async _onConnected() {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._ibus.create_input_context_async('gnome-shell', -1,
this._cancellable, this._setContext.bind(this));
}
_setContext(bus, res) {
try {
this._context = await this._ibus.create_input_context_async(
'gnome-shell', -1, this._cancellable);
this._context = this._ibus.create_input_context_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop } = imports.gi;
const { GLib, GnomeDesktop, Meta } = imports.gi;
const Main = imports.ui.main;
@@ -62,11 +62,11 @@ var KeyboardManager = class {
return;
this._currentKeymap = { layouts, variants, options };
global.backend.set_keymap(layouts, variants, options);
Meta.get_backend().set_keymap(layouts, variants, options);
}
_applyLayoutGroupIndex(idx) {
global.backend.lock_layout_group(idx);
Meta.get_backend().lock_layout_group(idx);
}
apply(id) {

View File

@@ -50,22 +50,25 @@ function canLock() {
}
async function registerSessionWithGDM() {
function registerSessionWithGDM() {
log("Registering session with GDM");
try {
await Gio.DBus.system.call(
'org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log('Not calling RegisterSession(): method not exported, GDM too old?');
}
Gio.DBus.system.call('org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null,
(source, result) => {
try {
source.call_finish(result);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log("Not calling RegisterSession(): method not exported, GDM too old?");
}
}
);
}
let _loginManager = null;
@@ -171,19 +174,24 @@ var LoginManagerSystemd = class {
this._proxy.SuspendRemote(true);
}
async inhibit(reason, callback) {
try {
const inVariant = new GLib.Variant('(ssss)',
['sleep', 'GNOME Shell', reason, 'delay']);
const [outVariant_, fdList] =
await this._proxy.call_with_unix_fd_list('Inhibit',
inVariant, 0, -1, null, null);
const [fd] = fdList.steal_fds();
callback(new Gio.UnixInputStream({ fd }));
} catch (e) {
logError(e, 'Error getting systemd inhibitor');
callback(null);
}
inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)',
['sleep',
'GNOME Shell',
reason,
'delay']);
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
(proxy, result) => {
let fd = -1;
try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd }));
} catch (e) {
logError(e, "Error getting systemd inhibitor");
callback(null);
}
});
}
_prepareForSleep(proxy, sender, [aboutToSuspend]) {

View File

@@ -57,7 +57,9 @@ var ObjectManager = class {
// Start out inhibiting load until at least the proxy
// manager is loaded and the remote objects are fetched
this._numLoadInhibitors = 1;
this._initManagerProxy();
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
this._onManagerProxyLoaded.bind(this));
}
_tryToCompleteLoad() {
@@ -71,7 +73,7 @@ var ObjectManager = class {
}
}
async _addInterface(objectPath, interfaceName, onFinished) {
_addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
if (!info) {
@@ -87,38 +89,40 @@ var ObjectManager = class {
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
try {
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
try {
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
});
}
_removeInterface(objectPath, interfaceName) {
@@ -147,10 +151,9 @@ var ObjectManager = class {
}
}
async _initManagerProxy() {
_onManagerProxyLoaded(initable, result) {
try {
await this._managerProxy.init_async(
GLib.PRIORITY_DEFAULT, this._cancellable);
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`);

View File

@@ -1,146 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// Copyright (C) 2018, 2019, 2020 Endless Mobile, Inc.
//
// This is a GNOME Shell component to wrap the interactions over
// D-Bus with the malcontent library.
//
// Licensed under the GNU General Public License Version 2
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/* exported getDefault */
const { Gio, GObject, Shell } = imports.gi;
// We require libmalcontent ≥ 0.6.0
const HAVE_MALCONTENT = imports.package.checkSymbol(
'Malcontent', '0', 'ManagerGetValueFlags');
var Malcontent = null;
if (HAVE_MALCONTENT) {
Malcontent = imports.gi.Malcontent;
Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async', 'get_app_filter_finish');
}
let _singleton = null;
function getDefault() {
if (_singleton === null)
_singleton = new ParentalControlsManager();
return _singleton;
}
// A manager class which provides cached access to the constructing users
// parental controls settings. Its possible for the users parental controls
// to change at runtime if the Parental Controls application is used by an
// administrator from within the users session.
var ParentalControlsManager = GObject.registerClass({
Signals: {
'app-filter-changed': {},
},
}, class ParentalControlsManager extends GObject.Object {
_init() {
super._init();
this._initialized = false;
this._disabled = false;
this._appFilter = null;
this._initializeManager();
}
async _initializeManager() {
if (!HAVE_MALCONTENT) {
log('Skipping parental controls support as its disabled');
this._initialized = true;
this.emit('app-filter-changed');
return;
}
log(`Getting parental controls for user ${Shell.util_get_uid()}`);
try {
const connection = await Gio.DBus.get(Gio.BusType.SYSTEM, null);
this._manager = new Malcontent.Manager({ connection });
this._appFilter = await this._manager.get_app_filter_async(
Shell.util_get_uid(),
Malcontent.ManagerGetValueFlags.NONE,
null);
} catch (e) {
if (e.matches(Malcontent.ManagerError, Malcontent.ManagerError.DISABLED)) {
log('Parental controls globally disabled');
this._disabled = true;
} else {
logError(e, 'Failed to get parental controls settings');
return;
}
}
this._manager.connect('app-filter-changed', this._onAppFilterChanged.bind(this));
// Signal initialisation is complete.
this._initialized = true;
this.emit('app-filter-changed');
}
async _onAppFilterChanged(manager, uid) {
// Emit 'changed' signal only if app-filter is changed for currently logged-in user.
let currentUid = Shell.util_get_uid();
if (currentUid !== uid)
return;
try {
this._appFilter = await this._manager.get_app_filter_async(
currentUid,
Malcontent.ManagerGetValueFlags.NONE,
null);
this.emit('app-filter-changed');
} catch (e) {
// Log an error and keep the old app filter.
logError(e, `Failed to get new MctAppFilter for uid ${Shell.util_get_uid()} on app-filter-changed`);
}
}
get initialized() {
return this._initialized;
}
// Calculate whether the given app (a Gio.DesktopAppInfo) should be shown
// on the desktop, in search results, etc. The app should be shown if:
// - The .desktop file doesnt say it should be hidden.
// - The executable from the .desktop files Exec line isnt blacklisted in
// the users parental controls.
// - None of the flatpak app IDs from the X-Flatpak and the
// X-Flatpak-RenamedFrom lines are blacklisted in the users parental
// controls.
shouldShowApp(appInfo) {
// Quick decision?
if (!appInfo.should_show())
return false;
// Are parental controls enabled (at configure time or runtime)?
if (!HAVE_MALCONTENT || this._disabled)
return true;
// Have we finished initialising yet?
if (!this.initialized) {
log(`Warning: Hiding app because parental controls not yet initialised: ${appInfo.get_id()}`);
return false;
}
return this._appFilter.is_appinfo_allowed(appInfo);
}
});

View File

@@ -83,17 +83,13 @@ const SystemActions = GObject.registerClass({
this._canHavePowerOff = true;
this._canHaveSuspend = true;
function tokenizeKeywords(keywords) {
return keywords.split(';').map(keyword => GLib.str_tokenize_and_fold(keyword, null)).flat(2);
}
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID, {
// Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: tokenizeKeywords(_('power off;shutdown;reboot;restart;halt;stop')),
keywords: _('power off;shutdown;reboot;restart;halt;stop').split(/[; ]/),
available: false,
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
@@ -101,7 +97,7 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: tokenizeKeywords(_('lock screen')),
keywords: _("lock screen").split(/[; ]/),
available: false,
});
this._actions.set(LOGOUT_ACTION_ID, {
@@ -109,7 +105,7 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: tokenizeKeywords(_('logout;log out;sign off')),
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false,
});
this._actions.set(SUSPEND_ACTION_ID, {
@@ -117,7 +113,7 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: tokenizeKeywords(_('suspend;sleep')),
keywords: _("suspend;sleep").split(/[; ]/),
available: false,
});
this._actions.set(SWITCH_USER_ACTION_ID, {
@@ -125,14 +121,14 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: tokenizeKeywords(_('switch user')),
keywords: _("switch user").split(/[; ]/),
available: false,
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
name: '',
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: tokenizeKeywords(_('lock orientation;unlock orientation;screen;rotation')),
keywords: _("lock orientation;unlock orientation;screen;rotation").split(/[; ]/),
available: false,
});
@@ -281,7 +277,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map(term => GLib.str_tokenize_and_fold(term, null)[0]);
terms = terms.map(term => term.toLowerCase());
let results = [];

View File

@@ -7,8 +7,6 @@ const PermissionStore = imports.misc.permissionStore;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(Geoclue.Simple, 'new', 'new_finish');
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
const WEATHER_BUS_NAME = 'org.gnome.Weather';
@@ -81,7 +79,16 @@ var WeatherClient = class {
this._weatherApp = null;
this._weatherProxy = null;
this._createWeatherProxy();
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather',
@@ -139,17 +146,9 @@ var WeatherClient = class {
(!this._needsAuth || this._weatherAuthorized);
}
async _createWeatherProxy() {
const nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
_onWeatherProxyReady(o, res) {
try {
this._weatherProxy = await Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null);
this._weatherProxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
@@ -240,23 +239,25 @@ var WeatherClient = class {
}
}
async _startGClueService() {
_startGClueService() {
if (this._gclueStarting)
return;
this._gclueStarting = true;
try {
this._gclueService = await Geoclue.Simple.new(
'org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
return;
}
this._gclueStarted = true;
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
Geoclue.Simple.new('org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null,
(o, res) => {
try {
this._gclueService = Geoclue.Simple.new_finish(res);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
return;
}
this._gclueStarted = true;
this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring();
});
}
_onGClueLocationChanged() {

View File

@@ -10,7 +10,6 @@ const GrabHelper = imports.ui.grabHelper;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const PageIndicators = imports.ui.pageIndicators;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const PopupMenu = imports.ui.popupMenu;
const Search = imports.ui.search;
const SwipeTracker = imports.ui.swipeTracker;
@@ -115,8 +114,7 @@ function _findBestFolderName(apps) {
}, commonCategories);
for (let category of commonCategories) {
const directory = '%s.directory'.format(category);
const translated = Shell.util_get_translated_folder_name(directory);
let translated = Shell.util_get_translated_folder_name(category);
if (translated !== null)
return translated;
}
@@ -163,12 +161,6 @@ var BaseAppView = GObject.registerClass({
this._animateLaterId = 0;
this._viewLoadedHandlerId = 0;
this._viewIsReady = false;
// Filter the apps through the users parental controls.
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', () => {
this._redisplay();
});
}
_childFocused(_actor) {
@@ -342,37 +334,14 @@ var AllView = GObject.registerClass({
use_pagination: true,
});
this._grid._delegate = this;
this._stack = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_actor(this._stack);
let box = new St.BoxLayout({
vertical: true,
y_align: Clutter.ActorAlign.START,
});
box.add_child(this._grid);
this._scrollView = new St.ScrollView({
style_class: 'all-apps',
x_expand: true,
y_expand: true,
reactive: true,
});
this._scrollView.add_actor(box);
this._stack.add_actor(this._scrollView);
this._eventBlocker = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
visible: false,
});
this._stack.add_actor(this._eventBlocker);
this.add_actor(this._scrollView);
this._grid._delegate = this;
this._scrollView.set_policy(St.PolicyType.NEVER,
St.PolicyType.EXTERNAL);
@@ -393,7 +362,24 @@ var AllView = GObject.registerClass({
this._folderIcons = [];
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
let box = new St.BoxLayout({
vertical: true,
y_align: Clutter.ActorAlign.START,
});
this._grid.currentPage = 0;
this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
visible: false,
});
this._stack.add_actor(this._eventBlocker);
box.add_actor(this._stack);
this._scrollView.add_actor(box);
this._scrollView.connect('scroll-event', this._onScroll.bind(this));
@@ -528,7 +514,7 @@ var AllView = GObject.registerClass({
} catch (e) {
return false;
}
return this._parentalControlsManager.shouldShowApp(appInfo);
return appInfo.should_show();
});
let apps = this._appInfoList.map(app => app.get_id());
@@ -638,7 +624,7 @@ var AllView = GObject.registerClass({
this._grid.currentPage = pageNumber;
// Animate the change between pages.
// Tween the change between pages.
this._adjustment.ease(this._grid.getPageY(this._grid.currentPage), {
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
duration: animate ? PAGE_SWITCH_TIME : 0,
@@ -1018,7 +1004,7 @@ class FrequentView extends BaseAppView {
let favoritesWritable = global.settings.is_writable('favorite-apps');
for (let i = 0; i < mostUsed.length; i++) {
if (!this._parentalControlsManager.shouldShowApp(mostUsed[i].get_app_info()))
if (!mostUsed[i].get_app_info().should_show())
continue;
let appIcon = this._items.get(mostUsed[i].get_id());
if (!appIcon) {
@@ -1264,8 +1250,6 @@ var AppSearchProvider = class AppSearchProvider {
this.canLaunchSearch = false;
this._systemActions = new SystemActions.getDefault();
this._parentalControlsManager = ParentalControlsManager.getDefault();
}
getResultMetas(apps, callback) {
@@ -1300,27 +1284,14 @@ var AppSearchProvider = class AppSearchProvider {
}
getInitialResultSet(terms, callback, _cancellable) {
// Defer until the parental controls manager is initialised, so the
// results can be filtered correctly.
if (!this._parentalControlsManager.initialized) {
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
if (this._parentalControlsManager.initialized) {
this._parentalControlsManager.disconnect(initializedId);
this.getInitialResultSet(terms, callback, _cancellable);
}
});
return;
}
let query = terms.join(' ');
let groups = Shell.AppSystem.search(query);
let usage = Shell.AppUsage.get_default();
let results = [];
groups.forEach(group => {
group = group.filter(appID => {
const app = this._appSys.lookup_app(appID);
return app && this._parentalControlsManager.shouldShowApp(app.app_info);
return app && app.app_info.should_show();
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)
@@ -1459,7 +1430,7 @@ class FolderView extends BaseAppView {
if (!app)
return;
if (!this._parentalControlsManager.shouldShowApp(app.get_app_info()))
if (!app.get_app_info().should_show())
return;
if (apps.some(appIcon => appIcon.id == appId))
@@ -2205,7 +2176,7 @@ var AppIcon = GObject.registerClass({
}
vfunc_leave_event(crossingEvent) {
const ret = super.vfunc_leave_event(crossingEvent);
let ret = super.vfunc_leave_event(crossingEvent);
this.fake_release();
this._removeMenuTimeout();
@@ -2213,22 +2184,22 @@ var AppIcon = GObject.registerClass({
}
vfunc_button_press_event(buttonEvent) {
const ret = super.vfunc_button_press_event(buttonEvent);
super.vfunc_button_press_event(buttonEvent);
if (buttonEvent.button == 1) {
this._setPopupTimeout();
} else if (buttonEvent.button == 3) {
this.popupMenu();
return Clutter.EVENT_STOP;
}
return ret;
return Clutter.EVENT_PROPAGATE;
}
vfunc_touch_event(touchEvent) {
const ret = super.vfunc_touch_event(touchEvent);
super.vfunc_touch_event(touchEvent);
if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return ret;
return Clutter.EVENT_PROPAGATE;
}
vfunc_clicked(button) {
@@ -2580,18 +2551,19 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
this._appendSeparator();
let item = this._appendMenuItem(_("Show Details"));
item.connect('activate', async () => {
item.connect('activate', () => {
let id = this._source.app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
new GLib.Variant.new(
'(sava{sv})', ['details', [args], null]),
null, 0, -1, null);
Main.overview.hide();
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
Main.overview.hide();
});
});
}
}

View File

@@ -2,7 +2,6 @@
/* exported getAppFavorites */
const Shell = imports.gi.Shell;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -65,13 +64,6 @@ const RENAMED_DESKTOP_IDS = {
class AppFavorites {
constructor() {
// Filter the apps through the users parental controls.
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', () => {
this.reload();
this.emit('changed');
});
this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {};
global.settings.connect('changed::%s'.format(this.FAVORITE_APPS_KEY), this._onFavsChanged.bind(this));
@@ -103,7 +95,7 @@ class AppFavorites {
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let apps = ids.map(id => appSys.lookup_app(id))
.filter(app => app !== null && this._parentalControlsManager.shouldShowApp(app.app_info));
.filter(app => app != null);
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
@@ -142,9 +134,6 @@ class AppFavorites {
if (!app)
return false;
if (!this._parentalControlsManager.shouldShowApp(app.app_info))
return false;
let ids = this._getIds();
if (pos == -1)
ids.push(appId);

View File

@@ -199,52 +199,46 @@ class DBusEventSource extends EventSourceBase {
this._initialized = false;
this._dbusProxy = new CalendarServer();
this._initProxy();
}
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
let loaded = false;
async _initProxy() {
let loaded = false;
try {
await this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null);
loaded = true;
} catch (e) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
//
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
log('Error loading calendars: %s'.format(e.message));
return;
try {
this._dbusProxy.init_finish(result);
loaded = true;
} catch (e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
//
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
log('Error loading calendars: %s'.format(e.message));
return;
}
}
}
this._dbusProxy.connectSignal('EventsAddedOrUpdated',
this._onEventsAddedOrUpdated.bind(this));
this._dbusProxy.connectSignal('EventsRemoved',
this._onEventsRemoved.bind(this));
this._dbusProxy.connectSignal('ClientDisappeared',
this._onClientDisappeared.bind(this));
this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
});
this._dbusProxy.connect('g-properties-changed', () => {
this.notify('has-calendars');
});
this._initialized = loaded;
if (loaded) {
this.notify('has-calendars');
this._onNameAppeared();
else
this._onNameVanished();
}
});
this._dbusProxy.connect('g-properties-changed', () => {
this.notify('has-calendars');
});
this._initialized = loaded;
if (loaded) {
this.notify('has-calendars');
this._onNameAppeared();
}
}
destroy() {
@@ -263,7 +257,7 @@ class DBusEventSource extends EventSourceBase {
}
_resetCache() {
this._events = new Map();
this._events = [];
this._lastRequestBegin = null;
this._lastRequestEnd = null;
}
@@ -279,47 +273,28 @@ class DBusEventSource extends EventSourceBase {
this.emit('changed');
}
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
const [appointments = []] = argArray;
let changed = false;
_onChanged() {
this._loadEvents(false);
}
_onEventsReceived(results, _error) {
let newEvents = [];
let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) {
const [id, summary, allDay, startTime, endTime] = appointments[n];
const date = new Date(startTime * 1000);
const end = new Date(endTime * 1000);
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
this._events.set(event.id, event);
changed = true;
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
if (changed)
this.emit('changed');
}
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
const [ids = []] = argArray;
let changed = false;
for (const id of ids)
changed |= this._events.delete(id);
if (changed)
this.emit('changed');
}
_onClientDisappeared(dbusProxy, nameOwner, argArray) {
let [sourceUid = ''] = argArray;
sourceUid += '\n';
let changed = false;
for (const id of this._events.keys()) {
if (id.startsWith(sourceUid))
changed |= this._events.delete(id);
}
if (changed)
this.emit('changed');
this._events = newEvents;
this._isLoading = false;
this.emit('changed');
}
_loadEvents(forceReload) {
@@ -328,38 +303,33 @@ class DBusEventSource extends EventSourceBase {
return;
if (this._curRequestBegin && this._curRequestEnd) {
if (forceReload) {
this._events.clear();
this.emit('changed');
}
this._dbusProxy.SetTimeRangeRemote(
this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Gio.DBusCallFlags.NONE);
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE);
}
}
requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
this._isLoading = true;
this._lastRequestBegin = begin;
this._lastRequestEnd = end;
this._curRequestBegin = begin;
this._curRequestEnd = end;
this._loadEvents(true);
}
}
*_getFilteredEvents(begin, end) {
for (const event of this._events.values()) {
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
yield event;
this._loadEvents(false);
}
}
getEvents(begin, end) {
let result = [...this._getFilteredEvents(begin, end)];
let result = [];
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
result.push(event);
}
result.sort((event1, event2) => {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
@@ -373,8 +343,12 @@ class DBusEventSource extends EventSourceBase {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
const { done } = this._getFilteredEvents(dayBegin, dayEnd).next();
return !done;
let events = this.getEvents(dayBegin, dayEnd);
if (events.length == 0)
return false;
return true;
}
});
@@ -726,11 +700,12 @@ var Calendar = GObject.registerClass({
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', '');
super._init('', event.summary);
this._event = event;
this._date = date;
this.update(event);
this.setTitle(this._formatEventTime());
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
@@ -742,13 +717,6 @@ class EventMessage extends MessageList.Message {
super.vfunc_style_changed();
}
update(event) {
this._event = event;
this.setTitle(this._formatEventTime());
this.setBody(event.summary);
}
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
@@ -906,7 +874,7 @@ class EventsSection extends MessageList.MessageListSection {
}
_reloadEvents() {
if (this._eventSource.isLoading || this._reloading)
if (this._eventSource.isLoading)
return;
this._reloading = true;
@@ -932,7 +900,6 @@ class EventsSection extends MessageList.MessageListSection {
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
message.update(event);
this.moveMessage(message, i, false);
}
}

View File

@@ -10,7 +10,6 @@ const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype, 'init_async', 'init_finish');
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
@@ -483,37 +482,39 @@ var VPNRequestHandler = class {
}
}
async _readStdoutOldStyle() {
const [line, len_] =
await this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null);
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
if (line === null) {
// end of file
this._stdout.close(null);
return;
}
if (line == null) {
// end of file
this._stdout.close(null);
return;
}
this._vpnChildProcessLineOldStyle(line);
this._vpnChildProcessLineOldStyle(line);
// try to read more!
this._readStdoutOldStyle();
// try to read more!
this._readStdoutOldStyle();
});
}
async _readStdoutNewStyle() {
const cnt =
await this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null);
_readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let cnt = this._dataStdout.fill_finish(result);
if (cnt === 0) {
// end of file
this._showNewStyleDialog();
if (cnt == 0) {
// end of file
this._showNewStyleDialog();
this._stdout.close(null);
return;
}
this._stdout.close(null);
return;
}
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
});
}
_showNewStyleDialog() {
@@ -620,17 +621,15 @@ var NetworkAgent = class {
this._native.connect('cancel-request', this._cancelRequest.bind(this));
this._initialized = false;
this._initNative();
}
async _initNative() {
try {
await this._native.init_async(GLib.PRIORITY_DEFAULT, null);
this._initialized = true;
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
try {
this._native.init_finish(res);
this._initialized = true;
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
});
}
enable() {

View File

@@ -327,16 +327,12 @@ var AuthenticationDialog = GObject.registerClass({
}
let resetDialog = () => {
this._sessionRequestTimeoutId = 0;
if (this.state != ModalDialog.State.OPENED)
return GLib.SOURCE_REMOVE;
return;
this._passwordEntry.hide();
this._cancelButton.grab_key_focus();
this._okButton.reactive = false;
return GLib.SOURCE_REMOVE;
};
if (delay) {

View File

@@ -7,14 +7,6 @@ var Tpl = null;
var Tp = null;
try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
Gio._promisify(Tp.Channel.prototype, 'close_async', 'close_finish');
Gio._promisify(Tp.Channel.prototype,
'send_message_async', 'send_message_finish');
Gio._promisify(Tp.ChannelDispatchOperation.prototype,
'claim_with_async', 'claim_with_finish');
Gio._promisify(Tpl.LogManager.prototype,
'get_filtered_events_async', 'get_filtered_events_finish');
} catch (e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@@ -223,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
// We can only handle text channel, so close any other channel
if (!(channel instanceof Tp.TextChannel)) {
channel.close_async();
channel.close_async(null);
continue;
}
@@ -269,7 +261,7 @@ class TelepathyClient extends Tp.BaseClient {
}
}
async _approveTextChannel(account, conn, channel, dispatchOp, context) {
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle_, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
@@ -278,15 +270,17 @@ class TelepathyClient extends Tp.BaseClient {
return;
}
context.accept();
// Approve private text channels right away as we are going to handle it
try {
await dispatchOp.claim_with_async(this);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: %s'.format(err.toString()));
}
dispatchOp.claim_with_async(this, (o, result) => {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: %s'.format(err.toString()));
}
});
context.accept();
}
_delegatedChannelsCb(_client, _channels) {
@@ -447,14 +441,17 @@ class ChatSource extends MessageTray.Source {
}
}
async _getLogMessages() {
_getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
const [events] = await logManager.get_filtered_events_async(
this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null);
logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, this._displayPendingMessages.bind(this));
}
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
this._ensureNotification();
@@ -512,7 +509,9 @@ class ChatSource extends MessageTray.Source {
this._ackMessages();
// The chat box has been destroyed so it can't
// handle the channel any more.
this._channel.close_async();
this._channel.close_async((channel, result) => {
channel.close_finish(result);
});
} else {
// Don't indicate any unread messages when the notification
// that represents them has been destroyed.
@@ -610,7 +609,9 @@ class ChatSource extends MessageTray.Source {
}
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0);
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
});
}
setChatState(state) {

View File

@@ -281,13 +281,13 @@ class WeatherSection extends St.Button {
this.child = box;
let titleBox = new St.BoxLayout({ style_class: 'weather-header-box' });
this._titleLabel = new St.Label({
titleBox.add_child(new St.Label({
style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_align: Clutter.ActorAlign.END,
});
titleBox.add_child(this._titleLabel);
text: _('Weather'),
}));
box.add_child(titleBox);
this._titleLocation = new St.Label({
@@ -414,8 +414,10 @@ class WeatherSection extends St.Button {
_updateForecasts() {
this._forecastGrid.destroy_all_children();
if (!this._weatherClient.hasLocation)
if (!this._weatherClient.hasLocation) {
this._setStatusLabel(_("Select a location…"));
return;
}
const { info } = this._weatherClient;
this._titleLocation.text = this._findBestLocationName(info.location);
@@ -442,12 +444,6 @@ class WeatherSection extends St.Button {
if (!this.visible)
return;
if (this._weatherClient.hasLocation)
this._titleLabel.text = _('Weather');
else
this._titleLabel.text = _('Select weather location…');
this._forecastGrid.visible = this._weatherClient.hasLocation;
this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts();

View File

@@ -278,7 +278,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
}
async _onPkOfflineProxyCreated(proxy, error) {
_onPkOfflineProxyCreated(proxy, error) {
if (error) {
log(error.message);
return;
@@ -293,12 +293,15 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
// It only makes sense to check for this permission if PackageKit is available.
try {
this._updatesPermission = await Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null,
(source, res) => {
try {
this._updatesPermission = Polkit.Permission.new_finish(res);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
});
}
_onDestroy() {

View File

@@ -10,20 +10,11 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const System = imports.system;
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
Gio._promisify(Gio.DataInputStream.prototype,
'read_line_async', 'read_line_finish');
Gio._promisify(Gio.DBus, 'get', 'get_finish');
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
Gio._promisify(Gio.DBusProxy, 'new', 'new_finish');
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
Gio._promisify(Gio.DBusProxy.prototype,
'call_with_unix_fd_list', 'call_with_unix_fd_list_finish');
Gio._promisify(Polkit.Permission, 'new', 'new_finish');
let _localTimeZone = null;
@@ -245,15 +236,16 @@ function _loggingFunc(...args) {
}
function init() {
// Add some bindings to the global JS namespace
globalThis.global = Shell.Global.get();
// Add some bindings to the global JS namespace; (gjs keeps the web
// browser convention of having that namespace be called 'window'.)
window.global = Shell.Global.get();
globalThis.log = _loggingFunc;
window.log = _loggingFunc;
globalThis._ = Gettext.gettext;
globalThis.C_ = Gettext.pgettext;
globalThis.ngettext = Gettext.ngettext;
globalThis.N_ = s => s;
window._ = Gettext.gettext;
window.C_ = Gettext.pgettext;
window.ngettext = Gettext.ngettext;
window.N_ = s => s;
GObject.gtypeNameBasedOnJSPath = true;
@@ -355,7 +347,9 @@ function init() {
// OK, now things are initialized enough that we can import shell JS
const Format = imports.format;
const Tweener = imports.ui.tweener;
Tweener.init();
String.prototype.format = Format.format;
}

View File

@@ -229,7 +229,8 @@ var ExtensionManager = class {
null,
Gio.DBusCallFlags.NONE,
-1,
null);
null,
(conn, res) => conn.call_finish(res));
return true;
}

View File

@@ -114,11 +114,8 @@ class BaseIcon extends St.Bin {
if (this._setSizeManually) {
size = this.iconSize;
} else {
const { scaleFactor } =
St.ThemeContext.get_for_stage(global.stage);
let [found, len] = node.lookup_length('icon-size', false);
size = found ? len / scaleFactor : ICON_SIZE;
size = found ? len : ICON_SIZE;
}
if (this.iconSize == size && this._iconBin.child)

View File

@@ -1119,7 +1119,7 @@ var KeyboardManager = class KeyBoardManager {
this._seat.connect('notify::touch-mode', this._syncEnabled.bind(this));
this._lastDevice = null;
global.backend.connect('last-device-changed', (backend, device) => {
Meta.get_backend().connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
return;

View File

@@ -37,8 +37,8 @@ const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of globalThis (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(globalThis).filter(
// Don't add the private properties of window (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(window).filter(
a => a.charAt(0) != '_'
);
const headerProperties = JsParse.getDeclaredConstants(commandHeader);

View File

@@ -46,7 +46,6 @@ const XdndHandler = imports.ui.xdndHandler;
const KbdA11yDialog = imports.ui.kbdA11yDialog;
const LocatePointer = imports.ui.locatePointer;
const PointerA11yTimeout = imports.ui.pointerA11yTimeout;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
@@ -97,8 +96,6 @@ let _oskResource = null;
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
let _remoteAccessInhibited = false;
function _sessionUpdated() {
if (sessionMode.isPrimary)
_loadDefaultStylesheet();
@@ -123,23 +120,12 @@ function _sessionUpdated() {
if (lookingGlass)
lookingGlass.close();
}
let remoteAccessController = global.backend.get_remote_access_controller();
if (remoteAccessController) {
if (sessionMode.allowScreencast && _remoteAccessInhibited) {
remoteAccessController.uninhibit_remote_access();
_remoteAccessInhibited = false;
} else if (!sessionMode.allowScreencast && !_remoteAccessInhibited) {
remoteAccessController.inhibit_remote_access();
_remoteAccessInhibited = true;
}
}
}
function start() {
// These are here so we don't break compatibility.
global.logError = globalThis.log;
global.log = globalThis.log;
global.logError = window.log;
global.log = window.log;
// Chain up async errors reported from C
global.connect('notify-error', (global, msg, detail) => {
@@ -154,10 +140,6 @@ function start() {
sessionMode.connect('updated', _sessionUpdated);
St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
// Initialize ParentalControlsManager before the UI
ParentalControlsManager.getDefault();
_initializeUI();
shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
@@ -815,7 +797,7 @@ function showRestartMessage(message) {
var AnimationsSettings = class {
constructor() {
let backend = global.backend;
let backend = Meta.get_backend();
if (!backend.is_rendering_hardware_accelerated()) {
St.Settings.get().inhibit_animations();
return;

View File

@@ -136,22 +136,29 @@ var FocusGrabber = class FocusGrabber {
var NotificationPolicy = GObject.registerClass({
Properties: {
'enable': GObject.ParamSpec.boolean(
'enable', 'enable', 'enable', GObject.ParamFlags.READABLE, true),
'enable', 'enable', 'enable',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'enable-sound': GObject.ParamSpec.boolean(
'enable-sound', 'enable-sound', 'enable-sound',
GObject.ParamFlags.READABLE, true),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'show-banners': GObject.ParamSpec.boolean(
'show-banners', 'show-banners', 'show-banners',
GObject.ParamFlags.READABLE, true),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'force-expanded': GObject.ParamSpec.boolean(
'force-expanded', 'force-expanded', 'force-expanded',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'show-in-lock-screen': GObject.ParamSpec.boolean(
'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'details-in-lock-screen': GObject.ParamSpec.boolean(
'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
},
}, class NotificationPolicy extends GObject.Object {
// Do nothing for the default policy. These methods are only useful for the
@@ -163,23 +170,23 @@ var NotificationPolicy = GObject.registerClass({
}
get enableSound() {
return true;
return this.enable_sound;
}
get showBanners() {
return true;
return this.show_banners;
}
get forceExpanded() {
return false;
return this.force_expanded;
}
get showInLockScreen() {
return false;
return this.show_in_lock_screen;
}
get detailsInLockScreen() {
return false;
return this.details_in_lock_screen;
}
});

View File

@@ -90,16 +90,18 @@ class AppMenu extends PopupMenu.PopupMenu {
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._detailsItem = this.addAction(_('Show Details'), async () => {
this._detailsItem = this.addAction(_("Show Details"), () => {
let id = this._app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
bus.call(
'org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
new GLib.Variant('(sava{sv})', ['details', [args], null]),
null, 0, -1, null);
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
});
});
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@@ -281,7 +283,7 @@ var AppMenuButton = GObject.registerClass({
this.remove_all_transitions();
this.ease({
opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.Animation.EASE_OUT_QUAD,
duration: Overview.ANIMATION_TIME,
onComplete: () => this.hide(),
});

View File

@@ -204,7 +204,7 @@ var RemoteSearchProvider = class {
g_interface_info: proxyInfo,
g_interface_name: proxyInfo.name,
gFlags });
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null);
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
this.appInfo = appInfo;
this.id = appInfo.get_id();

View File

@@ -198,7 +198,7 @@ var ScreenShield = class {
let lockEnabled = this._settings.get_boolean(LOCK_ENABLED_KEY);
let lockLocked = this._lockSettings.get_boolean(DISABLE_LOCK_KEY);
let inhibit = this._loginSession && this._loginSession.Active &&
!this._isActive && lockEnabled && !lockLocked && Main.sessionMode.unlockDialog;
!this._isActive && lockEnabled && !lockLocked;
if (inhibit) {
this._loginManager.inhibit(_("GNOME needs to lock the screen"),
inhibitor => {
@@ -345,7 +345,7 @@ var ScreenShield = class {
this._lockDialogGroup.remove_all_transitions();
if (animate) {
// Animate the lock screen out of screen
// Tween the lock screen out of screen
// if velocity is not specified (i.e. we come here from pressing ESC),
// use the same speed regardless of original position
// if velocity is specified, it's in pixels per milliseconds
@@ -561,8 +561,7 @@ var ScreenShield = class {
if (this._activationTime == 0)
this._activationTime = GLib.get_monotonic_time();
if (!this._ensureUnlockDialog(true))
return;
this._ensureUnlockDialog(true);
this.actor.show();

View File

@@ -7,13 +7,6 @@ const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
Gio._promisify(Shell.Screenshot.prototype, 'pick_color', 'pick_color_finish');
Gio._promisify(Shell.Screenshot.prototype, 'screenshot', 'screenshot_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_window', 'screenshot_window_finish');
Gio._promisify(Shell.Screenshot.prototype,
'screenshot_area', 'screenshot_area_finish');
const { loadInterfaceXML } = imports.misc.fileUtils;
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
@@ -163,7 +156,7 @@ var ScreenshotService = class {
return [x, y, width, height];
}
async ScreenshotAreaAsync(params, invocation) {
ScreenshotAreaAsync(params, invocation) {
let [x, y, width, height, flash, filename] = params;
[x, y, width, height] = this._scaleArea(x, y, width, height);
if (!this._checkArea(x, y, width, height)) {
@@ -180,17 +173,21 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] =
await screenshot.screenshot_area(x, y, width, height, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot_area(x, y, width, height, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async ScreenshotWindowAsync(params, invocation) {
ScreenshotWindowAsync(params, invocation) {
let [includeFrame, includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@@ -200,17 +197,21 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] =
await screenshot.screenshot_window(includeFrame, includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot_window(includeFrame, includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async ScreenshotAsync(params, invocation) {
ScreenshotAsync(params, invocation) {
let [includeCursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
@@ -220,13 +221,18 @@ var ScreenshotService = class {
if (!stream)
return;
try {
let [area] = await screenshot.screenshot(includeCursor, stream);
this._onScreenshotComplete(area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
screenshot.screenshot(includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
}
});
}
async SelectAreaAsync(params, invocation) {
@@ -267,17 +273,19 @@ var ScreenshotService = class {
if (!screenshot)
return;
const [color] = await screenshot.pick_color(coords.x, coords.y);
const { red, green, blue } = color;
const retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0,
]),
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
screenshot.pick_color(coords.x, coords.y, (_o, res) => {
let [success_, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0,
]),
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
});
} catch (e) {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,

View File

@@ -6,7 +6,6 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const ParentalControlsManager = imports.misc.parentalControlsManager;
const RemoteSearch = imports.ui.remoteSearch;
const Util = imports.misc.util;
@@ -432,9 +431,6 @@ var SearchResultsView = GObject.registerClass({
_init() {
super._init({ name: 'searchResults', vertical: true });
this._parentalControlsManager = ParentalControlsManager.getDefault();
this._parentalControlsManager.connect('app-filter-changed', this._reloadRemoteProviders.bind(this));
this._content = new MaxWidthBox({
name: 'searchResultsContent',
vertical: true,
@@ -509,11 +505,6 @@ var SearchResultsView = GObject.registerClass({
_registerProvider(provider) {
provider.searchInProgress = false;
// Filter out unwanted providers.
if (provider.appInfo && !this._parentalControlsManager.shouldShowApp(provider.appInfo))
return;
this._providers.push(provider);
this._ensureProviderDisplay(provider);
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Gio, GLib, GnomeBluetooth, GObject } = imports.gi;
const { Gio, GnomeBluetooth, GObject } = imports.gi;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@@ -35,7 +35,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._sync();
});
this._proxy.connect('g-properties-changed', this._queueSync.bind(this));
this._proxy.connect('g-properties-changed', this._sync.bind(this));
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
this._item.icon.icon_name = 'bluetooth-active-symbolic';
@@ -49,27 +49,15 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
this.menu.addMenuItem(this._item);
this._syncId = 0;
this._adapter = null;
this._client = new GnomeBluetooth.Client();
this._model = this._client.get_model();
this._model.connect('row-deleted', this._queueSync.bind(this));
this._model.connect('row-changed', this._queueSync.bind(this));
this._model.connect('row-changed', this._sync.bind(this));
this._model.connect('row-deleted', this._sync.bind(this));
this._model.connect('row-inserted', this._sync.bind(this));
Main.sessionMode.connect('updated', this._sync.bind(this));
this._sync();
}
_setHadSetupDevices(value) {
if (this._hadSetupDevices === value)
return;
this._hadSetupDevices = value;
global.settings.set_boolean(
HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
}
_getDefaultAdapter() {
let [ret, iter] = this._model.get_iter_first();
while (ret) {
@@ -84,53 +72,46 @@ class Indicator extends PanelMenu.SystemIndicator {
return null;
}
_getDeviceInfos(adapter) {
// nDevices is the number of devices setup for the current default
// adapter if one exists and is powered. If unpowered or unavailable,
// nDevice is "1" if it had setup devices associated to it the last
// time it was seen, and "-1" if not.
//
// nConnectedDevices is the number of devices connected to the default
// adapter if one exists and is powered, or -1 if it's not available.
_getNDevices() {
let adapter = this._getDefaultAdapter();
if (!adapter)
return [];
return [this._hadSetupDevices ? 1 : -1, -1];
let deviceInfos = [];
let nConnectedDevices = 0;
let nDevices = 0;
let [ret, iter] = this._model.iter_children(adapter);
while (ret) {
const isPaired = this._model.get_value(iter,
GnomeBluetooth.Column.PAIRED);
const isTrusted = this._model.get_value(iter,
GnomeBluetooth.Column.TRUSTED);
if (isPaired || isTrusted) {
deviceInfos.push({
connected: this._model.get_value(iter,
GnomeBluetooth.Column.CONNECTED),
name: this._model.get_value(iter,
GnomeBluetooth.Column.ALIAS),
});
}
let isConnected = this._model.get_value(iter,
GnomeBluetooth.Column.CONNECTED);
if (isConnected)
nConnectedDevices++;
let isPaired = this._model.get_value(iter,
GnomeBluetooth.Column.PAIRED);
let isTrusted = this._model.get_value(iter,
GnomeBluetooth.Column.TRUSTED);
if (isPaired || isTrusted)
nDevices++;
ret = this._model.iter_next(iter);
}
return deviceInfos;
}
if (this._hadSetupDevices != (nDevices > 0)) {
this._hadSetupDevices = !this._hadSetupDevices;
global.settings.set_boolean(HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
}
_queueSync() {
if (this._syncId)
return;
this._syncId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._syncId = 0;
this._sync();
return GLib.SOURCE_REMOVE;
});
return [nDevices, nConnectedDevices];
}
_sync() {
let adapter = this._getDefaultAdapter();
let devices = this._getDeviceInfos(adapter);
const connectedDevices = devices.filter(dev => dev.connected);
const nConnectedDevices = connectedDevices.length;
if (adapter && this._adapter)
this._setHadSetupDevices(devices.length > 0);
this._adapter = adapter;
let [nDevices, nConnectedDevices] = this._getNDevices();
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
this.menu.setSensitive(sensitive);
@@ -138,21 +119,19 @@ class Indicator extends PanelMenu.SystemIndicator {
// Remember if there were setup devices and show the menu
// if we've seen setup devices and we're not hard blocked
if (this._hadSetupDevices)
if (nDevices > 0)
this._item.visible = !this._proxy.BluetoothHardwareAirplaneMode;
else
this._item.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode;
if (nConnectedDevices > 1)
if (nConnectedDevices > 0)
/* Translators: this is the number of connected bluetooth devices */
this._item.label.text = ngettext('%d Connected", "%d Connected', nConnectedDevices).format(nConnectedDevices);
else if (nConnectedDevices === 1)
this._item.label.text = connectedDevices[0].name;
else if (adapter === null)
this._item.label.text = _('Bluetooth Off');
this._item.label.text = ngettext("%d Connected", "%d Connected", nConnectedDevices).format(nConnectedDevices);
else if (nConnectedDevices == -1)
this._item.label.text = _("Off");
else
this._item.label.text = _('Bluetooth On');
this._item.label.text = _("On");
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _('Turn On') : _('Turn Off');
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off");
}
});

View File

@@ -199,36 +199,36 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
this._reload.bind(this));
}
async _reload() {
let props;
try {
const result = await Gio.DBus.system.call(
this._BUS_NAME,
this._BUS_PATH,
this._BUS_PROPS_IFACE,
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null);
[props] = result.deep_unpack();
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
_reload() {
Gio.DBus.system.call(this._BUS_NAME,
this._BUS_PATH,
this._BUS_PROPS_IFACE,
'GetAll',
new GLib.Variant('(s)', [this._BUS_IFACE]),
null, Gio.DBusCallFlags.NONE, -1, null,
(conn, result) => {
let props;
try {
props = conn.call_finish(result).deep_unpack()[0];
} catch (e) {
log('Could not get properties from %s'.format(this._BUS_NAME));
return;
}
let layouts = props['X11Layout'].unpack();
let variants = props['X11Variant'].unpack();
let options = props['X11Options'].unpack();
const layouts = props['X11Layout'].unpack();
const variants = props['X11Variant'].unpack();
const options = props['X11Options'].unpack();
if (layouts !== this._layouts ||
variants !== this._variants) {
this._layouts = layouts;
this._variants = variants;
this._emitInputSourcesChanged();
}
if (options !== this._options) {
this._options = options;
this._emitKeyboardOptionsChanged();
}
if (layouts != this._layouts ||
variants != this._variants) {
this._layouts = layouts;
this._variants = variants;
this._emitInputSourcesChanged();
}
if (options != this._options) {
this._options = options;
this._emitKeyboardOptionsChanged();
}
});
}
get inputSources() {

View File

@@ -15,10 +15,6 @@ const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
Gio._promisify(NM.Client, 'new_async', 'new_finish');
Gio._promisify(NM.Client.prototype,
'check_connectivity_async', 'check_connectivity_finish');
const NMConnectionCategory = {
INVALID: 'invalid',
WIRED: 'wired',
@@ -1631,11 +1627,11 @@ class Indicator extends PanelMenu.SystemIndicator {
this._ctypes[NM.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._getClient();
NM.Client.new_async(null, this._clientGot.bind(this));
}
async _getClient() {
this._client = await NM.Client.new_async(null);
_clientGot(obj, result) {
this._client = NM.Client.new_finish(result);
this._activeConnections = [];
this._connections = [];
@@ -1986,7 +1982,7 @@ class Indicator extends PanelMenu.SystemIndicator {
}
}
async _portalHelperDone(proxy, emitter, parameters) {
_portalHelperDone(proxy, emitter, parameters) {
let [path, result] = parameters;
if (result == PortalHelperResult.CANCELLED) {
@@ -1997,11 +1993,13 @@ class Indicator extends PanelMenu.SystemIndicator {
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
} else if (result == PortalHelperResult.RECHECK) {
try {
const state = await this._client.check_connectivity_async(null);
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch (e) { }
this._client.check_connectivity_async(null, (client, res) => {
try {
let state = client.check_connectivity_finish(res);
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch (e) { }
});
} else {
log('Invalid result from portal helper: %s'.format(result));
}

View File

@@ -11,7 +11,8 @@ class RemoteAccessApplet extends PanelMenu.SystemIndicator {
_init() {
super._init();
let controller = global.backend.get_remote_access_controller();
let backend = Meta.get_backend();
let controller = backend.get_remote_access_controller();
if (!controller)
return;

View File

@@ -52,21 +52,22 @@ const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
var Client = class {
constructor() {
this._proxy = null;
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
Gio.DBusProxy.new(Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null,
this._onProxyReady.bind(this));
this.probing = false;
this._getProxy();
}
async _getProxy() {
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
_onProxyReady(o, res) {
try {
this._proxy = await Gio.DBusProxy.new(
Gio.DBus.system,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
BOLT_DBUS_CLIENT_IFACE,
null);
this._proxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log('error creating bolt proxy: %s'.format(e.message));
return;
@@ -242,15 +243,14 @@ class Indicator extends PanelMenu.SystemIndicator {
this._source = null;
this._perm = null;
this._createPermission();
}
async _createPermission() {
try {
this._perm = await Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null);
} catch (e) {
log('Failed to get PolKit permission: %s'.format(e.toString()));
}
Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null, (source, res) => {
try {
this._perm = Polkit.Permission.new_finish(res);
} catch (e) {
log('Failed to get PolKit permission: %s'.format(e.toString()));
}
});
}
_onDestroy() {

View File

@@ -317,7 +317,7 @@ var SwitcherPopup = GObject.registerClass({
this.ease({
opacity: 0,
duration: POPUP_FADE_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.Animation.EASE_OUT_QUAD,
onComplete: () => this.destroy(),
});
} else {

228
js/ui/tweener.js Normal file
View File

@@ -0,0 +1,228 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, addCaller, addTween, getTweenCount, removeTweens,
pauseTweens, resumeTweens, registerSpecialProperty,
registerSpecialPropertyModifier, registerSpecialPropertySplitter */
const { Clutter, GLib, Shell } = imports.gi;
const Signals = imports.signals;
const Tweener = imports.tweener.tweener;
const { adjustAnimationTime } = imports.ui.environment;
// This is a wrapper around imports.tweener.tweener that adds a bit of
// Clutter integration. If the tweening target is a Clutter.Actor, then
// the tweenings will automatically be removed if the actor is destroyed.
// ActionScript Tweener methods that imports.tweener.tweener doesn't
// currently implement: getTweens, getVersion, registerTransition,
// setTimeScale, updateTime.
// imports.tweener.tweener methods that we don't re-export:
// pauseAllTweens, removeAllTweens, resumeAllTweens. (It would be hard
// to clean up properly after removeAllTweens, and also, any code that
// calls any of these is almost certainly wrong anyway, because they
// affect the entire application.)
// Called from Main.start
function init() {
Tweener.setFrameTicker(new ClutterFrameTicker());
}
function addCaller(target, tweeningParameters) {
_wrapTweening(target, tweeningParameters);
Tweener.addCaller(target, tweeningParameters);
}
function addTween(target, tweeningParameters) {
_wrapTweening(target, tweeningParameters);
Tweener.addTween(target, tweeningParameters);
}
function _wrapTweening(target, tweeningParameters) {
let state = _getTweenState(target);
if (!state.destroyedId) {
if (target instanceof Clutter.Actor) {
state.actor = target;
state.destroyedId = target.connect('destroy', _actorDestroyed);
} else if (target.actor && target.actor instanceof Clutter.Actor) {
state.actor = target.actor;
state.destroyedId = target.actor.connect('destroy', () => _actorDestroyed(target));
}
}
let { time, delay } = tweeningParameters;
if (!isNaN(time))
tweeningParameters['time'] = adjustAnimationTime(1000 * time) / 1000;
if (!isNaN(delay))
tweeningParameters['delay'] = adjustAnimationTime(1000 * delay) / 1000;
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
}
function _getTweenState(target) {
// If we were paranoid, we could keep a plist mapping targets to
// states... but we're not that paranoid.
if (!target.__ShellTweenerState)
target.__ShellTweenerState = {};
return target.__ShellTweenerState;
}
function _resetTweenState(target) {
let state = target.__ShellTweenerState;
if (state) {
if (state.destroyedId)
state.actor.disconnect(state.destroyedId);
}
target.__ShellTweenerState = {};
}
function _addHandler(target, params, name, handler) {
if (params[name]) {
let oldHandler = params[name];
let oldScope = params[`${name}Scope`];
let oldParams = params[`${name}Params`];
let eventScope = oldScope ? oldScope : target;
params[name] = () => {
oldHandler.apply(eventScope, oldParams);
handler(target);
};
} else {
params[name] = () => handler(target);
}
}
function _actorDestroyed(target) {
_resetTweenState(target);
Tweener.removeTweens(target);
}
function _tweenCompleted(target) {
if (!isTweening(target))
_resetTweenState(target);
}
function getTweenCount(scope) {
return Tweener.getTweenCount(scope);
}
// imports.tweener.tweener doesn't provide this method (which exists
// in the ActionScript version) but it's easy to implement.
function isTweening(scope) {
return Tweener.getTweenCount(scope) != 0;
}
function removeTweens(...args) {
if (Tweener.removeTweens(args)) {
let [scope] = args;
// If we just removed the last active tween, clean up
if (Tweener.getTweenCount(scope) == 0)
_tweenCompleted(scope);
return true;
} else {
return false;
}
}
function pauseTweens(...args) {
return Tweener.pauseTweens(...args);
}
function resumeTweens(...args) {
return Tweener.resumeTweens(...args);
}
function registerSpecialProperty(...args) {
Tweener.registerSpecialProperty(...args);
}
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
Tweener.registerSpecialPropertyModifier(name, modifyFunction, getFunction);
}
function registerSpecialPropertySplitter(name, splitFunction, parameters) {
Tweener.registerSpecialPropertySplitter(name, splitFunction, parameters);
}
// The 'FrameTicker' object is an object used to feed new frames to
// Tweener so it can update values and redraw. The default frame
// ticker for Tweener just uses a simple timeout at a fixed frame rate
// and has no idea of "catching up" by dropping frames.
//
// We substitute it with custom frame ticker here that connects
// Tweener to a Clutter.TimeLine. Now, Clutter.Timeline itself isn't a
// whole lot more sophisticated than a simple timeout at a fixed frame
// rate, but at least it knows how to drop frames. (See
// HippoAnimationManager for a more sophisticated view of continuous
// time updates; even better is to pay attention to the vertical
// vblank and sync to that when possible.)
//
var ClutterFrameTicker = class {
constructor() {
// We don't have a finite duration; tweener will tell us to stop
// when we need to stop, so use 1000 seconds as "infinity", and
// set the timeline to loop. Doing this means we have to track
// time ourselves, since clutter timeline's time will cycle
// instead of strictly increase.
this._timeline = new Clutter.Timeline({ duration: 1000 * 1000 });
this._timeline.set_loop(true);
this._startTime = -1;
this._currentTime = -1;
this._timeline.connect('new-frame', () => {
this._onNewFrame();
});
let perfLog = Shell.PerfLog.get_default();
perfLog.define_event("tweener.framePrepareStart",
"Start of a new animation frame",
"");
perfLog.define_event("tweener.framePrepareDone",
"Finished preparing frame",
"");
}
get FRAME_RATE() {
return 60;
}
_onNewFrame() {
// If there is a lot of setup to start the animation, then
// first frame number we get from clutter might be a long ways
// into the animation (or the animation might even be done).
// That looks bad, so we always start at the first frame of the
// animation then only do frame dropping from there.
if (this._startTime < 0)
this._startTime = GLib.get_monotonic_time() / 1000.0;
// currentTime is in milliseconds
let perfLog = Shell.PerfLog.get_default();
this._currentTime = GLib.get_monotonic_time() / 1000.0 - this._startTime;
perfLog.event("tweener.framePrepareStart");
this.emit('prepare-frame');
perfLog.event("tweener.framePrepareDone");
}
getTime() {
return this._currentTime;
}
start() {
this._timeline.start();
global.begin_work();
}
stop() {
this._timeline.stop();
this._startTime = -1;
this._currentTime = -1;
global.end_work();
}
};
Signals.addSignalMethods(ClutterFrameTicker.prototype);

View File

@@ -605,7 +605,7 @@ var UnlockDialog = GObject.registerClass({
this._showPrompt();
if (GLib.unichar_isgraph(unichar))
this._authPrompt.addCharacter(unichar);
this.addCharacter(unichar);
return Clutter.EVENT_PROPAGATE;
}
@@ -835,6 +835,11 @@ var UnlockDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(unichar) {
this._showPrompt();
this._authPrompt.addCharacter(unichar);
}
finish(onComplete) {
this._ensureAuthPrompt();
this._authPrompt.finish(onComplete);

View File

@@ -82,10 +82,8 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
_formatCountDown() {
const fmt = ngettext(
'Settings changes will revert in %d second',
'Settings changes will revert in %d seconds',
this._countDown);
let fmt = ngettext("Settings changes will revert in %d second",
"Settings changes will revert in %d seconds");
return fmt.format(this._countDown);
}

View File

@@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter } = imports.gi;
const { Clutter, Meta } = imports.gi;
const Signals = imports.signals;
const DND = imports.ui.dnd;
@@ -17,7 +17,7 @@ var XdndHandler = class {
Main.uiGroup.add_actor(this._dummy);
this._dummy.hide();
var dnd = global.backend.get_dnd();
var dnd = Meta.get_backend().get_dnd();
dnd.connect('dnd-enter', this._onEnter.bind(this));
dnd.connect('dnd-position-change', this._onPositionChanged.bind(this));
dnd.connect('dnd-leave', this._onLeave.bind(this));

View File

@@ -218,12 +218,12 @@ globals:
ARGV: readonly
Debugger: readonly
GIRepositoryGType: readonly
globalThis: readonly
imports: readonly
Intl: readonly
log: readonly
logError: readonly
print: readonly
printerr: readonly
window: readonly
parserOptions:
ecmaVersion: 2019

View File

@@ -1,6 +1,6 @@
project('gnome-shell', 'c',
version: '3.37.0',
meson_version: '>= 0.53.0',
version: '3.36.1',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@@ -19,11 +19,11 @@ cogl_pango_pc = 'mutter-cogl-pango-' + mutter_api_version
libmutter_pc = 'libmutter-' + mutter_api_version
ecal_req = '>= 3.33.1'
eds_req = '>= 3.33.1'
eds_req = '>= 3.17.2'
gcr_req = '>= 3.7.5'
gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.65.1'
gjs_req = '>= 1.63.2'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.36.0'
polkit_req = '>= 0.100'
@@ -63,9 +63,16 @@ portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
servicedir = join_paths(datadir, 'dbus-1', 'services')
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
# depend on this version, replace with something like:
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
# define_variable: ['prefix', prefix])
# and uncomment systemd_dep below
systemduserunitdir = join_paths(prefix, 'lib', 'systemd', 'user')
keybindings_dep = dependency('gnome-keybindings', required: false)
if keybindings_dep.found()
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir', define_variable: ['datadir', datadir])
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir')
else
keysdir = join_paths(datadir, 'gnome-control-center', 'keybindings')
endif
@@ -115,9 +122,8 @@ endif
if get_option('systemd')
libsystemd_dep = dependency('libsystemd')
systemd_dep = dependency('systemd')
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
define_variable: ['prefix', prefix])
# XXX: see systemduserunitdir
# systemd_dep = dependency('systemd')
have_systemd = true
else
libsystemd_dep = []
@@ -315,6 +321,8 @@ if get_option('man')
summary_dirs += { 'mandir': get_option('mandir') }
endif
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
if meson.version().version_compare('>= 0.53.0')
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
endif

View File

@@ -94,7 +94,5 @@ subprojects/extensions-tool/src/command-prefs.c
subprojects/extensions-tool/src/command-reset.c
subprojects/extensions-tool/src/command-uninstall.c
subprojects/extensions-tool/src/main.c
subprojects/extensions-tool/src/templates/00-plain.desktop.in
subprojects/extensions-tool/src/templates/indicator.desktop.in
# Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it.
subprojects/gvc/gvc-mixer-control.c

View File

@@ -1 +0,0 @@
subprojects/extensions-tool/src/templates/indicator/extension.js

871
po/cs.po

File diff suppressed because it is too large Load Diff

1262
po/eo.po

File diff suppressed because it is too large Load Diff

861
po/es.po

File diff suppressed because it is too large Load Diff

790
po/eu.po

File diff suppressed because it is too large Load Diff

604
po/fa.po

File diff suppressed because it is too large Load Diff

View File

@@ -25,8 +25,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-04-02 09:45+0000\n"
"PO-Revision-Date: 2020-04-13 18:02+0300\n"
"POT-Creation-Date: 2020-03-31 07:15+0000\n"
"PO-Revision-Date: 2020-04-02 12:43+0300\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos+l10n@iki.fi>\n"
"Language-Team: suomi <lokalisointi-lista@googlegroups.com>\n"
"Language: fi\n"
@@ -736,44 +736,44 @@ msgstr "Estä pääsy"
msgid "Grant Access"
msgstr "Salli pääsy"
#: js/ui/appDisplay.js:937
#: js/ui/appDisplay.js:932
msgid "Unnamed Folder"
msgstr "Nimetön kansio"
#: js/ui/appDisplay.js:960
#: js/ui/appDisplay.js:955
msgid "Frequently used applications will appear here"
msgstr "Usein käytetyt sovellukset ilmestyvät tänne"
#: js/ui/appDisplay.js:1095
#: js/ui/appDisplay.js:1090
msgid "Frequent"
msgstr "Käytetyimmät"
#: js/ui/appDisplay.js:1102
#: js/ui/appDisplay.js:1097
msgid "All"
msgstr "Kaikki"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2478 js/ui/panel.js:75
#: js/ui/appDisplay.js:2473 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Avoimet ikkunat"
#: js/ui/appDisplay.js:2498 js/ui/panel.js:82
#: js/ui/appDisplay.js:2493 js/ui/panel.js:82
msgid "New Window"
msgstr "Uusi ikkuna"
#: js/ui/appDisplay.js:2509
#: js/ui/appDisplay.js:2504
msgid "Launch using Dedicated Graphics Card"
msgstr "Käynnistä erillisnäytönohjainta käyttäen"
#: js/ui/appDisplay.js:2537 js/ui/dash.js:239
#: js/ui/appDisplay.js:2532 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Poista suosikeista"
#: js/ui/appDisplay.js:2543
#: js/ui/appDisplay.js:2538
msgid "Add to Favorites"
msgstr "Lisää suosikkeihin"
#: js/ui/appDisplay.js:2553 js/ui/panel.js:93
#: js/ui/appDisplay.js:2548 js/ui/panel.js:93
msgid "Show Details"
msgstr "Näytä tiedot"
@@ -1472,11 +1472,11 @@ msgstr "Näytä lähde"
msgid "Web Page"
msgstr "Verkkosivusto"
#: js/ui/main.js:279
#: js/ui/main.js:277
msgid "Logged in as a privileged user"
msgstr "Kirjautuneena etuoikeutettuna käyttäjänä"
#: js/ui/main.js:280
#: js/ui/main.js:278
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@@ -1484,11 +1484,11 @@ msgstr ""
"Istunnon suorittamista etuoikeutettuna käyttäjänä tulisi välttää "
"tietoturvasyistä. Jos mahdollista, kirjaudu tavallisena käyttäjänä."
#: js/ui/main.js:319
#: js/ui/main.js:317
msgid "Screen Lock disabled"
msgstr "Näytön lukitus pois käytöstä"
#: js/ui/main.js:320
#: js/ui/main.js:318
msgid "Screen Locking requires the GNOME display manager."
msgstr "Näytön lukitus vaatii Gnomen kirjautumishallinnan."
@@ -2407,9 +2407,6 @@ msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"Gnomen laajennussovellus Laajennukset käsittelee laajennusten päivitykset, "
"niiden asetukset ja sen avulla voi poistaa laajennuksia käytöstä tai "
"kokonaan järjestelmästä."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"

View File

@@ -24,8 +24,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-31 07:15+0000\n"
"PO-Revision-Date: 2020-04-22 09:30-0300\n"
"POT-Creation-Date: 2020-03-19 14:34+0000\n"
"PO-Revision-Date: 2020-03-19 11:36-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
@@ -413,12 +413,66 @@ msgstr "Atrasar foco altera o modo do mouse até o ponteiro parar de mover"
msgid "Network Login"
msgstr "Sessão de Rede"
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
#: subprojects/extensions-app/data/ui/extensions-window.ui:223
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:4
#: js/extensionPrefs/js/main.js:242
#: js/extensionPrefs/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensões"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: js/extensionPrefs/js/main.js:243
msgid "Manage your GNOME Extensions"
msgstr "Gerenciar suas extensões do GNOME"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME Extensões lida com a atualização da extensões, configuração das "
"preferências de extensões e remoção ou desabilitação de extensões "
"indesejadas."
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configurar extensões do Shell do GNOME"
#: js/extensionPrefs/js/main.js:164
#, javascript-format
msgid "Remove “%s”?"
msgstr "Remover “%s”?"
#: js/extensionPrefs/js/main.js:165
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Se você remover a extensão, você precisa voltar a baixá-la se você quiser "
"habilitá-la novamente"
#: js/extensionPrefs/js/main.js:168 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
msgid "Cancel"
msgstr "Cancelar"
#: js/extensionPrefs/js/main.js:169
msgid "Remove"
msgstr "Remover"
#: js/extensionPrefs/js/main.js:241
msgid "translator-credits"
msgstr "Rafael Fontenelle <rafaelff@gnome.org>"
#: js/extensionPrefs/js/main.js:285
#: js/extensionPrefs/data/ui/extensions-window.ui:223
msgid "Somethings gone wrong"
msgstr "Algo deu errado"
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
#: js/extensionPrefs/js/main.js:292
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@@ -428,25 +482,105 @@ msgstr ""
"ser exibidas. Recomendamos que você relate o problema aos autores da "
"extensão."
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
#: js/extensionPrefs/js/main.js:299
msgid "Technical Details"
msgstr "Detalhes técnicos"
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
#: js/extensionPrefs/js/main.js:334
msgid "Copy Error"
msgstr "Copiar erro"
#: js/extensionPrefs/js/main.js:361
msgid "Homepage"
msgstr "Site"
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
#: js/extensionPrefs/js/main.js:362
msgid "Visit extension homepage"
msgstr "Visita a página web da extensão"
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:181
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
msgid "Cancel"
msgstr "Cancelar"
#: js/extensionPrefs/js/main.js:479
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extensão será atualizada na próxima sessão."
msgstr[1] "%d extensões serão atualizadas na próxima sessão."
#: js/extensionPrefs/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Descrição"
#: js/extensionPrefs/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Versão"
#: js/extensionPrefs/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Autor"
#: js/extensionPrefs/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Site"
#: js/extensionPrefs/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Remover…"
#: js/extensionPrefs/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Ajuda"
#: js/extensionPrefs/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Sobre as Extensões"
#: js/extensionPrefs/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Para encontrar e adicionar extensões, visite <a href=\"https://extensions."
"gnome.org\">extensions.gnome.org</a>."
#: js/extensionPrefs/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Aviso"
#: js/extensionPrefs/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Extensões podem causar problemas no sistema, incluindo problemas de "
"desempenho. Se você encontrar problemas com o seu sistema, é recomendável "
"desativar todas as extensões."
#: js/extensionPrefs/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Instalada manualmente"
#: js/extensionPrefs/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Interna"
#: js/extensionPrefs/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "Nenhuma extensão instalada"
#: js/extensionPrefs/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Sentimos muito, mas não foi possível obter a lista de extensões instaladas. "
"Certifique-se de estar em uma sessão do GNOME e tente novamente."
#: js/extensionPrefs/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Encerrar sessão…"
#. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
@@ -728,44 +862,44 @@ msgstr "Negar acesso"
msgid "Grant Access"
msgstr "Conceder acesso"
#: js/ui/appDisplay.js:932
#: js/ui/appDisplay.js:898
msgid "Unnamed Folder"
msgstr "Pasta sem nome"
#: js/ui/appDisplay.js:955
#: js/ui/appDisplay.js:921
msgid "Frequently used applications will appear here"
msgstr "Aplicativos usados frequentemente vão aparecer aqui"
#: js/ui/appDisplay.js:1090
#: js/ui/appDisplay.js:1056
msgid "Frequent"
msgstr "Frequente"
#: js/ui/appDisplay.js:1097
#: js/ui/appDisplay.js:1063
msgid "All"
msgstr "Todos"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2473 js/ui/panel.js:75
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Janelas abertas"
#: js/ui/appDisplay.js:2493 js/ui/panel.js:82
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
msgid "New Window"
msgstr "Nova janela"
#: js/ui/appDisplay.js:2504
#: js/ui/appDisplay.js:2477
msgid "Launch using Dedicated Graphics Card"
msgstr "Inicia usando placa de vídeo dedicada"
#: js/ui/appDisplay.js:2532 js/ui/dash.js:239
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Remover dos favoritos"
#: js/ui/appDisplay.js:2538
#: js/ui/appDisplay.js:2511
msgid "Add to Favorites"
msgstr "Adicionar aos favoritos"
#: js/ui/appDisplay.js:2548 js/ui/panel.js:93
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
msgid "Show Details"
msgstr "Mostrar detalhes"
@@ -795,7 +929,7 @@ msgstr "Fones de ouvido"
msgid "Headset"
msgstr "Fone de ouvido com microfone"
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
msgid "Microphone"
msgstr "Microfone"
@@ -936,7 +1070,7 @@ msgstr "Nenhum evento"
msgid "Do Not Disturb"
msgstr "Não perturbe"
#: js/ui/calendar.js:1176
#: js/ui/calendar.js:1171
msgid "Clear"
msgstr "Limpar"
@@ -1086,7 +1220,7 @@ msgstr "Desculpe, isto não funcionou. Por favor, tente novamente."
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: js/ui/components/telepathyClient.js:823
#: js/ui/components/telepathyClient.js:787
#, javascript-format
msgid "%s is now known as %s"
msgstr "%s agora é conhecido como %s"
@@ -1130,106 +1264,106 @@ msgstr "Adicionar relógios mundiais…"
msgid "World Clocks"
msgstr "Relógios mundiais"
#: js/ui/dateMenu.js:289
#: js/ui/dateMenu.js:279
msgid "Weather"
msgstr "Meteorologia"
#: js/ui/dateMenu.js:418
#: js/ui/dateMenu.js:394
msgid "Select a location…"
msgstr "Selecione uma localização…"
#: js/ui/dateMenu.js:426
#: js/ui/dateMenu.js:407
msgid "Loading…"
msgstr "Carregando…"
#: js/ui/dateMenu.js:436
#: js/ui/dateMenu.js:417
msgid "Go online for weather information"
msgstr "Conecte-se à internet para obter as informações meteorológicas"
#: js/ui/dateMenu.js:438
#: js/ui/dateMenu.js:419
msgid "Weather information is currently unavailable"
msgstr "No momento as informações meteorológicas não estão disponíveis"
#: js/ui/endSessionDialog.js:39
#: js/ui/endSessionDialog.js:37
#, javascript-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Encerrar sessão de %s"
#: js/ui/endSessionDialog.js:40
#: js/ui/endSessionDialog.js:38
msgctxt "title"
msgid "Log Out"
msgstr "Encerrar sessão"
#: js/ui/endSessionDialog.js:42
#: js/ui/endSessionDialog.js:40
#, javascript-format
msgid "%s will be logged out automatically in %d second."
msgid_plural "%s will be logged out automatically in %d seconds."
msgstr[0] "%s encerrará a sessão automaticamente em %d segundo."
msgstr[1] "%s encerrará a sessão automaticamente em %d segundos."
#: js/ui/endSessionDialog.js:47
#: js/ui/endSessionDialog.js:45
#, javascript-format
msgid "You will be logged out automatically in %d second."
msgid_plural "You will be logged out automatically in %d seconds."
msgstr[0] "Sua sessão será encerrada automaticamente em %d segundo."
msgstr[1] "Sua sessão será encerrada automaticamente em %d segundos."
#: js/ui/endSessionDialog.js:53
#: js/ui/endSessionDialog.js:51
msgctxt "button"
msgid "Log Out"
msgstr "Encerrar sessão"
#: js/ui/endSessionDialog.js:58
#: js/ui/endSessionDialog.js:56
msgctxt "title"
msgid "Power Off"
msgstr "Desligar"
#: js/ui/endSessionDialog.js:59
#: js/ui/endSessionDialog.js:57
msgctxt "title"
msgid "Install Updates & Power Off"
msgstr "Instalar atualizações & desligar"
#: js/ui/endSessionDialog.js:61
#: js/ui/endSessionDialog.js:59
#, javascript-format
msgid "The system will power off automatically in %d second."
msgid_plural "The system will power off automatically in %d seconds."
msgstr[0] "O sistema será desligado automaticamente em %d segundo."
msgstr[1] "O sistema será desligado automaticamente em %d segundos."
#: js/ui/endSessionDialog.js:65
#: js/ui/endSessionDialog.js:63
msgctxt "checkbox"
msgid "Install pending software updates"
msgstr "Instalar atualizações de software pendentes"
#: js/ui/endSessionDialog.js:68 js/ui/endSessionDialog.js:84
#: js/ui/endSessionDialog.js:66 js/ui/endSessionDialog.js:82
msgctxt "button"
msgid "Restart"
msgstr "Reiniciar"
#: js/ui/endSessionDialog.js:70
#: js/ui/endSessionDialog.js:68
msgctxt "button"
msgid "Power Off"
msgstr "Desligar"
#: js/ui/endSessionDialog.js:76
#: js/ui/endSessionDialog.js:74
msgctxt "title"
msgid "Restart"
msgstr "Reiniciar"
#: js/ui/endSessionDialog.js:78
#: js/ui/endSessionDialog.js:76
#, javascript-format
msgid "The system will restart automatically in %d second."
msgid_plural "The system will restart automatically in %d seconds."
msgstr[0] "O sistema irá reiniciar automaticamente em %d segundo."
msgstr[1] "O sistema irá reiniciar automaticamente em %d segundos."
#: js/ui/endSessionDialog.js:91
#: js/ui/endSessionDialog.js:89
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Reiniciar & instalar atualizações"
#: js/ui/endSessionDialog.js:93
#: js/ui/endSessionDialog.js:91
#, javascript-format
msgid "The system will automatically restart and install updates in %d second."
msgid_plural ""
@@ -1241,22 +1375,22 @@ msgstr[1] ""
"O sistema irá reiniciar e instalar atualizações automaticamente em %d "
"segundos."
#: js/ui/endSessionDialog.js:99 js/ui/endSessionDialog.js:118
#: js/ui/endSessionDialog.js:97 js/ui/endSessionDialog.js:116
msgctxt "button"
msgid "Restart &amp; Install"
msgstr "Reiniciar &amp; instalar"
#: js/ui/endSessionDialog.js:100
#: js/ui/endSessionDialog.js:98
msgctxt "button"
msgid "Install &amp; Power Off"
msgstr "Instalar &amp; desligar"
#: js/ui/endSessionDialog.js:101
#: js/ui/endSessionDialog.js:99
msgctxt "checkbox"
msgid "Power off after updates are installed"
msgstr "Desligar após atualizações serem instaladas"
#: js/ui/endSessionDialog.js:108
#: js/ui/endSessionDialog.js:106
msgctxt "title"
msgid "Restart & Install Upgrade"
msgstr "Reiniciar & instalar atualizações"
@@ -1264,7 +1398,7 @@ msgstr "Reiniciar & instalar atualizações"
#. Translators: This is the text displayed for system upgrades in the
#. shut down dialog. First %s gets replaced with the distro name and
#. second %s with the distro version to upgrade to
#: js/ui/endSessionDialog.js:113
#: js/ui/endSessionDialog.js:111
#, javascript-format
msgid ""
"%s %s will be installed after restart. Upgrade installation can take a long "
@@ -1274,16 +1408,16 @@ msgstr ""
"pode levar um longo tempo: certifique-se de que fez cópia de segurança (back "
"up) e que o computador esteja ligado na tomada."
#: js/ui/endSessionDialog.js:261
#: js/ui/endSessionDialog.js:259
msgid "Running on battery power: Please plug in before installing updates."
msgstr ""
"Funcionando na bateria: conecte na tomada antes de instalar atualizações."
#: js/ui/endSessionDialog.js:270
#: js/ui/endSessionDialog.js:268
msgid "Some applications are busy or have unsaved work"
msgstr "Alguns aplicativos estão ocupados ou possuem trabalhos não salvos"
#: js/ui/endSessionDialog.js:275
#: js/ui/endSessionDialog.js:273
msgid "Other users are logged in"
msgstr "Outros usuários estão com sessão aberta"
@@ -1299,24 +1433,24 @@ msgstr "%s (remoto)"
msgid "%s (console)"
msgstr "%s (console)"
#: js/ui/extensionDownloader.js:185
#: js/ui/extensionDownloader.js:181
msgid "Install"
msgstr "Instalar"
#: js/ui/extensionDownloader.js:191
#: js/ui/extensionDownloader.js:187
msgid "Install Extension"
msgstr "Instalar extensão"
#: js/ui/extensionDownloader.js:192
#: js/ui/extensionDownloader.js:188
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Baixar e instalar “%s” de extensions.gnome.org?"
#: js/ui/extensionSystem.js:233
#: js/ui/extensionSystem.js:228
msgid "Extension Updates Available"
msgstr "Atualizações de extensões disponíveis"
#: js/ui/extensionSystem.js:234
#: js/ui/extensionSystem.js:229
msgid "Extension updates are ready to be installed."
msgstr "Atualizações de extensões estão prontas para serem instaladas."
@@ -1465,11 +1599,11 @@ msgstr "Ver fonte"
msgid "Web Page"
msgstr "Página web"
#: js/ui/main.js:277
#: js/ui/main.js:274
msgid "Logged in as a privileged user"
msgstr "Sessão aberta como um usuário privilegiado"
#: js/ui/main.js:278
#: js/ui/main.js:275
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@@ -1477,15 +1611,15 @@ msgstr ""
"Usar uma sessão como um usuário privilegiado deve ser evitado por motivos de "
"segurança. Se possível, você deve abrir uma sessão como um usuário normal."
#: js/ui/main.js:317
#: js/ui/main.js:281
msgid "Screen Lock disabled"
msgstr "Bloqueio de tela desabilitado"
#: js/ui/main.js:318
#: js/ui/main.js:282
msgid "Screen Locking requires the GNOME display manager."
msgstr "O bloqueio de tela requer o gerenciador de exibição do GNOME."
#: js/ui/messageTray.js:1551
#: js/ui/messageTray.js:1554
msgid "System Information"
msgstr "Informações do sistema"
@@ -1692,13 +1826,13 @@ msgid "The PIM must be a number or empty."
msgstr "O PIM deve ser um número ou vazio."
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:465
#: js/ui/shellMountOperation.js:469
#, javascript-format
msgid "Unable to start %s"
msgstr "Não foi possível iniciar o %s"
#. Translators: %s is the Disks application
#: js/ui/shellMountOperation.js:467
#: js/ui/shellMountOperation.js:471
#, javascript-format
msgid "Couldnt find the %s application"
msgstr "Não foi possível localizar o aplicativo %s"
@@ -1851,13 +1985,13 @@ msgstr "<desconhecido>"
#: js/ui/status/network.js:420 js/ui/status/network.js:1317
#, javascript-format
msgid "%s Off"
msgstr "%s desligada"
msgstr "%s desligado"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:423
#, javascript-format
msgid "%s Connected"
msgstr "Conectado à %s"
msgstr "Conectado a %s"
# Não gerenciável para transmitir a ideia que o Networkmanager não consegue gerenciar o dispositivo --Enrico
#. Translators: this is for network devices that are physically present but are not
@@ -1878,7 +2012,7 @@ msgstr "Desconectando de %s"
#: js/ui/status/network.js:438 js/ui/status/network.js:1309
#, javascript-format
msgid "%s Connecting"
msgstr "Conectando à %s"
msgstr "Conectando a %s"
#. Translators: this is for network connections that require some kind of key or password; %s is a network identifier
#: js/ui/status/network.js:441
@@ -2175,11 +2309,11 @@ msgstr "Erro de autorização de thunderbolt"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Não foi possível autorizar o dispositivo Thunderbolt: %s"
#: js/ui/status/volume.js:151
#: js/ui/status/volume.js:150
msgid "Volume changed"
msgstr "Volume alterado"
#: js/ui/status/volume.js:222
#: js/ui/status/volume.js:221
msgid "Volume"
msgstr "Volume"
@@ -2213,23 +2347,23 @@ msgstr "Interna apenas"
#. Translators: This is a time format for a date in
#. long format
#: js/ui/unlockDialog.js:371
#: js/ui/unlockDialog.js:370
msgid "%A %B %-d"
msgstr "%A, %-d de %B"
#: js/ui/unlockDialog.js:377
#: js/ui/unlockDialog.js:376
msgid "Swipe up to unlock"
msgstr "Deslize para desbloquear"
#: js/ui/unlockDialog.js:378
#: js/ui/unlockDialog.js:377
msgid "Click or press a key to unlock"
msgstr "Clique ou pressione uma tecla para desbloquear"
#: js/ui/unlockDialog.js:550
#: js/ui/unlockDialog.js:549
msgid "Unlock Window"
msgstr "Desbloquear janela"
#: js/ui/unlockDialog.js:559
#: js/ui/unlockDialog.js:558
msgid "Log in as another user"
msgstr "Iniciar sessão como outro usuário"
@@ -2389,136 +2523,6 @@ msgstr "A senha não pode estar em branco"
msgid "Authentication dialog was dismissed by the user"
msgstr "O diálogo de autenticação foi descartado pelo usuário"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
#: subprojects/extensions-app/js/main.js:182
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensões"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: subprojects/extensions-app/js/main.js:183
msgid "Manage your GNOME Extensions"
msgstr "Gerenciar suas extensões do GNOME"
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
msgid ""
"GNOME Extensions handles updating extensions, configuring extension "
"preferences and removing or disabling unwanted extensions."
msgstr ""
"GNOME Extensões lida com a atualização da extensões, configuração das "
"preferências de extensões e remoção ou desabilitação de extensões "
"indesejadas."
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configurar extensões do Shell do GNOME"
#: subprojects/extensions-app/js/main.js:144
#, javascript-format
msgid "Remove “%s”?"
msgstr "Remover “%s”?"
#: subprojects/extensions-app/js/main.js:145
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Se você remover a extensão, você precisa voltar a baixá-la se você quiser "
"habilitá-la novamente"
#: subprojects/extensions-app/js/main.js:149
msgid "Remove"
msgstr "Remover"
#: subprojects/extensions-app/js/main.js:181
msgid "translator-credits"
msgstr "Rafael Fontenelle <rafaelff@gnome.org>"
#: subprojects/extensions-app/js/main.js:316
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extensão será atualizada na próxima sessão."
msgstr[1] "%d extensões serão atualizadas na próxima sessão."
#: subprojects/extensions-app/data/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Descrição"
#: subprojects/extensions-app/data/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Versão"
#: subprojects/extensions-app/data/ui/extension-row.ui:151
msgid "Author"
msgstr "Autor"
#: subprojects/extensions-app/data/ui/extension-row.ui:175
msgid "Website"
msgstr "Site"
#: subprojects/extensions-app/data/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Remover…"
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
msgid "Help"
msgstr "Ajuda"
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Sobre as Extensões"
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
msgstr ""
"Para encontrar e adicionar extensões, visite <a href=\"https://extensions."
"gnome.org\">extensions.gnome.org</a>."
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Aviso"
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
msgid ""
"Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all "
"extensions."
msgstr ""
"Extensões podem causar problemas no sistema, incluindo problemas de "
"desempenho. Se você encontrar problemas com o seu sistema, é recomendável "
"desativar todas as extensões."
#: subprojects/extensions-app/data/ui/extensions-window.ui:134
msgid "Manually Installed"
msgstr "Instalada manualmente"
#: subprojects/extensions-app/data/ui/extensions-window.ui:158
msgid "Built-In"
msgstr "Interna"
#: subprojects/extensions-app/data/ui/extensions-window.ui:199
msgid "No Installed Extensions"
msgstr "Nenhuma extensão instalada"
#: subprojects/extensions-app/data/ui/extensions-window.ui:235
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
msgstr ""
"Sentimos muito, mas não foi possível obter a lista de extensões instaladas. "
"Certifique-se de estar em uma sessão do GNOME e tente novamente."
#: subprojects/extensions-app/data/ui/extensions-window.ui:288
msgid "Log Out…"
msgstr "Encerrar sessão…"
#. Translators: a file path to an extension directory
#: subprojects/extensions-tool/src/command-create.c:125
#, c-format
@@ -2856,9 +2860,6 @@ msgstr[1] "%u entradas"
msgid "System Sounds"
msgstr "Sons do sistema"
#~ msgid "Copy Error"
#~ msgstr "Copiar erro"
#~| msgid "Username: "
#~ msgid "Username…"
#~ msgstr "Nome de usuário…"

874
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -45,223 +45,228 @@ struct _ClientData
gulong backend_died_id;
};
struct _CalendarSourceData
{
ECalClientSourceType source_type;
CalendarSources *sources;
guint changed_signal;
/* ESource -> EClient */
GHashTable *clients;
guint timeout_id;
guint loaded : 1;
};
typedef struct _CalendarSourcesPrivate CalendarSourcesPrivate;
struct _CalendarSources
{
GObject parent;
ESourceRegistryWatcher *registry_watcher;
gulong filter_id;
gulong appeared_id;
gulong disappeared_id;
GMutex clients_lock;
GHashTable *clients; /* ESource -> ClientData */
CalendarSourcesPrivate *priv;
};
G_DEFINE_TYPE (CalendarSources, calendar_sources, G_TYPE_OBJECT)
struct _CalendarSourcesPrivate
{
ESourceRegistry *registry;
gulong source_added_id;
gulong source_changed_id;
gulong source_removed_id;
CalendarSourceData appointment_sources;
CalendarSourceData task_sources;
};
G_DEFINE_TYPE_WITH_PRIVATE (CalendarSources, calendar_sources, G_TYPE_OBJECT)
static void calendar_sources_finalize (GObject *object);
static void backend_died_cb (EClient *client, CalendarSourceData *source_data);
static void calendar_sources_registry_source_changed_cb (ESourceRegistry *registry,
ESource *source,
CalendarSources *sources);
static void calendar_sources_registry_source_removed_cb (ESourceRegistry *registry,
ESource *source,
CalendarSources *sources);
enum
{
CLIENT_APPEARED,
CLIENT_DISAPPEARED,
APPOINTMENT_SOURCES_CHANGED,
TASK_SOURCES_CHANGED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0, };
static void
calendar_sources_client_connected_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
CalendarSources *sources = CALENDAR_SOURCES (source_object);
ESource *source = user_data;
EClient *client;
g_autoptr (GError) error = NULL;
/* The calendar_sources_connect_client_sync() already stored the 'client'
* into the sources->clients */
client = calendar_sources_connect_client_finish (sources, result, &error);
if (error)
{
g_warning ("Could not load source '%s': %s",
e_source_get_uid (source),
error->message);
}
else
{
g_signal_emit (sources, signals[CLIENT_APPEARED], 0, client, NULL);
}
g_clear_object (&client);
g_clear_object (&source);
}
static gboolean
registry_watcher_filter_cb (ESourceRegistryWatcher *watcher,
ESource *source,
CalendarSources *sources)
{
return e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR) &&
e_source_selectable_get_selected (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR));
}
static void
registry_watcher_source_appeared_cb (ESourceRegistryWatcher *watcher,
ESource *source,
CalendarSources *sources)
{
ECalClientSourceType source_type;
if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR))
source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
else if (e_source_has_extension (source, E_SOURCE_EXTENSION_MEMO_LIST))
source_type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
else if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
source_type = E_CAL_CLIENT_SOURCE_TYPE_TASKS;
else
g_return_if_reached ();
calendar_sources_connect_client (sources, source, source_type, 30, NULL, calendar_sources_client_connected_cb, g_object_ref (source));
}
static void
registry_watcher_source_disappeared_cb (ESourceRegistryWatcher *watcher,
ESource *source,
CalendarSources *sources)
{
gboolean emit;
g_mutex_lock (&sources->clients_lock);
emit = g_hash_table_remove (sources->clients, source);
g_mutex_unlock (&sources->clients_lock);
if (emit)
g_signal_emit (sources, signals[CLIENT_DISAPPEARED], 0, e_source_get_uid (source), NULL);
}
static GObjectClass *parent_class = NULL;
static CalendarSources *calendar_sources_singleton = NULL;
static void
client_data_free (ClientData *data)
{
g_signal_handler_disconnect (data->client, data->backend_died_id);
g_clear_signal_handler (&data->backend_died_id, data->client);
g_object_unref (data->client);
g_slice_free (ClientData, data);
}
static void
calendar_sources_constructed (GObject *object)
{
CalendarSources *sources = CALENDAR_SOURCES (object);
ESourceRegistry *registry = NULL;
GError *error = NULL;
G_OBJECT_CLASS (calendar_sources_parent_class)->constructed (object);
registry = e_source_registry_new_sync (NULL, &error);
if (error != NULL)
{
/* Any error is fatal, but we don't want to crash gnome-shell-calendar-server
because of e-d-s problems. So just exit here.
*/
g_warning ("Failed to start evolution-source-registry: %s", error->message);
exit (EXIT_FAILURE);
}
g_return_if_fail (registry != NULL);
sources->registry_watcher = e_source_registry_watcher_new (registry, NULL);
g_clear_object (&registry);
sources->clients = g_hash_table_new_full ((GHashFunc) e_source_hash,
(GEqualFunc) e_source_equal,
(GDestroyNotify) g_object_unref,
(GDestroyNotify) client_data_free);
sources->filter_id = g_signal_connect (sources->registry_watcher,
"filter",
G_CALLBACK (registry_watcher_filter_cb),
sources);
sources->appeared_id = g_signal_connect (sources->registry_watcher,
"appeared",
G_CALLBACK (registry_watcher_source_appeared_cb),
sources);
sources->disappeared_id = g_signal_connect (sources->registry_watcher,
"disappeared",
G_CALLBACK (registry_watcher_source_disappeared_cb),
sources);
e_source_registry_watcher_reclaim (sources->registry_watcher);
}
static void
calendar_sources_finalize (GObject *object)
{
CalendarSources *sources = CALENDAR_SOURCES (object);
g_clear_pointer (&sources->clients, g_hash_table_destroy);
if (sources->registry_watcher)
{
g_signal_handler_disconnect (sources->registry_watcher,
sources->filter_id);
g_signal_handler_disconnect (sources->registry_watcher,
sources->appeared_id);
g_signal_handler_disconnect (sources->registry_watcher,
sources->disappeared_id);
g_clear_object (&sources->registry_watcher);
}
g_mutex_clear (&sources->clients_lock);
G_OBJECT_CLASS (calendar_sources_parent_class)->finalize (object);
}
static void
calendar_sources_class_init (CalendarSourcesClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->constructed = calendar_sources_constructed;
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = calendar_sources_finalize;
signals [CLIENT_APPEARED] =
g_signal_new ("client-appeared",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
signals [APPOINTMENT_SOURCES_CHANGED] =
g_signal_new ("appointment-sources-changed",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
E_TYPE_CAL_CLIENT);
G_TYPE_NONE,
0);
signals [CLIENT_DISAPPEARED] =
g_signal_new ("client-disappeared",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
signals [TASK_SOURCES_CHANGED] =
g_signal_new ("task-sources-changed",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_STRING); /* ESource::uid of the disappeared client */
G_TYPE_NONE,
0);
}
static void
calendar_sources_init (CalendarSources *sources)
{
g_mutex_init (&sources->clients_lock);
GError *error = NULL;
GDBusConnection *session_bus;
GVariant *result;
sources->priv = calendar_sources_get_instance_private (sources);
/* WORKAROUND: the hardcoded timeout for e_source_registry_new_sync()
(and other library calls that eventually call g_dbus_proxy_new[_sync]())
is 25 seconds. This has been shown to be too small for
evolution-source-registry in certain cases (slow disk, concurrent IO,
many configured sources), so we first ensure that the service
starts with a manual call and a higher timeout.
HACK: every time the DBus API is bumped in e-d-s we need
to update this!
*/
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (session_bus == NULL)
{
g_error ("Failed to connect to the session bus: %s", error->message);
}
result = g_dbus_connection_call_sync (session_bus, "org.freedesktop.DBus",
"/", "org.freedesktop.DBus",
"StartServiceByName",
g_variant_new ("(su)",
"org.gnome.evolution.dataserver.Sources5",
0),
NULL,
G_DBUS_CALL_FLAGS_NONE,
60 * 1000,
NULL, &error);
if (result != NULL)
{
g_variant_unref (result);
sources->priv->registry = e_source_registry_new_sync (NULL, &error);
}
if (error != NULL)
{
/* Any error is fatal, but we don't want to crash gnome-shell-calendar-server
because of e-d-s problems. So just exit here.
*/
g_warning ("Failed to start evolution-source-registry: %s", error->message);
exit(EXIT_FAILURE);
}
g_object_unref (session_bus);
sources->priv->source_added_id = g_signal_connect (sources->priv->registry,
"source-added",
G_CALLBACK (calendar_sources_registry_source_changed_cb),
sources);
sources->priv->source_changed_id = g_signal_connect (sources->priv->registry,
"source-changed",
G_CALLBACK (calendar_sources_registry_source_changed_cb),
sources);
sources->priv->source_removed_id = g_signal_connect (sources->priv->registry,
"source-removed",
G_CALLBACK (calendar_sources_registry_source_removed_cb),
sources);
sources->priv->appointment_sources.source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
sources->priv->appointment_sources.sources = sources;
sources->priv->appointment_sources.changed_signal = signals [APPOINTMENT_SOURCES_CHANGED];
sources->priv->appointment_sources.clients = g_hash_table_new_full ((GHashFunc) e_source_hash,
(GEqualFunc) e_source_equal,
(GDestroyNotify) g_object_unref,
(GDestroyNotify) client_data_free);
sources->priv->appointment_sources.timeout_id = 0;
sources->priv->task_sources.source_type = E_CAL_CLIENT_SOURCE_TYPE_TASKS;
sources->priv->task_sources.sources = sources;
sources->priv->task_sources.changed_signal = signals [TASK_SOURCES_CHANGED];
sources->priv->task_sources.clients = g_hash_table_new_full ((GHashFunc) e_source_hash,
(GEqualFunc) e_source_equal,
(GDestroyNotify) g_object_unref,
(GDestroyNotify) client_data_free);
sources->priv->task_sources.timeout_id = 0;
}
static void
calendar_sources_finalize_source_data (CalendarSources *sources,
CalendarSourceData *source_data)
{
if (source_data->loaded)
{
g_hash_table_destroy (source_data->clients);
source_data->clients = NULL;
g_clear_handle_id (&source_data->timeout_id, g_source_remove);
source_data->loaded = FALSE;
}
}
static void
calendar_sources_finalize (GObject *object)
{
CalendarSources *sources = CALENDAR_SOURCES (object);
if (sources->priv->registry)
{
g_clear_signal_handler (&sources->priv->source_added_id,
sources->priv->registry);
g_clear_signal_handler (&sources->priv->source_changed_id,
sources->priv->registry);
g_clear_signal_handler (&sources->priv->source_removed_id,
sources->priv->registry);
g_object_unref (sources->priv->registry);
}
sources->priv->registry = NULL;
calendar_sources_finalize_source_data (sources, &sources->priv->appointment_sources);
calendar_sources_finalize_source_data (sources, &sources->priv->task_sources);
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
CalendarSources *
calendar_sources_get (void)
{
static CalendarSources *calendar_sources_singleton = NULL;
gpointer singleton_location = &calendar_sources_singleton;
if (calendar_sources_singleton)
@@ -269,70 +274,85 @@ calendar_sources_get (void)
calendar_sources_singleton = g_object_new (CALENDAR_TYPE_SOURCES, NULL);
g_object_add_weak_pointer (G_OBJECT (calendar_sources_singleton),
singleton_location);
singleton_location);
return calendar_sources_singleton;
}
ESourceRegistry *
calendar_sources_get_registry (CalendarSources *sources)
/* The clients are just created here but not loaded */
static void
create_client_for_source (ESource *source,
ECalClientSourceType source_type,
CalendarSourceData *source_data)
{
return e_source_registry_watcher_get_registry (sources->registry_watcher);
ClientData *data;
EClient *client;
GError *error = NULL;
client = g_hash_table_lookup (source_data->clients, source);
g_return_if_fail (client == NULL);
client = e_cal_client_connect_sync (source, source_type, -1, NULL, &error);
if (!client)
{
g_warning ("Could not load source '%s': %s",
e_source_get_uid (source),
error->message);
g_clear_error(&error);
return;
}
data = g_slice_new0 (ClientData);
data->client = E_CAL_CLIENT (client); /* takes ownership */
data->backend_died_id = g_signal_connect (client,
"backend-died",
G_CALLBACK (backend_died_cb),
source_data);
g_hash_table_insert (source_data->clients, g_object_ref (source), data);
}
static inline void
debug_dump_ecal_list (GHashTable *clients)
{
#ifdef CALENDAR_ENABLE_DEBUG
GList *list, *link;
dprintf ("Loaded clients:\n");
list = g_hash_table_get_keys (clients);
for (link = list; link != NULL; link = g_list_next (link))
{
ESource *source = E_SOURCE (link->data);
dprintf (" %s %s\n",
e_source_get_uid (source),
e_source_get_display_name (source));
}
g_list_free (list);
#endif
}
static void
gather_event_clients_cb (gpointer key,
gpointer value,
gpointer user_data)
calendar_sources_load_esource_list (ESourceRegistry *registry,
CalendarSourceData *source_data);
static gboolean
backend_restart (gpointer data)
{
GSList **plist = user_data;
ClientData *cd = value;
CalendarSourceData *source_data = data;
ESourceRegistry *registry;
if (cd)
*plist = g_slist_prepend (*plist, g_object_ref (cd->client));
}
registry = source_data->sources->priv->registry;
calendar_sources_load_esource_list (registry, source_data);
g_signal_emit (source_data->sources, source_data->changed_signal, 0);
GSList *
calendar_sources_ref_clients (CalendarSources *sources)
{
GSList *list = NULL;
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
g_mutex_lock (&sources->clients_lock);
g_hash_table_foreach (sources->clients, gather_event_clients_cb, &list);
g_mutex_unlock (&sources->clients_lock);
return list;
}
gboolean
calendar_sources_has_clients (CalendarSources *sources)
{
GHashTableIter iter;
gpointer value;
gboolean has = FALSE;
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), FALSE);
g_mutex_lock (&sources->clients_lock);
g_hash_table_iter_init (&iter, sources->clients);
while (!has && g_hash_table_iter_next (&iter, NULL, &value))
{
ClientData *cd = value;
has = cd != NULL;
}
g_mutex_unlock (&sources->clients_lock);
return has;
source_data->timeout_id = 0;
return FALSE;
}
static void
backend_died_cb (EClient *client,
CalendarSources *sources)
backend_died_cb (EClient *client, CalendarSourceData *source_data)
{
ESource *source;
const char *display_name;
@@ -340,167 +360,196 @@ backend_died_cb (EClient *client,
source = e_client_get_source (client);
display_name = e_source_get_display_name (source);
g_warning ("The calendar backend for '%s' has crashed.", display_name);
g_mutex_lock (&sources->clients_lock);
g_hash_table_remove (sources->clients, source);
g_mutex_unlock (&sources->clients_lock);
g_hash_table_remove (source_data->clients, source);
g_clear_handle_id (&source_data->timeout_id, g_source_remove);
source_data->timeout_id = g_timeout_add_seconds (2, backend_restart,
source_data);
g_source_set_name_by_id (source_data->timeout_id, "[gnome-shell] backend_restart");
}
static EClient *
calendar_sources_connect_client_sync (CalendarSources *sources,
ESource *source,
ECalClientSourceType source_type,
guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
EClient *client = NULL;
ClientData *client_data;
g_mutex_lock (&sources->clients_lock);
client_data = g_hash_table_lookup (sources->clients, source);
if (client_data)
client = E_CLIENT (g_object_ref (client_data->client));
g_mutex_unlock (&sources->clients_lock);
if (client)
return client;
client = e_cal_client_connect_sync (source, source_type, wait_for_connected_seconds, cancellable, error);
if (!client)
return NULL;
g_mutex_lock (&sources->clients_lock);
client_data = g_hash_table_lookup (sources->clients, source);
if (client_data)
{
g_clear_object (&client);
client = E_CLIENT (g_object_ref (client_data->client));
}
else
{
client_data = g_slice_new0 (ClientData);
client_data->client = E_CAL_CLIENT (g_object_ref (client));
client_data->backend_died_id = g_signal_connect (client,
"backend-died",
G_CALLBACK (backend_died_cb),
sources);
g_hash_table_insert (sources->clients, g_object_ref (source), client_data);
}
g_mutex_unlock (&sources->clients_lock);
return client;
}
typedef struct _AsyncContext {
ESource *source;
ECalClientSourceType source_type;
guint32 wait_for_connected_seconds;
} AsyncContext;
static void
async_context_free (gpointer ptr)
calendar_sources_load_esource_list (ESourceRegistry *registry,
CalendarSourceData *source_data)
{
AsyncContext *ctx = ptr;
GList *list, *link;
const gchar *extension_name;
if (ctx)
switch (source_data->source_type)
{
g_clear_object (&ctx->source);
g_slice_free (AsyncContext, ctx);
case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
extension_name = E_SOURCE_EXTENSION_CALENDAR;
break;
case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
extension_name = E_SOURCE_EXTENSION_TASK_LIST;
break;
default:
g_return_if_reached ();
}
list = e_source_registry_list_sources (registry, extension_name);
for (link = list; link != NULL; link = g_list_next (link))
{
ESource *source = E_SOURCE (link->data);
ESourceSelectable *extension;
gboolean show_source;
extension = e_source_get_extension (source, extension_name);
show_source = e_source_get_enabled (source) && e_source_selectable_get_selected (extension);
if (show_source)
create_client_for_source (source, source_data->source_type, source_data);
}
debug_dump_ecal_list (source_data->clients);
g_list_free_full (list, g_object_unref);
}
static void
calendar_sources_registry_source_changed_cb (ESourceRegistry *registry,
ESource *source,
CalendarSources *sources)
{
if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR))
{
CalendarSourceData *source_data;
ESourceSelectable *extension;
gboolean have_client;
gboolean show_source;
source_data = &sources->priv->appointment_sources;
extension = e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR);
have_client = (g_hash_table_lookup (source_data->clients, source) != NULL);
show_source = e_source_get_enabled (source) && e_source_selectable_get_selected (extension);
if (!show_source && have_client)
{
g_hash_table_remove (source_data->clients, source);
g_signal_emit (sources, source_data->changed_signal, 0);
}
if (show_source && !have_client)
{
create_client_for_source (source, source_data->source_type, source_data);
g_signal_emit (sources, source_data->changed_signal, 0);
}
}
if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
{
CalendarSourceData *source_data;
ESourceSelectable *extension;
gboolean have_client;
gboolean show_source;
source_data = &sources->priv->task_sources;
extension = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
have_client = (g_hash_table_lookup (source_data->clients, source) != NULL);
show_source = e_source_get_enabled (source) && e_source_selectable_get_selected (extension);
if (!show_source && have_client)
{
g_hash_table_remove (source_data->clients, source);
g_signal_emit (sources, source_data->changed_signal, 0);
}
if (show_source && !have_client)
{
create_client_for_source (source, source_data->source_type, source_data);
g_signal_emit (sources, source_data->changed_signal, 0);
}
}
}
static void
calendar_sources_connect_client_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
calendar_sources_registry_source_removed_cb (ESourceRegistry *registry,
ESource *source,
CalendarSources *sources)
{
CalendarSources *sources = source_object;
AsyncContext *ctx = task_data;
EClient *client;
GError *local_error = NULL;
client = calendar_sources_connect_client_sync (sources, ctx->source, ctx->source_type,
ctx->wait_for_connected_seconds, cancellable, &local_error);
if (!client)
if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR))
{
if (local_error)
g_task_return_error (task, local_error);
else
g_task_return_pointer (task, NULL, NULL);
} else {
g_task_return_pointer (task, client, g_object_unref);
CalendarSourceData *source_data;
source_data = &sources->priv->appointment_sources;
g_hash_table_remove (source_data->clients, source);
g_signal_emit (sources, source_data->changed_signal, 0);
}
if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
{
CalendarSourceData *source_data;
source_data = &sources->priv->task_sources;
g_hash_table_remove (source_data->clients, source);
g_signal_emit (sources, source_data->changed_signal, 0);
}
}
void
calendar_sources_connect_client (CalendarSources *sources,
ESource *source,
ECalClientSourceType source_type,
guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
static void
ensure_appointment_sources (CalendarSources *sources)
{
AsyncContext *ctx;
g_autoptr (GTask) task = NULL;
ctx = g_slice_new0 (AsyncContext);
ctx->source = g_object_ref (source);
ctx->source_type = source_type;
ctx->wait_for_connected_seconds = wait_for_connected_seconds;
task = g_task_new (sources, cancellable, callback, user_data);
g_task_set_source_tag (task, calendar_sources_connect_client);
g_task_set_task_data (task, ctx, async_context_free);
g_task_run_in_thread (task, calendar_sources_connect_client_thread);
}
EClient *
calendar_sources_connect_client_finish (CalendarSources *sources,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, sources), NULL);
g_return_val_if_fail (g_async_result_is_tagged (result, calendar_sources_connect_client), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
void
print_debug (const gchar *format,
...)
{
g_autofree char *s = NULL;
g_autofree char *timestamp = NULL;
va_list ap;
g_autoptr (GDateTime) now = NULL;
static volatile gsize once_init_value = 0;
static gboolean show_debug = FALSE;
static guint pid = 0;
if (g_once_init_enter (&once_init_value))
if (!sources->priv->appointment_sources.loaded)
{
show_debug = (g_getenv ("CALENDAR_SERVER_DEBUG") != NULL);
pid = getpid ();
g_once_init_leave (&once_init_value, 1);
calendar_sources_load_esource_list (sources->priv->registry,
&sources->priv->appointment_sources);
sources->priv->appointment_sources.loaded = TRUE;
}
if (!show_debug)
goto out;
now = g_date_time_new_now_local ();
timestamp = g_date_time_format (now, "%H:%M:%S");
va_start (ap, format);
s = g_strdup_vprintf (format, ap);
va_end (ap);
g_print ("gnome-shell-calendar-server[%d]: %s.%03d: %s\n",
pid, timestamp, g_date_time_get_microsecond (now), s);
out:
;
}
GList *
calendar_sources_get_appointment_clients (CalendarSources *sources)
{
GList *list, *link;
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
ensure_appointment_sources (sources);
list = g_hash_table_get_values (sources->priv->appointment_sources.clients);
for (link = list; link != NULL; link = g_list_next (link))
link->data = ((ClientData *) link->data)->client;
return list;
}
static void
ensure_task_sources (CalendarSources *sources)
{
if (!sources->priv->task_sources.loaded)
{
calendar_sources_load_esource_list (sources->priv->registry,
&sources->priv->task_sources);
sources->priv->task_sources.loaded = TRUE;
}
}
GList *
calendar_sources_get_task_clients (CalendarSources *sources)
{
GList *list, *link;
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
ensure_task_sources (sources);
list = g_hash_table_get_values (sources->priv->task_sources.clients);
for (link = list; link != NULL; link = g_list_next (link))
link->data = ((ClientData *) link->data)->client;
return list;
}
gboolean
calendar_sources_has_sources (CalendarSources *sources)
{
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), FALSE);
ensure_appointment_sources (sources);
ensure_task_sources (sources);
return g_hash_table_size (sources->priv->appointment_sources.clients) > 0 ||
g_hash_table_size (sources->priv->task_sources.clients) > 0;
}

View File

@@ -26,38 +26,17 @@
#include <glib-object.h>
#define EDS_DISABLE_DEPRECATED
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#include <libedataserver/libedataserver.h>
#include <libecal/libecal.h>
G_GNUC_END_IGNORE_DEPRECATIONS
G_BEGIN_DECLS
#define CALENDAR_TYPE_SOURCES (calendar_sources_get_type ())
G_DECLARE_FINAL_TYPE (CalendarSources, calendar_sources,
CALENDAR, SOURCES, GObject)
CalendarSources *calendar_sources_get (void);
ESourceRegistry *calendar_sources_get_registry (CalendarSources *sources);
GSList *calendar_sources_ref_clients (CalendarSources *sources);
gboolean calendar_sources_has_clients (CalendarSources *sources);
CalendarSources *calendar_sources_get (void);
GList *calendar_sources_get_appointment_clients (CalendarSources *sources);
GList *calendar_sources_get_task_clients (CalendarSources *sources);
void calendar_sources_connect_client (CalendarSources *sources,
ESource *source,
ECalClientSourceType source_type,
guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
EClient *calendar_sources_connect_client_finish
(CalendarSources *sources,
GAsyncResult *result,
GError **error);
/* Set the environment variable CALENDAR_SERVER_DEBUG to show debug */
void print_debug (const gchar *str,
...) G_GNUC_PRINTF (1, 2);
gboolean calendar_sources_has_sources (CalendarSources *sources);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -109,11 +109,17 @@ load_folder (GHashTable *folders,
while ((name = g_dir_read_name (dir)))
{
g_autofree gchar *stripped_name = NULL;
g_autofree gchar *filename = NULL;
g_autoptr(GKeyFile) keyfile = NULL;
if (!g_str_has_suffix (name, ".directory"))
continue;
stripped_name = g_strndup (name, strlen (name) - strlen (".directory"));
/* First added wins */
if (g_hash_table_contains (folders, name))
if (g_hash_table_contains (folders, stripped_name))
continue;
filename = g_build_filename (path, name, NULL);
@@ -128,7 +134,8 @@ load_folder (GHashTable *folders,
NULL, NULL);
if (translated != NULL)
g_hash_table_insert (folders, g_strdup (name), translated);
g_hash_table_insert (folders, g_steal_pointer (&stripped_name),
translated);
}
}
}

View File

@@ -1159,10 +1159,6 @@ shell_app_get_pids (ShellApp *app)
{
MetaWindow *window = iter->data;
int pid = meta_window_get_pid (window);
if (pid < 1)
continue;
/* Note in the (by far) common case, app will only have one pid, so
* we'll hit the first element, so don't worry about O(N^2) here.
*/

View File

@@ -57,7 +57,6 @@ struct _ShellGlobal {
ClutterStage *stage;
MetaBackend *backend;
MetaDisplay *meta_display;
MetaWorkspaceManager *workspace_manager;
Display *xdisplay;
@@ -96,7 +95,6 @@ enum {
PROP_0,
PROP_SESSION_MODE,
PROP_BACKEND,
PROP_DISPLAY,
PROP_WORKSPACE_MANAGER,
PROP_SCREEN_WIDTH,
@@ -232,9 +230,6 @@ shell_global_get_property(GObject *object,
case PROP_SESSION_MODE:
g_value_set_string (value, shell_global_get_session_mode (global));
break;
case PROP_BACKEND:
g_value_set_object (value, global->backend);
break;
case PROP_DISPLAY:
g_value_set_object (value, global->meta_display);
break;
@@ -477,13 +472,6 @@ shell_global_class_init (ShellGlobalClass *klass)
"Screen height, in pixels",
0, G_MAXINT, 1,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_BACKEND,
g_param_spec_object ("backend",
"Backend",
"MetaBackend object",
META_TYPE_BACKEND,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_DISPLAY,
g_param_spec_object ("display",
@@ -959,7 +947,6 @@ _shell_global_set_plugin (ShellGlobal *global,
g_return_if_fail (SHELL_IS_GLOBAL (global));
g_return_if_fail (global->plugin == NULL);
global->backend = meta_get_backend ();
global->plugin = plugin;
global->wm = shell_wm_new (plugin);
@@ -1612,8 +1599,10 @@ shell_global_end_work (ShellGlobal *global)
* Idle means here no animations, no redrawing, and no ongoing background
* work. Since there is currently no way to hook into the Clutter master
* clock and know when is running, the implementation here is somewhat
* approximation. Animations may be detected as terminating early if they
* can be drawn fast enough so that the event loop goes idle between frames.
* approximation. Animations done through the shell's Tweener module will
* be handled properly, but other animations may be detected as terminating
* early if they can be drawn fast enough so that the event loop goes idle
* between frames.
*
* The intent of this function is for performance measurement runs
* where a number of actions should be run serially and each action is

View File

@@ -638,20 +638,6 @@ shell_util_check_cloexec_fds (void)
g_info ("Open fd CLOEXEC check complete");
}
/**
* shell_util_get_uid:
*
* A wrapper around getuid() so that it can be used from JavaScript. This
* function will always succeed.
*
* Returns: the real user ID of the calling process
*/
gint
shell_util_get_uid (void)
{
return getuid ();
}
static void
on_systemd_call_cb (GObject *source,
GAsyncResult *res,

View File

@@ -78,8 +78,6 @@ gboolean shell_util_has_x11_display_extension (MetaDisplay *display,
char *shell_util_get_translated_folder_name (const char *name);
gint shell_util_get_uid (void);
G_END_DECLS
#endif /* __SHELL_UTIL_H__ */

View File

@@ -343,7 +343,7 @@ get_app_from_window_pid (ShellWindowTracker *tracker,
pid = meta_window_get_pid (window);
if (pid < 1)
if (pid == -1)
return NULL;
result = shell_window_tracker_get_app_from_pid (tracker, pid);

View File

@@ -291,6 +291,7 @@ cr_term_to_string (CRTerm const * a_this)
for (cur = a_this; cur; cur = cur->next) {
if ((cur->content.str == NULL)
&& (cur->content.num == NULL)
&& (cur->content.str == NULL)
&& (cur->content.rgb == NULL))
continue;
@@ -484,6 +485,7 @@ cr_term_one_to_string (CRTerm const * a_this)
if ((a_this->content.str == NULL)
&& (a_this->content.num == NULL)
&& (a_this->content.str == NULL)
&& (a_this->content.rgb == NULL))
return NULL ;

View File

@@ -314,7 +314,7 @@ st_entry_get_preferred_width (ClutterActor *actor,
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
gfloat hint_w, hint_min_w, icon_w;
gfloat hint_w, icon_w;
st_theme_node_adjust_for_height (theme_node, &for_height);
@@ -324,11 +324,10 @@ st_entry_get_preferred_width (ClutterActor *actor,
if (priv->hint_actor)
{
clutter_actor_get_preferred_width (priv->hint_actor, -1,
&hint_min_w, &hint_w);
clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
if (min_width_p && hint_min_w > *min_width_p)
*min_width_p = hint_min_w;
if (min_width_p && hint_w > *min_width_p)
*min_width_p = hint_w;
if (natural_width_p && hint_w > *natural_width_p)
*natural_width_p = hint_w;
@@ -423,7 +422,7 @@ st_entry_allocate (ClutterActor *actor,
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
ClutterActorBox content_box, child_box, icon_box, hint_box;
gfloat icon_w, icon_h;
gfloat hint_w, hint_min_w, hint_h;
gfloat hint_w, hint_h;
gfloat entry_h, min_h, pref_h, avail_h;
ClutterActor *left_icon, *right_icon;
gboolean is_rtl;
@@ -489,11 +488,9 @@ st_entry_allocate (ClutterActor *actor,
/* now allocate the hint actor */
hint_box = child_box;
clutter_actor_get_preferred_width (priv->hint_actor, -1, &hint_min_w, &hint_w);
clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
clutter_actor_get_preferred_height (priv->hint_actor, -1, NULL, &hint_h);
hint_w = CLAMP (hint_w, hint_min_w, child_box.x2 - child_box.x1);
if (is_rtl)
hint_box.x1 = hint_box.x2 - hint_w;
else

View File

@@ -517,9 +517,7 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
clutter_actor_set_opacity_override (actor, 255);
paint_context =
clutter_paint_context_new_for_framebuffer (fb, NULL,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_framebuffer (fb);
clutter_actor_paint (actor, paint_context);
clutter_paint_context_destroy (paint_context);

View File

@@ -546,8 +546,7 @@ main (int argc, char **argv)
meta_test_init ();
if (chdir (cwd) < 0)
g_error ("chdir('%s') failed: %s", cwd, g_strerror (errno));
chdir (cwd);
/* Make sure our assumptions about resolution are correct */
g_object_set (clutter_settings_get_default (), "font-dpi", -1, NULL);

View File

@@ -5,14 +5,6 @@ used as a stand-alone project as well.
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Installation
If Extensions is not already installed on your GNOME system, we
recommend getting it from [flathub].
<a href='https://flathub.org/apps/details/org.gnome.Extensions'>
<img width='240' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/>
</a>
## Building
Before the project can be built stand-alone, the po directory has
to be populated with translations (from gnome-shell).
@@ -28,5 +20,4 @@ License, version 2 or later. See the [COPYING][license] file for details.
[logo]: logo.png
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell/issues
[flathub]: https://flathub.org
[license]: COPYING

View File

@@ -6,7 +6,6 @@ gnome.compile_resources(
install_dir: pkgdatadir
)
desktop_file = app_id + '.desktop'
desktopconf = configuration_data()
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
@@ -16,25 +15,17 @@ desktopconf.set('prgname', prgname)
i18n.merge_file('desktop',
input: configure_file(
input: desktop_file + '.in.in',
output: desktop_file + '.in',
input: app_id + '.desktop.in.in',
output: app_id + '.desktop.in',
configuration: desktopconf
),
output: desktop_file,
output: app_id + '.desktop',
po_dir: po_dir,
install: true,
install_dir: desktopdir,
type: 'desktop'
)
if (desktop_file_validate.found())
test('Validating ' + desktop_file,
desktop_file_validate,
args: [desktop_file],
workdir: meson.current_build_dir()
)
endif
configure_file(
input: app_id + '.service.in',
output: app_id + '.service',

View File

@@ -14,7 +14,6 @@
<url type="translate">https://wiki.gnome.org/TranslationProject</url>
<project_group>GNOME</project_group>
<developer_name>The GNOME Project</developer_name>
<launchable type="desktop-id">org.gnome.Extensions.desktop</launchable>
@@ -39,18 +38,19 @@
</description>
<releases>
<release version="3.37.0" date="2020-03-31"/>
<release version="3.36.1" date="2020-03-29"/>
<release version="3.36.0" date="2020-03-07"/>
</releases>
<screenshots>
<screenshot type="default">
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/master/subprojects/extensions-app/data/metainfo/extensions-main.png</image>
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/gnome-3-36/subprojects/extensions-app/data/metainfo/extensions-main.png</image>
</screenshot>
<screenshot>
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/master/subprojects/extensions-app/data/metainfo/extensions-update.png</image>
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/gnome-3-36/subprojects/extensions-app/data/metainfo/extensions-update.png</image>
</screenshot>
<screenshot>
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/master/subprojects/extensions-app/data/metainfo/extensions-remove.png</image>
<image>https://gitlab.gnome.org/GNOME/gnome-shell/raw/gnome-3-36/subprojects/extensions-app/data/metainfo/extensions-remove.png</image>
</screenshot>
</screenshots>
</component>

View File

@@ -201,7 +201,10 @@ var ExtensionsWindow = GObject.registerClass({
null,
Gio.DBusCallFlags.NONE,
-1,
null);
null,
(o, res) => {
o.call_finish(res);
});
}
_sortList(row1, row2) {
@@ -476,7 +479,7 @@ var ExtensionRow = GObject.registerClass({
function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
globalThis.global = {
window.global = {
log(...args) {
print(args.join(', '));
},

View File

@@ -1,6 +1,6 @@
project('gnome-extensions-app',
version: '3.37.0',
meson_version: '>= 0.53.0',
version: '3.36.1',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@@ -37,7 +37,6 @@ servicedir = join_paths(datadir, 'dbus-1', 'services')
gjs = find_program('gjs')
appstream_util = find_program('appstream-util', required: false)
desktop_file_validate = find_program('desktop-file-validate', required: false)
subdir('data')
subdir('js')
@@ -65,6 +64,8 @@ if not meson.is_subproject()
'debug': get_option('debug'),
}
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
if meson.version().version_compare('>= 0.53.0')
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
endif
endif

View File

@@ -44,14 +44,6 @@ __gnome_extensions() {
esac
case "$COMMAND" in
create)
case "$prev" in
--template)
COMPREPLY=($(compgen -W "`gnome-extensions create --list-templates`" -- "$2"))
return 0
;;
esac
;;
pack)
case "$prev" in
--podir|--out-dir|-o)

View File

@@ -42,13 +42,6 @@ DESCRIPTION
*gnome-extensions* is a utility that makes some common GNOME extensions
operations available on the command line.
COMMON OPTIONS
--------------
All commands except for *help* and *version* handle the following options:
*--quiet*, *-q*::
Do not print error messages
COMMANDS
--------
*help* ['COMMAND']::
@@ -128,9 +121,6 @@ Creates a new extension from a template.
*--uuid*='UUID':::
Set the unique extension ID in the metadata to 'UUID'
*--template*='TEMPLATE':::
Use 'TEMPLATE' as base for the new extension
*-i*:::
*--interactive*:::
Prompt for any extension metadata that hasn't been provided

View File

@@ -1,6 +1,6 @@
project('gnome-extensions-tool', 'c',
version: '3.37.0',
meson_version: '>= 0.53.0',
version: '3.36.1',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@@ -35,13 +35,11 @@ cc = meson.get_compiler('c')
bash_completion = dependency('bash-completion', required: get_option('bash_completion'))
po_dir = meson.source_root() + '/po'
subdir('src')
if bash_completion.found()
install_data('completion/bash/gnome-extensions',
install_dir: bash_completion.get_pkgconfig_variable('completionsdir', define_variable: ['datadir', datadir])
install_dir: bash_completion.get_pkgconfig_variable('completionsdir')
)
endif
@@ -74,7 +72,9 @@ if not meson.is_subproject()
'bash_completion': bash_completion.found(),
}
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
if meson.version().version_compare('>= 0.53.0')
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
endif
endif

View File

@@ -18,22 +18,14 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define _GNU_SOURCE /* for strcasestr */
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <gio/gunixinputstream.h>
#include "commands.h"
#include "common.h"
#include "config.h"
#define TEMPLATES_PATH "/org/gnome/extensions-tool/templates"
#define TEMPLATE_KEY "Path"
#define SORT_DATA "desktop-id"
static char *
get_shell_version (GError **error)
{
@@ -56,66 +48,6 @@ get_shell_version (GError **error)
return g_strjoinv (".", split_version);
}
static GDesktopAppInfo *
load_app_info_from_resource (const char *uri)
{
g_autoptr (GFile) file = NULL;
g_autofree char *contents = NULL;
g_autoptr (GKeyFile) keyfile = NULL;
file = g_file_new_for_uri (uri);
if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
return NULL;
keyfile = g_key_file_new ();
if (!g_key_file_load_from_data (keyfile, contents, -1, G_KEY_FILE_NONE, NULL))
return NULL;
return g_desktop_app_info_new_from_keyfile (keyfile);
}
static int
sort_func (gconstpointer a, gconstpointer b)
{
GObject *info1 = *((GObject **) a);
GObject *info2 = *((GObject **) b);
const char *desktop1 = g_object_get_data (info1, SORT_DATA);
const char *desktop2 = g_object_get_data (info2, SORT_DATA);
return g_strcmp0 (desktop1, desktop2);
}
static GPtrArray *
get_templates (void)
{
g_auto (GStrv) children = NULL;
GPtrArray *templates = g_ptr_array_new_with_free_func (g_object_unref);
char **s;
children = g_resources_enumerate_children (TEMPLATES_PATH, 0, NULL);
for (s = children; *s; s++)
{
g_autofree char *uri = NULL;
GDesktopAppInfo *info;
if (!g_str_has_suffix (*s, ".desktop"))
continue;
uri = g_strdup_printf ("resource://" TEMPLATES_PATH "/%s", *s);
info = load_app_info_from_resource (uri);
if (!info)
continue;
g_object_set_data_full (G_OBJECT (info), SORT_DATA, g_strdup (*s), g_free);
g_ptr_array_add (templates, info);
}
g_ptr_array_sort (templates, sort_func);
return templates;
}
static gboolean
create_metadata (GFile *target_dir,
const char *uuid,
@@ -153,30 +85,21 @@ create_metadata (GFile *target_dir,
}
#define TEMPLATE_PATH "/org/gnome/extensions-tool/template"
static gboolean
copy_extension_template (const char *template, GFile *target_dir, GError **error)
copy_extension_template (GFile *target_dir, GError **error)
{
g_auto (GStrv) templates = NULL;
g_autofree char *path = NULL;
char **s;
path = g_strdup_printf (TEMPLATES_PATH "/%s", template);
templates = g_resources_enumerate_children (path, 0, NULL);
if (templates == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No template %s", template);
return FALSE;
}
templates = g_resources_enumerate_children (TEMPLATE_PATH, 0, NULL);
for (s = templates; *s; s++)
{
g_autoptr (GFile) target = NULL;
g_autoptr (GFile) source = NULL;
g_autofree char *uri = NULL;
uri = g_strdup_printf ("resource://%s/%s", path, *s);
uri = g_strdup_printf ("resource://%s/%s", TEMPLATE_PATH, *s);
source = g_file_new_for_uri (uri);
target = g_file_get_child (target_dir, *s);
@@ -211,14 +134,11 @@ launch_extension_source (GFile *dir, GError **error)
}
static gboolean
create_extension (const char *uuid, const char *name, const char *description, const char *template)
create_extension (const char *uuid, const char *name, const char *description)
{
g_autoptr (GFile) dir = NULL;
g_autoptr (GError) error = NULL;
if (template == NULL)
template = "plain";
dir = g_file_new_build_filename (g_get_user_data_dir (),
"gnome-shell",
"extensions",
@@ -237,7 +157,7 @@ create_extension (const char *uuid, const char *name, const char *description, c
return FALSE;
}
if (!copy_extension_template (template, dir, &error))
if (!copy_extension_template (dir, &error))
{
g_printerr ("%s\n", error->message);
return FALSE;
@@ -253,15 +173,14 @@ create_extension (const char *uuid, const char *name, const char *description, c
}
static void
prompt_metadata (char **uuid, char **name, char **description, char **template)
prompt_metadata (char **uuid, char **name, char **description)
{
g_autoptr (GInputStream) stdin = NULL;
g_autoptr (GDataInputStream) istream = NULL;
if ((uuid == NULL || *uuid != NULL) &&
(name == NULL || *name != NULL) &&
(description == NULL || *description != NULL) &&
(template == NULL || *template != NULL))
(description == NULL || *description != NULL))
return;
stdin = g_unix_input_stream_new (0, FALSE);
@@ -269,127 +188,43 @@ prompt_metadata (char **uuid, char **name, char **description, char **template)
if (name != NULL && *name == NULL)
{
char *line = NULL;
char *line;
g_print (
_("Name should be a very short (ideally descriptive) string.\n"
"Examples are: %s"),
"“Click To Focus”, “Adblock”, “Shell Window Shrinker”\n");
g_print ("%s: ", _("Name"));
while (line == NULL)
{
g_print ("%s: ", _("Name"));
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
}
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
*name = g_strdelimit (line, "\n", '\0');
g_print ("\n");
}
if (description != NULL && *description == NULL)
{
char *line = NULL;
char *line;
g_print (
_("Description is a single-sentence explanation of what your extension does.\n"
"Examples are: %s"),
"“Make windows visible on click”, “Block advertisement popups”, “Animate windows shrinking on minimize”\n");
g_print ("%s: ", _("Description"));
while (line == NULL)
{
g_print ("%s: ", _("Description"));
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
}
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
*description = g_strdelimit (line, "\n", '\0');
g_print ("\n");
}
if (uuid != NULL && *uuid == NULL)
{
char *line = NULL;
char *line;
g_print (
_("UUID is a globally-unique identifier for your extension.\n"
"This should be in the format of an email address (clicktofocus@janedoe.example.com)\n"));
g_print ("UUID: ");
while (line == NULL)
{
g_print ("UUID: ");
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
}
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
*uuid = g_strdelimit (line, "\n", '\0');
g_print ("\n");
}
if (template != NULL && *template == NULL)
{
g_autoptr (GPtrArray) templates = get_templates ();
if (templates->len == 1)
{
GDesktopAppInfo *info = g_ptr_array_index (templates, 0);
*template = g_desktop_app_info_get_string (info, TEMPLATE_KEY);
}
else
{
int i;
g_print (_("Choose one of the available templates:\n"));
for (i = 0; i < templates->len; i++)
{
GAppInfo *info = g_ptr_array_index (templates, i);
g_print ("%d) %-10s %s\n",
i + 1,
g_app_info_get_name (info),
g_app_info_get_description (info));
}
while (*template == NULL)
{
g_autofree char *line = NULL;
g_print ("%s [1-%d]: ", _("Template"), templates->len);
line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL);
if (line == NULL)
continue;
if (g_ascii_isdigit (*line))
{
long i = strtol (line, NULL, 10);
if (i > 0 && i <= templates->len)
{
GDesktopAppInfo *info;
info = g_ptr_array_index (templates, i - 1);
*template =
g_desktop_app_info_get_string (info, TEMPLATE_KEY);
}
}
else
{
for (i = 0; i < templates->len; i++)
{
GDesktopAppInfo *info = g_ptr_array_index (templates, i);
g_autofree char *cur_template = NULL;
cur_template =
g_desktop_app_info_get_string (info, TEMPLATE_KEY);
if (strcasestr (cur_template, line) != NULL)
*template = g_steal_pointer (&cur_template);
}
}
}
g_print ("\n");
}
}
}
@@ -401,9 +236,7 @@ handle_create (int argc, char *argv[], gboolean do_help)
g_autofree char *name = NULL;
g_autofree char *description = NULL;
g_autofree char *uuid = NULL;
g_autofree char *template = NULL;
gboolean interactive = FALSE;
gboolean list_templates = FALSE;
GOptionEntry entries[] = {
{ .long_name = "uuid",
.arg = G_OPTION_ARG_STRING, .arg_data = &uuid,
@@ -417,13 +250,6 @@ handle_create (int argc, char *argv[], gboolean do_help)
.arg_description = _("DESCRIPTION"),
.arg = G_OPTION_ARG_STRING, .arg_data = &description,
.description = _("A short description of what the extension does") },
{ .long_name = "template",
.arg = G_OPTION_ARG_STRING, .arg_data = &template,
.arg_description = _("TEMPLATE"),
.description = _("The template to use for the new extension") },
{ .long_name = "list-templates",
.arg = G_OPTION_ARG_NONE, .arg_data = &list_templates,
.flags = G_OPTION_FLAG_HIDDEN },
{ .long_name = "interactive", .short_name = 'i',
.arg = G_OPTION_ARG_NONE, .arg_data = &interactive,
.description = _("Enter extension information interactively") },
@@ -436,7 +262,6 @@ handle_create (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Create a new extension"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group ());
if (do_help)
{
@@ -456,24 +281,8 @@ handle_create (int argc, char *argv[], gboolean do_help)
return 1;
}
if (list_templates)
{
g_autoptr (GPtrArray) templates = get_templates ();
int i;
for (i = 0; i < templates->len; i++)
{
GDesktopAppInfo *info = g_ptr_array_index (templates, i);
g_autofree char *template = NULL;
template = g_desktop_app_info_get_string (info, TEMPLATE_KEY);
g_print ("%s\n", template);
}
return 0;
}
if (interactive)
prompt_metadata (&uuid, &name, &description, &template);
prompt_metadata (&uuid, &name, &description);
if (uuid == NULL || name == NULL || description == NULL)
{
@@ -481,5 +290,5 @@ handle_create (int argc, char *argv[], gboolean do_help)
return 1;
}
return create_extension (uuid, name, description, template) ? 0 : 2;
return create_extension (uuid, name, description) ? 0 : 2;
}

View File

@@ -26,37 +26,7 @@
#include "config.h"
static gboolean
disable_extension_dbus (GDBusProxy *proxy,
const char *uuid)
{
g_autoptr (GVariant) response = NULL;
g_autoptr (GError) error = NULL;
gboolean success = FALSE;
response = g_dbus_proxy_call_sync (proxy,
"DisableExtension",
g_variant_new ("(s)", uuid),
0,
-1,
NULL,
&error);
if (response == NULL)
{
g_printerr (_("Failed to connect to GNOME Shell\n"));
return FALSE;
}
g_variant_get (response, "(b)", &success);
if (!success)
g_printerr (_("Extension “%s” does not exist\n"), uuid);
return success;
}
static gboolean
disable_extension_gsettings (const char *uuid)
disable_extension (const char *uuid)
{
g_autoptr(GSettings) settings = get_shell_settings ();
@@ -67,20 +37,6 @@ disable_extension_gsettings (const char *uuid)
settings_list_add (settings, "disabled-extensions", uuid);
}
static gboolean
disable_extension (const char *uuid)
{
g_autoptr (GDBusProxy) proxy = NULL;
g_autoptr (GError) error = NULL;
proxy = get_shell_proxy (&error);
if (proxy != NULL)
return disable_extension_dbus (proxy, uuid);
else
return disable_extension_gsettings (uuid);
}
int
handle_disable (int argc, char *argv[], gboolean do_help)
{
@@ -100,7 +56,6 @@ handle_disable (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Disable an extension"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -26,37 +26,7 @@
#include "config.h"
static gboolean
enable_extension_dbus (GDBusProxy *proxy,
const char *uuid)
{
g_autoptr (GVariant) response = NULL;
g_autoptr (GError) error = NULL;
gboolean success = FALSE;
response = g_dbus_proxy_call_sync (proxy,
"EnableExtension",
g_variant_new ("(s)", uuid),
0,
-1,
NULL,
&error);
if (response == NULL)
{
g_printerr (_("Failed to connect to GNOME Shell\n"));
return FALSE;
}
g_variant_get (response, "(b)", &success);
if (!success)
g_printerr (_("Extension “%s” does not exist\n"), uuid);
return success;
}
static gboolean
enable_extension_gsettings (const char *uuid)
enable_extension (const char *uuid)
{
g_autoptr(GSettings) settings = get_shell_settings ();
@@ -67,20 +37,6 @@ enable_extension_gsettings (const char *uuid)
settings_list_remove (settings, "disabled-extensions", uuid);
}
static gboolean
enable_extension (const char *uuid)
{
g_autoptr (GDBusProxy) proxy = NULL;
g_autoptr (GError) error = NULL;
proxy = get_shell_proxy (&error);
if (proxy != NULL)
return enable_extension_dbus (proxy, uuid);
else
return enable_extension_gsettings (uuid);
}
int
handle_enable (int argc, char *argv[], gboolean do_help)
{
@@ -100,7 +56,6 @@ handle_enable (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Enable an extension"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -46,19 +46,13 @@ show_extension_info (const char *uuid)
NULL,
&error);
if (response == NULL)
{
g_printerr (_("Failed to connect to GNOME Shell\n"));
return FALSE;
}
return FALSE;
asv = g_variant_get_child_value (response, 0);
info = g_variant_dict_new (asv);
if (!g_variant_dict_contains (info, "uuid"))
{
g_printerr (_("Extension “%s” doesn't exist\n"), uuid);
return FALSE;
}
return FALSE;
print_extension_info (info, DISPLAY_DETAILED);
@@ -84,7 +78,6 @@ handle_info (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Show extensions info"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -183,7 +183,6 @@ handle_install (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Install an extension bundle"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -60,10 +60,7 @@ list_extensions (ListFilterFlags filter, DisplayFormat format)
NULL,
&error);
if (response == NULL)
{
g_printerr (_("Failed to connect to GNOME Shell\n"));
return FALSE;
}
return FALSE;
extensions = g_variant_get_child_value (response, 0);
@@ -153,7 +150,6 @@ handle_list (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("List installed extensions"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -480,7 +480,6 @@ handle_pack (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Create an extension bundle"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -29,7 +29,9 @@ static gboolean
launch_extension_prefs (const char *uuid)
{
g_autoptr (GDBusProxy) proxy = NULL;
g_autoptr (GVariant) info = NULL;
g_autoptr (GVariant) response = NULL;
g_autoptr (GVariant) asv = NULL;
g_autoptr (GVariantDict) info = NULL;
g_autoptr (GError) error = NULL;
gboolean has_prefs;
@@ -37,16 +39,25 @@ launch_extension_prefs (const char *uuid)
if (proxy == NULL)
return FALSE;
info = get_extension_property (proxy, uuid, "hasPrefs");
if (info == NULL)
response = g_dbus_proxy_call_sync (proxy,
"GetExtensionInfo",
g_variant_new ("(s)", uuid),
0,
-1,
NULL,
&error);
if (response == NULL)
return FALSE;
has_prefs = g_variant_get_boolean (info);
asv = g_variant_get_child_value (response, 0);
info = g_variant_dict_new (asv);
if (!g_variant_dict_contains (info, "uuid"))
return FALSE;
g_variant_dict_lookup (info, "hasPrefs", "b", &has_prefs);
if (!has_prefs)
{
g_printerr (_("Extension “%s” doesn't have preferences\n"), uuid);
return FALSE;
}
return FALSE;
g_dbus_proxy_call_sync (proxy,
"OpenExtensionPrefs",
@@ -78,7 +89,6 @@ handle_prefs (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Opens extension preferences"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -1,5 +1,4 @@
/* command-reset.c
g_option_context_add_group (context, get_option_group());
*
* Copyright 2019 Florian Müllner <fmuellner@gnome.org>
*
@@ -57,7 +56,6 @@ handle_reset (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Reset an extension"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -29,27 +29,14 @@ static gboolean
uninstall_extension (const char *uuid)
{
g_autoptr (GDBusProxy) proxy = NULL;
g_autoptr (GVariant) info = NULL;
g_autoptr (GVariant) response = NULL;
g_autoptr (GError) error = NULL;
gboolean success = FALSE;
double type;
proxy = get_shell_proxy (&error);
if (proxy == NULL)
return FALSE;
info = get_extension_property (proxy, uuid, "type");
if (info == NULL)
return FALSE;
type = g_variant_get_double (info);
if (type == TYPE_SYSTEM)
{
g_printerr (_("Cannot uninstall system extensions\n"));
return FALSE;
}
response = g_dbus_proxy_call_sync (proxy,
"UninstallExtension",
g_variant_new ("(s)", uuid),
@@ -57,12 +44,11 @@ uninstall_extension (const char *uuid)
-1,
NULL,
&error);
if (response == NULL)
return FALSE;
g_variant_get (response, "(b)", &success);
if (!success)
g_printerr (_("Failed to uninstall “%s”\n"), uuid);
return success;
}
@@ -85,7 +71,6 @@ handle_uninstall (int argc, char *argv[], gboolean do_help)
g_option_context_set_help_enabled (context, FALSE);
g_option_context_set_summary (context, _("Uninstall an extension"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_add_group (context, get_option_group());
if (do_help)
{

View File

@@ -45,8 +45,6 @@ typedef enum {
DISPLAY_DETAILED
} DisplayFormat;
GOptionGroup *get_option_group (void);
void show_help (GOptionContext *context,
const char *message);
@@ -54,10 +52,6 @@ void print_extension_info (GVariantDict *info,
DisplayFormat format);
GDBusProxy *get_shell_proxy (GError **error);
GVariant *get_extension_property (GDBusProxy *proxy,
const char *uuid,
const char *property);
GSettings *get_shell_settings (void);
gboolean settings_list_add (GSettings *settings,

View File

@@ -1,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/extensions-tool">
<file>templates/00-plain.desktop</file>
<file>templates/indicator.desktop</file>
<file>templates/indicator/extension.js</file>
<file>templates/indicator/stylesheet.css</file>
<file>templates/plain/extension.js</file>
<file>templates/plain/stylesheet.css</file>
<file>template/extension.js</file>
<file>template/stylesheet.css</file>
</gresource>
</gresources>

View File

@@ -49,39 +49,6 @@ extension_state_to_string (ExtensionState state)
return "UNKNOWN";
}
static void
print_nothing (const char *message)
{
}
static gboolean
quiet_cb (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
g_set_printerr_handler (print_nothing);
return TRUE;
}
GOptionGroup *
get_option_group ()
{
GOptionEntry entries[] = {
{ .long_name = "quiet", .short_name = 'q',
.description = _("Do not print error messages"),
.arg = G_OPTION_ARG_CALLBACK, .arg_data = &quiet_cb,
.flags = G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_IN_MAIN },
{ NULL }
};
GOptionGroup *group;
group = g_option_group_new ("Common", "common options", "common options", NULL, NULL);
g_option_group_add_entries (group, entries);
return group;
}
void
show_help (GOptionContext *context, const char *message)
{
@@ -124,41 +91,6 @@ get_shell_settings (void)
return g_settings_new_full (schema, NULL, NULL);
}
GVariant *
get_extension_property (GDBusProxy *proxy,
const char *uuid,
const char *property)
{
g_autoptr (GVariant) response = NULL;
g_autoptr (GVariant) asv = NULL;
g_autoptr (GVariantDict) info = NULL;
g_autoptr (GError) error = NULL;
response = g_dbus_proxy_call_sync (proxy,
"GetExtensionInfo",
g_variant_new ("(s)", uuid),
0,
-1,
NULL,
&error);
if (response == NULL)
{
g_printerr (_("Failed to connect to GNOME Shell"));
return NULL;
}
asv = g_variant_get_child_value (response, 0);
info = g_variant_dict_new (asv);
if (!g_variant_dict_contains (info, "uuid"))
{
g_printerr (_("Extension “%s” doesn't exist\n"), uuid);
return NULL;
}
return g_variant_dict_lookup_value (info, property, NULL);
}
gboolean
settings_list_add (GSettings *settings,
const char *key,

View File

@@ -22,12 +22,9 @@ sources = [
'main.c'
]
subdir('templates')
resources = gnome.compile_resources('resources',
'gnome-extensions-tool.gresource.xml',
source_dir: ['.', meson.current_build_dir()],
dependencies: template_deps,
source_dir: '.'
)
executable('gnome-extensions',

View File

@@ -1,5 +0,0 @@
[Desktop Entry]
Type=Application
Name=Plain
Comment=An empty extension
Path=plain

View File

@@ -1,5 +0,0 @@
[Desktop Entry]
Type=Application
Name=Indicator
Comment=Add an icon to the top bar
Path=indicator

View File

@@ -1,74 +0,0 @@
/* extension.js
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/* exported init */
const GETTEXT_DOMAIN = 'my-indicator-extension';
const { GObject, St } = imports.gi;
const Gettext = imports.gettext.domain(GETTEXT_DOMAIN);
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.Button {
_init() {
super._init(0.0, _('My Shiny Indicator'));
let box = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
box.add_child(new St.Icon({
icon_name: 'face-smile-symbolic',
style_class: 'system-status-icon',
}));
box.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.add_child(box);
let item = new PopupMenu.PopupMenuItem(_('Show Notification'));
item.connect('activate', () => {
Main.notify(_('Whatʼs up, folks?'));
});
this.menu.addMenuItem(item);
}
});
class Extension {
constructor(uuid) {
this._uuid = uuid;
ExtensionUtils.initTranslations(GETTEXT_DOMAIN);
}
enable() {
this._indicator = new Indicator();
Main.panel.addToStatusArea(this._uuid, this._indicator);
}
disable() {
this._indicator.destroy();
this._indicator = null;
}
}
function init(meta) {
return new Extension(meta.uuid);
}

Some files were not shown because too many files have changed in this diff Show More