Compare commits

..

2 Commits

Author SHA1 Message Date
Milan Crha
13ddf1eb83 calendar-server: Add 'Dismiss' button and application action
- adds 'Dismiss' button to the notification
- introduces org.gnome.Shell.CalendarServer.desktop.in.in to benefit from GNotification API

Related to https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1064
2020-03-03 15:58:13 +01:00
Milan Crha
15ab33a11a Move functionality from evolution-alarm-notify to gnome-shell-calendar-server
Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/155
2020-03-03 12:00:27 +01:00
207 changed files with 13379 additions and 20542 deletions

View File

@@ -1,13 +1,9 @@
include: 'https://gitlab.gnome.org/GNOME/citemplates/raw/master/flatpak/flatpak_ci_initiative.yml'
stages:
- review
- build
- test
- deploy
variables:
BUNDLE: "extensions-git.flatpak"
JS_LOG: "js-report.txt"
POT_LOG: "pot-update.txt"
@@ -114,24 +110,3 @@ test-pot:
' | tee $POT_LOG
- (! grep -q . $POT_LOG)
<<: *only_default
flatpak:
stage: build
variables:
SUBPROJECT: "subprojects/extensions-app"
# Your manifest path
MANIFEST_PATH: "$SUBPROJECT/build-aux/flatpak/org.gnome.Extensions.json"
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:
extends: '.publish_nightly'
variables:
BUNDLES: '$BUNDLE'

View File

@@ -23,7 +23,7 @@ run_eslint() {
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js subprojects/extensions-app/js
eslint -f unix ${!extra_args} -o $output js
}
list_commit_range_additions() {

107
NEWS
View File

@@ -1,110 +1,3 @@
3.36.2
======
* Add openPrefs() convenience method for extensions [Florian; !1163]
* Bring back support for empty StIcons [Andre, Jonas D.; !1173, !1178]
* Wake up screen when unlocking programmatically [Florian; !1158]
* Improve handling of scale-factor changes [Georges; !1176]
* Fix translations of folder names [Florian; #2623]
* Fix delay on lock screen after entering wrong password [Jonas D.; #2655]
* Match ASCII alternatives of system actions [Will; #2688]
* Tone down weekend days with events in calendar [Jakub; #2588]
* Fix area screenshots on multi-monitor systems [Jonas Å; !1224]
* Fix stuck lock screen after unlock [Jonas D., Florian; #2446]
* Fixed crashes [Jonas D., Florian, Carlos; #2584, #2625, !1223, !1218]
* Misc. bug fixes and cleanups [Jonas Å., Marco, Andre, Florian, Jonas D.;
!1155, !1156, !1169, !1168, #2551, #2563, !1172, !1179, !1160, #2562, #2578,
!1203, #2649, #2628, #2691, #1615, #2607, !1228]
Contributors:
Marco Trevisan (Treviño), Jonas Dreßler, Carlos Garnacho,
Andre Moreira Magalhaes, Florian Müllner, Georges Basile Stavracas Neto,
Jakub Steiner, Will Thompson, Jonas Ådahl
Translators:
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Danial Behzadi [fa],
Jiri Grönroos [fi], Ibai Oihanguren Sala [eu], Марко Костић [sr],
Rūdolfs Mazurs [lv], Rafael Fontenelle [pt_BR], Petr Kovář [cs],
Daniel Rusek [cs]
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]
* Fix crash on startup with topIcons* extension enabled [Florian; #2308]
* Don't require gsd-xsettings for X11 support on wayland [Olivier; !1065]
* Fix ibus support in Xorg session [Carlos; #1690]
* Improve Extensions D-Bus API [Florian; !1074]
* Allow session modes to specify alternative resource name [Marco; !1063]
* Fix link to location settings in aggregate menu [Sebastian; #2316]
* Fix illegible app folder titles with light theme [ub; !1059]
* Really fix visual glitch in sliders [Jonas; #1569]
Contributors:
Marco Trevisan (Treviño), Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Sebastian Keller, Florian Müllner, ub
Translators:
Aman Alam [pa], Goran Vidović [hr], Aurimas Černius [lt],
Milo Casagrande [it], Daniel Korostil [uk], sicklylife [ja],
Marek Černocký [cs], Nathan Follens [nl]
3.35.92
=======
* Plug a memory leak [Jonas D.; !1015]

View File

@@ -161,16 +161,12 @@ def convert_file(source_file, destination_path):
try:
xkb_name = locale_to_xkb(root["locale"], root["name"])
except KeyError as e:
logging.warning(e)
logging.warn(e)
return False
destination_file = os.path.join(destination_path, xkb_name + ".json")
try:
with open(destination_file, 'x', encoding="utf-8") as dest_fd:
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
except FileExistsError as e:
logging.info("File %s exists, not updating", destination_file)
return False
with open(destination_file, 'w', encoding="utf-8") as dest_fd:
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
logging.debug("written %s", destination_file)

View File

@@ -1,12 +1,19 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<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 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>
<signal name="EventsAdded">
<arg type="a(ssbxxa{sv})" name="events" direction="out"/>
</signal>
<signal name="EventsRemoved">
<arg type="as" name="ids" direction="out"/>
</signal>
<signal name="ClientDisappeared">
<arg type="s" name="source_uid" direction="out"/>
</signal>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>

View File

@@ -199,37 +199,14 @@
<!--
LaunchExtensionPrefs:
Deprecated for OpenExtensionPrefs
@uuid: The UUID of the extension
Launch preferences of an extension.
-->
<method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
</method>
<!--
OpenExtensionPrefs:
@uuid: The UUID of the extension
@parent_window: Identifier for the application window
@options: Vardict with further options
Opens the prefs dialog of extension @uuid.
The following @options are recognized:
<variablelist>
<varlistentry>
<term>modal b</term>
<listitem>
<para>Whether the prefs window should be modal, default: false</para>
</listitem>
</varlistentry>
</variablelist>
-->
<method name="OpenExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="in" name="parent_window"/>
<arg type="a{sv}" direction="in" name="options"/>
</method>
<!--
CheckForUpdates:
Update all extensions for which updates are available
@@ -257,11 +234,5 @@
-->
<property name="ShellVersion" type="s" access="read"/>
<!--
UserExtensionsEnabled:
Whether user extensions are enabled
-->
<property name="UserExtensionsEnabled" type="b" access="readwrite"/>
</interface>
</node>

View File

@@ -19,10 +19,6 @@ Before=gnome-session-initialized.target
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# unset some environment variables that were set by the shell and won't work now that the shell is gone
ExecStopPost=-systemctl --user unset-environment GNOME_SETUP_DISPLAY WAYLAND_DISPLAY DISPLAY XAUTHORITY
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On wayland we cannot restart

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M6.5 1.031c-.371 0-.742-.035-1.11.016-.367.05-.73.203-.972.476-.125.141-.215.309-.266.485-.047.18-.054.367-.02.55.032.184.102.356.192.516.09.164.203.309.317.457L5 4H2a1.8 1.8 0 00-.41.035.791.791 0 00-.36.195.791.791 0 00-.195.36C1 4.723 1 4.863 1 5v2.75l.77-.344c.265-.117.542-.23.832-.242.289-.016.586.074.812.254.227.18.383.441.465.723.082.277.101.57.121.859.02.316.04.637-.016.95-.058.312-.199.616-.43.831a1.264 1.264 0 01-.874.32c-.317-.007-.618-.128-.91-.257L1 10.5V14c0 .137.004.277.035.41a.791.791 0 00.195.36c.098.097.227.16.36.195.133.035.273.035.41.035h3l-.328-.68c-.14-.293-.274-.597-.29-.922-.015-.32.095-.652.31-.894.214-.242.523-.39.84-.453.316-.067.644-.059.968-.059.324 0 .652-.008.969.059.316.062.625.21.84.453.214.242.324.574.308.894-.015.325-.148.63-.289.922L8 15h3a1.8 1.8 0 00.41-.035.791.791 0 00.36-.195.791.791 0 00.195-.36C12 14.277 12 14.137 12 14v-3.563l.703.297c.29.125.59.239.902.246.313.004.63-.101.864-.308.238-.203.386-.496.46-.8C15 9.565 15 9.25 15 8.937c0-.313 0-.63-.07-.934-.075-.305-.223-.598-.461-.8a1.288 1.288 0 00-.864-.31c-.312.008-.613.122-.902.247L12 7.437V5a1.8 1.8 0 00-.035-.41.791.791 0 00-.195-.36.791.791 0 00-.36-.195C11.277 4 11.137 4 11 4H8l.36-.469c.113-.148.226-.293.316-.457.09-.16.16-.332.191-.515a1.248 1.248 0 00-.02-.551 1.256 1.256 0 00-.265-.485c-.242-.273-.605-.425-.973-.476-.367-.05-.738-.016-1.109-.016zm0 0" fill="#474747"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,6 +1,7 @@
desktop_files = [
'org.gnome.Shell.desktop',
'org.gnome.Shell.Extensions.desktop',
'org.gnome.Shell.CalendarServer.desktop',
'org.gnome.Extensions.desktop',
]
service_files = []
@@ -13,6 +14,7 @@ desktopconf = configuration_data()
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
desktopconf.set('bindir', bindir)
desktopconf.set('libexecdir', libexecdir)
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files

View File

@@ -2,9 +2,8 @@
Type=Application
Name=Extensions
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=@app_id@
Icon=org.gnome.Extensions
Comment=Configure GNOME Shell Extensions
Exec=@bindir@/@prgname@
DBusActivatable=true
Categories=GNOME;GTK;Utility;
Exec=@bindir@/gnome-shell-extension-prefs %u
Categories=GNOME;GTK;
OnlyShowIn=GNOME;

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=Clock Applet
Icon=appointment-soon
Exec=@libexecdir@/gnome-shell-calendar-server
Terminal=false
Categories=
OnlyShowIn=GNOME
NoDisplay=true

View File

@@ -1,10 +0,0 @@
[Desktop Entry]
Type=Application
# Keep in sync with subprojects/extensions-app
Name=Extensions
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Shell.Extensions
# Never launch this, just provide name+icon to portal dialog
Exec=false
OnlyShowIn=GNOME;
NoDisplay=true

View File

@@ -12,9 +12,7 @@
"w"
],
[
"e",
"é",
"ë"
"e"
],
[
"r"
@@ -23,58 +21,30 @@
"t"
],
[
"y",
"ý",
"ÿ"
"y"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
"u"
],
[
"i",
"í",
"ï"
"i"
],
[
"o",
"ó",
"ô",
"ò",
"õ",
"œ",
"ō"
"o"
],
[
"p"
],
[
"å"
]
],
[
[
"a",
"á",
"ä",
"à",
"â",
"ã",
"ā"
"a"
],
[
"s",
"ß",
"ś",
"š"
"s"
],
[
"d",
"ð"
"d"
],
[
"f"
@@ -92,16 +62,7 @@
"k"
],
[
"l",
"ł"
],
[
"ø",
"ö"
],
[
"æ",
"ä"
"l"
]
],
[
@@ -121,9 +82,7 @@
"b"
],
[
"n",
"ñ",
"ń"
"n"
],
[
"m"
@@ -162,9 +121,7 @@
"W"
],
[
"E",
"É",
"Ë"
"E"
],
[
"R"
@@ -173,58 +130,30 @@
"T"
],
[
"Y",
"Ý",
"Ÿ"
"Y"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
"U"
],
[
"I",
"Í",
"Ï"
"I"
],
[
"O",
"Ó",
"Ô",
"Ò",
"Õ",
"Œ",
"Ō"
"O"
],
[
"P"
],
[
"Å"
]
],
[
[
"A",
"Á",
"Ä",
"À",
"Â",
"Ã",
"Ā"
"A"
],
[
"S",
"SS",
"Ś",
"Š"
"S"
],
[
"D",
"Ð"
"D"
],
[
"F"
@@ -242,16 +171,7 @@
"K"
],
[
"L",
"Ł"
],
[
"Ø",
"Ö"
],
[
"Æ",
"Ä"
"L"
]
],
[
@@ -271,9 +191,7 @@
"B"
],
[
"N",
"Ñ",
"Ń"
"N"
],
[
"M"
@@ -359,10 +277,10 @@
"#"
],
[
"",
"$",
"¢",
"£",
"$",
"",
"¥",
"₱"
],
@@ -500,16 +418,15 @@
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
@@ -587,4 +504,4 @@
],
"locale": "nb",
"name": "Norwegian Bokmål"
}
}

View File

@@ -35,9 +35,9 @@ $app_grid_fg_color: #fff;
}
/* App Folders */
.app-well-app.app-folder {
background-color: transparentize($osd_bg_color, 0.8);
border-radius: $base_border_radius + 4px; // same as %icon_tile
.app-folder {
.overview-icon {
}
}
// expanded folder
@@ -60,7 +60,7 @@ $app_grid_fg_color: #fff;
& .folder-name-entry { width: 300px }
/* FIXME: this is to keep the label in sync with the entry */
& .folder-name-label { padding: 5px 7px; color: $osd_fg_color; }
& .folder-name-label { padding: 5px 7px }
& .edit-folder-button {
@extend %button;
@@ -73,6 +73,10 @@ $app_grid_fg_color: #fff;
& > StIcon { icon-size: 16px }
}
}
& StButton#vhandle,
& StButton#vhandle:hover,
& StButton#vhandle:active { background-color: transparent; }
}
.app-folder-dialog-container {
padding: 12px;

View File

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

View File

@@ -15,11 +15,13 @@
border: 1px solid transparent;
&:outlined {
background-color: transparentize($osd_fg_color, 0.7);
border: 1px solid darken($borders_color,5%);
background-color: transparentize($osd_fg_color, 0.9);
box-shadow: inset 0 2px 2px 0 rgba(0,0,0,0.4);
}
&:selected {
background-color: transparentize($osd_fg_color, 0.7);
background-color: transparentize($osd_fg_color, 0.9);
color: $osd_fg_color;
}
}

View File

@@ -1,9 +1,10 @@
#!/bin/env bash
CLDR_LAYOUTS_TARBALL="http://www.unicode.org/Public/cldr/latest/keyboards.zip"
CLDR2JSON_GIT="git://repo.or.cz/cldr2json.git"
WORKDIR=".osk-layout-workbench"
CLDR2JSON="cldr2json/cldr2json.py"
CLDR2JSON="$WORKDIR/cldr2json/cldr2json.py"
SRCDIR="$WORKDIR/keyboards/android"
DESTDIR="osk-layouts"
GRESOURCE_FILE="gnome-shell-osk-layouts.gresource.xml"
@@ -19,6 +20,7 @@ mkdir -p "osk-layouts"
# Download stuff on the work dir
pushd $WORKDIR
gio copy $CLDR_LAYOUTS_TARBALL .
git clone $CLDR2JSON_GIT
unzip keyboards.zip
popd

View File

@@ -1,5 +0,0 @@
imports.package.start({
name: '@PACKAGE_NAME@',
prefix: '@prefix@',
libdir: '@libdir@',
});

View File

@@ -1,3 +0,0 @@
[D-BUS Service]
Name=@service@
Exec=@gjs@ @pkgdatadir@/@service@

View File

@@ -1,177 +0,0 @@
/* exported DBusService, ServiceImplementation */
const { Gio, GLib } = imports.gi;
const Signals = imports.signals;
const IDLE_SHUTDOWN_TIME = 2; // s
var ServiceImplementation = class {
constructor(info, objectPath) {
this._objectPath = objectPath;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(info, this);
this._injectTracking('return_dbus_error');
this._injectTracking('return_error_literal');
this._injectTracking('return_gerror');
this._injectTracking('return_value');
this._injectTracking('return_value_with_unix_fd_list');
this._senders = new Map();
this._holdCount = 0;
this._hasSignals = this._dbusImpl.get_info().signals.length > 0;
this._shutdownTimeoutId = 0;
// subclasses may override this to disable automatic shutdown
this._autoShutdown = true;
}
// subclasses may override this to own additional names
register() {
}
export() {
this._dbusImpl.export(Gio.DBus.session, this._objectPath);
}
unexport() {
this._dbusImpl.unexport();
}
hold() {
this._holdCount++;
}
release() {
if (this._holdCount === 0) {
logError(new Error('Unmatched call to release()'));
return;
}
this._holdCount--;
if (this._holdCount === 0)
this._queueShutdownCheck();
}
/**
* _handleError:
* @param {Gio.DBusMethodInvocation}
* @param {Error}
*
* Complete @invocation with an appropriate error if @error is set;
* useful for implementing early returns from method implementations.
*
* @returns {bool} - true if @invocation was completed
*/
_handleError(invocation, error) {
if (error === null)
return false;
if (error instanceof GLib.Error) {
invocation.return_gerror(error);
} else {
let name = error.name;
if (!name.includes('.')) // likely a normal JS error
name = `org.gnome.gjs.JSError.${name}`;
invocation.return_dbus_error(name, error.message);
}
return true;
}
_maybeShutdown() {
if (!this._autoShutdown)
return;
if (this._holdCount > 0)
return;
this.emit('shutdown');
}
_queueShutdownCheck() {
if (this._shutdownTimeoutId)
GLib.source_remove(this._shutdownTimeoutId);
this._shutdownTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT, IDLE_SHUTDOWN_TIME,
() => {
this._shutdownTimeoutId = 0;
this._maybeShutdown();
return GLib.SOURCE_REMOVE;
});
}
_trackSender(sender) {
if (this._senders.has(sender))
return;
this.hold();
this._senders.set(sender,
this._dbusImpl.get_connection().watch_name(
sender,
Gio.BusNameWatcherFlags.NONE,
null,
() => this._untrackSender(sender)));
}
_untrackSender(sender) {
const id = this._senders.get(sender);
if (id)
this._dbusImpl.get_connection().unwatch_name(id);
if (this._senders.delete(sender))
this.release();
}
_injectTracking(methodName) {
const { prototype } = Gio.DBusMethodInvocation;
const origMethod = prototype[methodName];
const that = this;
prototype[methodName] = function (...args) {
origMethod.apply(this, args);
if (that._hasSignals)
that._trackSender(this.get_sender());
that._queueShutdownCheck();
};
}
};
Signals.addSignalMethods(ServiceImplementation.prototype);
var DBusService = class {
constructor(name, service) {
this._name = name;
this._service = service;
this._loop = new GLib.MainLoop(null, false);
this._service.connect('shutdown', () => this._loop.quit());
}
run() {
// Bail out when not running under gnome-shell
Gio.DBus.watch_name(Gio.BusType.SESSION,
'org.gnome.Shell',
Gio.BusNameWatcherFlags.NONE,
null,
() => this._loop.quit());
this._service.register();
Gio.DBus.own_name(Gio.BusType.SESSION,
this._name,
Gio.BusNameOwnerFlags.REPLACE,
() => this._service.export(),
null,
() => this._loop.quit());
this._loop.run();
}
};

View File

@@ -1,2 +0,0 @@
.expander-frame > * { border-top-width: 0; }
.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; }

View File

@@ -1,274 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionsService */
const { Gdk, Gio, GLib, GObject, Gtk, Shew } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ServiceImplementation } = imports.dbusService;
const ExtensionsIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const ExtensionsProxy = Gio.DBusProxy.makeProxyWrapper(ExtensionsIface);
var ExtensionsService = class extends ServiceImplementation {
constructor() {
super(ExtensionsIface, '/org/gnome/Shell/Extensions');
this._proxy = new ExtensionsProxy(Gio.DBus.session,
'org.gnome.Shell', '/org/gnome/Shell');
this._proxy.connectSignal('ExtensionStateChanged',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('ExtensionStateChanged',
new GLib.Variant('(sa{sv})', params));
});
this._proxy.connect('g-properties-changed', () => {
this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
new GLib.Variant('b', this._proxy.UserExtensionsEnabled));
});
}
get ShellVersion() {
return this._proxy.ShellVersion;
}
get UserExtensionsEnabled() {
return this._proxy.UserExtensionsEnabled;
}
set UserExtensionsEnabled(enable) {
this._proxy.UserExtensionsEnabled = enable;
}
ListExtensionsAsync(params, invocation) {
this._proxy.ListExtensionsRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(a{sa{sv}})', res));
});
}
GetExtensionInfoAsync(params, invocation) {
this._proxy.GetExtensionInfoRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(a{sv})', res));
});
}
GetExtensionErrorsAsync(params, invocation) {
this._proxy.GetExtensionErrorsRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(as)', res));
});
}
InstallRemoteExtensionAsync(params, invocation) {
this._proxy.InstallRemoteExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(s)', res));
});
}
UninstallExtensionAsync(params, invocation) {
this._proxy.UninstallExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
EnableExtensionAsync(params, invocation) {
this._proxy.EnableExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
DisableExtensionAsync(params, invocation) {
this._proxy.DisableExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
LaunchExtensionPrefsAsync([uuid], invocation) {
this.OpenExtensionPrefsAsync([uuid, '', {}], invocation);
}
OpenExtensionPrefsAsync(params, invocation) {
const [uuid, parentWindow, options] = params;
this._proxy.GetExtensionInfoRemote(uuid, (res, error) => {
if (this._handleError(invocation, error))
return;
const [serialized] = res;
const extension = ExtensionUtils.deserializeExtension(serialized);
const window = new ExtensionPrefsDialog(extension);
window.realize();
let externalWindow = null;
if (parentWindow)
externalWindow = Shew.ExternalWindow.new_from_handle(parentWindow);
if (externalWindow)
externalWindow.set_parent_of(window.window);
if (options.modal)
window.modal = options.modal.get_boolean();
window.connect('destroy', () => this.release());
this.hold();
window.show();
invocation.return_value(null);
});
}
CheckForUpdatesAsync(params, invocation) {
this._proxy.CheckForUpdatesRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(null);
});
}
};
var ExtensionPrefsDialog = GObject.registerClass({
GTypeName: 'ExtensionPrefsDialog',
Template: 'resource:///org/gnome/Shell/Extensions/ui/extension-prefs-dialog.ui',
InternalChildren: [
'headerBar',
'stack',
'expander',
'expanderArrow',
'revealer',
'errorView',
],
}, class ExtensionPrefsDialog extends Gtk.Window {
_init(extension) {
super._init();
this._uuid = extension.uuid;
this._url = extension.metadata.url || '';
this._headerBar.title = extension.metadata.name;
this._actionGroup = new Gio.SimpleActionGroup();
this.insert_action_group('win', this._actionGroup);
this._initActions();
this._addCustomStylesheet();
this._gesture = new Gtk.GestureMultiPress({
widget: this._expander,
button: 0,
exclusive: true,
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress === 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
this._expanderArrow.icon_name = this._revealer.reveal_child
? 'pan-down-symbolic'
: 'pan-end-symbolic';
});
try {
ExtensionUtils.installImporter(extension);
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => extension;
const prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
const widget = prefsModule.buildPrefsWidget();
this._stack.add(widget);
this._stack.visible_child = widget;
} catch (e) {
this._setError(e);
}
}
_setError(exc) {
this._errorView.buffer.text = `${exc}\n\nStack trace:\n`;
// Indent stack trace.
this._errorView.buffer.text +=
exc.stack.split('\n').map(line => ` ${line}`).join('\n');
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${this._uuid} had an error:`,
'```',
`${exc}`,
'```',
'',
'Stack trace:',
'```',
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```',
'',
];
this._errorMarkdown = lines.join('\n');
this._actionGroup.lookup('copy-error').enabled = true;
}
_initActions() {
let action;
action = new Gio.SimpleAction({
name: 'copy-error',
enabled: false,
});
action.connect('activate', () => {
const clipboard = Gtk.Clipboard.get_default(this.get_display());
clipboard.set_text(this._errorMarkdown, -1);
});
this._actionGroup.add_action(action);
action = new Gio.SimpleAction({
name: 'show-url',
enabled: this._url !== '',
});
action.connect('activate', () => {
Gio.AppInfo.launch_default_for_uri(this._url,
this.get_display().get_app_launch_context());
});
this._actionGroup.add_action(action);
}
_addCustomStylesheet() {
let provider = new Gtk.CssProvider();
let uri = 'resource:///org/gnome/Shell/Extensions/css/application.css';
try {
provider.load_from_file(Gio.File.new_for_uri(uri));
} catch (e) {
logError(e, 'Failed to add application style');
}
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
}
});

View File

@@ -1,20 +0,0 @@
/* exported main */
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const { Gtk } = imports.gi;
const pkg = imports.package;
const { DBusService } = imports.dbusService;
const { ExtensionsService } = imports.extensionsService;
function main() {
Gtk.init(null);
pkg.initFormat();
const service = new DBusService(
'org.gnome.Shell.Extensions',
new ExtensionsService());
service.run();
}

View File

@@ -1,197 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="ExtensionPrefsDialog" parent="GtkWindow">
<property name="default_width">600</property>
<property name="default_height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerBar">
<property name="visible">True</property>
<property name="show_close_button">True</property>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="hscrollbar_policy">never</property>
<property name="propagate_natural_height">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="margin">100</property>
<property name="margin_bottom">60</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Somethings gone wrong</property>
<attributes>
<attribute name="scale" value="1.44"/> <!-- x-large -->
</attributes>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors.</property>
<property name="justify">center</property>
<property name="wrap">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="margin_top">12</property>
<child>
<object class="GtkFrame" id="expander">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkEventBox">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="margin">12</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage" id="expanderArrow">
<property name="visible">True</property>
<property name="icon_name">pan-end-symbolic</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Technical Details</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkRevealer" id="revealer">
<property name="visible">True</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="shadow_type">in</property>
<style>
<class name="expander-frame"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTextView" id="errorView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="monospace">True</property>
<property name="editable">False</property>
<property name="wrap_mode">word</property>
<property name="left_margin">12</property>
<property name="right_margin">12</property>
<property name="top_margin">12</property>
<property name="bottom_margin">12</property>
</object>
</child>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<style>
<class name="expander-toolbar"/>
</style>
<child>
<object class="GtkToolItem">
<property name="visible">True</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">win.copy-error</property>
<style>
<class name="flat"/>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">edit-copy-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparatorToolItem">
<property name="visible">True</property>
<property name="draw">False</property>
</object>
<packing>
<property name="expand">True</property>
</packing>
</child>
<child>
<object class="GtkToolItem">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="homeButton">
<property name="visible"
bind-source="homeButton"
bind-property="sensitive"
bind-flags="sync-create"/>
<property name="label" translatable="yes">Homepage</property>
<property name="tooltip_text" translatable="yes">Visit extension homepage</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="action_name">win.show-url</property>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,42 +0,0 @@
launcherconf = configuration_data()
launcherconf.set('PACKAGE_NAME', meson.project_name())
launcherconf.set('prefix', prefix)
launcherconf.set('libdir', libdir)
dbus_services = {
'org.gnome.Shell.Extensions': 'extensions',
'org.gnome.Shell.Notifications': 'notifications',
}
config_dir = '@0@/..'.format(meson.current_build_dir())
foreach service, dir : dbus_services
configure_file(
input: 'dbus-service.in',
output: service,
configuration: launcherconf,
install_dir: pkgdatadir,
)
serviceconf = configuration_data()
serviceconf.set('service', service)
serviceconf.set('gjs', gjs.path())
serviceconf.set('pkgdatadir', pkgdatadir)
configure_file(
input: 'dbus-service.service.in',
output: service + '.service',
configuration: serviceconf,
install_dir: servicedir
)
gnome.compile_resources(
service + '.src',
service + '.src.gresource.xml',
dependencies: [config_js],
source_dir: ['.', '..', dir, config_dir],
gresource_bundle: true,
install: true,
install_dir: pkgdatadir
)
endforeach

View File

@@ -1,11 +0,0 @@
/* exported main */
const { DBusService } = imports.dbusService;
const { NotificationDaemon } = imports.notificationDaemon;
function main() {
const service = new DBusService(
'org.gnome.Shell.Notifications',
new NotificationDaemon());
service.run();
}

View File

@@ -1,80 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { Gio, GLib } = imports.gi;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ServiceImplementation } = imports.dbusService;
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
var NotificationDaemon = class extends ServiceImplementation {
constructor() {
super(NotificationsIface, '/org/freedesktop/Notifications');
this._autoShutdown = false;
this._proxy = new NotificationsProxy(Gio.DBus.session,
'org.gnome.Shell',
'/org/freedesktop/Notifications',
(proxy, error) => {
if (error)
log(error.message);
});
this._proxy.connectSignal('ActionInvoked',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('ActionInvoked',
new GLib.Variant('(us)', params));
});
this._proxy.connectSignal('NotificationClosed',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('NotificationClosed',
new GLib.Variant('(uu)', params));
});
}
register() {
Gio.DBus.session.own_name(
'org.freedesktop.Notifications',
Gio.BusNameOwnerFlags.REPLACE,
null, null);
}
NotifyAsync(params, invocation) {
this._proxy.NotifyRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(u)', res));
});
}
CloseNotificationAsync(params, invocation) {
this._proxy.CloseNotificationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(null);
});
}
GetCapabilitiesAsync(params, invocation) {
this._proxy.GetCapabilitiesRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(as)', res));
});
}
GetServerInformationAsync(params, invocation) {
this._proxy.GetServerInformationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(ssss)', res));
});
}
};

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Shell/Extensions/js">
<file>main.js</file>
<file>extensionsService.js</file>
<file>dbusService.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource>
<gresource prefix="/org/gnome/Shell/Extensions">
<file>css/application.css</file>
<file>ui/extension-prefs-dialog.ui</file>
</gresource>
</gresources>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Shell/Notifications/js">
<file>main.js</file>
<file>notificationDaemon.js</file>
<file>dbusService.js</file>
<file>misc/config.js</file>
<file>misc/fileUtils.js</file>
</gresource>
</gresources>

View File

@@ -3,44 +3,34 @@ imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext;
const Package = imports.package;
const { Gdk, GLib, Gio, GObject, Gtk, Shew } = imports.gi;
const { Gdk, GLib, Gio, GObject, Gtk } = imports.gi;
const Format = imports.format;
Package.initFormat();
const _ = Gettext.gettext;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState, ExtensionType } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
Gio._promisify(Shew.WindowExporter.prototype, 'export', 'export_finish');
function loadInterfaceXML(iface) {
const uri = 'resource:///org/gnome/Extensions/dbus-interfaces/%s.xml'.format(iface);
const f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
return imports.byteArray.toString(bytes);
} catch (e) {
log('Failed to load D-Bus interface %s'.format(iface));
}
return null;
}
function toggleState(action) {
let state = action.get_state();
action.change_state(new GLib.Variant('b', !state.get_boolean()));
function stripPrefix(string, prefix) {
if (string.slice(0, prefix.length) == prefix)
return string.slice(prefix.length);
return string;
}
var Application = GObject.registerClass(
class Application extends Gtk.Application {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs');
super._init({ application_id: 'org.gnome.Extensions' });
super._init({
application_id: 'org.gnome.Extensions',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
});
}
get shellProxy() {
@@ -56,7 +46,7 @@ class Application extends Gtk.Application {
super.vfunc_startup();
let provider = new Gtk.CssProvider();
let uri = 'resource:///org/gnome/Extensions/css/application.css';
let uri = 'resource:///org/gnome/shell/css/application.css';
try {
provider.load_from_file(Gio.File.new_for_uri(uri));
} catch (e) {
@@ -66,19 +56,34 @@ class Application extends Gtk.Application {
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session,
'org.gnome.Shell.Extensions', '/org/gnome/Shell/Extensions');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._window = new ExtensionsWindow({ application: this });
}
vfunc_command_line(commandLine) {
let args = commandLine.get_arguments();
if (args.length) {
let uuid = args[0];
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, 'extension:///');
this._window.openPrefs(uuid);
} else {
this.activate();
}
return 0;
}
});
var ExtensionsWindow = GObject.registerClass({
GTypeName: 'ExtensionsWindow',
Template: 'resource:///org/gnome/Extensions/ui/extensions-window.ui',
Template: 'resource:///org/gnome/shell/ui/extensions-window.ui',
InternalChildren: [
'userList',
'systemList',
'killSwitch',
'mainBox',
'mainStack',
'scrolledWindow',
@@ -89,11 +94,11 @@ var ExtensionsWindow = GObject.registerClass({
_init(params) {
super._init(params);
this._startupUuid = null;
this._loaded = false;
this._prefsDialog = null;
this._updatesCheckId = 0;
this._exporter = new Shew.WindowExporter({ window: this });
this._exportedHandle = '';
this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment);
let action;
@@ -105,15 +110,10 @@ var ExtensionsWindow = GObject.registerClass({
action.connect('activate', this._logout.bind(this));
this.add_action(action);
action = new Gio.SimpleAction({
name: 'user-extensions-enabled',
state: new GLib.Variant('b', false),
});
action.connect('activate', toggleState);
action.connect('change-state', (a, state) => {
this._shellProxy.UserExtensionsEnabled = state.get_boolean();
});
this.add_action(action);
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.bind('disable-user-extensions',
this._killSwitch, 'active',
Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._userList.set_sort_func(this._sortList.bind(this));
this._userList.set_header_func(this._updateHeader.bind(this));
@@ -124,10 +124,6 @@ var ExtensionsWindow = GObject.registerClass({
this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this));
this._shellProxy.connect('g-properties-changed',
this._onUserExtensionsEnabledChanged.bind(this));
this._onUserExtensionsEnabledChanged();
this._scanExtensions();
}
@@ -157,18 +153,58 @@ var ExtensionsWindow = GObject.registerClass({
dialog.present();
}
async openPrefs(uuid) {
if (!this._exportedHandle) {
try {
this._exportedHandle = await this._exporter.export();
} catch (e) {
log('Failed to export window: %s'.format(e.message));
}
openPrefs(uuid) {
if (!this._loaded)
this._startupUuid = uuid;
else if (!this._showPrefs(uuid))
this.present();
}
_showPrefs(uuid) {
if (this._prefsDialog)
return false;
let row = this._findExtensionRow(uuid);
if (!row || !row.hasPrefs)
return false;
let widget;
try {
widget = row.prefsModule.buildPrefsWidget();
} catch (e) {
widget = this._buildErrorUI(row, e);
}
this._shellProxy.OpenExtensionPrefsRemote(uuid,
this._exportedHandle,
{ modal: new GLib.Variant('b', true) });
this._prefsDialog = new Gtk.Window({
application: this.application,
default_width: 600,
default_height: 400,
modal: this.visible,
type_hint: Gdk.WindowTypeHint.DIALOG,
window_position: Gtk.WindowPosition.CENTER,
});
this._prefsDialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true,
}));
if (this.visible)
this._prefsDialog.transient_for = this;
this._prefsDialog.connect('destroy', () => {
this._prefsDialog = null;
if (!this.visible)
this.destroy();
});
this._prefsDialog.add(widget);
this._prefsDialog.show();
return true;
}
_showAbout() {
@@ -183,7 +219,7 @@ var ExtensionsWindow = GObject.registerClass({
comments: _('Manage your GNOME Extensions'),
license_type: Gtk.License.GPL_2_0,
logo_icon_name: 'org.gnome.Extensions',
version: imports.package.version,
version: Config.PACKAGE_VERSION,
transient_for: this,
modal: true,
@@ -207,6 +243,121 @@ var ExtensionsWindow = GObject.registerClass({
});
}
_buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true,
});
let box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
});
scroll.add(box);
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(_("Somethings gone wrong")),
use_markup: true,
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
box.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors."),
justify: Gtk.Justification.CENTER,
wrap: true,
});
box.add(label);
let expander = new Expander({
label: _("Technical Details"),
margin_top: 12,
});
box.add(expander);
let errortext = '%s\n\nStack trace:\n'.format(exc);
// Indent stack trace.
errortext +=
exc.stack.split('\n').map(line => ' %s'.format(line)).join('\n');
let buffer = new Gtk.TextBuffer({ text: errortext });
let textview = new Gtk.TextView({
buffer,
wrap_mode: Gtk.WrapMode.WORD,
monospace: true,
editable: false,
top_margin: 12,
bottom_margin: 12,
left_margin: 12,
right_margin: 12,
});
let toolbar = new Gtk.Toolbar();
let provider = new Gtk.CssProvider();
provider.load_from_data(`* {
border: 0 solid @borders;
border-top-width: 1px;
}`);
toolbar.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
let copyButton = new Gtk.ToolButton({
icon_name: 'edit-copy-symbolic',
tooltip_text: _("Copy Error"),
});
toolbar.add(copyButton);
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues
let lines = [
'The settings of extension %s had an error:'.format(row.uuid),
'```', // '`' (xgettext throws up on odd number of backticks)
exc.toString(),
'```', // '`'
'',
'Stack trace:',
'```', // '`'
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```', // '`'
'',
];
clipboard.set_text(lines.join('\n'), -1);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
toolbar.add(spacing);
toolbar.child_set_property(spacing, "expand", true);
let urlButton = new Gtk.ToolButton({
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: row.url !== '',
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(row.url, context);
});
let expandedBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
});
expandedBox.add(textview);
expandedBox.add(toolbar);
expander.add(expandedBox);
scroll.show_all();
return scroll;
}
_sortList(row1, row2) {
return row1.name.localeCompare(row2.name);
}
@@ -226,12 +377,6 @@ var ExtensionsWindow = GObject.registerClass({
].find(c => c.uuid === uuid);
}
_onUserExtensionsEnabledChanged() {
let action = this.lookup_action('user-extensions-enabled');
action.set_state(
new GLib.Variant('b', this._shellProxy.UserExtensionsEnabled));
}
_onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let extension = ExtensionUtils.deserializeExtension(newState);
let row = this._findExtensionRow(uuid);
@@ -249,11 +394,9 @@ var ExtensionsWindow = GObject.registerClass({
if (row) {
if (extension.state === ExtensionState.UNINSTALLED)
row.destroy();
} else {
this._addExtensionRow(extension);
return; // we only deal with new and deleted extensions here
}
this._syncListVisibility();
this._addExtensionRow(extension);
}
_scanExtensions() {
@@ -299,16 +442,6 @@ var ExtensionsWindow = GObject.registerClass({
});
}
_syncListVisibility() {
this._userList.visible = this._userList.get_children().length > 0;
this._systemList.visible = this._systemList.get_children().length > 0;
if (this._userList.visible || this._systemList.visible)
this._mainStack.visible_child_name = 'main';
else
this._mainStack.visible_child_name = 'placeholder';
}
_checkUpdates() {
let nUpdates = this._userList.get_children().filter(c => c.hasUpdate).length;
@@ -320,14 +453,125 @@ var ExtensionsWindow = GObject.registerClass({
}
_extensionsLoaded() {
this._syncListVisibility();
this._userList.visible = this._userList.get_children().length > 0;
this._systemList.visible = this._systemList.get_children().length > 0;
if (this._userList.visible || this._systemList.visible)
this._mainStack.visible_child_name = 'main';
else
this._mainStack.visible_child_name = 'placeholder';
this._checkUpdates();
if (this._startupUuid)
this._showPrefs(this._startupUuid);
this._startupUuid = null;
this._loaded = true;
}
});
var Expander = GObject.registerClass({
Properties: {
'label': GObject.ParamSpec.string(
'label', 'label', 'label',
GObject.ParamFlags.READWRITE,
null
),
},
}, class Expander extends Gtk.Box {
_init(params = {}) {
this._labelText = null;
super._init(Object.assign(params, {
orientation: Gtk.Orientation.VERTICAL,
spacing: 0,
}));
this._frame = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
hexpand: true,
});
let eventBox = new Gtk.EventBox();
this._frame.add(eventBox);
let hbox = new Gtk.Box({
spacing: 6,
margin: 12,
});
eventBox.add(hbox);
this._arrow = new Gtk.Image({
icon_name: 'pan-end-symbolic',
});
hbox.add(this._arrow);
this._label = new Gtk.Label({ label: this._labelText });
hbox.add(this._label);
this._revealer = new Gtk.Revealer();
this._childBin = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
});
this._revealer.add(this._childBin);
// Directly chain up to parent for internal children
super.add(this._frame);
super.add(this._revealer);
let provider = new Gtk.CssProvider();
provider.load_from_data('* { border-top-width: 0; }');
this._childBin.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
this._gesture = new Gtk.GestureMultiPress({
widget: this._frame,
button: 0,
exclusive: true,
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress == 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
if (this._revealer.reveal_child)
this._arrow.icon_name = 'pan-down-symbolic';
else
this._arrow.icon_name = 'pan-end-symbolic';
});
}
get label() {
return this._labelText;
}
set label(text) {
if (this._labelText == text)
return;
if (this._label)
this._label.label = text;
this._labelText = text;
this.notify('label');
}
add(child) {
// set expanded child
this._childBin.get_children().forEach(c => {
this._childBin.remove(c);
});
if (child)
this._childBin.add(child);
}
});
var ExtensionRow = GObject.registerClass({
GTypeName: 'ExtensionRow',
Template: 'resource:///org/gnome/Extensions/ui/extension-row.ui',
Template: 'resource:///org/gnome/shell/ui/extension-row.ui',
InternalChildren: [
'nameLabel',
'descriptionLabel',
@@ -377,7 +621,10 @@ var ExtensionRow = GObject.registerClass({
name: 'enabled',
state: new GLib.Variant('b', false),
});
action.connect('activate', toggleState);
action.connect('activate', () => {
let state = action.get_state();
action.change_state(new GLib.Variant('b', !state.get_boolean()));
});
action.connect('change-state', (a, state) => {
if (state.get_boolean())
this._app.shellProxy.EnableExtensionRemote(this.uuid);
@@ -386,7 +633,8 @@ var ExtensionRow = GObject.registerClass({
});
this._actionGroup.add_action(action);
this._nameLabel.label = this.name;
let name = GLib.markup_escape_text(this.name, -1);
this._nameLabel.label = name;
let desc = this._extension.metadata.description.split('\n')[0];
this._descriptionLabel.label = desc;
@@ -474,6 +722,20 @@ var ExtensionRow = GObject.registerClass({
_canToggle() {
return this._extension.canChange;
}
get prefsModule() {
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
return this._prefsModule;
}
});
function initEnvironment() {
@@ -490,11 +752,12 @@ function initEnvironment() {
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']),
};
String.prototype.format = Format.format;
}
function main(argv) {
initEnvironment();
Package.initGettext();
new Application().run(argv);
}

View File

@@ -90,10 +90,8 @@
</packing>
</child>
<child>
<object class="GtkSwitch">
<object class="GtkSwitch" id="killSwitch">
<property name="visible">True</property>
<property name="action-name">win.user-extensions-enabled</property>
<property name="valign">center</property>
</object>
<packing>
<property name="pack_type">end</property>

View File

@@ -120,7 +120,7 @@ var AuthPrompt = GObject.registerClass({
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
_initEntryRow() {
@@ -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,8 @@ var AuthPrompt = GObject.registerClass({
}
updateSensitivity(sensitive) {
if (this._entry.reactive === sensitive)
return;
this._entry.reactive = sensitive;
if (sensitive)
this._entry.grab_key_focus();
this._entry.clutter_text.editable = sensitive;
}
vfunc_hide() {

View File

@@ -35,6 +35,7 @@ const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
var UserListItem = GObject.registerClass({
Signals: { 'activate': {} },
@@ -177,7 +178,6 @@ var UserList = GObject.registerClass({
}
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._moveFocusToItems();
}
@@ -813,7 +813,7 @@ var LoginDialog = GObject.registerClass({
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,
-1, _LOGO_ICON_HEIGHT,
scaleFactor,
this._logoBin.resource_scale));
}

View File

@@ -1,5 +1,4 @@
subdir('misc')
subdir('dbusServices')
js_resources = gnome.compile_resources(
'js-resources', 'js-resources.gresource.xml',
@@ -14,3 +13,10 @@ portal_resources = gnome.compile_resources(
c_name: 'portal_js_resources',
dependencies: [config_js]
)
prefs_resources = gnome.compile_resources(
'prefs-resources', 'prefs-resources.gresource.xml',
source_dir: ['.', meson.current_build_dir()],
c_name: 'prefs_js_resources',
dependencies: [config_js]
)

View File

@@ -15,5 +15,6 @@ var LOCALEDIR = '@datadir@/locale';
/* other standard directories */
var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
var VPNDIR = '@vpndir@';
/* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, openPrefs, isOutOfDate,
installImporter, serializeExtension, deserializeExtension */
getSettings, initTranslations, isOutOfDate, installImporter,
serializeExtension, deserializeExtension */
// Common utils for the extension system and the extension
// preferences tool
@@ -153,27 +153,6 @@ function getSettings(schema) {
return new Gio.Settings({ settings_schema: schemaObj });
}
/**
* openPrefs:
*
* Open the preference dialog of the current extension
*/
function openPrefs() {
const extension = getCurrentExtension();
if (!extension)
throw new Error('openPrefs() can only be called from extensions');
try {
const extensionManager = imports.ui.main.extensionManager;
extensionManager.openExtensionPrefs(extension.uuid, '', {});
} catch (e) {
if (e.name === 'ImportError')
throw new Error('openPrefs() cannot be called from preferences');
logError(e, 'Failed to open extension preferences');
}
}
/**
* versionCheck:
* @param {string[]} required - an array of versions we're compatible with

View File

@@ -76,15 +76,19 @@ function loadInterfaceXML(iface) {
_ifaceResource._register();
}
let xml = null;
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
let f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
return imports.byteArray.toString(bytes);
if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes);
else
xml = bytes.toString();
} catch (e) {
log(`Failed to load D-Bus interface ${iface}`);
}
return null;
return xml;
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus, Meta } = imports.gi;
const { Gio, GLib, IBus } = imports.gi;
const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@@ -55,7 +55,7 @@ var IBusManager = class {
this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn(Meta.is_wayland_compositor() ? [] : ['--xim']);
this._spawn();
}
_spawn(extraArgs = []) {
@@ -66,7 +66,7 @@ var IBusManager = class {
let display = GLib.getenv('GNOME_SETUP_DISPLAY');
if (display)
launcher.setenv('DISPLAY', display, true);
launcher.spawnv(cmdLine);
launcher.launch(cmdLine);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
}
@@ -127,55 +127,56 @@ var IBusManager = class {
}
_initPanelService(ibus, result) {
let success = false;
try {
this._ibus.request_name_async_finish(result);
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
this._clear();
}
return;
}
this._panelService = new IBus.PanelService({
connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL,
});
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
let cursorLocation = { x, y, width: w, height: h };
this.emit('set-cursor-location', cursorLocation);
});
this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
// 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) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
let cursorLocation = { x, y, width: w, height: h };
this.emit('set-cursor-location', cursorLocation);
});
this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
this._engineChanged(this._ibus, engine.get_name());
});
this._updateReadiness();
// 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();
} else {
this._clear();
}
}
_updateReadiness() {

View File

@@ -97,13 +97,8 @@ class InputMethod extends Clutter.InputMethod {
this.commit(text.get_text());
}
_onDeleteSurroundingText(_context, offset, nchars) {
try {
this.delete_surrounding(offset, nchars);
} catch (e) {
// We may get out of bounds for negative offset on older mutter
this.delete_surrounding(0, nchars + offset);
}
_onDeleteSurroundingText() {
this.delete_surrounding();
}
_onUpdatePreeditText(_context, text, pos, visible) {

View File

@@ -7,6 +7,7 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file(
input: 'config.js.in',

View File

@@ -223,7 +223,7 @@ var BroadbandModem = GObject.registerClass({
}, class BroadbandModem extends ModemBase {
_init(path, capabilities) {
super._init({ capabilities });
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
@@ -249,7 +249,7 @@ var BroadbandModem = GObject.registerClass({
}
_reloadSignalQuality() {
let [quality, recent_] = this._proxy.SignalQuality;
let [quality, recent_] = this.SignalQuality;
this._setSignalQuality(quality);
}

View File

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

View File

@@ -5,5 +5,6 @@
<file>misc/config.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
<file alias="css/application.css">extensionPrefs/css/application.css</file>
<file alias="ui/extension-row.ui">extensionPrefs/ui/extension-row.ui</file>
<file alias="ui/extensions-window.ui">extensionPrefs/ui/extensions-window.ui</file>
</gresource>
</gresources>

View File

@@ -1060,25 +1060,25 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node();
let contentBox = themeNode.get_content_box(box);
const labelHeight = this._label.height;
const totalLabelHeight =
labelHeight + themeNode.get_padding(St.Side.BOTTOM);
box.y2 -= totalLabelHeight;
super.vfunc_allocate(box, flags);
let childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;
childBox.y2 = box.y2 - totalLabelHeight;
super.vfunc_allocate(childBox, flags);
// Hooking up the parent vfunc will call this.set_allocation() with
// the height without the label height, so call it again with the
// correct size here.
box.y2 += totalLabelHeight;
this.set_allocation(box, flags);
const childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - labelHeight;
this._label.allocate(childBox, flags);
}
highlight(index, justOutline) {

View File

@@ -15,7 +15,8 @@ class Animation extends St.Bin {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
super._init({
style: `width: ${width}px; height: ${height}px;`,
width: width * themeContext.scale_factor,
height: height * themeContext.scale_factor,
});
this.connect('destroy', this._onDestroy.bind(this));

View File

@@ -71,9 +71,15 @@ function _getFolderName(folder) {
let name = folder.get_string('name');
if (folder.get_boolean('translate')) {
let translated = Shell.util_get_translated_folder_name(name);
if (translated !== null)
return translated;
let keyfile = new GLib.KeyFile();
let path = 'desktop-directories/%s'.format(name);
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch (e) {
return name;
}
}
return name;
@@ -114,10 +120,15 @@ function _findBestFolderName(apps) {
}, commonCategories);
for (let category of commonCategories) {
const directory = '%s.directory'.format(category);
const translated = Shell.util_get_translated_folder_name(directory);
if (translated !== null)
return translated;
let keyfile = new GLib.KeyFile();
let path = 'desktop-directories/%s.directory'.format(category);
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
return keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch (e) {
continue;
}
}
return null;
@@ -158,10 +169,6 @@ var BaseAppView = GObject.registerClass({
this._items = new Map();
this._orderedItems = [];
this._animateLaterId = 0;
this._viewLoadedHandlerId = 0;
this._viewIsReady = false;
}
_childFocused(_actor) {
@@ -197,7 +204,6 @@ var BaseAppView = GObject.registerClass({
this._items.set(icon.id, icon);
});
this._viewIsReady = true;
this.emit('view-loaded');
}
@@ -247,18 +253,6 @@ var BaseAppView = GObject.registerClass({
Main.overview.dash.showAppsButton);
}
_clearAnimateLater() {
if (this._animateLaterId) {
Meta.later_remove(this._animateLaterId);
this._animateLaterId = 0;
}
if (this._viewLoadedHandlerId) {
this.disconnect(this._viewLoadedHandlerId);
this._viewLoadedHandlerId = 0;
}
this._grid.opacity = 255;
}
animate(animationDirection, onComplete) {
if (onComplete) {
let animationDoneId = this._grid.connect('animation-done', () => {
@@ -267,38 +261,16 @@ var BaseAppView = GObject.registerClass({
});
}
this._clearAnimateLater();
if (animationDirection == IconGrid.AnimationDirection.IN) {
const doSpringAnimationLater = laterType => {
this._animateLaterId = Meta.later_add(laterType,
() => {
this._animateLaterId = 0;
this._doSpringAnimation(animationDirection);
return GLib.SOURCE_REMOVE;
});
};
if (this._viewIsReady) {
this._grid.opacity = 0;
doSpringAnimationLater(Meta.LaterType.IDLE);
} else {
this._viewLoadedHandlerId = this.connect('view-loaded',
() => {
this._clearAnimateLater();
doSpringAnimationLater(Meta.LaterType.BEFORE_REDRAW);
});
}
let id = this._grid.connect('paint', () => {
this._grid.disconnect(id);
this._doSpringAnimation(animationDirection);
});
} else {
this._doSpringAnimation(animationDirection);
}
}
vfunc_unmap() {
this._clearAnimateLater();
super.vfunc_unmap();
}
animateSwitch(animationDirection) {
this.remove_all_transitions();
this._grid.remove_all_transitions();
@@ -420,12 +392,10 @@ var AllView = GObject.registerClass({
this._redisplayWorkId = Main.initializeDeferredWork(this, this._redisplay.bind(this));
Shell.AppSystem.get_default().connect('installed-changed', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId);
});
this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
this._folderSettings.connect('changed::folder-children', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId);
});
@@ -461,10 +431,6 @@ var AllView = GObject.registerClass({
_redisplay() {
super._redisplay();
this._folderIcons.forEach(icon => {
icon.view._redisplay();
});
this._refilterApps();
}
@@ -733,6 +699,8 @@ var AllView = GObject.registerClass({
// Toggle search entry
Main.overview.searchEntry.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.editable = !isOpen;
this._displayingPopup = isOpen;
});
@@ -1291,8 +1259,8 @@ var AppSearchProvider = class AppSearchProvider {
let results = [];
groups.forEach(group => {
group = group.filter(appID => {
const app = this._appSys.lookup_app(appID);
return app && app.app_info.should_show();
let app = Gio.DesktopAppInfo.new(appID);
return app && app.should_show();
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)
@@ -1340,7 +1308,7 @@ class FolderView extends BaseAppView {
x_expand: true,
y_expand: true,
});
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
this.add_actor(this._scrollView);
let scrollableContainer = new St.BoxLayout({
@@ -1356,6 +1324,7 @@ class FolderView extends BaseAppView {
action.connect('pan', this._onPan.bind(this));
this._scrollView.add_action(action);
this._folder.connect('changed', this._redisplay.bind(this));
this._redisplay();
}
@@ -1377,12 +1346,12 @@ class FolderView extends BaseAppView {
});
layout.hookup_style(icon);
let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let numItems = this._orderedItems.length;
let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
for (let i = 0; i < 4; i++) {
const style = 'width: %dpx; height: %dpx;'.format(subSize, subSize);
let bin = new St.Bin({ style });
let bin = new St.Bin({ width: subSize * scale, height: subSize * scale });
if (i < numItems)
bin.child = this._orderedItems[i].app.create_icon_texture(subSize);
layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1);
@@ -1460,22 +1429,6 @@ class FolderView extends BaseAppView {
return apps;
}
addApp(app) {
let folderApps = this._folder.get_strv('apps');
folderApps.push(app.id);
this._folder.set_strv('apps', folderApps);
// Also remove from 'excluded-apps' if the app id is listed
// there. This is only possible on categories-based folders.
let excludedApps = this._folder.get_strv('excluded-apps');
let index = excludedApps.indexOf(app.id);
if (index >= 0) {
excludedApps.splice(index, 1);
this._folder.set_strv('excluded-apps', excludedApps);
}
}
removeApp(app) {
let folderApps = this._folder.get_strv('apps');
let index = folderApps.indexOf(app.id);
@@ -1506,6 +1459,8 @@ class FolderView extends BaseAppView {
} else {
this._folder.set_strv('apps', folderApps);
}
return true;
}
});
@@ -1539,26 +1494,26 @@ var FolderIcon = GObject.registerClass({
this.view = new FolderView(this._folder, id, parentView);
this._iconIsHovering = false;
this._itemDragBeginId = Main.overview.connect(
'item-drag-begin', this._onDragBegin.bind(this));
this._itemDragEndId = Main.overview.connect(
'item-drag-end', this._onDragEnd.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this._folderChangedId = this._folder.connect(
'changed', this._sync.bind(this));
this._sync();
this._folder.connect('changed', this._redisplay.bind(this));
this._redisplay();
}
_onDestroy() {
if (this._dragMonitor) {
DND.removeDragMonitor(this._dragMonitor);
this._dragMonitor = null;
}
Main.overview.disconnect(this._itemDragBeginId);
Main.overview.disconnect(this._itemDragEndId);
this.view.destroy();
if (this._folderChangedId) {
this._folder.disconnect(this._folderChangedId);
delete this._folderChangedId;
if (this._spaceReadySignalId) {
this._parentView.disconnect(this._spaceReadySignalId);
this._spaceReadySignalId = 0;
}
if (this._dialog)
@@ -1586,32 +1541,29 @@ var FolderIcon = GObject.registerClass({
return this.view.getAllItems().map(item => item.id);
}
_setHoveringByDnd(hovering) {
if (this._iconIsHovering == hovering)
return;
this._iconIsHovering = hovering;
if (hovering) {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
this.add_style_pseudo_class('drop');
} else {
DND.removeDragMonitor(this._dragMonitor);
this.remove_style_pseudo_class('drop');
}
_onDragBegin() {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
}
_onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor) ||
!this._canAccept(dragEvent.source))
this._setHoveringByDnd(false);
let target = dragEvent.targetActor;
if (!this.contains(target) || !this._canAccept(dragEvent.source))
this.remove_style_pseudo_class('drop');
else
this.add_style_pseudo_class('drop');
return DND.DragMotionResult.CONTINUE;
}
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
_canAccept(source) {
if (!(source instanceof AppIcon))
return false;
@@ -1630,18 +1582,27 @@ var FolderIcon = GObject.registerClass({
if (!this._canAccept(source))
return DND.DragMotionResult.NO_DROP;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP;
}
acceptDrop(source) {
this._setHoveringByDnd(false);
if (!this._canAccept(source))
return false;
this.view.addApp(source.app);
let app = source.app;
let folderApps = this._folder.get_strv('apps');
folderApps.push(app.id);
this._folder.set_strv('apps', folderApps);
// Also remove from 'excluded-apps' if the app id is listed
// there. This is only possible on categories-based folders.
let excludedApps = this._folder.get_strv('excluded-apps');
let index = excludedApps.indexOf(app.id);
if (index >= 0) {
excludedApps.splice(index, 1);
this._folder.set_strv('excluded-apps', excludedApps);
}
return true;
}
@@ -1656,11 +1617,11 @@ var FolderIcon = GObject.registerClass({
this.emit('name-changed');
}
_sync() {
this.emit('apps-changed');
_redisplay() {
this._updateName();
this.visible = this.view.getAllItems().length > 0;
this.icon.update();
this.emit('apps-changed');
}
_createIcon(iconSize) {
@@ -1941,7 +1902,6 @@ var AppFolderDialog = GObject.registerClass({
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
contentBox = this._viewBox.get_theme_node().get_content_box(contentBox);
let [, entryBoxHeight] = this._entryBox.get_size();
let spacing = this._viewBox.layout_manager.spacing;
@@ -1950,8 +1910,6 @@ var AppFolderDialog = GObject.registerClass({
contentBox.get_width(),
contentBox.get_height() - entryBoxHeight - spacing);
this._view._grid.topPadding = 0;
super.vfunc_allocate(box, flags);
// We can only start zooming after receiving an allocation
@@ -2067,6 +2025,7 @@ var AppIcon = GObject.registerClass({
this._delegate = this;
this._hasDndHover = false;
this._folderPreviewId = 0;
// Get the isDraggable property without passing it on to the BaseIcon:
@@ -2115,7 +2074,11 @@ var AppIcon = GObject.registerClass({
});
}
this._otherIconIsHovering = false;
this._dragMonitor = null;
this._itemDragBeginId = Main.overview.connect(
'item-drag-begin', this._onDragBegin.bind(this));
this._itemDragEndId = Main.overview.connect(
'item-drag-end', this._onDragEnd.bind(this));
this._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', () => {
@@ -2127,6 +2090,9 @@ var AppIcon = GObject.registerClass({
}
_onDestroy() {
Main.overview.disconnect(this._itemDragBeginId);
Main.overview.disconnect(this._itemDragEndId);
if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0;
@@ -2373,17 +2339,7 @@ var AppIcon = GObject.registerClass({
}
_setHoveringByDnd(hovering) {
if (this._otherIconIsHovering == hovering)
return;
this._otherIconIsHovering = hovering;
if (hovering) {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0)
return;
@@ -2395,8 +2351,6 @@ var AppIcon = GObject.registerClass({
return GLib.SOURCE_REMOVE;
});
} else {
DND.removeDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0;
@@ -2406,13 +2360,32 @@ var AppIcon = GObject.registerClass({
}
}
_onDragBegin() {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
}
_onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor))
this._setHoveringByDnd(false);
let target = dragEvent.targetActor;
let isHovering = target == this || this.contains(target);
let canDrop = this._canAccept(dragEvent.source);
let hasDndHover = isHovering && canDrop;
if (this._hasDndHover != hasDndHover) {
this._setHoveringByDnd(hasDndHover);
this._hasDndHover = hasDndHover;
}
return DND.DragMotionResult.CONTINUE;
}
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
handleDragOver(source) {
if (source == this)
return DND.DragMotionResult.NO_DROP;
@@ -2420,8 +2393,6 @@ var AppIcon = GObject.registerClass({
if (!this._canAccept(source))
return DND.DragMotionResult.CONTINUE;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP;
}
@@ -2466,7 +2437,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
Main.uiGroup.add_actor(this.actor);
}
_rebuildMenu() {
_redisplay() {
this.removeAll();
let windows = this._source.app.get_windows().filter(
@@ -2562,7 +2533,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
null, 0, -1, null, null);
Main.overview.hide();
});
});
@@ -2583,7 +2554,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
}
popup(_activatingButton) {
this._rebuildMenu();
this._redisplay();
this.open();
}
};

View File

@@ -197,11 +197,6 @@ var BoxPointer = GObject.registerClass({
}
vfunc_allocate(box, flags) {
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
}
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
@@ -235,6 +230,12 @@ var BoxPointer = GObject.registerClass({
break;
}
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
this.set_allocation(box, flags);
}
}
_drawBorder(area) {

View File

@@ -220,7 +220,9 @@ class DBusEventSource extends EventSourceBase {
}
}
this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
this._dbusProxy.connectSignal('EventsAdded', this._onEventsAdded.bind(this));
this._dbusProxy.connectSignal('EventsRemoved', this._onEventsRemoved.bind(this));
this._dbusProxy.connectSignal('ClientDisappeared', this._onClientDisappeared.bind(this));
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
@@ -257,7 +259,7 @@ class DBusEventSource extends EventSourceBase {
}
_resetCache() {
this._events = [];
this._events = new Map();
this._lastRequestBegin = null;
this._lastRequestEnd = null;
}
@@ -273,28 +275,59 @@ class DBusEventSource extends EventSourceBase {
this.emit('changed');
}
_onChanged() {
this._loadEvents(false);
}
_onEventsAdded(dbusProxy, nameOwner, argArray) {
let appointments = argArray[0] || [];
let changed = false;
_onEventsReceived(results, _error) {
let newEvents = [];
let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) {
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 allDay = a[2];
let date = new Date(a[3] * 1000);
let end = new Date(a[4] * 1000);
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
this._events.set(event.id, event);
this._events = newEvents;
this._isLoading = false;
this.emit('changed');
changed = true;
}
if (changed)
this.emit('changed');
}
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
let ids = argArray[0] || [];
let changed = false;
for (let n = 0; n < ids.length; n++) {
let id = ids[n];
if (this._events.delete(id))
changed = true;
}
if (changed)
this.emit('changed');
}
_onClientDisappeared(dbusProxy, nameOwner, argArray) {
let sourceUid = argArray[0] || "";
let changed = false;
let idsIter = this._events.keys();
sourceUid += '\n';
for (let item = idsIter.next(); !item.done; item = idsIter.next()) {
let id = item.value;
if (id.startsWith(sourceUid) &&
this._events.delete(id))
changed = true;
}
if (changed)
this.emit('changed');
}
_loadEvents(forceReload) {
@@ -303,32 +336,40 @@ class DBusEventSource extends EventSourceBase {
return;
if (this._curRequestBegin && this._curRequestEnd) {
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE);
if (forceReload) {
this._events.clear();
this.emit('changed');
}
this._dbusProxy.SetTimeRangeRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
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(false);
this._loadEvents(true);
}
}
getEvents(begin, end) {
getEvents(begin, end, onlyCheckExistence) {
let result = [];
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
let eventsIter = this._events.values();
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
for (let item = eventsIter.next(); !item.done; item = eventsIter.next()) {
let event = item.value;
if (_dateIntervalsOverlap(event.date, event.end, begin, end)) {
result.push(event);
if (onlyCheckExistence)
return result;
}
}
result.sort((event1, event2) => {
// sort events by end time on ending day
@@ -343,7 +384,7 @@ class DBusEventSource extends EventSourceBase {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let events = this.getEvents(dayBegin, dayEnd);
let events = this.getEvents(dayBegin, dayEnd, true);
if (events.length == 0)
return false;
@@ -837,9 +878,8 @@ class EventsSection extends MessageList.MessageListSection {
this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
this._appSys = Shell.AppSystem.get_default();
this._appSys.connect('installed-changed',
this._appInstalledChanged.bind(this));
Shell.AppSystem.get_default().connect('installed-changed',
this._appInstalledChanged.bind(this));
this._appInstalledChanged();
}
@@ -874,7 +914,7 @@ class EventsSection extends MessageList.MessageListSection {
}
_reloadEvents() {
if (this._eventSource.isLoading)
if (this._eventSource.isLoading || this._reloading)
return;
this._reloading = true;
@@ -883,10 +923,7 @@ class EventsSection extends MessageList.MessageListSection {
let periodEnd = _getEndOfDay(this._date);
let events = this._eventSource.getEvents(periodBegin, periodEnd);
let ids = events.map(e => e.id);
this._messageById.forEach((message, id) => {
if (ids.includes(id))
return;
this._messageById.delete(id);
this.removeMessage(message);
});
@@ -932,13 +969,10 @@ class EventsSection extends MessageList.MessageListSection {
Main.overview.hide();
Main.panel.closeCalendar();
let appInfo = this._getCalendarApp();
if (appInfo.get_id() === 'org.gnome.Evolution.desktop') {
let app = this._appSys.lookup_app('evolution-calendar.desktop');
if (app)
appInfo = app.app_info;
}
appInfo.launch([], global.create_app_launch_context(0, -1));
let app = this._getCalendarApp();
if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1));
}
setDate(date) {
@@ -1153,22 +1187,17 @@ class CalendarMessageList extends St.Widget {
let hbox = new St.BoxLayout({ style_class: 'message-list-controls' });
box.add_child(hbox);
const dndLabel = new St.Label({
hbox.add_child(new St.Label({
text: _('Do Not Disturb'),
y_align: Clutter.ActorAlign.CENTER,
});
hbox.add_child(dndLabel);
}));
this._dndSwitch = new DoNotDisturbSwitch();
this._dndButton = new St.Button({
can_focus: true,
toggle_mode: true,
child: this._dndSwitch,
label_actor: dndLabel,
});
this._dndButton.bind_property('checked',
this._dndSwitch, 'state',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
this._dndButton.connect('clicked', () => this._dndSwitch.toggle());
hbox.add_child(this._dndButton);
this._clearButton = new St.Button({

View File

@@ -1,5 +1,5 @@
/* exported CheckBox */
const { Atk, Clutter, GObject, Pango, St } = imports.gi;
const { Clutter, GObject, Pango, St } = imports.gi;
var CheckBox = GObject.registerClass(
class CheckBox extends St.Button {
@@ -15,7 +15,6 @@ class CheckBox extends St.Button {
toggle_mode: true,
can_focus: true,
});
this.set_accessible_role(Atk.Role.CHECK_BOX);
this._box = new St.Bin({ y_align: Clutter.ActorAlign.START });
container.add_actor(this._box);
@@ -23,7 +22,6 @@ class CheckBox extends St.Button {
this._label = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._label.clutter_text.set_line_wrap(true);
this._label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this.set_label_actor(this._label);
container.add_actor(this._label);
if (label)

View File

@@ -188,8 +188,6 @@ var CloseDialog = GObject.registerClass({
global.stage.disconnect(this._keyFocusChangedId);
this._keyFocusChangedId = 0;
this._dialog._dialog.remove_all_transitions();
let dialog = this._dialog;
this._dialog = null;
this._removeWindowEffect();

View File

@@ -111,11 +111,15 @@ class KeyringDialog extends ModalDialog.ModalDialog {
}
_updateSensitivity(sensitive) {
if (this._passwordEntry)
if (this._passwordEntry) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
}
if (this._confirmEntry)
if (this._confirmEntry) {
this._confirmEntry.reactive = sensitive;
this._confirmEntry.clutter_text.editable = sensitive;
}
this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive;

View File

@@ -4,15 +4,13 @@
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = GObject.registerClass(
@@ -617,6 +615,14 @@ var NetworkAgent = class {
this._vpnRequests = { };
this._notifications = { };
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => (this._vpnCacheBuilt = false));
} catch (e) {
log('Failed to create monitor for VPN plugin dir: %s'.format(e.message));
}
this._native.connect('new-request', this._newRequest.bind(this));
this._native.connect('cancel-request', this._cancelRequest.bind(this));
@@ -760,11 +766,13 @@ var NetworkAgent = class {
}
}
async _vpnRequest(requestId, connection, hints, flags) {
_vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn();
let serviceType = vpnSetting.service_type;
let binary = await this._findAuthBinary(serviceType);
this._buildVPNServiceCache();
let binary = this._vpnBinaries[serviceType];
if (!binary) {
log('Invalid VPN service type (cannot find authentication binary)');
@@ -780,30 +788,36 @@ var NetworkAgent = class {
this._vpnRequests[requestId] = vpnRequest;
}
async _findAuthBinary(serviceType) {
let plugin;
_buildVPNServiceCache() {
if (this._vpnCacheBuilt)
return;
try {
plugin = await this._native.search_vpn_plugin(serviceType);
} catch (e) {
logError(e);
return null;
}
this._vpnCacheBuilt = true;
this._vpnBinaries = { };
const fileName = plugin.get_auth_dialog();
if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
log('VPN plugin at %s is not executable'.format(fileName));
return null;
}
NM.VpnPluginInfo.list_load().forEach(plugin => {
let service = plugin.get_service();
let fileName = plugin.get_auth_dialog();
let supportsHints = plugin.supports_hints();
let externalUIMode = false;
const prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
const trimmedProp = prop ? prop.trim().toLowerCase() : '';
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
if (prop) {
prop = prop.trim().toLowerCase();
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
}
return {
fileName,
supportsHints: plugin.supports_hints(),
externalUIMode: ['true', 'yes', 'on', '1'].includes(trimmedProp),
};
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
let binary = { fileName, externalUIMode, supportsHints };
this._vpnBinaries[service] = binary;
plugin.get_aliases().forEach(alias => {
this._vpnBinaries[alias] = binary;
});
} else {
log('VPN plugin at %s is not executable'.format(fileName));
}
});
}
};
var Component = NetworkAgent;

View File

@@ -327,8 +327,6 @@ var AuthenticationDialog = GObject.registerClass({
}
let resetDialog = () => {
this._sessionRequestTimeoutId = 0;
if (this.state != ModalDialog.State.OPENED)
return;

View File

@@ -2,6 +2,7 @@
/* exported Component */
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
var Tpl = null;
var Tp = null;
@@ -39,59 +40,36 @@ var NotificationDirection = {
RECEIVED: 'chat-received',
};
const ChatMessage = HAVE_TP ? GObject.registerClass({
Properties: {
'message-type': GObject.ParamSpec.int(
'message-type', 'message-type', 'message-type',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
Math.min(...Object.values(Tp.ChannelTextMessageType)),
Math.max(...Object.values(Tp.ChannelTextMessageType)),
Tp.ChannelTextMessageType.NORMAL),
'text': GObject.ParamSpec.string(
'text', 'text', 'text',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'sender': GObject.ParamSpec.string(
'sender', 'sender', 'sender',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'timestamp': GObject.ParamSpec.int64(
'timestamp', 'timestamp', 'timestamp',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
0, Number.MAX_SAFE_INTEGER, 0),
'direction': GObject.ParamSpec.string(
'direction', 'direction', 'direction',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
},
}, class ChatMessageClass extends GObject.Object {
static newFromTpMessage(tpMessage, direction) {
return new ChatMessage({
'message-type': tpMessage.get_message_type(),
'text': tpMessage.to_text()[0],
'sender': tpMessage.sender.alias,
'timestamp': direction === NotificationDirection.RECEIVED
? tpMessage.get_received_timestamp() : tpMessage.get_sent_timestamp(),
direction,
});
}
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags_] = tpMessage.to_text();
static newFromTplTextEvent(tplTextEvent) {
let direction =
tplTextEvent.get_sender().get_entity_type() === Tpl.EntityType.SELF
? NotificationDirection.SENT : NotificationDirection.RECEIVED;
let timestamp = tpMessage.get_sent_timestamp();
if (timestamp == 0)
timestamp = tpMessage.get_received_timestamp();
return new ChatMessage({
'message-type': tplTextEvent.get_message_type(),
'text': tplTextEvent.get_message(),
'sender': tplTextEvent.get_sender().get_alias(),
'timestamp': tplTextEvent.get_timestamp(),
direction,
});
}
}) : null;
return {
messageType: tpMessage.get_message_type(),
text,
sender: tpMessage.sender.alias,
timestamp,
direction,
};
}
function makeMessageFromTplEvent(event) {
let sent = event.get_sender().get_entity_type() == Tpl.EntityType.SELF;
let direction = sent ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
return {
messageType: event.get_message_type(),
text: event.get_message(),
sender: event.get_sender().get_alias(),
timestamp: event.get_timestamp(),
direction,
};
}
var TelepathyComponent = class {
constructor() {
this._client = null;
@@ -292,12 +270,12 @@ class TelepathyClient extends Tp.BaseClient {
var ChatSource = HAVE_TP ? GObject.registerClass(
class ChatSource extends MessageTray.Source {
_init(account, conn, channel, contact, client) {
super._init(contact.get_alias());
this._account = account;
this._contact = contact;
this._client = client;
super._init(contact.get_alias());
this.isChat = true;
this._pendingMessages = [];
@@ -453,7 +431,7 @@ class ChatSource extends MessageTray.Source {
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification();
let pendingTpMessages = this._channel.get_pending_messages();
@@ -465,8 +443,7 @@ class ChatSource extends MessageTray.Source {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
continue;
pendingMessages.push(ChatMessage.newFromTpMessage(message,
NotificationDirection.RECEIVED));
pendingMessages.push(makeMessageFromTpMessage(message, NotificationDirection.RECEIVED));
this._pendingMessages.push(message);
}
@@ -564,8 +541,7 @@ class ChatSource extends MessageTray.Source {
this._pendingMessages.push(message);
this.countUpdated();
message = ChatMessage.newFromTpMessage(message,
NotificationDirection.RECEIVED);
message = makeMessageFromTpMessage(message, NotificationDirection.RECEIVED);
this._notification.appendMessage(message);
// Wait a bit before notifying for the received message, a handler
@@ -590,8 +566,7 @@ class ChatSource extends MessageTray.Source {
// our client and other clients as well.
_messageSent(channel, message, _flags, _token) {
this._ensureNotification();
message = ChatMessage.newFromTpMessage(message,
NotificationDirection.SENT);
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
}
@@ -655,19 +630,11 @@ class ChatSource extends MessageTray.Source {
}
}) : null;
const ChatNotificationMessage = HAVE_TP ? GObject.registerClass(
class ChatNotificationMessage extends GObject.Object {
_init(props = {}) {
super._init();
this.set(props);
}
}) : null;
var ChatNotification = HAVE_TP ? GObject.registerClass({
Signals: {
'message-removed': { param_types: [ChatNotificationMessage.$gtype] },
'message-added': { param_types: [ChatNotificationMessage.$gtype] },
'timestamp-changed': { param_types: [ChatNotificationMessage.$gtype] },
'message-removed': { param_types: [Tp.Message.$gtype] },
'message-added': { param_types: [Tp.Message.$gtype] },
'timestamp-changed': { param_types: [Tp.Message.$gtype] },
},
}, class ChatNotification extends MessageTray.Notification {
_init(source) {
@@ -768,24 +735,21 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
styles: [],
timestamp: currentTime,
noTimestamp: false });
const { noTimestamp } = props;
delete props.noTimestamp;
// Reset the old message timeout
if (this._timestampTimeoutId)
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
let message = new ChatNotificationMessage({
realMessage: props.group !== 'meta',
showTimestamp: false,
...props,
});
let message = { realMessage: props.group != 'meta',
showTimestamp: false };
Lang.copyProperties(props, message);
delete message.noTimestamp;
this.messages.unshift(message);
this.emit('message-added', message);
if (!noTimestamp) {
if (!props.noTimestamp) {
let timestamp = props.timestamp;
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) {
this.appendTimestamp();

View File

@@ -180,27 +180,14 @@ class WorldClocksSection extends St.Button {
let time = new St.Label({ style_class: 'world-clocks-time' });
const utcOffset = this._getTimeAtLocation(l).get_utc_offset();
const offsetCurrentTz = utcOffset - localOffset;
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
const offsetMinutes =
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
GLib.TIME_SPAN_MINUTE;
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
const text = offsetMinutes === 0
? '%s%d'.format(prefix, offsetHours)
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
const tz = new St.Label({
style_class: 'world-clocks-timezone',
text,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
time.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
tz.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let fmt = Math.trunc(offset) == offset ? '%s%.0f' : '%s%.1f';
let prefix = offset >= 0 ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
text: fmt.format(prefix, Math.abs(offset)),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER });
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(tz, 0, i + 1, 1, 1);
@@ -397,20 +384,6 @@ class WeatherSection extends St.Button {
layout.attach(label, 0, 0, 1, 1);
}
_findBestLocationName(loc) {
const locName = loc.get_name();
if (loc.get_level() === GWeather.LocationLevel.CITY ||
!loc.has_coords())
return locName;
const world = GWeather.Location.get_world();
const city = world.find_nearest_city(...loc.get_coords());
const cityName = city.get_name();
return locName.includes(cityName) ? cityName : locName;
}
_updateForecasts() {
this._forecastGrid.destroy_all_children();
@@ -419,8 +392,13 @@ class WeatherSection extends St.Button {
return;
}
const { info } = this._weatherClient;
this._titleLocation.text = this._findBestLocationName(info.location);
let info = this._weatherClient.info;
let loc = info.get_location();
if (loc.get_level() !== GWeather.LocationLevel.CITY && loc.has_coords()) {
let world = GWeather.Location.get_world();
loc = world.find_nearest_city(...loc.get_coords());
}
this._titleLocation.text = loc.get_name();
if (this._weatherClient.loading) {
this._setStatusLabel(_("Loading…"));

View File

@@ -346,8 +346,10 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
// Use a different description when we are installing a system upgrade
// if the PackageKit proxy is available (i.e. PackageKit is available).
if (dialogContent.upgradeDescription) {
const { name, version } = this._updateInfo.PreparedUpgrade;
if (this._pkOfflineProxy && dialogContent.upgradeDescription) {
let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
if (name != null && version != null)
description = dialogContent.upgradeDescription(name, version);
}
@@ -606,46 +608,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
});
}
async _getUpdateInfo() {
const connection = this._pkOfflineProxy.get_connection();
const reply = await connection.call(
this._pkOfflineProxy.g_name,
this._pkOfflineProxy.g_object_path,
'org.freedesktop.DBus.Properties',
'GetAll',
new GLib.Variant('(s)', [this._pkOfflineProxy.g_interface_name]),
null,
Gio.DBusCallFlags.NONE,
-1,
null);
const [info] = reply.recursiveUnpack();
return info;
}
async OpenAsync(parameters, invocation) {
OpenAsync(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type;
try {
this._updateInfo = await this._getUpdateInfo();
} catch (e) {
if (this._pkOfflineProxy !== null)
log('Failed to get update info from PackageKit: %s'.format(e.message));
this._updateInfo = {
UpdateTriggered: false,
UpdatePrepared: false,
UpgradeTriggered: false,
PreparedUpgrade: {},
};
}
// Only consider updates and upgrades if PackageKit is available.
if (this._pkOfflineProxy && this._type == DialogType.RESTART) {
if (this._updateInfo.UpdateTriggered)
if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART;
else if (this._updateInfo.UpgradeTriggered)
else if (this._pkOfflineProxy.UpgradeTriggered)
this._type = DialogType.UPGRADE_RESTART;
}
@@ -674,8 +646,9 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
if (dialogContent.showOtherSessions)
this._loadSessions();
let updateTriggered = this._updateInfo.UpdateTriggered;
let updatePrepared = this._updateInfo.UpdatePrepared;
// Only consider updates and upgrades if PackageKit is available.
let updateTriggered = this._pkOfflineProxy ? this._pkOfflineProxy.UpdateTriggered : false;
let updatePrepared = this._pkOfflineProxy ? this._pkOfflineProxy.UpdatePrepared : false;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');

View File

@@ -10,12 +10,10 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const System = imports.system;
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
let _localTimeZone = null;
// We can't import shell JS modules yet, because they may have
@@ -290,13 +288,6 @@ function init() {
},
});
Gio._LocalFilePrototype.touch_async = function (callback) {
Shell.util_touch_file_async(this, callback);
};
Gio._LocalFilePrototype.touch_finish = function (result) {
return Shell.util_touch_file_finish(this, result);
};
St.set_slow_down_factor = function (factor) {
let { stack } = new Error();
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);

View File

@@ -56,15 +56,6 @@ function uninstallExtension(uuid) {
return false;
FileUtils.recursivelyDeleteDir(extension.dir, true);
try {
const updatesDir = Gio.File.new_for_path(GLib.build_filenamev(
[global.userdatadir, 'extension-updates', extension.uuid]));
FileUtils.recursivelyDeleteDir(updatesDir, true);
} catch (e) {
// not an error
}
return true;
}
@@ -108,9 +99,6 @@ function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
}
function downloadExtensionUpdate(uuid) {
if (!Main.extensionManager.updatesSupported)
return;
let dir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extension-updates', uuid]));
@@ -129,9 +117,6 @@ function downloadExtensionUpdate(uuid) {
}
function checkForUpdates() {
if (!Main.extensionManager.updatesSupported)
return;
let metadatas = {};
Main.extensionManager.getUuids().forEach(uuid => {
let extension = Main.extensionManager.lookup(uuid);
@@ -142,9 +127,6 @@ function checkForUpdates() {
metadatas[uuid] = extension.metadata;
});
if (Object.keys(metadatas).length === 0)
return; // nothing to update
let versionCheck = global.settings.get_boolean(
'disable-extension-version-validation');
let params = {
@@ -162,7 +144,9 @@ function checkForUpdates() {
let operations = JSON.parse(message.response_body.data);
for (let uuid in operations) {
let operation = operations[uuid];
if (operation === 'upgrade' || operation === 'downgrade')
if (operation == 'blacklist')
uninstallExtension(uuid);
else if (operation == 'upgrade' || operation == 'downgrade')
downloadExtensionUpdate(uuid);
}
});

View File

@@ -60,11 +60,6 @@ var ExtensionManager = class {
ExtensionDownloader.checkForUpdates();
}
get updatesSupported() {
const appSys = Shell.AppSystem.get_default();
return appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
}
lookup(uuid) {
return this._extensions.get(uuid);
}
@@ -215,25 +210,6 @@ var ExtensionManager = class {
return true;
}
openExtensionPrefs(uuid, parentWindow, options) {
const extension = this.lookup(uuid);
if (!extension || !extension.hasPrefs)
return false;
Gio.DBus.session.call(
'org.gnome.Shell.Extensions',
'/org/gnome/Shell/Extensions',
'org.gnome.Shell.Extensions',
'OpenExtensionPrefs',
new GLib.Variant('(ssa{sv})', [uuid, parentWindow, options]),
null,
Gio.DBusCallFlags.NONE,
-1,
null,
(conn, res) => conn.call_finish(res));
return true;
}
notifyExtensionUpdate(uuid) {
let extension = this.lookup(uuid);
if (!extension)
@@ -505,9 +481,6 @@ var ExtensionManager = class {
}
_installExtensionUpdates() {
if (!this.updatesSupported)
return;
FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => {
let fileType = info.get_file_type();
if (fileType !== Gio.FileType.DIRECTORY)
@@ -516,14 +489,9 @@ var ExtensionManager = class {
let extensionDir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
try {
FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(dir, extensionDir);
} catch (e) {
log('Failed to install extension updates for %s'.format(uuid));
} finally {
FileUtils.recursivelyDeleteDir(dir, true);
}
FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(dir, extensionDir);
FileUtils.recursivelyDeleteDir(dir, true);
});
}

View File

@@ -498,7 +498,7 @@ var Key = GObject.registerClass({
var KeyboardModel = class {
constructor(groupName) {
let names = [groupName];
if (groupName.includes('+'))
if (names.includes('+'))
names.push(groupName.replace(/\+.*/, ''));
names.push('us');
@@ -1120,11 +1120,10 @@ var KeyboardManager = class KeyBoardManager {
this._lastDevice = null;
Meta.get_backend().connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
return;
this._lastDevice = device;
this._syncEnabled();
if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDevice = device;
this._syncEnabled();
}
});
this._syncEnabled();
}
@@ -1149,9 +1148,9 @@ var KeyboardManager = class KeyBoardManager {
this._keyboard = new Keyboard();
} else if (!enabled && this._keyboard) {
this._keyboard.setCursorLocation(null);
Main.layoutManager.hideKeyboard(true);
this._keyboard.destroy();
this._keyboard = null;
Main.layoutManager.hideKeyboard(true);
}
}
@@ -1257,10 +1256,6 @@ class Keyboard extends St.BoxLayout {
return this._keyboardVisible && super.visible;
}
set visible(visible) {
super.visible = visible;
}
_onFocusPositionChanged(focusTracker) {
let rect = focusTracker.getCurrentRect();
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
@@ -1873,10 +1868,6 @@ var KeyboardController = class {
Main.inputMethod.disconnect(this._notifyContentPurposeId);
Main.inputMethod.disconnect(this._notifyContentHintsId);
Main.inputMethod.disconnect(this._notifyInputPanelStateId);
// Make sure any buttons pressed by the virtual device are released
// immediately instead of waiting for the next GC cycle
this._virtualDevice.run_dispose();
}
_onSourcesModified() {

View File

@@ -612,20 +612,10 @@ var LayoutManager = GObject.registerClass({
let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId);
this._systemBackground.show();
global.stage.show();
// We're mostly prepared for the startup animation
// now, but since a lot is going on asynchronously
// during startup, let's defer the startup animation
// until the event loop is uncontended and idle.
// This helps to prevent us from running the animation
// when the system is bogged down
const id = GLib.idle_add(GLib.PRIORITY_LOW, () => {
this._systemBackground.show();
global.stage.show();
this._prepareStartupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] Startup Animation');
this._prepareStartupAnimation();
});
}
@@ -682,7 +672,17 @@ var LayoutManager = GObject.registerClass({
this.emit('startup-prepared');
this._startupAnimation();
// We're mostly prepared for the startup animation
// now, but since a lot is going on asynchronously
// during startup, let's defer the startup animation
// until the event loop is uncontended and idle.
// This helps to prevent us from running the animation
// when the system is bogged down
let id = GLib.idle_add(GLib.PRIORITY_LOW, () => {
this._startupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
}
_startupAnimation() {
@@ -765,7 +765,7 @@ var LayoutManager = GObject.registerClass({
this._keyboardHeightNotifyId = 0;
}
this.keyboardBox.ease({
translation_y: 0,
translation_y: this.keyboardBox.height,
opacity: 0,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,

View File

@@ -1127,7 +1127,7 @@ class LookingGlass extends St.BoxLayout {
else if (symbol == Clutter.KEY_Page_Down)
this._notebook.nextTab();
}
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
open() {

View File

@@ -93,9 +93,6 @@ let _a11ySettings = null;
let _themeResource = null;
let _oskResource = null;
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
function _sessionUpdated() {
if (sessionMode.isPrimary)
_loadDefaultStylesheet();
@@ -132,9 +129,7 @@ function start() {
notifyError(msg, detail);
});
let currentDesktop = GLib.getenv('XDG_CURRENT_DESKTOP');
if (!currentDesktop || !currentDesktop.split(':').includes('GNOME'))
Gio.DesktopAppInfo.set_desktop_env('GNOME');
Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode();
sessionMode.connect('updated', _sessionUpdated);
@@ -147,11 +142,6 @@ function start() {
shellDBusService = new ShellDBus.GnomeShell();
shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();
const watchId = Gio.DBus.session.watch_name('org.gnome.Shell.Notifications',
Gio.BusNameWatcherFlags.AUTO_START,
bus => bus.unwatch_name(watchId),
bus => bus.unwatch_name(watchId));
_sessionUpdated();
}
@@ -281,8 +271,11 @@ function _initializeUI() {
}
if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup')
_handleLockScreenWarning();
sessionMode.currentMode !== 'initial-setup' &&
screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM();
@@ -295,32 +288,6 @@ function _initializeUI() {
});
}
async function _handleLockScreenWarning() {
const path = '%s/lock-warning-shown'.format(global.userdatadir);
const file = Gio.File.new_for_path(path);
const hasLockScreen = screenShield !== null;
if (hasLockScreen) {
try {
await file.delete_async(0, null);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
logError(e);
}
} else {
try {
if (!await file.touch_async())
return;
} catch (e) {
logError(e);
}
notify(
_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
}
function _getStylesheet(name) {
let stylesheet;
@@ -394,8 +361,7 @@ function reloadThemeResource() {
if (_themeResource)
_themeResource._unregister();
_themeResource = Gio.Resource.load('%s/%s'.format(global.datadir,
sessionMode.themeResourceName));
_themeResource = Gio.Resource.load('%s/gnome-shell-theme.gresource'.format(global.datadir));
_themeResource._register();
}
@@ -521,9 +487,7 @@ function pushModal(actor, params) {
let prevFocusDestroyId;
if (prevFocus != null) {
prevFocusDestroyId = prevFocus.connect('destroy', () => {
const index = modalActorFocusStack.findIndex(
record => record.prevFocus === prevFocus);
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack[index].prevFocus = null;
});

View File

@@ -530,7 +530,7 @@ var Message = GObject.registerClass({
this.close();
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyEvent);
return Clutter.EVENT_PROPAGATE;
}
});

View File

@@ -762,10 +762,12 @@ var Source = GObject.registerClass({
this.notifications = [];
this._policy = this._createPolicy();
this._policy = null;
}
get policy() {
if (!this._policy)
this._policy = this._createPolicy();
return this._policy;
}
@@ -878,6 +880,8 @@ var Source = GObject.registerClass({
}
destroy(reason) {
this.policy.destroy();
let notifications = this.notifications;
this.notifications = [];
@@ -886,7 +890,6 @@ var Source = GObject.registerClass({
this.emit('destroy', reason);
this.policy.destroy();
this.run_dispose();
}

View File

@@ -416,11 +416,11 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
_init(title, pid, sender, appId) {
super._init(title);
this.pid = pid;
this.app = this._getApp(appId);
super._init(title);
this.initialTitle = title;
if (this.app)
@@ -631,12 +631,12 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!app)
throw new InvalidAppError();
super._init(app.get_name());
this._appId = appId;
this._app = app;
this._objectPath = objectPath;
super._init(app.get_name());
this._notifications = {};
this._notificationPending = false;
}

View File

@@ -473,7 +473,6 @@ class ControlsManager extends St.Widget {
// A workspace might have been inserted or removed before the active
// one, causing the adjustment to go out of sync, so update the value
this._workspaceAdjustment.remove_transition('value');
this._workspaceAdjustment.value = activeIndex;
}

View File

@@ -89,7 +89,7 @@ var PadChooser = GObject.registerClass({
});
var KeybindingEntry = GObject.registerClass({
Signals: { 'keybinding-edited': { param_types: [GObject.TYPE_STRING] } },
Signals: { 'keybinding-edited': {} },
}, class KeybindingEntry extends St.Entry {
_init() {
super._init({ hint_text: _("New shortcut…"), style: 'width: 10em' });

View File

@@ -100,7 +100,7 @@ class AppMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
null, 0, -1, null, null);
});
});
@@ -964,7 +964,7 @@ class Panel extends St.Widget {
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyEvent);
return Clutter.EVENT_PROPAGATE;
}
_toggleMenu(indicator) {

View File

@@ -247,7 +247,7 @@ var RemoteSearchProvider = class {
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
log('Received error from D-Bus search provider %s: %s'.format(this.id, String(error)));
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
callback([]);
return;
}
@@ -274,7 +274,7 @@ var RemoteSearchProvider = class {
_getResultMetasFinished(results, error, callback) {
if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from D-Bus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
log('Received error from DBus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
callback([]);
return;
}

View File

@@ -498,8 +498,6 @@ var ScreenShield = class {
if (Main.sessionMode.currentMode == 'unlock-dialog')
Main.sessionMode.popMode('unlock-dialog');
this.emit('wake-up-screen');
if (this._isGreeter) {
// We don't want to "deactivate" any more than
// this. In particular, we don't want to drop
@@ -521,9 +519,6 @@ var ScreenShield = class {
this._isModal = false;
}
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
this._lockDialogGroup.ease({
translation_y: -global.screen_height,
duration: Overview.ANIMATION_TIME,
@@ -538,6 +533,8 @@ var ScreenShield = class {
this._dialog = null;
}
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
this.actor.hide();
if (this._becameActiveId != 0) {

View File

@@ -84,7 +84,7 @@ var ScreenshotService = class {
}
}
_createStream(filename, invocation) {
_createStream(filename) {
if (filename == '')
return [Gio.MemoryOutputStream.new_resizable(), null];
@@ -94,7 +94,6 @@ var ScreenshotService = class {
let stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
return [stream, file];
} catch (e) {
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return [null, null];
}
}
@@ -105,22 +104,23 @@ var ScreenshotService = class {
return [stream, file];
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS))
break;
return [null, null];
}
}
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return [null, null];
}
_onScreenshotComplete(area, stream, file, flash, invocation) {
if (flash) {
let flashspot = new Flashspot(area);
flashspot.fire(() => {
_onScreenshotComplete(result, area, stream, file, flash, invocation) {
if (result) {
if (flash) {
let flashspot = new Flashspot(area);
flashspot.fire(() => {
this._removeShooterForSender(invocation.get_sender());
});
} else {
this._removeShooterForSender(invocation.get_sender());
});
} else {
this._removeShooterForSender(invocation.get_sender());
}
}
stream.close(null);
@@ -134,7 +134,7 @@ var ScreenshotService = class {
clipboard.set_content(St.ClipboardType.CLIPBOARD, 'image/png', bytes);
}
let retval = GLib.Variant.new('(bs)', [true, filenameUsed]);
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
invocation.return_value(retval);
}
@@ -169,20 +169,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_area(x, y, width, height, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}
@@ -193,20 +190,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_window(includeFrame, includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}
@@ -217,20 +211,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot(includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}

View File

@@ -15,7 +15,6 @@ const _modes = {
'restrictive': {
parentMode: null,
stylesheetName: 'gnome-shell.css',
themeResourceName: 'gnome-shell-theme.gresource',
hasOverview: false,
showCalendarEvents: false,
allowSettings: false,

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GnomeShell, ScreenSaverDBus */
const { Gio, GLib, Meta } = imports.gi;
const { Gio, GLib, Meta, Shell } = imports.gi;
const Config = imports.misc.config;
const ExtensionDownloader = imports.ui.extensionDownloader;
@@ -255,17 +255,6 @@ var GnomeShellExtensions = class {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
this._userExtensionsEnabled = this.UserExtensionsEnabled;
global.settings.connect('changed::disable-user-extensions', () => {
if (this._userExtensionsEnabled === this.UserExtensionsEnabled)
return;
this._userExtensionsEnabled = this.UserExtensionsEnabled;
this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
new GLib.Variant('b', this._userExtensionsEnabled));
});
Main.extensionManager.connect('extension-state-changed',
this._extensionStateChanged.bind(this));
}
@@ -312,18 +301,20 @@ var GnomeShellExtensions = class {
}
LaunchExtensionPrefs(uuid) {
this.OpenExtensionPrefs(uuid, '', {});
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.Extensions.desktop');
let info = app.get_app_info();
let timestamp = global.display.get_current_time_roundtrip();
info.launch_uris([`extension:///${uuid}`],
global.create_app_launch_context(timestamp, -1));
}
OpenExtensionPrefs(uuid, parentWindow, options) {
Main.extensionManager.openExtensionPrefs(uuid, parentWindow, options);
}
ReloadExtension(uuid) {
let extension = Main.extensionManager.lookup(uuid);
if (!extension)
return;
ReloadExtensionAsync(params, invocation) {
invocation.return_error_literal(
Gio.DBusError,
Gio.DBusError.NOT_SUPPORTED,
'ReloadExtension is deprecated and does not work');
Main.extensionManager.reloadExtension(extension);
}
CheckForUpdates() {
@@ -334,14 +325,6 @@ var GnomeShellExtensions = class {
return Config.PACKAGE_VERSION;
}
get UserExtensionsEnabled() {
return !global.settings.get_boolean('disable-user-extensions');
}
set UserExtensionsEnabled(enable) {
global.settings.set_boolean('disable-user-extensions', !enable);
}
_extensionStateChanged(_, newState) {
let state = ExtensionUtils.serializeExtension(newState);
this._dbusImpl.emit_signal('ExtensionStateChanged',

View File

@@ -447,8 +447,12 @@ var ShellMountPasswordDialog = GObject.registerClass({
let useKeyfiles = this._keyfilesCheckbox.checked;
this._passwordEntry.reactive = !useKeyfiles;
this._passwordEntry.can_focus = !useKeyfiles;
this._passwordEntry.clutter_text.editable = !useKeyfiles;
this._passwordEntry.clutter_text.selectable = !useKeyfiles;
this._pimEntry.reactive = !useKeyfiles;
this._pimEntry.can_focus = !useKeyfiles;
this._pimEntry.clutter_text.editable = !useKeyfiles;
this._pimEntry.clutter_text.selectable = !useKeyfiles;
this._rememberChoice.reactive = !useKeyfiles;
this._rememberChoice.can_focus = !useKeyfiles;
this._keyfilesLabel.visible = useKeyfiles;

View File

@@ -43,10 +43,10 @@ var Slider = GObject.registerClass({
let [hasHandleColor, handleBorderColor] =
themeNode.lookup_color('-slider-handle-border-color', false);
const ceiledHandleRadius = Math.ceil(handleRadius + handleBorderWidth);
const handleX = ceiledHandleRadius +
(width - 2 * ceiledHandleRadius) * this._value / this._maxValue;
const handleY = height / 2;
let wholeHandleRadius = Math.ceil(handleRadius);
let handleX = wholeHandleRadius +
(width - 2 * wholeHandleRadius) * this._value / this._maxValue;
let handleY = height / 2;
let color = themeNode.get_foreground_color();
Clutter.cairo_set_source_color(cr, color);
@@ -186,7 +186,7 @@ var Slider = GObject.registerClass({
this.value = Math.max(0, Math.min(this._value + delta, this._maxValue));
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
_moveHandle(absX, _absY) {

View File

@@ -139,14 +139,14 @@ class ATIndicator extends PanelMenu.Button {
interfaceSettings.is_writable(KEY_ICON_THEME),
enabled => {
if (enabled) {
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
} else if (!hasHC) {
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
} else {
interfaceSettings.reset(KEY_ICON_THEME);
interfaceSettings.reset(KEY_GTK_THEME);
interfaceSettings.reset(KEY_ICON_THEME);
}
});

View File

@@ -64,7 +64,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.label.text = _("Location Enabled");
this._onOffAction = this._item.menu.addAction(_("Disable"), this._onOnOffAction.bind(this));
this._item.menu.addSettingsAction(_('Privacy Settings'), 'gnome-location-panel.desktop');
this._item.menu.addSettingsAction(_("Privacy Settings"), 'gnome-privacy-panel.desktop');
this.menu.addMenuItem(this._item);

View File

@@ -138,13 +138,12 @@ var StreamSlider = class {
}
_notifyVolumeChange() {
if (this._volumeCancellable)
this._volumeCancellable.cancel();
this._volumeCancellable = null;
if (this._stream.state === Gvc.MixerStreamState.RUNNING)
return; // feedback not necessary while playing
if (this._volumeCancellable)
this._volumeCancellable.cancel();
this._volumeCancellable = new Gio.Cancellable();
let player = global.display.get_sound_player();
player.play_from_theme('audio-volume-change',

View File

@@ -115,7 +115,7 @@ var NotificationsBox = GObject.registerClass({
box.add_child(textBox);
let title = new St.Label({
text: source.title.replace(/\n/g, ' '),
text: source.title,
style_class: 'unlock-dialog-notification-label',
});
textBox.add(title);
@@ -129,10 +129,9 @@ var NotificationsBox = GObject.registerClass({
let body = '';
if (n.bannerBodyText) {
const bodyText = n.bannerBodyText.replace(/\n/g, ' ');
body = n.bannerBodyMarkup
? bodyText
: GLib.markup_escape_text(bodyText, -1);
? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
}
let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' });
@@ -605,7 +604,7 @@ var UnlockDialog = GObject.registerClass({
this._showPrompt();
if (GLib.unichar_isgraph(unichar))
this._authPrompt.addCharacter(unichar);
this.addCharacter(unichar);
return Clutter.EVENT_PROPAGATE;
}
@@ -761,7 +760,7 @@ var UnlockDialog = GObject.registerClass({
}
_escape() {
if (this._authPrompt && this.allowCancel)
if (this.allowCancel)
this._authPrompt.cancel();
}
@@ -835,6 +834,11 @@ var UnlockDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(unichar) {
this._showPrompt();
this._authPrompt.addCharacter(unichar);
}
finish(onComplete) {
this._ensureAuthPrompt();
this._authPrompt.finish(onComplete);

View File

@@ -57,11 +57,11 @@ var WindowAttentionHandler = class {
var WindowAttentionSource = GObject.registerClass(
class WindowAttentionSource extends MessageTray.Source {
_init(app, window) {
super._init(app.get_name());
this._window = window;
this._app = app;
super._init(app.get_name());
this.signalIDs = [];
this.signalIDs.push(this._window.connect('notify::demands-attention',
this._sync.bind(this)));

View File

@@ -82,10 +82,8 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
_formatCountDown() {
const fmt = ngettext(
'Settings changes will revert in %d second',
'Settings changes will revert in %d seconds',
this._countDown);
let fmt = ngettext("Settings changes will revert in %d second",
"Settings changes will revert in %d seconds");
return fmt.format(this._countDown);
}
@@ -905,8 +903,7 @@ var WindowManager = class {
/* Leave this watchdog timeout so don't block indefinitely here */
let timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, () => {
Gio.DBus.session.unwatch_name(watchId);
log('Warning: Failed to start gsd-xsettings');
task.return_boolean(true);
task.return_boolean(false);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
@@ -926,8 +923,6 @@ var WindowManager = class {
return true;
});
global.display.connect('x11-display-closing', () => {
if (!Meta.is_wayland_compositor())
return;
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
IBusManager.getIBusManager().restartDaemon();
});

View File

@@ -404,7 +404,7 @@ var WindowClone = GObject.registerClass({
return true;
}
return super.vfunc_key_press_event(keyEvent);
return false;
}
_onClicked() {

View File

@@ -226,4 +226,4 @@ globals:
printerr: readonly
window: readonly
parserOptions:
ecmaVersion: 2019
ecmaVersion: 2017

View File

@@ -17,6 +17,7 @@ rules:
overrides:
- files: js/**
excludedFiles:
- js/extensionPrefs/*
- js/portalHelper/*
globals:
global: readonly
@@ -24,8 +25,3 @@ overrides:
C_: readonly
N_: readonly
ngettext: readonly
- files: subprojects/extensions-app/js/**
globals:
_: readonly
C_: readonly
N_: readonly

View File

@@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.36.2',
version: '3.35.92',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@@ -19,18 +19,18 @@ cogl_pango_pc = 'mutter-cogl-pango-' + mutter_api_version
libmutter_pc = 'libmutter-' + mutter_api_version
ecal_req = '>= 3.33.1'
eds_req = '>= 3.17.2'
eds_req = '>= 3.33.1'
gcr_req = '>= 3.7.5'
gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1'
gjs_req = '>= 1.63.2'
gtk_req = '>= 3.15.0'
mutter_req = '>= 3.36.0'
mutter_req = '>= 3.35.92'
polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'
ibus_req = '>= 1.5.2'
gnome_desktop_req = '>= 3.35.90'
gnome_desktop_req = '>= 3.34.2'
bt_req = '>= 3.9.0'
gst_req = '>= 0.11.92'
@@ -58,7 +58,6 @@ desktopdir = join_paths(datadir, 'applications')
icondir = join_paths(datadir, 'icons')
ifacedir = join_paths(datadir, 'dbus-1', 'interfaces')
localedir = join_paths(datadir, 'locale')
metainfodir = join_paths(datadir, 'metainfo')
portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
servicedir = join_paths(datadir, 'dbus-1', 'services')
@@ -115,8 +114,12 @@ if get_option('networkmanager')
nm_deps += dependency('libnm', version: nm_req)
nm_deps += dependency('libsecret-1', version: secret_req)
vpndir = nm_deps[0].get_pkgconfig_variable('vpnservicedir')
have_networkmanager = true
else
vpndir = prefix
have_networkmanager = false
endif
@@ -139,7 +142,6 @@ endif
mutter_typelibdir = mutter_dep.get_pkgconfig_variable('typelibdir')
python = find_program('python3')
sassc = find_program('sassc')
gjs = find_program('gjs')
cc = meson.get_compiler('c')
@@ -242,40 +244,13 @@ libgvc = subproject('gvc',
)
libgvc_gir = libgvc.get_variable('libgvc_gir')
libshew = subproject('shew',
default_options: [
'package_name=@0@'.format(meson.project_name()),
]
)
libshew_version = libshew.get_variable('package_version')
assert(libshew_version == meson.project_version(),
'shew version does not match project version')
if get_option('extensions_tool')
extension_tool = subproject('extensions-tool',
subproject('extensions-tool',
default_options: [
'man=@0@'.format(get_option('man')),
'package_name=@0@'.format(meson.project_name()),
]
)
extension_tool_version = extension_tool.get_variable('package_version')
assert(extension_tool_version == meson.project_version(),
'extension-tool version does not match project version'
)
endif
if get_option('extensions_app')
extensions_app = subproject('extensions-app',
default_options: [
'package_name=@0@'.format(meson.project_name()),
]
)
extensions_app_version = extensions_app.get_variable('package_version')
assert(extensions_app_version == meson.project_version(),
'Extensions app version does not match project version'
)
endif
@@ -293,36 +268,3 @@ if get_option('gtk_doc')
endif
meson.add_install_script('meson/postinstall.py')
summary_options = {
'networkmanager': get_option('networkmanager'),
'systemd': get_option('systemd'),
'extensions_app': get_option('extensions_app'),
'extensions_tool': get_option('extensions_tool'),
'man': get_option('man'),
'gtk_doc': get_option('gtk_doc'),
}
summary_build = {
'buildtype': get_option('buildtype'),
'debug': get_option('debug'),
}
summary_dirs = {
'prefix': get_option('prefix'),
'bindir': get_option('bindir'),
'libdir': get_option('libdir'),
'libexecdir': get_option('libexecdir'),
'datadir': get_option('datadir'),
'sysconfdir': get_option('sysconfdir'),
}
if get_option('man')
summary_dirs += { 'mandir': get_option('mandir') }
endif
if meson.version().version_compare('>= 0.53.0')
summary(summary_dirs, section: 'Directories')
summary(summary_build, section: 'Build Configuration')
summary(summary_options, section: 'Build Options')
endif

View File

@@ -4,12 +4,6 @@ option('extensions_tool',
description: 'Build gnome-extensions CLI tool'
)
option('extensions_app',
type: 'boolean',
value: true,
description: 'Build gnome-extensions GUI application'
)
option('gtk_doc',
type: 'boolean',
value: false,

View File

@@ -10,7 +10,6 @@ bn_IN
bs
ca
ca@valencia
ckb
cs
da
de

View File

@@ -1,10 +1,13 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
data/50-gnome-shell-system.xml
data/org.gnome.Extensions.desktop.in.in
data/org.gnome.Shell.desktop.in.in
data/org.gnome.shell.gschema.xml.in
data/org.gnome.Shell.PortalHelper.desktop.in.in
js/dbusServices/extensions/ui/extension-prefs-dialog.ui
js/extensionPrefs/main.js
js/extensionPrefs/ui/extension-row.ui
js/extensionPrefs/ui/extensions-window.ui
js/gdm/authPrompt.js
js/gdm/loginDialog.js
js/gdm/util.js
@@ -71,6 +74,7 @@ js/ui/windowAttentionHandler.js
js/ui/windowManager.js
js/ui/windowMenu.js
src/calendar-server/evolution-calendar.desktop.in
src/calendar-server/reminder-watcher.c
src/main.c
src/shell-app.c
src/shell-app-system.c
@@ -78,11 +82,6 @@ src/shell-global.c
src/shell-keyring-prompt.c
src/shell-polkit-authentication-agent.c
src/shell-util.c
subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in
subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in
subprojects/extensions-app/js/main.js
subprojects/extensions-app/data/ui/extension-row.ui
subprojects/extensions-app/data/ui/extensions-window.ui
subprojects/extensions-tool/src/command-create.c
subprojects/extensions-tool/src/command-disable.c
subprojects/extensions-tool/src/command-enable.c

250
po/ca.po
View File

@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2020-03-21 18:07+0000\n"
"POT-Creation-Date: 2020-02-25 23:44+0000\n"
"PO-Revision-Date: 2020-02-18 20:44+0100\n"
"Last-Translator: Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
@@ -45,6 +45,15 @@ msgstr "Mostra totes les aplicacions"
msgid "Open the application menu"
msgstr "Obre el menú d'aplicació"
#: data/org.gnome.Extensions.desktop.in.in:4 js/extensionPrefs/main.js:218
#: js/extensionPrefs/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configureu les extensions del GNOME Shell"
#: data/org.gnome.Shell.desktop.in.in:4
msgid "GNOME Shell"
msgstr "GNOME Shell"
@@ -191,7 +200,7 @@ msgid ""
msgstr ""
"El GNOME Shell us demanarà la contrasenya quan es munti un dispositiu "
"encriptat o un sistema de fitxers remot. Si es pot desar la contrasenya per "
"a utilitzar-la en el futur, es mostrarà la casella de selecció «Recorda la "
"utilitzar-lo en el futur, es mostrarà la casella de selecció «Recorda la "
"contrasenya». Aquesta clau estableix el valor per defecte d'aquesta casella "
"de selecció."
@@ -228,48 +237,48 @@ msgstr ""
#: data/org.gnome.shell.gschema.xml.in:119
msgid "Keybinding to open the application menu"
msgstr "Vinculació per a obrir el menú d'aplicació"
msgstr "Vinculació per obrir el menú d'aplicació"
#: data/org.gnome.shell.gschema.xml.in:120
msgid "Keybinding to open the application menu."
msgstr "La vinculació per a obrir el menú d'aplicació."
msgstr "La vinculació per obrir el menú d'aplicació."
#: data/org.gnome.shell.gschema.xml.in:126
msgid "Keybinding to open the “Show Applications” view"
msgstr "Vinculació de tecles per a obrir la vista «Mostra les aplicacions»"
msgstr "Vinculació de tecles per obrir la vista «Mostra les aplicacions»"
#: data/org.gnome.shell.gschema.xml.in:127
msgid ""
"Keybinding to open the “Show Applications” view of the Activities Overview."
msgstr ""
"Vinculació de tecles per a obrir la vista «Mostra les aplicacions» de les "
"Vinculació de tecles per obrir la vista «Mostra les aplicacions» de les "
"activitats de la vista general."
#: data/org.gnome.shell.gschema.xml.in:134
msgid "Keybinding to open the overview"
msgstr "Vinculació per a obrir la vista general"
msgstr "Vinculació per obrir la vista general"
#: data/org.gnome.shell.gschema.xml.in:135
msgid "Keybinding to open the Activities Overview."
msgstr "Vinculació per a obrir la vista general d'activitats."
msgstr "Vinculació per obrir la vista general d'activitats."
#: data/org.gnome.shell.gschema.xml.in:141
msgid "Keybinding to toggle the visibility of the notification list"
msgstr ""
"La vinculació per a commutar la visibilitat de la llista de notificacions"
"La vinculació per commutar la visibilitat de la llista de notificacions"
#: data/org.gnome.shell.gschema.xml.in:142
msgid "Keybinding to toggle the visibility of the notification list."
msgstr ""
"La vinculació per a commutar la visibilitat de la llista de notificacions."
"La vinculació per commutar la visibilitat de la llista de notificacions."
#: data/org.gnome.shell.gschema.xml.in:148
msgid "Keybinding to focus the active notification"
msgstr "Vinculació per a posar el focus a la notificació activa"
msgstr "Vinculació per posar el focus a la notificació activa"
#: data/org.gnome.shell.gschema.xml.in:149
msgid "Keybinding to focus the active notification."
msgstr "Vinculació per a posar el focus a la notificació activa."
msgstr "Vinculació per posar el focus a la notificació activa."
#: data/org.gnome.shell.gschema.xml.in:155
msgid "Switch to application 1"
@@ -406,56 +415,32 @@ msgstr ""
msgid "Network Login"
msgstr "Inici de sessió de xarxa"
#: 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:241
#: js/extensionPrefs/data/ui/extensions-window.ui:61
msgid "Extensions"
msgstr "Extensions"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
#: js/extensionPrefs/js/main.js:242
msgid "Manage your GNOME Extensions"
msgstr "Gestioneu les extensions del GNOME Shell"
#: 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 ""
"Les extensions del GNOME gestiona les actualitzacions de les extensions, configurant "
"les preferències de l'extensió i suprimint o desactivant les extensions no desitjades."
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
msgid "Configure GNOME Shell Extensions"
msgstr "Configureu les extensions del GNOME Shell"
#: js/extensionPrefs/js/main.js:163
#: js/extensionPrefs/main.js:140
#, javascript-format
msgid "Remove “%s”?"
msgstr "Voleu suprimir «%s»?"
#: js/extensionPrefs/js/main.js:164
#: js/extensionPrefs/main.js:141
msgid ""
"If you remove the extension, you need to return to download it if you want "
"to enable it again"
msgstr ""
"Si suprimiu una extensió, us cal tornar-la a baixar si voleu habilitar-la de "
"nou"
"nou."
#: js/extensionPrefs/js/main.js:167 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
#: js/extensionPrefs/main.js:144 js/gdm/authPrompt.js:135
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:107
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
#: js/ui/extensionDownloader.js:165 js/ui/shellMountOperation.js:376
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
msgid "Cancel"
msgstr "Cancel·la"
#: js/extensionPrefs/js/main.js:168
#: js/extensionPrefs/main.js:145
msgid "Remove"
msgstr "Suprimeix"
#: js/extensionPrefs/js/main.js:240
#: js/extensionPrefs/main.js:217
msgid "translator-credits"
msgstr ""
"Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
@@ -463,12 +448,15 @@ msgstr ""
"Gil Forcada <gilforcada@guifi.net>\n"
"Jordi Mas i Hernàndez <jmas@softcatala.org>"
#: js/extensionPrefs/js/main.js:284
#: js/extensionPrefs/data/ui/extensions-window.ui:223
#: js/extensionPrefs/main.js:219
msgid "Manage your GNOME Extensions"
msgstr "Gestioneu les extensions del GNOME Shell"
#: js/extensionPrefs/main.js:261 js/extensionPrefs/ui/extensions-window.ui:222
msgid "Somethings gone wrong"
msgstr "Alguna cosa ha anat malament"
#: js/extensionPrefs/js/main.js:291
#: js/extensionPrefs/main.js:268
msgid ""
"Were very sorry, but theres been a problem: the settings for this "
"extension cant be displayed. We recommend that you report the issue to the "
@@ -477,61 +465,61 @@ msgstr ""
"Hi ha un problema: no es poden mostrar els paràmetres per a aquesta "
"extensió. Us recomanem que informeu del problema als autors de l'extensió."
#: js/extensionPrefs/js/main.js:298
#: js/extensionPrefs/main.js:275
msgid "Technical Details"
msgstr "Detalls tècnics"
#: js/extensionPrefs/js/main.js:333
#: js/extensionPrefs/main.js:310
msgid "Copy Error"
msgstr "Copia l'error"
#: js/extensionPrefs/js/main.js:360
#: js/extensionPrefs/main.js:337
msgid "Homepage"
msgstr "Pàgina d'inici"
#: js/extensionPrefs/js/main.js:361
#: js/extensionPrefs/main.js:338
msgid "Visit extension homepage"
msgstr "Visiteu la pàgina d'inici de l'extensió"
#: js/extensionPrefs/js/main.js:478
#: js/extensionPrefs/main.js:449
#, javascript-format
msgid "%d extension will be updated on next login."
msgid_plural "%d extensions will be updated on next login."
msgstr[0] "%d extensió serà actualitzada la següent vegada que entreu."
msgstr[1] "%d extensions seran actualitzades la següent vegada que entreu."
#: js/extensionPrefs/data/ui/extension-row.ui:100
#: js/extensionPrefs/ui/extension-row.ui:100
#: subprojects/extensions-tool/src/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173
msgid "Description"
msgstr "Descripció"
#: js/extensionPrefs/data/ui/extension-row.ui:123
#: js/extensionPrefs/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185
msgid "Version"
msgstr "Versió"
#: js/extensionPrefs/data/ui/extension-row.ui:151
#: js/extensionPrefs/ui/extension-row.ui:151
msgid "Author"
msgstr "Autoria"
#: js/extensionPrefs/data/ui/extension-row.ui:175
#: js/extensionPrefs/ui/extension-row.ui:175
msgid "Website"
msgstr "Lloc web"
#: js/extensionPrefs/data/ui/extension-row.ui:192
#: js/extensionPrefs/ui/extension-row.ui:192
msgid "Remove…"
msgstr "Suprimeix…"
#: js/extensionPrefs/data/ui/extensions-window.ui:8
#: js/extensionPrefs/ui/extensions-window.ui:8
msgid "Help"
msgstr "Ajuda"
#: js/extensionPrefs/data/ui/extensions-window.ui:12
#: js/extensionPrefs/ui/extensions-window.ui:12
msgid "About Extensions"
msgstr "Quant a les extensions"
#: js/extensionPrefs/data/ui/extensions-window.ui:27
#: js/extensionPrefs/ui/extensions-window.ui:27
msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>."
@@ -539,11 +527,11 @@ msgstr ""
"Per visitar i afegir extensions, visiteu <a href=\"https://extensions.gnome."
"org\">extensions.gnome.org</a>."
#: js/extensionPrefs/data/ui/extensions-window.ui:35
#: js/extensionPrefs/ui/extensions-window.ui:35
msgid "Warning"
msgstr "Avís"
#: js/extensionPrefs/data/ui/extensions-window.ui:46
#: js/extensionPrefs/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 "
@@ -553,19 +541,19 @@ msgstr ""
"rendiment. Si us trobeu amb problemes amb el sistema, us recomanem "
"inhabilitar totes les extensions."
#: js/extensionPrefs/data/ui/extensions-window.ui:134
#: js/extensionPrefs/ui/extensions-window.ui:133
msgid "Manually Installed"
msgstr "Instal·lada manualment"
#: js/extensionPrefs/data/ui/extensions-window.ui:158
#: js/extensionPrefs/ui/extensions-window.ui:157
msgid "Built-In"
msgstr "Integrada"
#: js/extensionPrefs/data/ui/extensions-window.ui:199
#: js/extensionPrefs/ui/extensions-window.ui:198
msgid "No Installed Extensions"
msgstr "No hi ha cap extensió instal·lada"
#: js/extensionPrefs/data/ui/extensions-window.ui:235
#: js/extensionPrefs/ui/extensions-window.ui:234
msgid ""
"Were very sorry, but it was not possible to get the list of installed "
"extensions. Make sure you are logged into GNOME and try again."
@@ -573,15 +561,15 @@ msgstr ""
"No s'ha pogut obtenir la llista d'extensions instal·lades. Assegureu-vos que "
"heu entrat al GNOME i torneu a provar-ho."
#: js/extensionPrefs/data/ui/extensions-window.ui:288
#: js/extensionPrefs/ui/extensions-window.ui:287
msgid "Log Out…"
msgstr "Surt…"
#. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
#: js/ui/components/networkAgent.js:220 js/ui/components/networkAgent.js:244
#: js/ui/components/networkAgent.js:265 js/ui/components/networkAgent.js:285
#: js/ui/components/networkAgent.js:295 js/ui/components/polkitAgent.js:277
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:202
#: js/ui/components/networkAgent.js:218 js/ui/components/networkAgent.js:242
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:283
#: js/ui/components/networkAgent.js:293 js/ui/components/polkitAgent.js:277
#: js/ui/shellMountOperation.js:326
msgid "Password"
msgstr "Contrasenya"
@@ -604,8 +592,8 @@ msgstr "(p. ex. l'usuari o %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:240
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:238
#: js/ui/components/networkAgent.js:261 js/ui/components/networkAgent.js:279
msgid "Username"
msgstr "Nom d'usuari"
@@ -857,44 +845,44 @@ msgstr "Denega l'accés"
msgid "Grant Access"
msgstr "Permet l'accés"
#: js/ui/appDisplay.js:898
#: js/ui/appDisplay.js:906
msgid "Unnamed Folder"
msgstr "Carpeta sense nom"
#: js/ui/appDisplay.js:921
#: js/ui/appDisplay.js:929
msgid "Frequently used applications will appear here"
msgstr "Les aplicacions utilitzades freqüentment apareixeran aquí"
#: js/ui/appDisplay.js:1056
#: js/ui/appDisplay.js:1064
msgid "Frequent"
msgstr "Freqüent"
#: js/ui/appDisplay.js:1063
#: js/ui/appDisplay.js:1071
msgid "All"
msgstr "Totes"
#. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
#: js/ui/appDisplay.js:2450 js/ui/panel.js:75
msgid "Open Windows"
msgstr "Obre finestres"
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
#: js/ui/appDisplay.js:2470 js/ui/panel.js:82
msgid "New Window"
msgstr "Finestra nova"
#: js/ui/appDisplay.js:2477
#: js/ui/appDisplay.js:2481
msgid "Launch using Dedicated Graphics Card"
msgstr "Inicia usant una targeta gràfica dedicada"
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
#: js/ui/appDisplay.js:2509 js/ui/dash.js:239
msgid "Remove from Favorites"
msgstr "Suprimeix dels preferits"
#: js/ui/appDisplay.js:2511
#: js/ui/appDisplay.js:2515
msgid "Add to Favorites"
msgstr "Afegeix als preferits"
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
#: js/ui/appDisplay.js:2525 js/ui/panel.js:93
msgid "Show Details"
msgstr "Mostra els detalls"
@@ -1042,30 +1030,30 @@ msgid "All Day"
msgstr "Tot el dia"
#. Translators: Shown on calendar heading when selected day occurs on current year
#: js/ui/calendar.js:868
#: js/ui/calendar.js:867
msgctxt "calendar heading"
msgid "%A, %B %-d"
msgstr "%A %-d %B"
#. Translators: Shown on calendar heading when selected day occurs on different year
#: js/ui/calendar.js:871
#: js/ui/calendar.js:870
msgctxt "calendar heading"
msgid "%A, %B %-d, %Y"
msgstr "%A %d %B de %Y"
#: js/ui/calendar.js:1100
#: js/ui/calendar.js:1096
msgid "No Notifications"
msgstr "Cap notificació"
#: js/ui/calendar.js:1103
#: js/ui/calendar.js:1099
msgid "No Events"
msgstr "Cap cita"
#: js/ui/calendar.js:1157
#: js/ui/calendar.js:1153
msgid "Do Not Disturb"
msgstr "No molesteu"
#: js/ui/calendar.js:1171
#: js/ui/calendar.js:1167
msgid "Clear"
msgstr "Neteja-ho"
@@ -1113,38 +1101,38 @@ msgstr ""
msgid "Open with %s"
msgstr "Obre amb %s"
#: js/ui/components/networkAgent.js:91
#: js/ui/components/networkAgent.js:89
msgid ""
"Alternatively you can connect by pushing the “WPS” button on your router."
msgstr "També us podeu connectar prement el botó «WPS» del vostre encaminador."
#: js/ui/components/networkAgent.js:103 js/ui/status/network.js:223
#: js/ui/components/networkAgent.js:101 js/ui/status/network.js:223
#: js/ui/status/network.js:314 js/ui/status/network.js:916
msgid "Connect"
msgstr "Connecta"
#: js/ui/components/networkAgent.js:210
#: js/ui/components/networkAgent.js:208
msgid "Key"
msgstr "Clau"
#: js/ui/components/networkAgent.js:248 js/ui/components/networkAgent.js:271
#: js/ui/components/networkAgent.js:246 js/ui/components/networkAgent.js:269
msgid "Private key password"
msgstr "Contrasenya de la clau privada"
#: js/ui/components/networkAgent.js:269
#: js/ui/components/networkAgent.js:267
msgid "Identity"
msgstr "Identitat"
#: js/ui/components/networkAgent.js:283
#: js/ui/components/networkAgent.js:281
msgid "Service"
msgstr "Servei"
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:340
#: js/ui/components/networkAgent.js:679 js/ui/components/networkAgent.js:700
#: js/ui/components/networkAgent.js:310 js/ui/components/networkAgent.js:338
#: js/ui/components/networkAgent.js:685 js/ui/components/networkAgent.js:706
msgid "Authentication required"
msgstr "Cal autenticació"
#: js/ui/components/networkAgent.js:313 js/ui/components/networkAgent.js:680
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:686
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@@ -1153,42 +1141,42 @@ msgstr ""
"Per accedir a la xarxa sense fil «%s» calen les contrasenyes o les claus "
"d'encriptació."
#: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:684
#: js/ui/components/networkAgent.js:315 js/ui/components/networkAgent.js:690
msgid "Wired 802.1X authentication"
msgstr "Autenticació 802.1X amb fil"
#: js/ui/components/networkAgent.js:319
#: js/ui/components/networkAgent.js:317
msgid "Network name"
msgstr "Nom de la xarxa"
#: js/ui/components/networkAgent.js:324 js/ui/components/networkAgent.js:688
#: js/ui/components/networkAgent.js:322 js/ui/components/networkAgent.js:694
msgid "DSL authentication"
msgstr "Autenticació DSL"
#: js/ui/components/networkAgent.js:331 js/ui/components/networkAgent.js:693
#: js/ui/components/networkAgent.js:329 js/ui/components/networkAgent.js:699
msgid "PIN code required"
msgstr "Cal que introduïu el codi PIN"
#: js/ui/components/networkAgent.js:332 js/ui/components/networkAgent.js:694
#: js/ui/components/networkAgent.js:330 js/ui/components/networkAgent.js:700
msgid "PIN code is needed for the mobile broadband device"
msgstr "Cal que introduïu el codi PIN del dispositiu de banda ampla mòbil"
#: js/ui/components/networkAgent.js:333
#: js/ui/components/networkAgent.js:331
msgid "PIN"
msgstr "PIN"
#: js/ui/components/networkAgent.js:341 js/ui/components/networkAgent.js:685
#: js/ui/components/networkAgent.js:689 js/ui/components/networkAgent.js:701
#: js/ui/components/networkAgent.js:705
#: js/ui/components/networkAgent.js:339 js/ui/components/networkAgent.js:691
#: js/ui/components/networkAgent.js:695 js/ui/components/networkAgent.js:707
#: js/ui/components/networkAgent.js:711
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "Cal introduir una contrasenya per connectar-vos a «%s»."
#: js/ui/components/networkAgent.js:668 js/ui/status/network.js:1691
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1691
msgid "Network Manager"
msgstr "Gestor de connexions de xarxa"
#: js/ui/components/networkAgent.js:704
#: js/ui/components/networkAgent.js:710
msgid "VPN password"
msgstr "Contrasenya VPN"
@@ -1258,23 +1246,23 @@ msgstr "Afegeix rellotges del món…"
msgid "World Clocks"
msgstr "Rellotges del món"
#: js/ui/dateMenu.js:289
#: js/ui/dateMenu.js:276
msgid "Weather"
msgstr "El temps"
#: js/ui/dateMenu.js:404
#: js/ui/dateMenu.js:391
msgid "Select a location…"
msgstr "Trieu una ubicació…"
#: js/ui/dateMenu.js:417
#: js/ui/dateMenu.js:404
msgid "Loading…"
msgstr "S'està carregant…"
#: js/ui/dateMenu.js:427
#: js/ui/dateMenu.js:414
msgid "Go online for weather information"
msgstr "Vés en línia per a informació sobre el temps"
#: js/ui/dateMenu.js:429
#: js/ui/dateMenu.js:416
msgid "Weather information is currently unavailable"
msgstr "La informació sobre el temps no està disponible"
@@ -1430,15 +1418,15 @@ msgstr "%s (remot)"
msgid "%s (console)"
msgstr "%s (consola)"
#: js/ui/extensionDownloader.js:181
#: js/ui/extensionDownloader.js:169
msgid "Install"
msgstr "Instal·la"
#: js/ui/extensionDownloader.js:187
#: js/ui/extensionDownloader.js:175
msgid "Install Extension"
msgstr "Instal·la l'extensió"
#: js/ui/extensionDownloader.js:188
#: js/ui/extensionDownloader.js:176
#, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» d'extensions.gnome.org?"
@@ -1598,11 +1586,11 @@ msgstr "Mostra el codi font"
msgid "Web Page"
msgstr "Pàgina web"
#: js/ui/main.js:274
#: js/ui/main.js:269
msgid "Logged in as a privileged user"
msgstr "Sessió iniciada com a usuari privilegiat"
#: js/ui/main.js:275
#: js/ui/main.js:270
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
@@ -1610,11 +1598,11 @@ msgstr ""
"Cal evitar iniciar sessions com a usuari privilegiat per raons de seguretat. "
"Si és possible, entreu com a un usuari normal."
#: js/ui/main.js:281
#: js/ui/main.js:276
msgid "Screen Lock disabled"
msgstr "La pantalla de bloqueig està inhabilitada"
#: js/ui/main.js:282
#: js/ui/main.js:277
msgid "Screen Locking requires the GNOME display manager."
msgstr "El bloqueig de pantalla requereix el gestor de pantalla del GNOME."
@@ -1646,7 +1634,7 @@ msgstr "Vista general"
#. characters.
#: js/ui/overview.js:107
msgid "Type to search"
msgstr "Teclegeu per a cercar"
msgstr "Teclegeu per començar la cerca"
#: js/ui/padOsd.js:95
msgid "New shortcut…"
@@ -1686,11 +1674,11 @@ msgstr "Premeu un botó per a configurar"
#: js/ui/padOsd.js:864
msgid "Press Esc to exit"
msgstr "Premeu Esc per a sortir"
msgstr "Premeu Esc per sortir"
#: js/ui/padOsd.js:867
msgid "Press any key to exit"
msgstr "Premeu qualsevol tecla per a sortir"
msgstr "Premeu qualsevol tecla per sortir"
#: js/ui/panel.js:109
msgid "Quit"
@@ -2351,11 +2339,11 @@ msgstr "%A %-d %B"
#: js/ui/unlockDialog.js:376
msgid "Swipe up to unlock"
msgstr "Llisqueu amunt per a desbloquejar"
msgstr "Llisqueu amunt per desbloquejar"
#: js/ui/unlockDialog.js:377
msgid "Click or press a key to unlock"
msgstr "Feu clic o premeu una tecla per a desbloquejar"
msgstr "Feu clic o premeu una tecla per desbloquejar"
#: js/ui/unlockDialog.js:549
msgid "Unlock Window"
@@ -2480,19 +2468,19 @@ msgstr "Tanca"
msgid "Evolution Calendar"
msgstr "Calendari de l'Evolution"
#: src/main.c:458 subprojects/extensions-tool/src/main.c:249
#: src/main.c:460 subprojects/extensions-tool/src/main.c:249
msgid "Print version"
msgstr "Mostra la versió"
#: src/main.c:464
#: src/main.c:466
msgid "Mode used by GDM for login screen"
msgstr "El mode que utilitzarà el GDM per a la pantalla d'entrada"
#: src/main.c:470
#: src/main.c:472
msgid "Use a specific mode, e.g. “gdm” for login screen"
msgstr "Utilitza un mode específic, p. ex. «gdm» per la pantalla d'entrada"
#: src/main.c:476
#: src/main.c:478
msgid "List possible modes"
msgstr "Llista els modes possibles"
@@ -2830,7 +2818,7 @@ msgstr "Instal·la un paquet d'extensió"
#: subprojects/extensions-tool/src/main.c:262
#, c-format
msgid "Use “%s” to get detailed help.\n"
msgstr "Feu servir «%s» per a obtenir ajuda detallada.\n"
msgstr "Feu servir «%s» per obtenir ajuda detallada.\n"
#. translators:
#. * The number of sound outputs on a particular device

2619
po/ckb.po

File diff suppressed because it is too large Load Diff

1693
po/cs.po

File diff suppressed because it is too large Load Diff

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