Compare commits
33 Commits
wip/mcrha/
...
gtk3-ci
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a6783692c5 | ||
![]() |
1c27b68bcc | ||
![]() |
717c05a288 | ||
![]() |
e68604b1aa | ||
![]() |
0368ad29e9 | ||
![]() |
b982ce394e | ||
![]() |
025647f585 | ||
![]() |
7125b726ad | ||
![]() |
aebfab7207 | ||
![]() |
698bd5b3a9 | ||
![]() |
51e9f19f2f | ||
![]() |
6d38a4a7b3 | ||
![]() |
dfcc5ffb1e | ||
![]() |
8b80a4cf4d | ||
![]() |
01e894c028 | ||
![]() |
856adfd1f1 | ||
![]() |
efee3aa749 | ||
![]() |
15e72da648 | ||
![]() |
3f8bd1db25 | ||
![]() |
3a863ee341 | ||
![]() |
654a7af929 | ||
![]() |
8dd9cbac7f | ||
![]() |
331db650dd | ||
![]() |
428d38179d | ||
![]() |
fe9708ebd8 | ||
![]() |
8398769321 | ||
![]() |
768c08ba9d | ||
![]() |
69426cbfda | ||
![]() |
9f968e7378 | ||
![]() |
1ab5e6973a | ||
![]() |
1dea3341ec | ||
![]() |
8fda054dc5 | ||
![]() |
e989684602 |
@@ -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:
|
||||
|
@@ -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
58
NEWS
@@ -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]
|
||||
|
@@ -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>
|
||||
|
@@ -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 {
|
||||
|
@@ -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() {
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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() {
|
||||
|
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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]) {
|
||||
|
@@ -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}`);
|
||||
|
||||
|
@@ -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 user’s
|
||||
// parental controls settings. It’s possible for the user’s parental controls
|
||||
// to change at runtime if the Parental Controls application is used by an
|
||||
// administrator from within the user’s 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 it’s 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 doesn’t say it should be hidden.
|
||||
// - The executable from the .desktop file’s Exec line isn’t blacklisted in
|
||||
// the user’s parental controls.
|
||||
// - None of the flatpak app IDs from the X-Flatpak and the
|
||||
// X-Flatpak-RenamedFrom lines are blacklisted in the user’s 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);
|
||||
}
|
||||
});
|
@@ -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 = [];
|
||||
|
||||
|
@@ -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() {
|
||||
|
@@ -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 user’s 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();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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 user’s 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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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() {
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
|
@@ -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() {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -229,7 +229,8 @@ var ExtensionManager = class {
|
||||
null,
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
null);
|
||||
null,
|
||||
(conn, res) => conn.call_finish(res));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -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(),
|
||||
});
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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");
|
||||
}
|
||||
});
|
||||
|
@@ -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() {
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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() {
|
||||
|
@@ -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
228
js/ui/tweener.js
Normal 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);
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
|
@@ -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
|
||||
|
30
meson.build
30
meson.build
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -1 +0,0 @@
|
||||
subprojects/extensions-tool/src/templates/indicator/extension.js
|
35
po/fi.po
35
po/fi.po
@@ -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"
|
||||
|
423
po/pt_BR.po
423
po/pt_BR.po
@@ -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 "Something’s gone wrong"
|
||||
msgstr "Algo deu errado"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
|
||||
#: js/extensionPrefs/js/main.js:292
|
||||
msgid ""
|
||||
"We’re very sorry, but there’s been a problem: the settings for this "
|
||||
"extension can’t 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 ""
|
||||
"We’re 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 & Install"
|
||||
msgstr "Reiniciar & instalar"
|
||||
|
||||
#: js/ui/endSessionDialog.js:100
|
||||
#: js/ui/endSessionDialog.js:98
|
||||
msgctxt "button"
|
||||
msgid "Install & Power Off"
|
||||
msgstr "Instalar & 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 "Couldn’t 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 ""
|
||||
"We’re 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…"
|
||||
|
1945
po/zh_CN.po
1945
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -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 (®istry);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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__ */
|
||||
|
@@ -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);
|
||||
|
@@ -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 ;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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',
|
||||
|
@@ -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>
|
||||
|
@@ -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(', '));
|
||||
},
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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,
|
||||
|
@@ -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>
|
||||
|
@@ -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,
|
||||
|
@@ -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',
|
||||
|
@@ -1,5 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Plain
|
||||
Comment=An empty extension
|
||||
Path=plain
|
@@ -1,5 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Indicator
|
||||
Comment=Add an icon to the top bar
|
||||
Path=indicator
|
@@ -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
Reference in New Issue
Block a user