Compare commits

..

7 Commits

Author SHA1 Message Date
Alexander Mikhaylenko
b1afb946b2 workspaceAnimation: Support multiple monitors
Currently, there's one animation for the whole canvas. While it looks fine
with just one screen, it causes windows to move between screens when
switching workspaces. Instead, have a separate animation on each screen,
and sync their progress so that at any given time the progress "fraction"
is the same between all screens. Clip all animations to their screens so
that the windows don't leak to other screens.

If a window is placed between every screen, can end up in multiple
animations, in that case each part is still animated separately.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
46d5bccfc6 workspaceAnimation: Use window clones
Instead of reparenting windows, clone them. This will allow to properly
support multi-monitor setups in subsequent commits.

Block window mapping animation while the animation is running to prevent
new windows appearing during the animation from being visible at the same
time as their clones.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/929

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
f0d498062d workspaceAnimation: Only create moving window bin when needed
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
eeac4a3b6d workspaceAnimation: Extract WorkspaceGroup
Reimplement _syncStacking().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
272cb4d523 workspaceAnimation: Extract WorkspaceAnimation
Simplify the logic a bit. Introduce WorkspaceAnimation class that reparents
the windows from current, surrounding and destination workspaces and manages
them. Expose 'progress' property and have WorkspaceAnimationController animate
it instead of animating everything separately.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
6d5446e4a6 workspaceAnimation: Stop depending on shellwm
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
Alexander Mikhaylenko
fa31bcaa7a workspaceAnimation: Split from WindowManager
It's already too complex, and will get more complex in future, split it
out.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605
2020-02-26 10:36:10 +01:00
206 changed files with 14201 additions and 22839 deletions

View File

@@ -1,13 +1,9 @@
include: 'https://gitlab.gnome.org/GNOME/citemplates/raw/master/flatpak/flatpak_ci_initiative.yml'
stages: stages:
- review - review
- build - build
- test - test
- deploy
variables: variables:
BUNDLE: "extensions-git.flatpak"
JS_LOG: "js-report.txt" JS_LOG: "js-report.txt"
POT_LOG: "pot-update.txt" POT_LOG: "pot-update.txt"
@@ -50,20 +46,6 @@ eslint:
- reports - reports
when: always when: always
potfile_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/check-potfiles.sh
<<: *only_default
no_template_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/check-template-strings.sh
<<: *only_default
build: build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3 image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: build stage: build
@@ -114,24 +96,3 @@ test-pot:
' | tee $POT_LOG ' | tee $POT_LOG
- (! grep -q . $POT_LOG) - (! grep -q . $POT_LOG)
<<: *only_default <<: *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

@@ -1,26 +0,0 @@
#!/usr/bin/env bash
srcdirs="js src subprojects/extensions-tool"
globs=('*.js' '*.c')
# find source files that contain gettext keywords
files=$(grep -lR ${globs[@]/#/--include=} '\(gettext\|[^I_)]_\)(' $srcdirs)
# find those that aren't listed in POTFILES.in
missing=$(for f in $files; do ! grep -q ^$f po/POTFILES.in && echo $f; done)
if [ ${#missing} -eq 0 ]; then
exit 0
fi
cat >&2 <<EOT
The following files are missing from po/POTFILES.po:
EOT
for f in $missing; do
echo " $f" >&2
done
echo >&2
exit 1

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
# find files from POTFILES.in that use js template strings
baddies=$(grep -l '${' $(grep ^js po/POTFILES.in))
if [ ${#baddies} -eq 0 ]; then
exit 0
fi
cat >&2 <<EOT
xgettext cannot handle template strings properly, so we ban their use
in files with translatable strings.
The following files are listed in po/POTFILES.in and use template strings:
EOT
for f in $baddies; do
echo " $f" >&2
done
echo >&2
exit 1

View File

@@ -23,7 +23,7 @@ run_eslint() {
mkdir -p $(dirname $output) mkdir -p $(dirname $output)
touch $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() { list_commit_range_additions() {

125
NEWS
View File

@@ -1,128 +1,3 @@
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]
* Fix missing "back" button on login screen [Florian; #2228]
* Fix width of window preview titles in overview [Jonas D.; #58]
* Fix looking glass text with light style variant [Feichtmeier; !1023]
* Center unlock entry [Florian; !1021]
* Hide overlay scrollbars in notification popup [Jonas D.; !1013]
* Work around add_actor() slowness in icon spring animation [Daniel; !1002]
* Add disable-animations heuristics [Jonas Å.; !757]
* Fix visual glitches in on-screen keyboard [Carlos; #2214]
* Fix clearing changed textures from cache [Florian; #2244]
* Fix visual glitch in sliders [Daniel; #1569]
* Stop using dedicated lock screen background [Florian; !1001]
* Fix entries disappearing after authentication errors [Florian; #2236]
* Fix crash when animations are disabled [Florian; #2255]
* Fix passing pointer events to clients when magnified [Jonas D.; !993]
* Fix keynav on new lock screen [Florian; #2210]
* Avoid short-lived allocations on actor removal [Christian; #2263]
* Fix super-sized default avatars in user list [Florian, Sam; #2242]
* Leave overview when locking the screen [Jonas D.; !1043]
* Hide message list on login screen [Florian; #2241]
* Avoid IO on the main thread [Christian, Florian; !1050, !1051]
* Fix window animations getting stuck when client doesn't respond [Jonas; !1055]
* Only subscribe to touchpad events for touchpad gestures [Daniel; !925]
* Start X11 session services before Xwayland clients [Carlos; !836, !1056]
* Only show switch-user button with unlock prompt [Florian; !1029]
* Misc. bug fixes and cleanups [Jonas D., Florian, Georges, Jonas Å., Daniel,
Jakub, Philippe; !1018, !1020, !1024, !1027, !1026, !1022, !1031, !1035,
!1032, !1025, !1039, #2157, !1037, !1042, !1047, !1048, #2270, !1046,
!167, !1016]
Contributors:
Jonas Dreßler, Feichtmeier, Carlos Garnacho, Christian Hergert, Sam Hewitt,
Florian Müllner, Georges Basile Stavracas Neto, Jakub Steiner, Philippe Troin,
Daniel van Vugt, Jonas Ådahl
Translators:
Danial Behzadi [fa], Efstathios Iosifidis [el], Daniel Mustieles [es],
Sabri Ünal [tr], sicklylife [ja], Piotr Drąg [pl], Jordi Mas [ca],
Anders Jonsson [sv], Chao-Hsiung Liao [zh_TW], Asier Sarasua Garmendia [eu],
Rafael Fontenelle [pt_BR], Марко Костић [sr], Changwoo Ryu [ko],
Charles Monzat [fr], Jiri Grönroos [fi], Jor Teron [mjw], Bruce Cowan [en_GB],
Emin Tufan Çetin [tr], Alan Mortensen [da], Balázs Úr [hu], Fran Dieguez [gl],
Kukuh Syafaat [id]
3.35.91 3.35.91
======= =======
* Improve magnifier [Carlos; !984] * Improve magnifier [Carlos; !984]

View File

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

View File

@@ -199,37 +199,14 @@
<!-- <!--
LaunchExtensionPrefs: LaunchExtensionPrefs:
Deprecated for OpenExtensionPrefs @uuid: The UUID of the extension
Launch preferences of an extension.
--> -->
<method name="LaunchExtensionPrefs"> <method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/> <arg type="s" direction="in" name="uuid"/>
</method> </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: CheckForUpdates:
Update all extensions for which updates are available Update all extensions for which updates are available
@@ -257,11 +234,5 @@
--> -->
<property name="ShellVersion" type="s" access="read"/> <property name="ShellVersion" type="s" access="read"/>
<!--
UserExtensionsEnabled:
Whether user extensions are enabled
-->
<property name="UserExtensionsEnabled" type="b" access="readwrite"/>
</interface> </interface>
</node> </node>

View File

@@ -19,10 +19,6 @@ Before=gnome-session-initialized.target
[Service] [Service]
Type=notify Type=notify
ExecStart=@bindir@/gnome-shell 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 # Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1 SuccessExitStatus=1
# On wayland we cannot restart # 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,6 @@
desktop_files = [ desktop_files = [
'org.gnome.Shell.desktop', 'org.gnome.Shell.desktop',
'org.gnome.Shell.Extensions.desktop', 'org.gnome.Extensions.desktop',
] ]
service_files = [] service_files = []

View File

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

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

View File

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

View File

@@ -15,11 +15,13 @@
border: 1px solid transparent; border: 1px solid transparent;
&:outlined { &: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 { &:selected {
background-color: transparentize($osd_fg_color, 0.7); background-color: transparentize($osd_fg_color, 0.9);
color: $osd_fg_color; color: $osd_fg_color;
} }
} }

View File

@@ -1,9 +1,10 @@
#!/bin/env bash #!/bin/env bash
CLDR_LAYOUTS_TARBALL="http://www.unicode.org/Public/cldr/latest/keyboards.zip" CLDR_LAYOUTS_TARBALL="http://www.unicode.org/Public/cldr/latest/keyboards.zip"
CLDR2JSON_GIT="git://repo.or.cz/cldr2json.git"
WORKDIR=".osk-layout-workbench" WORKDIR=".osk-layout-workbench"
CLDR2JSON="cldr2json/cldr2json.py" CLDR2JSON="$WORKDIR/cldr2json/cldr2json.py"
SRCDIR="$WORKDIR/keyboards/android" SRCDIR="$WORKDIR/keyboards/android"
DESTDIR="osk-layouts" DESTDIR="osk-layouts"
GRESOURCE_FILE="gnome-shell-osk-layouts.gresource.xml" GRESOURCE_FILE="gnome-shell-osk-layouts.gresource.xml"
@@ -19,6 +20,7 @@ mkdir -p "osk-layouts"
# Download stuff on the work dir # Download stuff on the work dir
pushd $WORKDIR pushd $WORKDIR
gio copy $CLDR_LAYOUTS_TARBALL . gio copy $CLDR_LAYOUTS_TARBALL .
git clone $CLDR2JSON_GIT
unzip keyboards.zip unzip keyboards.zip
popd 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'; imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext; const Gettext = imports.gettext;
const Package = imports.package; const { Gdk, GLib, Gio, GObject, Gtk } = imports.gi;
const { Gdk, GLib, Gio, GObject, Gtk, Shew } = imports.gi; const Format = imports.format;
Package.initFormat(); const _ = Gettext.gettext;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState, ExtensionType } = ExtensionUtils; const { ExtensionState, ExtensionType } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions'); const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
Gio._promisify(Shew.WindowExporter.prototype, 'export', 'export_finish'); function stripPrefix(string, prefix) {
if (string.slice(0, prefix.length) == prefix)
function loadInterfaceXML(iface) { return string.slice(prefix.length);
const uri = 'resource:///org/gnome/Extensions/dbus-interfaces/%s.xml'.format(iface); return string;
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()));
} }
var Application = GObject.registerClass( var Application = GObject.registerClass(
class Application extends Gtk.Application { class Application extends Gtk.Application {
_init() { _init() {
GLib.set_prgname('gnome-shell-extension-prefs'); 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() { get shellProxy() {
@@ -56,7 +46,7 @@ class Application extends Gtk.Application {
super.vfunc_startup(); super.vfunc_startup();
let provider = new Gtk.CssProvider(); let provider = new Gtk.CssProvider();
let uri = 'resource:///org/gnome/Extensions/css/application.css'; let uri = 'resource:///org/gnome/shell/css/application.css';
try { try {
provider.load_from_file(Gio.File.new_for_uri(uri)); provider.load_from_file(Gio.File.new_for_uri(uri));
} catch (e) { } catch (e) {
@@ -66,19 +56,34 @@ class Application extends Gtk.Application {
provider, provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
'org.gnome.Shell.Extensions', '/org/gnome/Shell/Extensions');
this._window = new ExtensionsWindow({ application: this }); 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({ var ExtensionsWindow = GObject.registerClass({
GTypeName: 'ExtensionsWindow', GTypeName: 'ExtensionsWindow',
Template: 'resource:///org/gnome/Extensions/ui/extensions-window.ui', Template: 'resource:///org/gnome/shell/ui/extensions-window.ui',
InternalChildren: [ InternalChildren: [
'userList', 'userList',
'systemList', 'systemList',
'killSwitch',
'mainBox', 'mainBox',
'mainStack', 'mainStack',
'scrolledWindow', 'scrolledWindow',
@@ -89,11 +94,11 @@ var ExtensionsWindow = GObject.registerClass({
_init(params) { _init(params) {
super._init(params); super._init(params);
this._startupUuid = null;
this._loaded = false;
this._prefsDialog = null;
this._updatesCheckId = 0; this._updatesCheckId = 0;
this._exporter = new Shew.WindowExporter({ window: this });
this._exportedHandle = '';
this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment); this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment);
let action; let action;
@@ -105,15 +110,10 @@ var ExtensionsWindow = GObject.registerClass({
action.connect('activate', this._logout.bind(this)); action.connect('activate', this._logout.bind(this));
this.add_action(action); this.add_action(action);
action = new Gio.SimpleAction({ this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
name: 'user-extensions-enabled', this._settings.bind('disable-user-extensions',
state: new GLib.Variant('b', false), this._killSwitch, 'active',
}); Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN);
action.connect('activate', toggleState);
action.connect('change-state', (a, state) => {
this._shellProxy.UserExtensionsEnabled = state.get_boolean();
});
this.add_action(action);
this._userList.set_sort_func(this._sortList.bind(this)); this._userList.set_sort_func(this._sortList.bind(this));
this._userList.set_header_func(this._updateHeader.bind(this)); this._userList.set_header_func(this._updateHeader.bind(this));
@@ -124,10 +124,6 @@ var ExtensionsWindow = GObject.registerClass({
this._shellProxy.connectSignal('ExtensionStateChanged', this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this)); this._onExtensionStateChanged.bind(this));
this._shellProxy.connect('g-properties-changed',
this._onUserExtensionsEnabledChanged.bind(this));
this._onUserExtensionsEnabledChanged();
this._scanExtensions(); this._scanExtensions();
} }
@@ -157,18 +153,58 @@ var ExtensionsWindow = GObject.registerClass({
dialog.present(); dialog.present();
} }
async openPrefs(uuid) { openPrefs(uuid) {
if (!this._exportedHandle) { if (!this._loaded)
try { this._startupUuid = uuid;
this._exportedHandle = await this._exporter.export(); else if (!this._showPrefs(uuid))
} catch (e) { this.present();
log('Failed to export window: %s'.format(e.message));
}
} }
this._shellProxy.OpenExtensionPrefsRemote(uuid, _showPrefs(uuid) {
this._exportedHandle, if (this._prefsDialog)
{ modal: new GLib.Variant('b', true) }); 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._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() { _showAbout() {
@@ -183,7 +219,7 @@ var ExtensionsWindow = GObject.registerClass({
comments: _('Manage your GNOME Extensions'), comments: _('Manage your GNOME Extensions'),
license_type: Gtk.License.GPL_2_0, license_type: Gtk.License.GPL_2_0,
logo_icon_name: 'org.gnome.Extensions', logo_icon_name: 'org.gnome.Extensions',
version: imports.package.version, version: Config.PACKAGE_VERSION,
transient_for: this, transient_for: this,
modal: true, 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) { _sortList(row1, row2) {
return row1.name.localeCompare(row2.name); return row1.name.localeCompare(row2.name);
} }
@@ -226,12 +377,6 @@ var ExtensionsWindow = GObject.registerClass({
].find(c => c.uuid === uuid); ].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]) { _onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let extension = ExtensionUtils.deserializeExtension(newState); let extension = ExtensionUtils.deserializeExtension(newState);
let row = this._findExtensionRow(uuid); let row = this._findExtensionRow(uuid);
@@ -249,11 +394,9 @@ var ExtensionsWindow = GObject.registerClass({
if (row) { if (row) {
if (extension.state === ExtensionState.UNINSTALLED) if (extension.state === ExtensionState.UNINSTALLED)
row.destroy(); row.destroy();
} else { return; // we only deal with new and deleted extensions here
this._addExtensionRow(extension);
} }
this._addExtensionRow(extension);
this._syncListVisibility();
} }
_scanExtensions() { _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() { _checkUpdates() {
let nUpdates = this._userList.get_children().filter(c => c.hasUpdate).length; let nUpdates = this._userList.get_children().filter(c => c.hasUpdate).length;
@@ -320,14 +453,125 @@ var ExtensionsWindow = GObject.registerClass({
} }
_extensionsLoaded() { _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(); 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({ var ExtensionRow = GObject.registerClass({
GTypeName: 'ExtensionRow', GTypeName: 'ExtensionRow',
Template: 'resource:///org/gnome/Extensions/ui/extension-row.ui', Template: 'resource:///org/gnome/shell/ui/extension-row.ui',
InternalChildren: [ InternalChildren: [
'nameLabel', 'nameLabel',
'descriptionLabel', 'descriptionLabel',
@@ -377,7 +621,10 @@ var ExtensionRow = GObject.registerClass({
name: 'enabled', name: 'enabled',
state: new GLib.Variant('b', false), 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) => { action.connect('change-state', (a, state) => {
if (state.get_boolean()) if (state.get_boolean())
this._app.shellProxy.EnableExtensionRemote(this.uuid); this._app.shellProxy.EnableExtensionRemote(this.uuid);
@@ -386,7 +633,8 @@ var ExtensionRow = GObject.registerClass({
}); });
this._actionGroup.add_action(action); 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]; let desc = this._extension.metadata.description.split('\n')[0];
this._descriptionLabel.label = desc; this._descriptionLabel.label = desc;
@@ -474,6 +722,20 @@ var ExtensionRow = GObject.registerClass({
_canToggle() { _canToggle() {
return this._extension.canChange; 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() { function initEnvironment() {
@@ -490,11 +752,12 @@ function initEnvironment() {
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']), userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']),
}; };
String.prototype.format = Format.format;
} }
function main(argv) { function main(argv) {
initEnvironment(); initEnvironment();
Package.initGettext();
new Application().run(argv); new Application().run(argv);
} }

View File

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

View File

@@ -120,7 +120,7 @@ var AuthPrompt = GObject.registerClass({
vfunc_key_press_event(keyPressEvent) { vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape) if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel(); this.cancel();
return super.vfunc_key_press_event(keyPressEvent); return Clutter.EVENT_PROPAGATE;
} }
_initEntryRow() { _initEntryRow() {
@@ -425,6 +425,7 @@ var AuthPrompt = GObject.registerClass({
updateSensitivity(sensitive) { updateSensitivity(sensitive) {
this._entry.reactive = sensitive; this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
} }
vfunc_hide() { vfunc_hide() {

View File

@@ -35,6 +35,7 @@ const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250; const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500; const _SCROLL_ANIMATION_TIME = 500;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
var UserListItem = GObject.registerClass({ var UserListItem = GObject.registerClass({
Signals: { 'activate': {} }, Signals: { 'activate': {} },
@@ -177,7 +178,6 @@ var UserList = GObject.registerClass({
} }
vfunc_key_focus_in() { vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._moveFocusToItems(); this._moveFocusToItems();
} }
@@ -456,6 +456,7 @@ var LoginDialog = GObject.registerClass({
let notListedLabel = new St.Label({ let notListedLabel = new St.Label({
text: _("Not listed?"), text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label', style_class: 'login-dialog-not-listed-label',
x_align: Clutter.ActorAlign.START,
}); });
this._notListedButton = new St.Button({ this._notListedButton = new St.Button({
style_class: 'login-dialog-not-listed-button', style_class: 'login-dialog-not-listed-button',
@@ -463,7 +464,6 @@ var LoginDialog = GObject.registerClass({
can_focus: true, can_focus: true,
child: notListedLabel, child: notListedLabel,
reactive: true, reactive: true,
x_align: Clutter.ActorAlign.START,
}); });
this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this)); this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this));
@@ -813,7 +813,7 @@ var LoginDialog = GObject.registerClass({
if (this._logoFile && this._logoBin.resource_scale > 0) { if (this._logoFile && this._logoBin.resource_scale > 0) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile, this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, -1, -1, _LOGO_ICON_HEIGHT,
scaleFactor, scaleFactor,
this._logoBin.resource_scale)); this._logoBin.resource_scale));
} }

View File

@@ -109,6 +109,7 @@
<file>ui/windowMenu.js</file> <file>ui/windowMenu.js</file>
<file>ui/windowManager.js</file> <file>ui/windowManager.js</file>
<file>ui/workspace.js</file> <file>ui/workspace.js</file>
<file>ui/workspaceAnimation.js</file>
<file>ui/workspaceSwitcherPopup.js</file> <file>ui/workspaceSwitcherPopup.js</file>
<file>ui/workspaceThumbnail.js</file> <file>ui/workspaceThumbnail.js</file>
<file>ui/workspacesView.js</file> <file>ui/workspacesView.js</file>

View File

@@ -1,5 +1,4 @@
subdir('misc') subdir('misc')
subdir('dbusServices')
js_resources = gnome.compile_resources( js_resources = gnome.compile_resources(
'js-resources', 'js-resources.gresource.xml', 'js-resources', 'js-resources.gresource.xml',
@@ -14,3 +13,10 @@ portal_resources = gnome.compile_resources(
c_name: 'portal_js_resources', c_name: 'portal_js_resources',
dependencies: [config_js] 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 */ /* other standard directories */
var LIBEXECDIR = '@libexecdir@'; var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@'; var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
var VPNDIR = '@vpndir@';
/* g-i package versions */ /* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@' var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension, /* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, openPrefs, isOutOfDate, getSettings, initTranslations, isOutOfDate, installImporter,
installImporter, serializeExtension, deserializeExtension */ serializeExtension, deserializeExtension */
// Common utils for the extension system and the extension // Common utils for the extension system and the extension
// preferences tool // preferences tool
@@ -153,27 +153,6 @@ function getSettings(schema) {
return new Gio.Settings({ settings_schema: schemaObj }); 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: * versionCheck:
* @param {string[]} required - an array of versions we're compatible with * @param {string[]} required - an array of versions we're compatible with

View File

@@ -76,15 +76,19 @@ function loadInterfaceXML(iface) {
_ifaceResource._register(); _ifaceResource._register();
} }
let xml = null;
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`; let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
let f = Gio.File.new_for_uri(uri); let f = Gio.File.new_for_uri(uri);
try { try {
let [ok_, bytes] = f.load_contents(null); 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) { } catch (e) {
log(`Failed to load D-Bus interface ${iface}`); 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 -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */ /* exported getIBusManager */
const { Gio, GLib, IBus, Meta } = imports.gi; const { Gio, GLib, IBus } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup; const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@@ -55,18 +55,13 @@ var IBusManager = class {
this._ibus.set_watch_ibus_signal(true); this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this)); this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn(Meta.is_wayland_compositor() ? [] : ['--xim']); this._spawn();
} }
_spawn(extraArgs = []) { _spawn(extraArgs = []) {
try { try {
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs]; let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs];
let launcher = Gio.SubprocessLauncher.new(Gio.SubprocessFlags.NONE); Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE);
// Forward the right X11 Display for ibus-x11
let display = GLib.getenv('GNOME_SETUP_DISPLAY');
if (display)
launcher.setenv('DISPLAY', display, true);
launcher.spawnv(cmdLine);
} catch (e) { } catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`); log(`Failed to launch ibus-daemon: ${e.message}`);
} }
@@ -127,20 +122,18 @@ var IBusManager = class {
} }
_initPanelService(ibus, result) { _initPanelService(ibus, result) {
let success = false;
try { try {
this._ibus.request_name_async_finish(result); success = !!this._ibus.request_name_async_finish(result);
} catch (e) { } catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
this._clear();
}
return; return;
logError(e);
} }
this._panelService = new IBus.PanelService({ if (success) {
connection: this._ibus.get_connection(), this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL, object_path: IBus.PATH_PANEL });
});
this._candidatePopup.setPanelService(this._panelService); this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this)); this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => { this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
@@ -176,6 +169,9 @@ var IBusManager = class {
this._engineChanged(this._ibus, engine.get_name()); this._engineChanged(this._ibus, engine.get_name());
}); });
this._updateReadiness(); this._updateReadiness();
} else {
this._clear();
}
} }
_updateReadiness() { _updateReadiness() {

View File

@@ -97,13 +97,8 @@ class InputMethod extends Clutter.InputMethod {
this.commit(text.get_text()); this.commit(text.get_text());
} }
_onDeleteSurroundingText(_context, offset, nchars) { _onDeleteSurroundingText() {
try { this.delete_surrounding();
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);
}
} }
_onUpdatePreeditText(_context, text, pos, visible) { _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.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir) jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir) jsconf.set('libexecdir', libexecdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file( config_js = configure_file(
input: 'config.js.in', input: 'config.js.in',

View File

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

View File

@@ -5,5 +5,6 @@
<file>misc/config.js</file> <file>misc/config.js</file>
<file>misc/fileUtils.js</file> <file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource> </gresource>
</gresources> </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

@@ -280,10 +280,12 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
_onDestroy() { _onDestroy() {
super._onDestroy();
if (this._thumbnails)
this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0) if (this._thumbnailTimeoutId != 0)
GLib.source_remove(this._thumbnailTimeoutId); GLib.source_remove(this._thumbnailTimeoutId);
super._onDestroy();
} }
/** /**
@@ -363,7 +365,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}, },
}); });
this._thumbnails = null; this._thumbnails = null;
this._switcherList.removeAccessibleState(this._selectedIndex, Atk.StateType.EXPANDED); if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state(Atk.StateType.EXPANDED);
} }
_createThumbnails() { _createThumbnails() {
@@ -392,7 +395,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}, },
}); });
this._switcherList.addAccessibleState(this._selectedIndex, Atk.StateType.EXPANDED); this._switcherList._items[this._selectedIndex].add_accessible_state(Atk.StateType.EXPANDED);
} }
}); });
@@ -773,9 +776,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// We override SwitcherList's _onItemEnter method to delay // We override SwitcherList's _onItemEnter method to delay
// activation when the thumbnail list is open // activation when the thumbnail list is open
_onItemEnter(item) { _onItemEnter(index) {
const index = this._items.indexOf(item);
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
GLib.source_remove(this._mouseTimeOutId); GLib.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) { if (this._altTabPopup.thumbnailsVisible) {

View File

@@ -15,7 +15,8 @@ class Animation extends St.Bin {
const themeContext = St.ThemeContext.get_for_stage(global.stage); const themeContext = St.ThemeContext.get_for_stage(global.stage);
super._init({ 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)); this.connect('destroy', this._onDestroy.bind(this));

View File

@@ -71,9 +71,15 @@ function _getFolderName(folder) {
let name = folder.get_string('name'); let name = folder.get_string('name');
if (folder.get_boolean('translate')) { if (folder.get_boolean('translate')) {
let translated = Shell.util_get_translated_folder_name(name); let keyfile = new GLib.KeyFile();
if (translated !== null) let path = 'desktop-directories/%s'.format(name);
return translated;
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; return name;
@@ -114,9 +120,15 @@ function _findBestFolderName(apps) {
}, commonCategories); }, commonCategories);
for (let category of commonCategories) { for (let category of commonCategories) {
let translated = Shell.util_get_translated_folder_name(category); let keyfile = new GLib.KeyFile();
if (translated !== null) let path = 'desktop-directories/%s.directory'.format(category);
return translated;
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
return keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch (e) {
continue;
}
} }
return null; return null;
@@ -157,10 +169,6 @@ var BaseAppView = GObject.registerClass({
this._items = new Map(); this._items = new Map();
this._orderedItems = []; this._orderedItems = [];
this._animateLaterId = 0;
this._viewLoadedHandlerId = 0;
this._viewIsReady = false;
} }
_childFocused(_actor) { _childFocused(_actor) {
@@ -196,7 +204,6 @@ var BaseAppView = GObject.registerClass({
this._items.set(icon.id, icon); this._items.set(icon.id, icon);
}); });
this._viewIsReady = true;
this.emit('view-loaded'); this.emit('view-loaded');
} }
@@ -246,18 +253,6 @@ var BaseAppView = GObject.registerClass({
Main.overview.dash.showAppsButton); 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) { animate(animationDirection, onComplete) {
if (onComplete) { if (onComplete) {
let animationDoneId = this._grid.connect('animation-done', () => { let animationDoneId = this._grid.connect('animation-done', () => {
@@ -266,38 +261,16 @@ var BaseAppView = GObject.registerClass({
}); });
} }
this._clearAnimateLater();
if (animationDirection == IconGrid.AnimationDirection.IN) { if (animationDirection == IconGrid.AnimationDirection.IN) {
const doSpringAnimationLater = laterType => { let id = this._grid.connect('paint', () => {
this._animateLaterId = Meta.later_add(laterType, this._grid.disconnect(id);
() => {
this._animateLaterId = 0;
this._doSpringAnimation(animationDirection); 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);
});
}
} else { } else {
this._doSpringAnimation(animationDirection); this._doSpringAnimation(animationDirection);
} }
} }
vfunc_unmap() {
this._clearAnimateLater();
super.vfunc_unmap();
}
animateSwitch(animationDirection) { animateSwitch(animationDirection) {
this.remove_all_transitions(); this.remove_all_transitions();
this._grid.remove_all_transitions(); this._grid.remove_all_transitions();
@@ -419,12 +392,10 @@ var AllView = GObject.registerClass({
this._redisplayWorkId = Main.initializeDeferredWork(this, this._redisplay.bind(this)); this._redisplayWorkId = Main.initializeDeferredWork(this, this._redisplay.bind(this));
Shell.AppSystem.get_default().connect('installed-changed', () => { Shell.AppSystem.get_default().connect('installed-changed', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId); Main.queueDeferredWork(this._redisplayWorkId);
}); });
this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' }); this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
this._folderSettings.connect('changed::folder-children', () => { this._folderSettings.connect('changed::folder-children', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId); Main.queueDeferredWork(this._redisplayWorkId);
}); });
@@ -460,10 +431,6 @@ var AllView = GObject.registerClass({
_redisplay() { _redisplay() {
super._redisplay(); super._redisplay();
this._folderIcons.forEach(icon => {
icon.view._redisplay();
});
this._refilterApps(); this._refilterApps();
} }
@@ -732,6 +699,8 @@ var AllView = GObject.registerClass({
// Toggle search entry // Toggle search entry
Main.overview.searchEntry.reactive = !isOpen; Main.overview.searchEntry.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.editable = !isOpen;
this._displayingPopup = isOpen; this._displayingPopup = isOpen;
}); });
@@ -1290,8 +1259,8 @@ var AppSearchProvider = class AppSearchProvider {
let results = []; let results = [];
groups.forEach(group => { groups.forEach(group => {
group = group.filter(appID => { group = group.filter(appID => {
const app = this._appSys.lookup_app(appID); let app = Gio.DesktopAppInfo.new(appID);
return app && app.app_info.should_show(); return app && app.should_show();
}); });
results = results.concat(group.sort( results = results.concat(group.sort(
(a, b) => usage.compare(a, b) (a, b) => usage.compare(a, b)
@@ -1339,7 +1308,7 @@ class FolderView extends BaseAppView {
x_expand: true, x_expand: true,
y_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); this.add_actor(this._scrollView);
let scrollableContainer = new St.BoxLayout({ let scrollableContainer = new St.BoxLayout({
@@ -1355,6 +1324,7 @@ class FolderView extends BaseAppView {
action.connect('pan', this._onPan.bind(this)); action.connect('pan', this._onPan.bind(this));
this._scrollView.add_action(action); this._scrollView.add_action(action);
this._folder.connect('changed', this._redisplay.bind(this));
this._redisplay(); this._redisplay();
} }
@@ -1376,12 +1346,12 @@ class FolderView extends BaseAppView {
}); });
layout.hookup_style(icon); layout.hookup_style(icon);
let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size); 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 numItems = this._orderedItems.length;
let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL; let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
const style = 'width: %dpx; height: %dpx;'.format(subSize, subSize); let bin = new St.Bin({ width: subSize * scale, height: subSize * scale });
let bin = new St.Bin({ style });
if (i < numItems) if (i < numItems)
bin.child = this._orderedItems[i].app.create_icon_texture(subSize); 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); layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1);
@@ -1459,22 +1429,6 @@ class FolderView extends BaseAppView {
return apps; 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) { removeApp(app) {
let folderApps = this._folder.get_strv('apps'); let folderApps = this._folder.get_strv('apps');
let index = folderApps.indexOf(app.id); let index = folderApps.indexOf(app.id);
@@ -1505,6 +1459,8 @@ class FolderView extends BaseAppView {
} else { } else {
this._folder.set_strv('apps', folderApps); this._folder.set_strv('apps', folderApps);
} }
return true;
} }
}); });
@@ -1538,26 +1494,26 @@ var FolderIcon = GObject.registerClass({
this.view = new FolderView(this._folder, id, parentView); 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.connect('destroy', this._onDestroy.bind(this));
this._folderChangedId = this._folder.connect( this._folder.connect('changed', this._redisplay.bind(this));
'changed', this._sync.bind(this)); this._redisplay();
this._sync();
} }
_onDestroy() { _onDestroy() {
if (this._dragMonitor) { Main.overview.disconnect(this._itemDragBeginId);
DND.removeDragMonitor(this._dragMonitor); Main.overview.disconnect(this._itemDragEndId);
this._dragMonitor = null;
}
this.view.destroy(); this.view.destroy();
if (this._folderChangedId) { if (this._spaceReadySignalId) {
this._folder.disconnect(this._folderChangedId); this._parentView.disconnect(this._spaceReadySignalId);
delete this._folderChangedId; this._spaceReadySignalId = 0;
} }
if (this._dialog) if (this._dialog)
@@ -1585,32 +1541,29 @@ var FolderIcon = GObject.registerClass({
return this.view.getAllItems().map(item => item.id); return this.view.getAllItems().map(item => item.id);
} }
_setHoveringByDnd(hovering) { _onDragBegin() {
if (this._iconIsHovering == hovering)
return;
this._iconIsHovering = hovering;
if (hovering) {
this._dragMonitor = { this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this), dragMotion: this._onDragMotion.bind(this),
}; };
DND.addDragMonitor(this._dragMonitor); DND.addDragMonitor(this._dragMonitor);
this.add_style_pseudo_class('drop');
} else {
DND.removeDragMonitor(this._dragMonitor);
this.remove_style_pseudo_class('drop');
}
} }
_onDragMotion(dragEvent) { _onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor) || let target = dragEvent.targetActor;
!this._canAccept(dragEvent.source))
this._setHoveringByDnd(false); 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; return DND.DragMotionResult.CONTINUE;
} }
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
_canAccept(source) { _canAccept(source) {
if (!(source instanceof AppIcon)) if (!(source instanceof AppIcon))
return false; return false;
@@ -1629,18 +1582,27 @@ var FolderIcon = GObject.registerClass({
if (!this._canAccept(source)) if (!this._canAccept(source))
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
} }
acceptDrop(source) { acceptDrop(source) {
this._setHoveringByDnd(false);
if (!this._canAccept(source)) if (!this._canAccept(source))
return false; 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; return true;
} }
@@ -1655,11 +1617,11 @@ var FolderIcon = GObject.registerClass({
this.emit('name-changed'); this.emit('name-changed');
} }
_sync() { _redisplay() {
this.emit('apps-changed');
this._updateName(); this._updateName();
this.visible = this.view.getAllItems().length > 0; this.visible = this.view.getAllItems().length > 0;
this.icon.update(); this.icon.update();
this.emit('apps-changed');
} }
_createIcon(iconSize) { _createIcon(iconSize) {
@@ -1940,7 +1902,6 @@ var AppFolderDialog = GObject.registerClass({
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box); 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 [, entryBoxHeight] = this._entryBox.get_size();
let spacing = this._viewBox.layout_manager.spacing; let spacing = this._viewBox.layout_manager.spacing;
@@ -1949,8 +1910,6 @@ var AppFolderDialog = GObject.registerClass({
contentBox.get_width(), contentBox.get_width(),
contentBox.get_height() - entryBoxHeight - spacing); contentBox.get_height() - entryBoxHeight - spacing);
this._view._grid.topPadding = 0;
super.vfunc_allocate(box, flags); super.vfunc_allocate(box, flags);
// We can only start zooming after receiving an allocation // We can only start zooming after receiving an allocation
@@ -2066,6 +2025,7 @@ var AppIcon = GObject.registerClass({
this._delegate = this; this._delegate = this;
this._hasDndHover = false;
this._folderPreviewId = 0; this._folderPreviewId = 0;
// Get the isDraggable property without passing it on to the BaseIcon: // Get the isDraggable property without passing it on to the BaseIcon:
@@ -2114,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._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', () => { this._stateChangedId = this.app.connect('notify::state', () => {
@@ -2126,6 +2090,9 @@ var AppIcon = GObject.registerClass({
} }
_onDestroy() { _onDestroy() {
Main.overview.disconnect(this._itemDragBeginId);
Main.overview.disconnect(this._itemDragEndId);
if (this._folderPreviewId > 0) { if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId); GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0; this._folderPreviewId = 0;
@@ -2372,17 +2339,7 @@ var AppIcon = GObject.registerClass({
} }
_setHoveringByDnd(hovering) { _setHoveringByDnd(hovering) {
if (this._otherIconIsHovering == hovering)
return;
this._otherIconIsHovering = hovering;
if (hovering) { if (hovering) {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0) if (this._folderPreviewId > 0)
return; return;
@@ -2394,8 +2351,6 @@ var AppIcon = GObject.registerClass({
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
} else { } else {
DND.removeDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0) { if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId); GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0; this._folderPreviewId = 0;
@@ -2405,13 +2360,32 @@ var AppIcon = GObject.registerClass({
} }
} }
_onDragBegin() {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
}
_onDragMotion(dragEvent) { _onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor)) let target = dragEvent.targetActor;
this._setHoveringByDnd(false); 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; return DND.DragMotionResult.CONTINUE;
} }
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
handleDragOver(source) { handleDragOver(source) {
if (source == this) if (source == this)
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
@@ -2419,8 +2393,6 @@ var AppIcon = GObject.registerClass({
if (!this._canAccept(source)) if (!this._canAccept(source))
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
} }
@@ -2465,7 +2437,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
Main.uiGroup.add_actor(this.actor); Main.uiGroup.add_actor(this.actor);
} }
_rebuildMenu() { _redisplay() {
this.removeAll(); this.removeAll();
let windows = this._source.app.get_windows().filter( let windows = this._source.app.get_windows().filter(
@@ -2561,7 +2533,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate', 'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})', GLib.Variant.new('(sava{sv})',
['details', [args], null]), ['details', [args], null]),
null, 0, -1, null); null, 0, -1, null, null);
Main.overview.hide(); Main.overview.hide();
}); });
}); });
@@ -2582,7 +2554,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
} }
popup(_activatingButton) { popup(_activatingButton) {
this._rebuildMenu(); this._redisplay();
this.open(); this.open();
} }
}; };

View File

@@ -837,8 +837,7 @@ class EventsSection extends MessageList.MessageListSection {
this._title.connect('clicked', this._onTitleClicked.bind(this)); this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this)); this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
this._appSys = Shell.AppSystem.get_default(); Shell.AppSystem.get_default().connect('installed-changed',
this._appSys.connect('installed-changed',
this._appInstalledChanged.bind(this)); this._appInstalledChanged.bind(this));
this._appInstalledChanged(); this._appInstalledChanged();
} }
@@ -932,13 +931,10 @@ class EventsSection extends MessageList.MessageListSection {
Main.overview.hide(); Main.overview.hide();
Main.panel.closeCalendar(); Main.panel.closeCalendar();
let appInfo = this._getCalendarApp(); let app = this._getCalendarApp();
if (appInfo.get_id() === 'org.gnome.Evolution.desktop') { if (app.get_id() == 'evolution.desktop')
let app = this._appSys.lookup_app('evolution-calendar.desktop'); app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
if (app) app.launch([], global.create_app_launch_context(0, -1));
appInfo = app.app_info;
}
appInfo.launch([], global.create_app_launch_context(0, -1));
} }
setDate(date) { setDate(date) {
@@ -1153,22 +1149,17 @@ class CalendarMessageList extends St.Widget {
let hbox = new St.BoxLayout({ style_class: 'message-list-controls' }); let hbox = new St.BoxLayout({ style_class: 'message-list-controls' });
box.add_child(hbox); box.add_child(hbox);
const dndLabel = new St.Label({ hbox.add_child(new St.Label({
text: _('Do Not Disturb'), text: _('Do Not Disturb'),
y_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER,
}); }));
hbox.add_child(dndLabel);
this._dndSwitch = new DoNotDisturbSwitch(); this._dndSwitch = new DoNotDisturbSwitch();
this._dndButton = new St.Button({ this._dndButton = new St.Button({
can_focus: true, can_focus: true,
toggle_mode: true,
child: this._dndSwitch, child: this._dndSwitch,
label_actor: dndLabel,
}); });
this._dndButton.bind_property('checked', this._dndButton.connect('clicked', () => this._dndSwitch.toggle());
this._dndSwitch, 'state',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
hbox.add_child(this._dndButton); hbox.add_child(this._dndButton);
this._clearButton = new St.Button({ this._clearButton = new St.Button({

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -180,27 +180,14 @@ class WorldClocksSection extends St.Button {
let time = new St.Label({ style_class: 'world-clocks-time' }); let time = new St.Label({ style_class: 'world-clocks-time' });
const utcOffset = this._getTimeAtLocation(l).get_utc_offset(); let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
const offsetCurrentTz = utcOffset - localOffset; let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR; let fmt = Math.trunc(offset) == offset ? '%s%.0f' : '%s%.1f';
const offsetMinutes = let prefix = offset >= 0 ? '+' : '-';
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) / let tz = new St.Label({ style_class: 'world-clocks-timezone',
GLib.TIME_SPAN_MINUTE; text: fmt.format(prefix, Math.abs(offset)),
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, x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER });
});
time.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
tz.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
if (this._grid.text_direction == Clutter.TextDirection.RTL) { if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(tz, 0, i + 1, 1, 1); layout.attach(tz, 0, i + 1, 1, 1);
@@ -397,20 +384,6 @@ class WeatherSection extends St.Button {
layout.attach(label, 0, 0, 1, 1); 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() { _updateForecasts() {
this._forecastGrid.destroy_all_children(); this._forecastGrid.destroy_all_children();
@@ -419,8 +392,13 @@ class WeatherSection extends St.Button {
return; return;
} }
const { info } = this._weatherClient; let info = this._weatherClient.info;
this._titleLocation.text = this._findBestLocationName(info.location); 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) { if (this._weatherClient.loading) {
this._setStatusLabel(_("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 // Use a different description when we are installing a system upgrade
// if the PackageKit proxy is available (i.e. PackageKit is available). // if the PackageKit proxy is available (i.e. PackageKit is available).
if (dialogContent.upgradeDescription) { if (this._pkOfflineProxy && dialogContent.upgradeDescription) {
const { name, version } = this._updateInfo.PreparedUpgrade; let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
if (name != null && version != null) if (name != null && version != null)
description = dialogContent.upgradeDescription(name, version); description = dialogContent.upgradeDescription(name, version);
} }
@@ -606,46 +608,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}); });
} }
async _getUpdateInfo() { OpenAsync(parameters, invocation) {
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) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters; let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen; this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type; 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. // Only consider updates and upgrades if PackageKit is available.
if (this._pkOfflineProxy && this._type == DialogType.RESTART) { if (this._pkOfflineProxy && this._type == DialogType.RESTART) {
if (this._updateInfo.UpdateTriggered) if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART; this._type = DialogType.UPDATE_RESTART;
else if (this._updateInfo.UpgradeTriggered) else if (this._pkOfflineProxy.UpgradeTriggered)
this._type = DialogType.UPGRADE_RESTART; this._type = DialogType.UPGRADE_RESTART;
} }
@@ -674,13 +646,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
if (dialogContent.showOtherSessions) if (dialogContent.showOtherSessions)
this._loadSessions(); this._loadSessions();
let updateTriggered = this._updateInfo.UpdateTriggered; // Only consider updates and upgrades if PackageKit is available.
let updatePrepared = this._updateInfo.UpdatePrepared; let updateTriggered = this._pkOfflineProxy ? this._pkOfflineProxy.UpdateTriggered : false;
let updatePrepared = this._pkOfflineProxy ? this._pkOfflineProxy.UpdatePrepared : false;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed; let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || ''); _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.visible = dialogContent.checkBoxText && updatePrepared && updatesAllowed; this._checkBox.visible = dialogContent.checkBoxText && updatePrepared && updatesAllowed;
this._checkBox.checked = this._checkBox.visible; this._checkBox.checked = updatePrepared && updateTriggered;
// We show the warning either together with the checkbox, or when // We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have // updates have already been triggered, but the user doesn't have

View File

@@ -10,13 +10,8 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12'; imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2'; 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 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 // We can't import shell JS modules yet, because they may have
// variable initializations, etc, that depend on init() already having // variable initializations, etc, that depend on init() already having
@@ -290,13 +285,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) { St.set_slow_down_factor = function (factor) {
let { stack } = new Error(); let { stack } = new Error();
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`); log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);
@@ -316,25 +304,9 @@ function init() {
} }
}; };
// Override to clear our own timezone cache as well
const origClearDateCaches = System.clearDateCaches;
System.clearDateCaches = function () {
_localTimeZone = null;
origClearDateCaches();
};
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
Date.prototype.toLocaleFormat = function (format) { Date.prototype.toLocaleFormat = function (format) {
if (_localTimeZone === null) let dt = GLib.DateTime.new_from_unix_local(this.getTime() / 1000);
_localTimeZone = GLib.TimeZone.new_local();
let dt = GLib.DateTime.new(_localTimeZone,
this.getFullYear(),
this.getMonth() + 1,
this.getDate(),
this.getHours(),
this.getMinutes(),
this.getSeconds());
return dt ? dt.format(format) : ''; return dt ? dt.format(format) : '';
}; };

View File

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

View File

@@ -60,11 +60,6 @@ var ExtensionManager = class {
ExtensionDownloader.checkForUpdates(); ExtensionDownloader.checkForUpdates();
} }
get updatesSupported() {
const appSys = Shell.AppSystem.get_default();
return appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
}
lookup(uuid) { lookup(uuid) {
return this._extensions.get(uuid); return this._extensions.get(uuid);
} }
@@ -215,25 +210,6 @@ var ExtensionManager = class {
return true; 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) { notifyExtensionUpdate(uuid) {
let extension = this.lookup(uuid); let extension = this.lookup(uuid);
if (!extension) if (!extension)
@@ -505,9 +481,6 @@ var ExtensionManager = class {
} }
_installExtensionUpdates() { _installExtensionUpdates() {
if (!this.updatesSupported)
return;
FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => { FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => {
let fileType = info.get_file_type(); let fileType = info.get_file_type();
if (fileType !== Gio.FileType.DIRECTORY) if (fileType !== Gio.FileType.DIRECTORY)
@@ -516,14 +489,9 @@ var ExtensionManager = class {
let extensionDir = Gio.File.new_for_path( let extensionDir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extensions', uuid])); GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
try {
FileUtils.recursivelyDeleteDir(extensionDir, false); FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(dir, extensionDir); FileUtils.recursivelyMoveDir(dir, extensionDir);
} catch (e) {
log('Failed to install extension updates for %s'.format(uuid));
} finally {
FileUtils.recursivelyDeleteDir(dir, true); FileUtils.recursivelyDeleteDir(dir, true);
}
}); });
} }

View File

@@ -498,7 +498,7 @@ var Key = GObject.registerClass({
var KeyboardModel = class { var KeyboardModel = class {
constructor(groupName) { constructor(groupName) {
let names = [groupName]; let names = [groupName];
if (groupName.includes('+')) if (names.includes('+'))
names.push(groupName.replace(/\+.*/, '')); names.push(groupName.replace(/\+.*/, ''));
names.push('us'); names.push('us');
@@ -1120,11 +1120,10 @@ var KeyboardManager = class KeyBoardManager {
this._lastDevice = null; this._lastDevice = null;
Meta.get_backend().connect('last-device-changed', (backend, device) => { Meta.get_backend().connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE) if (device.get_device_name().indexOf('XTEST') < 0) {
return;
this._lastDevice = device; this._lastDevice = device;
this._syncEnabled(); this._syncEnabled();
}
}); });
this._syncEnabled(); this._syncEnabled();
} }
@@ -1149,9 +1148,9 @@ var KeyboardManager = class KeyBoardManager {
this._keyboard = new Keyboard(); this._keyboard = new Keyboard();
} else if (!enabled && this._keyboard) { } else if (!enabled && this._keyboard) {
this._keyboard.setCursorLocation(null); this._keyboard.setCursorLocation(null);
Main.layoutManager.hideKeyboard(true);
this._keyboard.destroy(); this._keyboard.destroy();
this._keyboard = null; this._keyboard = null;
Main.layoutManager.hideKeyboard(true);
} }
} }
@@ -1869,10 +1868,6 @@ var KeyboardController = class {
Main.inputMethod.disconnect(this._notifyContentPurposeId); Main.inputMethod.disconnect(this._notifyContentPurposeId);
Main.inputMethod.disconnect(this._notifyContentHintsId); Main.inputMethod.disconnect(this._notifyContentHintsId);
Main.inputMethod.disconnect(this._notifyInputPanelStateId); 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() { _onSourcesModified() {

View File

@@ -612,20 +612,10 @@ var LayoutManager = GObject.registerClass({
let signalId = this._systemBackground.connect('loaded', () => { let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId); this._systemBackground.disconnect(signalId);
// 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(); this._systemBackground.show();
global.stage.show(); global.stage.show();
this._prepareStartupAnimation(); this._prepareStartupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] Startup Animation');
}); });
} }
@@ -682,7 +672,17 @@ var LayoutManager = GObject.registerClass({
this.emit('startup-prepared'); this.emit('startup-prepared');
// 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(); this._startupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
} }
_startupAnimation() { _startupAnimation() {
@@ -765,7 +765,7 @@ var LayoutManager = GObject.registerClass({
this._keyboardHeightNotifyId = 0; this._keyboardHeightNotifyId = 0;
} }
this.keyboardBox.ease({ this.keyboardBox.ease({
translation_y: 0, translation_y: this.keyboardBox.height,
opacity: 0, opacity: 0,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME, duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD, mode: Clutter.AnimationMode.EASE_IN_QUAD,

View File

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

View File

@@ -93,9 +93,6 @@ let _a11ySettings = null;
let _themeResource = null; let _themeResource = null;
let _oskResource = null; let _oskResource = null;
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
function _sessionUpdated() { function _sessionUpdated() {
if (sessionMode.isPrimary) if (sessionMode.isPrimary)
_loadDefaultStylesheet(); _loadDefaultStylesheet();
@@ -132,8 +129,6 @@ function start() {
notifyError(msg, detail); 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 = new SessionMode.SessionMode();
@@ -147,11 +142,6 @@ function start() {
shellDBusService = new ShellDBus.GnomeShell(); shellDBusService = new ShellDBus.GnomeShell();
shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler(); 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(); _sessionUpdated();
} }
@@ -281,8 +271,11 @@ function _initializeUI() {
} }
if (sessionMode.currentMode !== 'gdm' && if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup') sessionMode.currentMode !== 'initial-setup' &&
_handleLockScreenWarning(); screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM(); 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) { function _getStylesheet(name) {
let stylesheet; let stylesheet;
@@ -394,8 +361,7 @@ function reloadThemeResource() {
if (_themeResource) if (_themeResource)
_themeResource._unregister(); _themeResource._unregister();
_themeResource = Gio.Resource.load('%s/%s'.format(global.datadir, _themeResource = Gio.Resource.load('%s/gnome-shell-theme.gresource'.format(global.datadir));
sessionMode.themeResourceName));
_themeResource._register(); _themeResource._register();
} }

View File

@@ -530,7 +530,7 @@ var Message = GObject.registerClass({
this.close(); this.close();
return Clutter.EVENT_STOP; 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.notifications = [];
this._policy = this._createPolicy(); this._policy = null;
} }
get policy() { get policy() {
if (!this._policy)
this._policy = this._createPolicy();
return this._policy; return this._policy;
} }
@@ -878,6 +880,8 @@ var Source = GObject.registerClass({
} }
destroy(reason) { destroy(reason) {
this.policy.destroy();
let notifications = this.notifications; let notifications = this.notifications;
this.notifications = []; this.notifications = [];
@@ -886,7 +890,6 @@ var Source = GObject.registerClass({
this.emit('destroy', reason); this.emit('destroy', reason);
this.policy.destroy();
this.run_dispose(); this.run_dispose();
} }

View File

@@ -251,10 +251,6 @@ class MediaSection extends MessageList.MessageListSection {
return !this.empty && Calendar.isToday(this._date); return !this.empty && Calendar.isToday(this._date);
} }
get allowed() {
return !Main.sessionMode.isGreeter;
}
_addPlayer(busName) { _addPlayer(busName) {
if (this._players.get(busName)) if (this._players.get(busName))
return; return;

View File

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

View File

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

View File

@@ -100,7 +100,7 @@ class AppMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate', 'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})', GLib.Variant.new('(sava{sv})',
['details', [args], null]), ['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 Clutter.EVENT_STOP;
} }
return super.vfunc_key_press_event(keyEvent); return Clutter.EVENT_PROPAGATE;
} }
_toggleMenu(indicator) { _toggleMenu(indicator) {

View File

@@ -247,7 +247,7 @@ var RemoteSearchProvider = class {
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return; 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([]); callback([]);
return; return;
} }
@@ -274,7 +274,7 @@ var RemoteSearchProvider = class {
_getResultMetasFinished(results, error, callback) { _getResultMetasFinished(results, error, callback) {
if (error) { if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) 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([]); callback([]);
return; return;
} }

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GnomeShell, ScreenSaverDBus */ /* exported GnomeShell, ScreenSaverDBus */
const { Gio, GLib, Meta } = imports.gi; const { Gio, GLib, Meta, Shell } = imports.gi;
const Config = imports.misc.config; const Config = imports.misc.config;
const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionDownloader = imports.ui.extensionDownloader;
@@ -255,17 +255,6 @@ var GnomeShellExtensions = class {
constructor() { constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); 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', Main.extensionManager.connect('extension-state-changed',
this._extensionStateChanged.bind(this)); this._extensionStateChanged.bind(this));
} }
@@ -312,18 +301,20 @@ var GnomeShellExtensions = class {
} }
LaunchExtensionPrefs(uuid) { 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) { ReloadExtension(uuid) {
Main.extensionManager.openExtensionPrefs(uuid, parentWindow, options); let extension = Main.extensionManager.lookup(uuid);
} if (!extension)
return;
ReloadExtensionAsync(params, invocation) { Main.extensionManager.reloadExtension(extension);
invocation.return_error_literal(
Gio.DBusError,
Gio.DBusError.NOT_SUPPORTED,
'ReloadExtension is deprecated and does not work');
} }
CheckForUpdates() { CheckForUpdates() {
@@ -334,14 +325,6 @@ var GnomeShellExtensions = class {
return Config.PACKAGE_VERSION; 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) { _extensionStateChanged(_, newState) {
let state = ExtensionUtils.serializeExtension(newState); let state = ExtensionUtils.serializeExtension(newState);
this._dbusImpl.emit_signal('ExtensionStateChanged', this._dbusImpl.emit_signal('ExtensionStateChanged',

View File

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

View File

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

View File

@@ -139,14 +139,14 @@ class ATIndicator extends PanelMenu.Button {
interfaceSettings.is_writable(KEY_ICON_THEME), interfaceSettings.is_writable(KEY_ICON_THEME),
enabled => { enabled => {
if (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_GTK_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
} else if (!hasHC) { } else if (!hasHC) {
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme); interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
} else { } else {
interfaceSettings.reset(KEY_ICON_THEME);
interfaceSettings.reset(KEY_GTK_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._item.label.text = _("Location Enabled");
this._onOffAction = this._item.menu.addAction(_("Disable"), this._onOnOffAction.bind(this)); 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); this.menu.addMenuItem(this._item);

View File

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

View File

@@ -58,7 +58,7 @@ const TouchpadSwipeGesture = GObject.registerClass({
this._orientation = Clutter.Orientation.VERTICAL; this._orientation = Clutter.Orientation.VERTICAL;
this._enabled = true; this._enabled = true;
global.stage.connect('captured-event::touchpad', this._handleEvent.bind(this)); global.stage.connect('captured-event', this._handleEvent.bind(this));
} }
get enabled() { get enabled() {

View File

@@ -130,7 +130,7 @@ var SwitcherPopup = GObject.registerClass({
let [x_, y_, mods] = global.get_pointer(); let [x_, y_, mods] = global.get_pointer();
if (!(mods & this._modifierMask)) { if (!(mods & this._modifierMask)) {
this._finish(global.get_current_time()); this._finish(global.get_current_time());
return true; return false;
} }
} else { } else {
this._resetNoModsTimeout(); this._resetNoModsTimeout();
@@ -228,9 +228,7 @@ var SwitcherPopup = GObject.registerClass({
} }
vfunc_scroll_event(scrollEvent) { vfunc_scroll_event(scrollEvent) {
this._disableHover(); this._scrollHandler(scrollEvent.scroll_direction);
this._scrollHandler(scrollEvent.direction);
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
@@ -255,15 +253,7 @@ var SwitcherPopup = GObject.registerClass({
_itemRemovedHandler(n) { _itemRemovedHandler(n) {
if (this._items.length > 0) { if (this._items.length > 0) {
let newIndex; let newIndex = Math.min(n, this._items.length - 1);
if (n < this._selectedIndex)
newIndex = this._selectedIndex - 1;
else if (n === this._selectedIndex)
newIndex = Math.min(n, this._items.length - 1);
else if (n > this._selectedIndex)
return; // No need to select something new in this case
this._select(newIndex); this._select(newIndex);
} else { } else {
this.fadeAndDestroy(); this.fadeAndDestroy();
@@ -427,8 +417,9 @@ var SwitcherList = GObject.registerClass({
bbox.set_child(item); bbox.set_child(item);
this._list.add_actor(bbox); this._list.add_actor(bbox);
bbox.connect('clicked', () => this._onItemClicked(bbox)); let n = this._items.length;
bbox.connect('motion-event', () => this._onItemEnter(bbox)); bbox.connect('clicked', () => this._onItemClicked(n));
bbox.connect('motion-event', () => this._onItemEnter(n));
bbox.label_actor = label; bbox.label_actor = label;
@@ -443,23 +434,16 @@ var SwitcherList = GObject.registerClass({
this.emit('item-removed', index); this.emit('item-removed', index);
} }
addAccessibleState(index, state) { _onItemClicked(index) {
this._items[index].add_accessible_state(state); this._itemActivated(index);
} }
removeAccessibleState(index, state) { _onItemEnter(index) {
this._items[index].remove_accessible_state(state);
}
_onItemClicked(item) {
this._itemActivated(this._items.indexOf(item));
}
_onItemEnter(item) {
// Avoid reentrancy // Avoid reentrancy
if (item !== this._items[this._highlighted]) if (index != this._currentItemEntered) {
this._itemEntered(this._items.indexOf(item)); this._currentItemEntered = index;
this._itemEntered(index);
}
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
@@ -484,40 +468,40 @@ var SwitcherList = GObject.registerClass({
let [result_, posX, posY_] = this.transform_stage_point(absItemX, 0); let [result_, posX, posY_] = this.transform_stage_point(absItemX, 0);
let [containerWidth] = this.get_transformed_size(); let [containerWidth] = this.get_transformed_size();
if (posX + this._items[index].get_width() > containerWidth) if (posX + this._items[index].get_width() > containerWidth)
this._scrollToRight(index); this._scrollToRight();
else if (this._items[index].allocation.x1 - value < 0) else if (this._items[index].allocation.x1 - value < 0)
this._scrollToLeft(index); this._scrollToLeft();
} }
_scrollToLeft(index) { _scrollToLeft() {
let adjustment = this._scrollView.hscroll.adjustment; let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values(); let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
let item = this._items[index]; let item = this._items[this._highlighted];
if (item.allocation.x1 < value) if (item.allocation.x1 < value)
value = Math.max(0, item.allocation.x1); value = Math.min(0, item.allocation.x1);
else if (item.allocation.x2 > value + pageSize) else if (item.allocation.x2 > value + pageSize)
value = Math.min(upper, item.allocation.x2 - pageSize); value = Math.max(upper, item.allocation.x2 - pageSize);
this._scrollableRight = true; this._scrollableRight = true;
adjustment.ease(value, { adjustment.ease(value, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD, progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: POPUP_SCROLL_TIME, duration: POPUP_SCROLL_TIME,
onComplete: () => { onComplete: () => {
if (index === 0) if (this._highlighted == 0)
this._scrollableLeft = false; this._scrollableLeft = false;
this.queue_relayout(); this.queue_relayout();
}, },
}); });
} }
_scrollToRight(index) { _scrollToRight() {
let adjustment = this._scrollView.hscroll.adjustment; let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values(); let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
let item = this._items[index]; let item = this._items[this._highlighted];
if (item.allocation.x1 < value) if (item.allocation.x1 < value)
value = Math.max(0, item.allocation.x1); value = Math.max(0, item.allocation.x1);
@@ -529,7 +513,7 @@ var SwitcherList = GObject.registerClass({
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD, progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: POPUP_SCROLL_TIME, duration: POPUP_SCROLL_TIME,
onComplete: () => { onComplete: () => {
if (index === this._items.length - 1) if (this._highlighted == this._items.length - 1)
this._scrollableRight = false; this._scrollableRight = false;
this.queue_relayout(); this.queue_relayout();
}, },

View File

@@ -115,7 +115,7 @@ var NotificationsBox = GObject.registerClass({
box.add_child(textBox); box.add_child(textBox);
let title = new St.Label({ let title = new St.Label({
text: source.title.replace(/\n/g, ' '), text: source.title,
style_class: 'unlock-dialog-notification-label', style_class: 'unlock-dialog-notification-label',
}); });
textBox.add(title); textBox.add(title);
@@ -129,10 +129,9 @@ var NotificationsBox = GObject.registerClass({
let body = ''; let body = '';
if (n.bannerBodyText) { if (n.bannerBodyText) {
const bodyText = n.bannerBodyText.replace(/\n/g, ' ');
body = n.bannerBodyMarkup body = n.bannerBodyMarkup
? bodyText ? n.bannerBodyText
: GLib.markup_escape_text(bodyText, -1); : GLib.markup_escape_text(n.bannerBodyText, -1);
} }
let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' }); let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' });
@@ -557,13 +556,12 @@ var UnlockDialog = GObject.registerClass({
this._otherUserButton = new St.Button({ this._otherUserButton = new St.Button({
style_class: 'modal-dialog-button button switch-user-button', style_class: 'modal-dialog-button button switch-user-button',
accessible_name: _('Log in as another user'), accessible_name: _('Log in as another user'),
reactive: false, can_focus: true,
opacity: 0, reactive: true,
x_align: Clutter.ActorAlign.END, x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END, y_align: Clutter.ActorAlign.END,
child: new St.Icon({ icon_name: 'system-users-symbolic' }), child: new St.Icon({ icon_name: 'system-users-symbolic' }),
}); });
this._otherUserButton.set_pivot_point(0.5, 0.5);
this._otherUserButton.connect('clicked', this._otherUserClicked.bind(this)); this._otherUserButton.connect('clicked', this._otherUserClicked.bind(this));
let screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' }); let screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' });
@@ -668,7 +666,7 @@ var UnlockDialog = GObject.registerClass({
this._promptBox.add_child(this._authPrompt); this._promptBox.add_child(this._authPrompt);
this._authPrompt.reset(); this._authPrompt.reset();
this._authPrompt.updateSensitivity(true); this._updateSensitivity(true);
} }
_maybeDestroyAuthPrompt() { _maybeDestroyAuthPrompt() {
@@ -684,6 +682,13 @@ var UnlockDialog = GObject.registerClass({
} }
} }
_updateSensitivity(sensitive) {
this._authPrompt.updateSensitivity(sensitive);
this._otherUserButton.reactive = sensitive;
this._otherUserButton.can_focus = sensitive;
}
_showClock() { _showClock() {
if (this._activePage === this._clock) if (this._activePage === this._clock)
return; return;
@@ -715,11 +720,6 @@ var UnlockDialog = GObject.registerClass({
this._promptBox.visible = progress > 0; this._promptBox.visible = progress > 0;
this._clock.visible = progress < 1; this._clock.visible = progress < 1;
this._otherUserButton.set({
reactive: progress > 0,
can_focus: progress > 0,
});
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
this._promptBox.set({ this._promptBox.set({
@@ -735,12 +735,6 @@ var UnlockDialog = GObject.registerClass({
scale_y: FADE_OUT_SCALE + (1 - FADE_OUT_SCALE) * (1 - progress), scale_y: FADE_OUT_SCALE + (1 - FADE_OUT_SCALE) * (1 - progress),
translation_y: -FADE_OUT_TRANSLATION * progress * scaleFactor, translation_y: -FADE_OUT_TRANSLATION * progress * scaleFactor,
}); });
this._otherUserButton.set({
opacity: 255 * progress,
scale_x: FADE_OUT_SCALE + (1 - FADE_OUT_SCALE) * progress,
scale_y: FADE_OUT_SCALE + (1 - FADE_OUT_SCALE) * progress,
});
} }
_fail() { _fail() {
@@ -761,7 +755,7 @@ var UnlockDialog = GObject.registerClass({
} }
_escape() { _escape() {
if (this._authPrompt && this.allowCancel) if (this.allowCancel)
this._authPrompt.cancel(); this._authPrompt.cancel();
} }

View File

@@ -44,7 +44,7 @@ function getTermsForSearchString(searchString) {
var TouchpadShowOverviewAction = class { var TouchpadShowOverviewAction = class {
constructor(actor) { constructor(actor) {
actor.connect('captured-event::touchpad', this._handleEvent.bind(this)); actor.connect('captured-event', this._handleEvent.bind(this));
} }
_handleEvent(actor, event) { _handleEvent(actor, event) {

View File

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

View File

@@ -14,9 +14,9 @@ const WindowMenu = imports.ui.windowMenu;
const PadOsd = imports.ui.padOsd; const PadOsd = imports.ui.padOsd;
const EdgeDragAction = imports.ui.edgeDragAction; const EdgeDragAction = imports.ui.edgeDragAction;
const CloseDialog = imports.ui.closeDialog; const CloseDialog = imports.ui.closeDialog;
const SwipeTracker = imports.ui.swipeTracker;
const SwitchMonitor = imports.ui.switchMonitor; const SwitchMonitor = imports.ui.switchMonitor;
const IBusManager = imports.misc.ibusManager; const IBusManager = imports.misc.ibusManager;
const WorkspaceAnimation = imports.ui.workspaceAnimation;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -559,7 +559,6 @@ var WindowManager = class {
this._resizing = new Set(); this._resizing = new Set();
this._resizePending = new Set(); this._resizePending = new Set();
this._destroying = new Set(); this._destroying = new Set();
this._movingWindow = null;
this._dimmedWindows = []; this._dimmedWindows = [];
@@ -569,15 +568,6 @@ var WindowManager = class {
this._isWorkspacePrepended = false; this._isWorkspacePrepended = false;
this._switchData = null;
this._shellwm.connect('kill-switch-workspace', shellwm => {
if (this._switchData) {
if (this._switchData.inProgress)
this._switchWorkspaceDone(shellwm);
else if (!this._switchData.gestureActivated)
this._finishWorkspaceSwitch(this._switchData);
}
});
this._shellwm.connect('kill-window-effects', (shellwm, actor) => { this._shellwm.connect('kill-window-effects', (shellwm, actor) => {
this._minimizeWindowDone(shellwm, actor); this._minimizeWindowDone(shellwm, actor);
this._mapWindowDone(shellwm, actor); this._mapWindowDone(shellwm, actor);
@@ -599,7 +589,6 @@ var WindowManager = class {
this._shellwm.connect('confirm-display-change', this._confirmDisplayChange.bind(this)); this._shellwm.connect('confirm-display-change', this._confirmDisplayChange.bind(this));
this._shellwm.connect('create-close-dialog', this._createCloseDialog.bind(this)); this._shellwm.connect('create-close-dialog', this._createCloseDialog.bind(this));
this._shellwm.connect('create-inhibit-shortcuts-dialog', this._createInhibitShortcutsDialog.bind(this)); this._shellwm.connect('create-inhibit-shortcuts-dialog', this._createInhibitShortcutsDialog.bind(this));
global.display.connect('restacked', this._syncStacking.bind(this));
this._workspaceSwitcherPopup = null; this._workspaceSwitcherPopup = null;
this._tilePreview = null; this._tilePreview = null;
@@ -896,54 +885,22 @@ var WindowManager = class {
} }
}); });
global.display.connect('init-xserver', (display, task) => { global.display.connect('x11-display-opened', () => {
IBusManager.getIBusManager().restartDaemon(['--xim']); IBusManager.getIBusManager().restartDaemon(['--xim']);
Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail'); Shell.util_start_systemd_unit('gnome-session-x11-services.target', 'fail');
/* 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);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
/* When gsd-xsettings daemon is started, we are good to resume */
let watchId = Gio.DBus.session.watch_name(
'org.gnome.SettingsDaemon.XSettings',
Gio.BusNameWatcherFlags.NONE,
() => {
Gio.DBus.session.unwatch_name(watchId);
if (timeoutId > 0) {
task.return_boolean(true);
GLib.source_remove(timeoutId);
}
},
null);
return true;
}); });
global.display.connect('x11-display-closing', () => { global.display.connect('x11-display-closing', () => {
if (!Meta.is_wayland_compositor()) Shell.util_stop_systemd_unit('gnome-session-x11-services.target', 'fail');
return;
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
IBusManager.getIBusManager().restartDaemon(); IBusManager.getIBusManager().restartDaemon();
}); });
Main.overview.connect('showing', () => { Main.overview.connect('showing', () => {
for (let i = 0; i < this._dimmedWindows.length; i++) for (let i = 0; i < this._dimmedWindows.length; i++)
this._undimWindow(this._dimmedWindows[i]); this._undimWindow(this._dimmedWindows[i]);
if (this._switchData) {
if (this._switchData.gestureActivated)
this._switchWorkspaceStop();
this._swipeTracker.enabled = false;
}
}); });
Main.overview.connect('hiding', () => { Main.overview.connect('hiding', () => {
for (let i = 0; i < this._dimmedWindows.length; i++) for (let i = 0; i < this._dimmedWindows.length; i++)
this._dimWindow(this._dimmedWindows[i]); this._dimWindow(this._dimmedWindows[i]);
this._swipeTracker.enabled = true;
}); });
this._windowMenuManager = new WindowMenu.WindowMenuManager(); this._windowMenuManager = new WindowMenu.WindowMenuManager();
@@ -954,13 +911,6 @@ var WindowManager = class {
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT,
false, -1, 1); false, -1, 1);
let swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
Shell.ActionMode.NORMAL, { allowDrag: false, allowScroll: false });
swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
this._swipeTracker = swipeTracker;
let appSwitchAction = new AppSwitchAction(); let appSwitchAction = new AppSwitchAction();
appSwitchAction.connect('activated', this._switchApp.bind(this)); appSwitchAction.connect('activated', this._switchApp.bind(this));
global.stage.add_action(appSwitchAction); global.stage.add_action(appSwitchAction);
@@ -992,6 +942,17 @@ var WindowManager = class {
global.display.connect('in-fullscreen-changed', updateUnfullscreenGesture); global.display.connect('in-fullscreen-changed', updateUnfullscreenGesture);
global.stage.add_action(topDragAction); global.stage.add_action(topDragAction);
this._workspaceAnimation =
new WorkspaceAnimation.WorkspaceAnimationController();
this._shellwm.connect('kill-switch-workspace', () => {
if (!this._workspaceAnimation.isAnimating() || this._workspaceAnimation.canCancelGesture())
return;
this._workspaceAnimation.cancelSwitchAnimation();
this._shellwm.completed_switch_workspace();
});
} }
_showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) { _showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) {
@@ -1114,8 +1075,7 @@ var WindowManager = class {
} }
_shouldAnimate() { _shouldAnimate() {
return !(Main.overview.visible || return !(Main.overview.visible || this._workspaceAnimation.isAnimating());
(this._switchData && this._switchData.gestureActivated));
} }
_shouldAnimateActor(actor, types) { _shouldAnimateActor(actor, types) {
@@ -1284,6 +1244,7 @@ var WindowManager = class {
actorClone.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); actorClone.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
actorClone.set_position(oldFrameRect.x, oldFrameRect.y); actorClone.set_position(oldFrameRect.x, oldFrameRect.y);
actorClone.set_size(oldFrameRect.width, oldFrameRect.height); actorClone.set_size(oldFrameRect.width, oldFrameRect.height);
Main.uiGroup.add_actor(actorClone);
if (this._clearAnimationInfo(actor)) if (this._clearAnimationInfo(actor))
this._shellwm.completed_size_change(actor); this._shellwm.completed_size_change(actor);
@@ -1314,8 +1275,6 @@ var WindowManager = class {
this._resizePending.delete(actor); this._resizePending.delete(actor);
this._resizing.add(actor); this._resizing.add(actor);
Main.uiGroup.add_child(actorClone);
// Now scale and fade out the clone // Now scale and fade out the clone
actorClone.ease({ actorClone.ease({
x: targetRect.x, x: targetRect.x,
@@ -1597,379 +1556,17 @@ var WindowManager = class {
return !(this._allowedKeybindings[binding.get_name()] & Main.actionMode); return !(this._allowedKeybindings[binding.get_name()] & Main.actionMode);
} }
_syncStacking() {
if (this._switchData == null)
return;
let windows = global.get_window_actors();
let lastCurSibling = null;
let lastDirSibling = [];
for (let i = 0; i < windows.length; i++) {
if (windows[i].get_parent() == this._switchData.curGroup) {
this._switchData.curGroup.set_child_above_sibling(windows[i], lastCurSibling);
lastCurSibling = windows[i];
} else {
for (let dir of Object.values(Meta.MotionDirection)) {
let info = this._switchData.surroundings[dir];
if (!info || windows[i].get_parent() != info.actor)
continue;
let sibling = lastDirSibling[dir];
if (sibling == undefined)
sibling = null;
info.actor.set_child_above_sibling(windows[i], sibling);
lastDirSibling[dir] = windows[i];
break;
}
}
}
}
_getPositionForDirection(direction, fromWs, toWs) {
let xDest = 0, yDest = 0;
let oldWsIsFullscreen = fromWs.list_windows().some(w => w.is_fullscreen());
let newWsIsFullscreen = toWs.list_windows().some(w => w.is_fullscreen());
// We have to shift windows up or down by the height of the panel to prevent having a
// visible gap between the windows while switching workspaces. Since fullscreen windows
// hide the panel, they don't need to be shifted up or down.
let shiftHeight = Main.panel.height;
if (direction == Meta.MotionDirection.UP ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.UP_RIGHT)
yDest = -global.screen_height + (oldWsIsFullscreen ? 0 : shiftHeight);
else if (direction == Meta.MotionDirection.DOWN ||
direction == Meta.MotionDirection.DOWN_LEFT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
yDest = global.screen_height - (newWsIsFullscreen ? 0 : shiftHeight);
if (direction == Meta.MotionDirection.LEFT ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.DOWN_LEFT)
xDest = -global.screen_width;
else if (direction == Meta.MotionDirection.RIGHT ||
direction == Meta.MotionDirection.UP_RIGHT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
xDest = global.screen_width;
return [xDest, yDest];
}
_prepareWorkspaceSwitch(from, to, direction) {
if (this._switchData)
return;
let wgroup = global.window_group;
let windows = global.get_window_actors();
let switchData = {};
this._switchData = switchData;
switchData.curGroup = new Clutter.Actor();
switchData.movingWindowBin = new Clutter.Actor();
switchData.windows = [];
switchData.surroundings = {};
switchData.gestureActivated = false;
switchData.inProgress = false;
switchData.container = new Clutter.Actor();
switchData.container.add_actor(switchData.curGroup);
wgroup.add_actor(switchData.movingWindowBin);
wgroup.add_actor(switchData.container);
let workspaceManager = global.workspace_manager;
let curWs = workspaceManager.get_workspace_by_index(from);
for (let dir of Object.values(Meta.MotionDirection)) {
let ws = null;
if (to < 0)
ws = curWs.get_neighbor(dir);
else if (dir == direction)
ws = workspaceManager.get_workspace_by_index(to);
if (ws == null || ws == curWs) {
switchData.surroundings[dir] = null;
continue;
}
let [x, y] = this._getPositionForDirection(dir, curWs, ws);
let info = {
index: ws.index(),
actor: new Clutter.Actor(),
xDest: x,
yDest: y,
};
switchData.surroundings[dir] = info;
switchData.container.add_actor(info.actor);
switchData.container.set_child_above_sibling(info.actor, null);
info.actor.set_position(x, y);
}
wgroup.set_child_above_sibling(switchData.movingWindowBin, null);
for (let i = 0; i < windows.length; i++) {
let actor = windows[i];
let window = actor.get_meta_window();
if (!window.showing_on_its_workspace())
continue;
if (window.is_on_all_workspaces())
continue;
let record = { window: actor,
parent: actor.get_parent() };
if (this._movingWindow && window == this._movingWindow) {
record.parent.remove_child(actor);
switchData.movingWindow = record;
switchData.windows.push(switchData.movingWindow);
switchData.movingWindowBin.add_child(actor);
} else if (window.get_workspace().index() == from) {
record.parent.remove_child(actor);
switchData.windows.push(record);
switchData.curGroup.add_child(actor);
} else {
let visible = false;
for (let dir of Object.values(Meta.MotionDirection)) {
let info = switchData.surroundings[dir];
if (!info || info.index != window.get_workspace().index())
continue;
record.parent.remove_child(actor);
switchData.windows.push(record);
info.actor.add_child(actor);
visible = true;
break;
}
actor.visible = visible;
}
}
for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
w.windowDestroyId = w.window.connect('destroy', () => {
switchData.windows.splice(switchData.windows.indexOf(w), 1);
});
}
}
_finishWorkspaceSwitch(switchData) {
this._switchData = null;
for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
w.window.disconnect(w.windowDestroyId);
w.window.get_parent().remove_child(w.window);
w.parent.add_child(w.window);
if (w.window.get_meta_window().get_workspace() !=
global.workspace_manager.get_active_workspace())
w.window.hide();
}
switchData.container.destroy();
switchData.movingWindowBin.destroy();
this._movingWindow = null;
}
_switchWorkspace(shellwm, from, to, direction) { _switchWorkspace(shellwm, from, to, direction) {
if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) { if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) {
shellwm.completed_switch_workspace(); shellwm.completed_switch_workspace();
return; return;
} }
this._prepareWorkspaceSwitch(from, to, direction); this._workspaceAnimation.animateSwitchWorkspace(from, to, direction, () => {
this._switchData.inProgress = true; this._shellwm.completed_switch_workspace();
let workspaceManager = global.workspace_manager;
let fromWs = workspaceManager.get_workspace_by_index(from);
let toWs = workspaceManager.get_workspace_by_index(to);
let [xDest, yDest] = this._getPositionForDirection(direction, fromWs, toWs);
/* @direction is the direction that the "camera" moves, so the
* screen contents have to move one screen's worth in the
* opposite direction.
*/
xDest = -xDest;
yDest = -yDest;
this._switchData.container.ease({
x: xDest,
y: yDest,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => this._switchWorkspaceDone(shellwm),
}); });
} }
_switchWorkspaceDone(shellwm) {
this._finishWorkspaceSwitch(this._switchData);
shellwm.completed_switch_workspace();
}
_directionForProgress(progress) {
if (global.workspace_manager.layout_rows === -1) {
return progress > 0
? Meta.MotionDirection.DOWN
: Meta.MotionDirection.UP;
} else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) {
return progress > 0
? Meta.MotionDirection.LEFT
: Meta.MotionDirection.RIGHT;
} else {
return progress > 0
? Meta.MotionDirection.RIGHT
: Meta.MotionDirection.LEFT;
}
}
_getProgressRange() {
if (!this._switchData)
return [0, 0];
let lower = 0;
let upper = 0;
let horiz = global.workspace_manager.layout_rows !== -1;
let baseDistance;
if (horiz)
baseDistance = global.screen_width;
else
baseDistance = global.screen_height;
let direction = this._directionForProgress(-1);
let info = this._switchData.surroundings[direction];
if (info !== null) {
let distance = horiz ? info.xDest : info.yDest;
lower = -Math.abs(distance) / baseDistance;
}
direction = this._directionForProgress(1);
info = this._switchData.surroundings[direction];
if (info !== null) {
let distance = horiz ? info.xDest : info.yDest;
upper = Math.abs(distance) / baseDistance;
}
return [lower, upper];
}
_switchWorkspaceBegin(tracker, monitor) {
if (Meta.prefs_get_workspaces_only_on_primary() &&
monitor !== Main.layoutManager.primaryIndex)
return;
let workspaceManager = global.workspace_manager;
let horiz = workspaceManager.layout_rows !== -1;
tracker.orientation = horiz
? Clutter.Orientation.HORIZONTAL
: Clutter.Orientation.VERTICAL;
let activeWorkspace = workspaceManager.get_active_workspace();
let baseDistance;
if (horiz)
baseDistance = global.screen_width;
else
baseDistance = global.screen_height;
let progress;
if (this._switchData && this._switchData.gestureActivated) {
this._switchData.container.remove_all_transitions();
if (!horiz)
progress = -this._switchData.container.y / baseDistance;
else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
progress = this._switchData.container.x / baseDistance;
else
progress = -this._switchData.container.x / baseDistance;
} else {
this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
progress = 0;
}
let points = [];
let [lower, upper] = this._getProgressRange();
if (lower !== 0)
points.push(lower);
points.push(0);
if (upper !== 0)
points.push(upper);
tracker.confirmSwipe(baseDistance, points, progress, 0);
}
_switchWorkspaceUpdate(tracker, progress) {
if (!this._switchData)
return;
let direction = this._directionForProgress(progress);
let info = this._switchData.surroundings[direction];
let xPos = 0;
let yPos = 0;
if (info) {
if (global.workspace_manager.layout_rows === -1)
yPos = -Math.round(progress * global.screen_height);
else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
xPos = Math.round(progress * global.screen_width);
else
xPos = -Math.round(progress * global.screen_width);
}
this._switchData.container.set_position(xPos, yPos);
}
_switchWorkspaceEnd(tracker, duration, endProgress) {
if (!this._switchData)
return;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace;
let xDest = 0;
let yDest = 0;
if (endProgress !== 0) {
let direction = this._directionForProgress(endProgress);
newWs = activeWorkspace.get_neighbor(direction);
xDest = -this._switchData.surroundings[direction].xDest;
yDest = -this._switchData.surroundings[direction].yDest;
}
let switchData = this._switchData;
switchData.gestureActivated = true;
this._switchData.container.ease({
x: xDest,
y: yDest,
duration,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => {
if (newWs !== activeWorkspace)
this.actionMoveWorkspace(newWs);
this._finishWorkspaceSwitch(switchData);
},
});
}
_switchWorkspaceStop() {
this._switchData.container.x = 0;
this._switchData.container.y = 0;
this._finishWorkspaceSwitch(this._switchData);
}
_showTilePreview(shellwm, window, tileRect, monitorIndex) { _showTilePreview(shellwm, window, tileRect, monitorIndex) {
if (!this._tilePreview) if (!this._tilePreview)
this._tilePreview = new TilePreview(); this._tilePreview = new TilePreview();
@@ -2167,7 +1764,7 @@ var WindowManager = class {
// This won't have any effect for "always sticky" windows // This won't have any effect for "always sticky" windows
// (like desktop windows or docks) // (like desktop windows or docks)
this._movingWindow = window; this._workspaceAnimation.movingWindow = window;
window.change_workspace(workspace); window.change_workspace(workspace);
global.display.clear_mouse_mode(); global.display.clear_mouse_mode();

View File

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

511
js/ui/workspaceAnimation.js Normal file
View File

@@ -0,0 +1,511 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspaceAnimationController */
const { Clutter, GObject, Meta, Shell } = imports.gi;
const Main = imports.ui.main;
const Layout = imports.ui.layout;
const SwipeTracker = imports.ui.swipeTracker;
const WINDOW_ANIMATION_TIME = 250;
const WorkspaceGroup = GObject.registerClass(
class WorkspaceGroup extends Clutter.Actor {
_init(controller, workspace, monitor) {
super._init();
this._controller = controller;
this._workspace = workspace;
this._monitor = monitor;
this._windows = [];
this._refreshWindows();
this.connect('destroy', this._onDestroy.bind(this));
this._restackedId = global.display.connect('restacked',
this._refreshWindows.bind(this));
}
_shouldShowWindow(window) {
if (window.get_workspace() !== this._workspace)
return false;
let geometry = global.display.get_monitor_geometry(this._monitor.index);
let [intersects, intersection_] = window.get_frame_rect().intersect(geometry);
if (!intersects)
return false;
if (!window.showing_on_its_workspace())
return false;
if (window.is_on_all_workspaces())
return false;
if (this._controller.movingWindow &&
window === this._controller.movingWindow)
return false;
return true;
}
_refreshWindows() {
if (this._windows.length > 0)
this._removeWindows();
let windows = global.get_window_actors();
windows = windows.filter(w => this._shouldShowWindow(w.meta_window));
for (let window of windows) {
let clone = new Clutter.Clone({
source: window,
x: window.x - this._monitor.x,
y: window.y - this._monitor.y,
});
this.add_actor(clone);
window.hide();
let record = { window, clone };
record.windowDestroyId = window.connect('destroy', () => {
clone.destroy();
this._windows.splice(this._windows.indexOf(record), 1);
});
this._windows.push(record);
}
}
_removeWindows() {
for (let i = 0; i < this._windows.length; i++) {
let w = this._windows[i];
w.window.disconnect(w.windowDestroyId);
w.clone.destroy();
if (w.window.get_meta_window().get_workspace() ===
global.workspace_manager.get_active_workspace())
w.window.show();
}
this._windows = [];
}
_onDestroy() {
global.display.disconnect(this._restackedId);
this._removeWindows();
}
});
const WorkspaceAnimation = GObject.registerClass({
Properties: {
'progress': GObject.ParamSpec.double(
'progress', 'progress', 'progress',
GObject.ParamFlags.READWRITE,
-1, 1, 0),
},
}, class WorkspaceAnimation extends Clutter.Actor {
_init(controller, from, to, direction) {
super._init();
this.connect('destroy', this._onDestroy.bind(this));
this._controller = controller;
this._movingWindow = null;
this._monitors = [];
this._progress = 0;
global.window_group.add_actor(this);
let workspaceManager = global.workspace_manager;
let curWs = workspaceManager.get_workspace_by_index(from);
for (let monitor of Main.layoutManager.monitors) {
let record = {
index: monitor.index,
clipBin: new Clutter.Actor({
x_expand: true,
y_expand: true,
clip_to_allocation: true,
}),
container: new Clutter.Actor(),
surroundings: {},
};
let constraint = new Layout.MonitorConstraint({ index: monitor.index });
record.clipBin.add_constraint(constraint);
record.clipBin.add_actor(record.container);
this.add_actor(record.clipBin);
record.curGroup = new WorkspaceGroup(controller, curWs, monitor);
record.container.add_actor(record.curGroup);
for (let dir of Object.values(Meta.MotionDirection)) {
let ws = null;
if (to < 0)
ws = curWs.get_neighbor(dir);
else if (dir === direction)
ws = workspaceManager.get_workspace_by_index(to);
if (ws === null || ws === curWs) {
record.surroundings[dir] = null;
continue;
}
let [x, y] = this._getPositionForDirection(dir, curWs, ws,
monitor.index);
let info = {
index: ws.index(),
actor: new WorkspaceGroup(controller, ws, monitor),
xDest: x,
yDest: y,
};
record.surroundings[dir] = info;
record.container.add_actor(info.actor);
record.container.set_child_above_sibling(info.actor, null);
info.actor.set_position(x, y);
}
this._monitors.push(record);
}
if (this._controller.movingWindow) {
let actor = this._controller.movingWindow.get_compositor_private();
let container = new Clutter.Actor();
this._movingWindow = {
container,
window: actor,
parent: actor.get_parent(),
};
this._movingWindow.parent.remove_child(actor);
this._movingWindow.container.add_child(actor);
this._movingWindow.windowDestroyId = actor.connect('destroy', () => {
this._movingWindow = null;
});
global.window_group.add_actor(container);
global.window_group.set_child_above_sibling(container, null);
}
}
_onDestroy() {
this._monitors = [];
if (this._movingWindow) {
let record = this._movingWindow;
record.window.disconnect(record.windowDestroyId);
record.window.get_parent().remove_child(record.window);
record.parent.add_child(record.window);
record.container.destroy();
this._movingWindow = null;
}
}
_getPositionForDirection(direction, fromWs, toWs, monitor) {
let xDest = 0, yDest = 0;
let condition = w => w.get_monitor() === monitor && w.is_fullscreen();
let oldWsIsFullscreen = fromWs.list_windows().some(condition);
let newWsIsFullscreen = toWs.list_windows().some(condition);
let geometry = Main.layoutManager.monitors[monitor];
// We have to shift windows up or down by the height of the panel to prevent having a
// visible gap between the windows while switching workspaces. Since fullscreen windows
// hide the panel, they don't need to be shifted up or down.
let shiftHeight = monitor === Main.layoutManager.primaryIndex
? Main.panel.height : 0;
if (direction === Meta.MotionDirection.UP ||
direction === Meta.MotionDirection.UP_LEFT ||
direction === Meta.MotionDirection.UP_RIGHT)
yDest = -geometry.height + (oldWsIsFullscreen ? 0 : shiftHeight);
else if (direction === Meta.MotionDirection.DOWN ||
direction === Meta.MotionDirection.DOWN_LEFT ||
direction === Meta.MotionDirection.DOWN_RIGHT)
yDest = geometry.height - (newWsIsFullscreen ? 0 : shiftHeight);
if (direction === Meta.MotionDirection.LEFT ||
direction === Meta.MotionDirection.UP_LEFT ||
direction === Meta.MotionDirection.DOWN_LEFT)
xDest = -geometry.width;
else if (direction === Meta.MotionDirection.RIGHT ||
direction === Meta.MotionDirection.UP_RIGHT ||
direction === Meta.MotionDirection.DOWN_RIGHT)
xDest = geometry.width;
return [xDest, yDest];
}
directionForProgress(progress) {
if (global.workspace_manager.layout_rows === -1) {
return progress > 0
? Meta.MotionDirection.DOWN
: Meta.MotionDirection.UP;
} else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) {
return progress > 0
? Meta.MotionDirection.LEFT
: Meta.MotionDirection.RIGHT;
} else {
return progress > 0
? Meta.MotionDirection.RIGHT
: Meta.MotionDirection.LEFT;
}
}
progressForDirection(dir) {
if (global.workspace_manager.layout_rows === -1)
return dir === Meta.MotionDirection.DOWN ? 1 : -1;
else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
return dir === Meta.MotionDirection.LEFT ? 1 : -1;
else
return dir === Meta.MotionDirection.RIGHT ? 1 : -1;
}
get progress() {
return this._progress;
}
set progress(progress) {
this._progress = progress;
let direction = this.directionForProgress(progress);
for (let monitorData of this._monitors) {
let xPos = 0;
let yPos = 0;
if (global.workspace_manager.layout_rows === -1)
yPos = -Math.round(progress * this._getDistance(monitorData, direction));
else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
xPos = Math.round(progress * this._getDistance(monitorData, direction));
else
xPos = -Math.round(progress * this._getDistance(monitorData, direction));
monitorData.container.set_position(xPos, yPos);
}
}
_getDistance(monitorData, direction) {
let info = monitorData.surroundings[direction];
if (!info)
return 0;
switch (direction) {
case Meta.MotionDirection.UP:
return -info.yDest;
case Meta.MotionDirection.DOWN:
return info.yDest;
case Meta.MotionDirection.LEFT:
return -info.xDest;
case Meta.MotionDirection.RIGHT:
return info.xDest;
}
return 0;
}
getProgressRange(monitor) {
let monitorData = null;
for (let data of this._monitors) {
if (data.index === monitor) {
monitorData = data;
break;
}
}
if (!monitorData)
return 0;
let baseDistance;
if (global.workspace_manager.layout_rows !== -1)
baseDistance = Main.layoutManager.monitors[monitor].width;
else
baseDistance = Main.layoutManager.monitors[monitor].height;
let direction = this.directionForProgress(-1);
let distance = this._getDistance(monitorData, direction);
let lower = -distance / baseDistance;
direction = this.directionForProgress(1);
distance = this._getDistance(monitorData, direction);
let upper = distance / baseDistance;
return [lower, upper];
}
});
var WorkspaceAnimationController = class {
constructor() {
this._blockAnimations = false;
this._movingWindow = null;
this._inProgress = false;
this._gestureActivated = false;
this._animation = null;
Main.overview.connect('showing', () => {
if (this._gestureActivated)
this._switchWorkspaceStop();
this._swipeTracker.enabled = false;
});
Main.overview.connect('hiding', () => {
this._swipeTracker.enabled = true;
});
let swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
Shell.ActionMode.NORMAL, { allowDrag: false, allowScroll: false });
swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
this._swipeTracker = swipeTracker;
}
_prepareWorkspaceSwitch(from, to, direction) {
if (this._animation)
return;
this._animation = new WorkspaceAnimation(this, from, to, direction);
}
_finishWorkspaceSwitch() {
if (this._animation)
this._animation.destroy();
this._animation = null;
this._inProgress = false;
this._gestureActivated = false;
this.movingWindow = null;
this._monitor = null;
}
animateSwitchWorkspace(from, to, direction, onComplete) {
this._prepareWorkspaceSwitch(from, to, direction);
this._inProgress = true;
let progress = this._animation.progressForDirection(direction);
this._animation.ease_property('progress', progress, {
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => {
this._finishWorkspaceSwitch();
onComplete();
},
});
}
_switchWorkspaceBegin(tracker, monitor) {
if (Meta.prefs_get_workspaces_only_on_primary() &&
monitor !== Main.layoutManager.primaryIndex)
return;
let workspaceManager = global.workspace_manager;
let horiz = workspaceManager.layout_rows !== -1;
tracker.orientation = horiz
? Clutter.Orientation.HORIZONTAL
: Clutter.Orientation.VERTICAL;
let activeWorkspace = workspaceManager.get_active_workspace();
let baseDistance;
if (horiz)
baseDistance = Main.layoutManager.monitors[monitor].width;
else
baseDistance = Main.layoutManager.monitors[monitor].height;
let progress;
if (this._gestureActivated) {
this._animation.remove_all_transitions();
progress = this._animation.progress;
} else {
this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
progress = 0;
}
this._monitor = monitor;
let [lower, upper] = this._animation.getProgressRange(monitor);
if (progress < 0)
progress *= -lower;
else if (progress > 0)
progress *= upper;
let points = [];
if (lower !== 0)
points.push(lower);
points.push(0);
if (upper !== 0)
points.push(upper);
tracker.confirmSwipe(baseDistance, points, progress, 0);
}
_switchWorkspaceUpdate(tracker, progress) {
// Translate the progress into [-1;1] range
let [lower, upper] = this._animation.getProgressRange(this._monitor);
if (progress < 0)
progress /= -lower;
else if (progress > 0)
progress /= upper;
this._animation.progress = progress;
}
_switchWorkspaceEnd(tracker, duration, endProgress) {
if (!this._animation)
return;
// Translate the progress into [-1;1] range
endProgress = Math.sign(endProgress);
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace;
if (endProgress !== 0) {
let direction = this._animation.directionForProgress(endProgress);
newWs = activeWorkspace.get_neighbor(direction);
}
this._gestureActivated = true;
this._animation.ease_property('progress', endProgress, {
duration,
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
onComplete: () => {
if (newWs !== activeWorkspace)
newWs.activate(global.get_current_time());
this._finishWorkspaceSwitch();
},
});
}
_switchWorkspaceStop() {
this._animation.progress = 0;
this._finishWorkspaceSwitch();
}
isAnimating() {
return this._animation !== null;
}
canCancelGesture() {
return this.isAnimating() && this._gestureActivated;
}
set movingWindow(movingWindow) {
this._movingWindow = movingWindow;
}
get movingWindow() {
return this._movingWindow;
}
};

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
project('gnome-shell', 'c', project('gnome-shell', 'c',
version: '3.36.1', version: '3.35.91',
meson_version: '>= 0.47.0', meson_version: '>= 0.47.0',
license: 'GPLv2+' license: 'GPLv2+'
) )
@@ -25,12 +25,12 @@ gio_req = '>= 2.56.0'
gi_req = '>= 1.49.1' gi_req = '>= 1.49.1'
gjs_req = '>= 1.63.2' gjs_req = '>= 1.63.2'
gtk_req = '>= 3.15.0' gtk_req = '>= 3.15.0'
mutter_req = '>= 3.36.0' mutter_req = '>= 3.35.91'
polkit_req = '>= 0.100' polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1' schemas_req = '>= 3.33.1'
startup_req = '>= 0.11' startup_req = '>= 0.11'
ibus_req = '>= 1.5.2' ibus_req = '>= 1.5.2'
gnome_desktop_req = '>= 3.35.90' gnome_desktop_req = '>= 3.34.2'
bt_req = '>= 3.9.0' bt_req = '>= 3.9.0'
gst_req = '>= 0.11.92' gst_req = '>= 0.11.92'
@@ -58,7 +58,6 @@ desktopdir = join_paths(datadir, 'applications')
icondir = join_paths(datadir, 'icons') icondir = join_paths(datadir, 'icons')
ifacedir = join_paths(datadir, 'dbus-1', 'interfaces') ifacedir = join_paths(datadir, 'dbus-1', 'interfaces')
localedir = join_paths(datadir, 'locale') localedir = join_paths(datadir, 'locale')
metainfodir = join_paths(datadir, 'metainfo')
portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals') portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
schemadir = join_paths(datadir, 'glib-2.0', 'schemas') schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
servicedir = join_paths(datadir, 'dbus-1', 'services') 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('libnm', version: nm_req)
nm_deps += dependency('libsecret-1', version: secret_req) nm_deps += dependency('libsecret-1', version: secret_req)
vpndir = nm_deps[0].get_pkgconfig_variable('vpnservicedir')
have_networkmanager = true have_networkmanager = true
else else
vpndir = prefix
have_networkmanager = false have_networkmanager = false
endif endif
@@ -139,7 +142,6 @@ endif
mutter_typelibdir = mutter_dep.get_pkgconfig_variable('typelibdir') mutter_typelibdir = mutter_dep.get_pkgconfig_variable('typelibdir')
python = find_program('python3') python = find_program('python3')
sassc = find_program('sassc') sassc = find_program('sassc')
gjs = find_program('gjs')
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
@@ -242,40 +244,13 @@ libgvc = subproject('gvc',
) )
libgvc_gir = libgvc.get_variable('libgvc_gir') 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') if get_option('extensions_tool')
extension_tool = subproject('extensions-tool', subproject('extensions-tool',
default_options: [ default_options: [
'man=@0@'.format(get_option('man')),
'package_name=@0@'.format(meson.project_name()), '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 endif
@@ -293,36 +268,3 @@ if get_option('gtk_doc')
endif endif
meson.add_install_script('meson/postinstall.py') 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' description: 'Build gnome-extensions CLI tool'
) )
option('extensions_app',
type: 'boolean',
value: true,
description: 'Build gnome-extensions GUI application'
)
option('gtk_doc', option('gtk_doc',
type: 'boolean', type: 'boolean',
value: false, value: false,

View File

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

View File

@@ -1,10 +1,13 @@
# List of source files containing translatable strings. # List of source files containing translatable strings.
# Please keep this file sorted alphabetically. # Please keep this file sorted alphabetically.
data/50-gnome-shell-system.xml data/50-gnome-shell-system.xml
data/org.gnome.Extensions.desktop.in.in
data/org.gnome.Shell.desktop.in.in data/org.gnome.Shell.desktop.in.in
data/org.gnome.shell.gschema.xml.in data/org.gnome.shell.gschema.xml.in
data/org.gnome.Shell.PortalHelper.desktop.in.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/authPrompt.js
js/gdm/loginDialog.js js/gdm/loginDialog.js
js/gdm/util.js js/gdm/util.js
@@ -78,11 +81,6 @@ src/shell-global.c
src/shell-keyring-prompt.c src/shell-keyring-prompt.c
src/shell-polkit-authentication-agent.c src/shell-polkit-authentication-agent.c
src/shell-util.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-create.c
subprojects/extensions-tool/src/command-disable.c subprojects/extensions-tool/src/command-disable.c
subprojects/extensions-tool/src/command-enable.c subprojects/extensions-tool/src/command-enable.c

299
po/ca.po
View File

@@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: HEAD\n" "Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\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-17 22:27+0000\n"
"PO-Revision-Date: 2020-02-18 20:44+0100\n" "PO-Revision-Date: 2020-02-18 20:44+0100\n"
"Last-Translator: Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>\n" "Last-Translator: Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n" "Language-Team: Catalan <tradgnome@softcatala.org>\n"
@@ -45,6 +45,15 @@ msgstr "Mostra totes les aplicacions"
msgid "Open the application menu" msgid "Open the application menu"
msgstr "Obre el menú d'aplicació" 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 #: data/org.gnome.Shell.desktop.in.in:4
msgid "GNOME Shell" msgid "GNOME Shell"
msgstr "GNOME Shell" msgstr "GNOME Shell"
@@ -191,7 +200,7 @@ msgid ""
msgstr "" msgstr ""
"El GNOME Shell us demanarà la contrasenya quan es munti un dispositiu " "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 " "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 " "contrasenya». Aquesta clau estableix el valor per defecte d'aquesta casella "
"de selecció." "de selecció."
@@ -228,48 +237,48 @@ msgstr ""
#: data/org.gnome.shell.gschema.xml.in:119 #: data/org.gnome.shell.gschema.xml.in:119
msgid "Keybinding to open the application menu" 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 #: data/org.gnome.shell.gschema.xml.in:120
msgid "Keybinding to open the application menu." 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 #: data/org.gnome.shell.gschema.xml.in:126
msgid "Keybinding to open the “Show Applications” view" 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 #: data/org.gnome.shell.gschema.xml.in:127
msgid "" msgid ""
"Keybinding to open the “Show Applications” view of the Activities Overview." "Keybinding to open the “Show Applications” view of the Activities Overview."
msgstr "" 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." "activitats de la vista general."
#: data/org.gnome.shell.gschema.xml.in:134 #: data/org.gnome.shell.gschema.xml.in:134
msgid "Keybinding to open the overview" 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 #: data/org.gnome.shell.gschema.xml.in:135
msgid "Keybinding to open the Activities Overview." 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 #: data/org.gnome.shell.gschema.xml.in:141
msgid "Keybinding to toggle the visibility of the notification list" msgid "Keybinding to toggle the visibility of the notification list"
msgstr "" 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 #: data/org.gnome.shell.gschema.xml.in:142
msgid "Keybinding to toggle the visibility of the notification list." msgid "Keybinding to toggle the visibility of the notification list."
msgstr "" 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 #: data/org.gnome.shell.gschema.xml.in:148
msgid "Keybinding to focus the active notification" 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 #: data/org.gnome.shell.gschema.xml.in:149
msgid "Keybinding to focus the active notification." 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 #: data/org.gnome.shell.gschema.xml.in:155
msgid "Switch to application 1" msgid "Switch to application 1"
@@ -406,56 +415,32 @@ msgstr ""
msgid "Network Login" msgid "Network Login"
msgstr "Inici de sessió de xarxa" msgstr "Inici de sessió de xarxa"
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5 #: js/extensionPrefs/main.js:140
#: 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
#, javascript-format #, javascript-format
msgid "Remove “%s”?" msgid "Remove “%s”?"
msgstr "Voleu suprimir «%s»?" msgstr "Voleu suprimir «%s»?"
#: js/extensionPrefs/js/main.js:164 #: js/extensionPrefs/main.js:141
msgid "" msgid ""
"If you remove the extension, you need to return to download it if you want " "If you remove the extension, you need to return to download it if you want "
"to enable it again" "to enable it again"
msgstr "" msgstr ""
"Si suprimiu una extensió, us cal tornar-la a baixar si voleu habilitar-la de " "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/extensionPrefs/main.js:144 js/ui/audioDeviceSelection.js:57
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109 #: js/ui/components/networkAgent.js:107 js/ui/components/polkitAgent.js:139
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374 #: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:165
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376 #: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913 #: js/ui/status/network.js:913
msgid "Cancel" msgid "Cancel"
msgstr "Cancel·la" msgstr "Cancel·la"
#: js/extensionPrefs/js/main.js:168 #: js/extensionPrefs/main.js:145
msgid "Remove" msgid "Remove"
msgstr "Suprimeix" msgstr "Suprimeix"
#: js/extensionPrefs/js/main.js:240 #: js/extensionPrefs/main.js:217
msgid "translator-credits" msgid "translator-credits"
msgstr "" msgstr ""
"Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n" "Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
@@ -463,12 +448,15 @@ msgstr ""
"Gil Forcada <gilforcada@guifi.net>\n" "Gil Forcada <gilforcada@guifi.net>\n"
"Jordi Mas i Hernàndez <jmas@softcatala.org>" "Jordi Mas i Hernàndez <jmas@softcatala.org>"
#: js/extensionPrefs/js/main.js:284 #: js/extensionPrefs/main.js:219
#: js/extensionPrefs/data/ui/extensions-window.ui:223 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" msgid "Somethings gone wrong"
msgstr "Alguna cosa ha anat malament" msgstr "Alguna cosa ha anat malament"
#: js/extensionPrefs/js/main.js:291 #: js/extensionPrefs/main.js:268
msgid "" msgid ""
"Were very sorry, but theres been a problem: the settings for this " "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 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 " "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ó." "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" msgid "Technical Details"
msgstr "Detalls tècnics" msgstr "Detalls tècnics"
#: js/extensionPrefs/js/main.js:333 #: js/extensionPrefs/main.js:310
msgid "Copy Error" msgid "Copy Error"
msgstr "Copia l'error" msgstr "Copia l'error"
#: js/extensionPrefs/js/main.js:360 #: js/extensionPrefs/main.js:337
msgid "Homepage" msgid "Homepage"
msgstr "Pàgina d'inici" msgstr "Pàgina d'inici"
#: js/extensionPrefs/js/main.js:361 #: js/extensionPrefs/main.js:338
msgid "Visit extension homepage" msgid "Visit extension homepage"
msgstr "Visiteu la pàgina d'inici de l'extensió" msgstr "Visiteu la pàgina d'inici de l'extensió"
#: js/extensionPrefs/js/main.js:478 #: js/extensionPrefs/main.js:449
#, javascript-format #, javascript-format
msgid "%d extension will be updated on next login." msgid "%d extension will be updated on next login."
msgid_plural "%d extensions 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[0] "%d extensió serà actualitzada la següent vegada que entreu."
msgstr[1] "%d extensions seran actualitzades 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/command-create.c:211
#: subprojects/extensions-tool/src/main.c:173 #: subprojects/extensions-tool/src/main.c:173
msgid "Description" msgid "Description"
msgstr "Descripció" msgstr "Descripció"
#: js/extensionPrefs/data/ui/extension-row.ui:123 #: js/extensionPrefs/ui/extension-row.ui:123
#: subprojects/extensions-tool/src/main.c:185 #: subprojects/extensions-tool/src/main.c:185
msgid "Version" msgid "Version"
msgstr "Versió" msgstr "Versió"
#: js/extensionPrefs/data/ui/extension-row.ui:151 #: js/extensionPrefs/ui/extension-row.ui:151
msgid "Author" msgid "Author"
msgstr "Autoria" msgstr "Autoria"
#: js/extensionPrefs/data/ui/extension-row.ui:175 #: js/extensionPrefs/ui/extension-row.ui:175
msgid "Website" msgid "Website"
msgstr "Lloc web" msgstr "Lloc web"
#: js/extensionPrefs/data/ui/extension-row.ui:192 #: js/extensionPrefs/ui/extension-row.ui:192
msgid "Remove…" msgid "Remove…"
msgstr "Suprimeix…" msgstr "Suprimeix…"
#: js/extensionPrefs/data/ui/extensions-window.ui:8 #: js/extensionPrefs/ui/extensions-window.ui:8
msgid "Help" msgid "Help"
msgstr "Ajuda" msgstr "Ajuda"
#: js/extensionPrefs/data/ui/extensions-window.ui:12 #: js/extensionPrefs/ui/extensions-window.ui:12
msgid "About Extensions" msgid "About Extensions"
msgstr "Quant a les extensions" msgstr "Quant a les extensions"
#: js/extensionPrefs/data/ui/extensions-window.ui:27 #: js/extensionPrefs/ui/extensions-window.ui:27
msgid "" msgid ""
"To find and add extensions, visit <a href=\"https://extensions.gnome.org" "To find and add extensions, visit <a href=\"https://extensions.gnome.org"
"\">extensions.gnome.org</a>." "\">extensions.gnome.org</a>."
@@ -539,11 +527,11 @@ msgstr ""
"Per visitar i afegir extensions, visiteu <a href=\"https://extensions.gnome." "Per visitar i afegir extensions, visiteu <a href=\"https://extensions.gnome."
"org\">extensions.gnome.org</a>." "org\">extensions.gnome.org</a>."
#: js/extensionPrefs/data/ui/extensions-window.ui:35 #: js/extensionPrefs/ui/extensions-window.ui:35
msgid "Warning" msgid "Warning"
msgstr "Avís" msgstr "Avís"
#: js/extensionPrefs/data/ui/extensions-window.ui:46 #: js/extensionPrefs/ui/extensions-window.ui:46
msgid "" msgid ""
"Extensions can cause system issues, including performance problems. If you " "Extensions can cause system issues, including performance problems. If you "
"encounter problems with your system, it is recommended to disable all " "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 " "rendiment. Si us trobeu amb problemes amb el sistema, us recomanem "
"inhabilitar totes les extensions." "inhabilitar totes les extensions."
#: js/extensionPrefs/data/ui/extensions-window.ui:134 #: js/extensionPrefs/ui/extensions-window.ui:133
msgid "Manually Installed" msgid "Manually Installed"
msgstr "Instal·lada manualment" msgstr "Instal·lada manualment"
#: js/extensionPrefs/data/ui/extensions-window.ui:158 #: js/extensionPrefs/ui/extensions-window.ui:157
msgid "Built-In" msgid "Built-In"
msgstr "Integrada" msgstr "Integrada"
#: js/extensionPrefs/data/ui/extensions-window.ui:199 #: js/extensionPrefs/ui/extensions-window.ui:198
msgid "No Installed Extensions" msgid "No Installed Extensions"
msgstr "No hi ha cap extensió instal·lada" msgstr "No hi ha cap extensió instal·lada"
#: js/extensionPrefs/data/ui/extensions-window.ui:235 #: js/extensionPrefs/ui/extensions-window.ui:234
msgid "" msgid ""
"Were very sorry, but it was not possible to get the list of installed " "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." "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 " "No s'ha pogut obtenir la llista d'extensions instal·lades. Assegureu-vos que "
"heu entrat al GNOME i torneu a provar-ho." "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…" msgid "Log Out…"
msgstr "Surt…" msgstr "Surt…"
#. Cisco LEAP #. Cisco LEAP
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204 #: js/gdm/authPrompt.js:235 js/ui/components/networkAgent.js:202
#: js/ui/components/networkAgent.js:220 js/ui/components/networkAgent.js:244 #: js/ui/components/networkAgent.js:218 js/ui/components/networkAgent.js:242
#: js/ui/components/networkAgent.js:265 js/ui/components/networkAgent.js:285 #: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:283
#: js/ui/components/networkAgent.js:295 js/ui/components/polkitAgent.js:277 #: js/ui/components/networkAgent.js:293 js/ui/components/polkitAgent.js:277
#: js/ui/shellMountOperation.js:326 #: js/ui/shellMountOperation.js:326
msgid "Password" msgid "Password"
msgstr "Contrasenya" msgstr "Contrasenya"
@@ -604,8 +592,8 @@ msgstr "(p. ex. l'usuari o %s)"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (and don't even care of which one)
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:240 #: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:238
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281 #: js/ui/components/networkAgent.js:261 js/ui/components/networkAgent.js:279
msgid "Username" msgid "Username"
msgstr "Nom d'usuari" msgstr "Nom d'usuari"
@@ -857,44 +845,44 @@ msgstr "Denega l'accés"
msgid "Grant Access" msgid "Grant Access"
msgstr "Permet l'accés" msgstr "Permet l'accés"
#: js/ui/appDisplay.js:898 #: js/ui/appDisplay.js:906
msgid "Unnamed Folder" msgid "Unnamed Folder"
msgstr "Carpeta sense nom" msgstr "Carpeta sense nom"
#: js/ui/appDisplay.js:921 #: js/ui/appDisplay.js:929
msgid "Frequently used applications will appear here" msgid "Frequently used applications will appear here"
msgstr "Les aplicacions utilitzades freqüentment apareixeran aquí" msgstr "Les aplicacions utilitzades freqüentment apareixeran aquí"
#: js/ui/appDisplay.js:1056 #: js/ui/appDisplay.js:1064
msgid "Frequent" msgid "Frequent"
msgstr "Freqüent" msgstr "Freqüent"
#: js/ui/appDisplay.js:1063 #: js/ui/appDisplay.js:1071
msgid "All" msgid "All"
msgstr "Totes" msgstr "Totes"
#. Translators: This is the heading of a list of open windows #. 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:2454 js/ui/panel.js:75
msgid "Open Windows" msgid "Open Windows"
msgstr "Obre finestres" msgstr "Obre finestres"
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82 #: js/ui/appDisplay.js:2474 js/ui/panel.js:82
msgid "New Window" msgid "New Window"
msgstr "Finestra nova" msgstr "Finestra nova"
#: js/ui/appDisplay.js:2477 #: js/ui/appDisplay.js:2485
msgid "Launch using Dedicated Graphics Card" msgid "Launch using Dedicated Graphics Card"
msgstr "Inicia usant una targeta gràfica dedicada" msgstr "Inicia usant una targeta gràfica dedicada"
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239 #: js/ui/appDisplay.js:2513 js/ui/dash.js:239
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Suprimeix dels preferits" msgstr "Suprimeix dels preferits"
#: js/ui/appDisplay.js:2511 #: js/ui/appDisplay.js:2519
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Afegeix als preferits" msgstr "Afegeix als preferits"
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93 #: js/ui/appDisplay.js:2529 js/ui/panel.js:93
msgid "Show Details" msgid "Show Details"
msgstr "Mostra els detalls" msgstr "Mostra els detalls"
@@ -1042,30 +1030,30 @@ msgid "All Day"
msgstr "Tot el dia" msgstr "Tot el dia"
#. Translators: Shown on calendar heading when selected day occurs on current year #. 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" msgctxt "calendar heading"
msgid "%A, %B %-d" msgid "%A, %B %-d"
msgstr "%A %-d %B" msgstr "%A %-d %B"
#. Translators: Shown on calendar heading when selected day occurs on different year #. 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" msgctxt "calendar heading"
msgid "%A, %B %-d, %Y" msgid "%A, %B %-d, %Y"
msgstr "%A %d %B de %Y" msgstr "%A %d %B de %Y"
#: js/ui/calendar.js:1100 #: js/ui/calendar.js:1096
msgid "No Notifications" msgid "No Notifications"
msgstr "Cap notificació" msgstr "Cap notificació"
#: js/ui/calendar.js:1103 #: js/ui/calendar.js:1099
msgid "No Events" msgid "No Events"
msgstr "Cap cita" msgstr "Cap cita"
#: js/ui/calendar.js:1157 #: js/ui/calendar.js:1153
msgid "Do Not Disturb" msgid "Do Not Disturb"
msgstr "No molesteu" msgstr "No molesteu"
#: js/ui/calendar.js:1171 #: js/ui/calendar.js:1167
msgid "Clear" msgid "Clear"
msgstr "Neteja-ho" msgstr "Neteja-ho"
@@ -1113,38 +1101,38 @@ msgstr ""
msgid "Open with %s" msgid "Open with %s"
msgstr "Obre amb %s" msgstr "Obre amb %s"
#: js/ui/components/networkAgent.js:91 #: js/ui/components/networkAgent.js:89
msgid "" msgid ""
"Alternatively you can connect by pushing the “WPS” button on your router." "Alternatively you can connect by pushing the “WPS” button on your router."
msgstr "També us podeu connectar prement el botó «WPS» del vostre encaminador." 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 #: js/ui/status/network.js:314 js/ui/status/network.js:916
msgid "Connect" msgid "Connect"
msgstr "Connecta" msgstr "Connecta"
#: js/ui/components/networkAgent.js:210 #: js/ui/components/networkAgent.js:208
msgid "Key" msgid "Key"
msgstr "Clau" 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" msgid "Private key password"
msgstr "Contrasenya de la clau privada" msgstr "Contrasenya de la clau privada"
#: js/ui/components/networkAgent.js:269 #: js/ui/components/networkAgent.js:267
msgid "Identity" msgid "Identity"
msgstr "Identitat" msgstr "Identitat"
#: js/ui/components/networkAgent.js:283 #: js/ui/components/networkAgent.js:281
msgid "Service" msgid "Service"
msgstr "Servei" msgstr "Servei"
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:340 #: js/ui/components/networkAgent.js:310 js/ui/components/networkAgent.js:338
#: js/ui/components/networkAgent.js:679 js/ui/components/networkAgent.js:700 #: js/ui/components/networkAgent.js:685 js/ui/components/networkAgent.js:706
msgid "Authentication required" msgid "Authentication required"
msgstr "Cal autenticació" 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 #, javascript-format
msgid "" msgid ""
"Passwords or encryption keys are required to access the wireless network " "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 " "Per accedir a la xarxa sense fil «%s» calen les contrasenyes o les claus "
"d'encriptació." "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" msgid "Wired 802.1X authentication"
msgstr "Autenticació 802.1X amb fil" msgstr "Autenticació 802.1X amb fil"
#: js/ui/components/networkAgent.js:319 #: js/ui/components/networkAgent.js:317
msgid "Network name" msgid "Network name"
msgstr "Nom de la xarxa" 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" msgid "DSL authentication"
msgstr "Autenticació DSL" 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" msgid "PIN code required"
msgstr "Cal que introduïu el codi PIN" 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" 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" 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" msgid "PIN"
msgstr "PIN" msgstr "PIN"
#: js/ui/components/networkAgent.js:341 js/ui/components/networkAgent.js:685 #: js/ui/components/networkAgent.js:339 js/ui/components/networkAgent.js:691
#: js/ui/components/networkAgent.js:689 js/ui/components/networkAgent.js:701 #: js/ui/components/networkAgent.js:695 js/ui/components/networkAgent.js:707
#: js/ui/components/networkAgent.js:705 #: js/ui/components/networkAgent.js:711
#, javascript-format #, javascript-format
msgid "A password is required to connect to “%s”." msgid "A password is required to connect to “%s”."
msgstr "Cal introduir una contrasenya per connectar-vos a «%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" msgid "Network Manager"
msgstr "Gestor de connexions de xarxa" msgstr "Gestor de connexions de xarxa"
#: js/ui/components/networkAgent.js:704 #: js/ui/components/networkAgent.js:710
msgid "VPN password" msgid "VPN password"
msgstr "Contrasenya VPN" msgstr "Contrasenya VPN"
@@ -1258,23 +1246,23 @@ msgstr "Afegeix rellotges del món…"
msgid "World Clocks" msgid "World Clocks"
msgstr "Rellotges del món" msgstr "Rellotges del món"
#: js/ui/dateMenu.js:289 #: js/ui/dateMenu.js:276
msgid "Weather" msgid "Weather"
msgstr "El temps" msgstr "El temps"
#: js/ui/dateMenu.js:404 #: js/ui/dateMenu.js:391
msgid "Select a location…" msgid "Select a location…"
msgstr "Trieu una ubicació…" msgstr "Trieu una ubicació…"
#: js/ui/dateMenu.js:417 #: js/ui/dateMenu.js:404
msgid "Loading…" msgid "Loading…"
msgstr "S'està carregant…" msgstr "S'està carregant…"
#: js/ui/dateMenu.js:427 #: js/ui/dateMenu.js:414
msgid "Go online for weather information" msgid "Go online for weather information"
msgstr "Vés en línia per a informació sobre el temps" 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" msgid "Weather information is currently unavailable"
msgstr "La informació sobre el temps no està disponible" msgstr "La informació sobre el temps no està disponible"
@@ -1430,15 +1418,15 @@ msgstr "%s (remot)"
msgid "%s (console)" msgid "%s (console)"
msgstr "%s (consola)" msgstr "%s (consola)"
#: js/ui/extensionDownloader.js:181 #: js/ui/extensionDownloader.js:169
msgid "Install" msgid "Install"
msgstr "Instal·la" msgstr "Instal·la"
#: js/ui/extensionDownloader.js:187 #: js/ui/extensionDownloader.js:175
msgid "Install Extension" msgid "Install Extension"
msgstr "Instal·la l'extensió" msgstr "Instal·la l'extensió"
#: js/ui/extensionDownloader.js:188 #: js/ui/extensionDownloader.js:176
#, javascript-format #, javascript-format
msgid "Download and install “%s” from extensions.gnome.org?" msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» d'extensions.gnome.org?" msgstr "Voleu baixar i instal·lar «%s» d'extensions.gnome.org?"
@@ -1550,59 +1538,59 @@ msgstr "Deixa-ho desactivat"
msgid "Region & Language Settings" msgid "Region & Language Settings"
msgstr "Configuració de regió i idioma" msgstr "Configuració de regió i idioma"
#: js/ui/lookingGlass.js:665 #: js/ui/lookingGlass.js:659
msgid "No extensions installed" msgid "No extensions installed"
msgstr "No hi ha cap extensió instal·lada" msgstr "No hi ha cap extensió instal·lada"
#. Translators: argument is an extension UUID. #. Translators: argument is an extension UUID.
#: js/ui/lookingGlass.js:720 #: js/ui/lookingGlass.js:714
#, javascript-format #, javascript-format
msgid "%s has not emitted any errors." msgid "%s has not emitted any errors."
msgstr "%s no ha emès cap error." msgstr "%s no ha emès cap error."
#: js/ui/lookingGlass.js:726 #: js/ui/lookingGlass.js:720
msgid "Hide Errors" msgid "Hide Errors"
msgstr "Amaga els errors" msgstr "Amaga els errors"
#: js/ui/lookingGlass.js:730 js/ui/lookingGlass.js:795 #: js/ui/lookingGlass.js:724 js/ui/lookingGlass.js:789
msgid "Show Errors" msgid "Show Errors"
msgstr "Mostra els errors" msgstr "Mostra els errors"
#: js/ui/lookingGlass.js:739 #: js/ui/lookingGlass.js:733
msgid "Enabled" msgid "Enabled"
msgstr "Habilitat" msgstr "Habilitat"
#. translators: #. translators:
#. * The device has been disabled #. * The device has been disabled
#: js/ui/lookingGlass.js:742 subprojects/gvc/gvc-mixer-control.c:1892 #: js/ui/lookingGlass.js:736 subprojects/gvc/gvc-mixer-control.c:1892
msgid "Disabled" msgid "Disabled"
msgstr "Inhabilitat" msgstr "Inhabilitat"
#: js/ui/lookingGlass.js:744 #: js/ui/lookingGlass.js:738
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
#: js/ui/lookingGlass.js:746 #: js/ui/lookingGlass.js:740
msgid "Out of date" msgid "Out of date"
msgstr "Fora d'hora" msgstr "Fora d'hora"
#: js/ui/lookingGlass.js:748 #: js/ui/lookingGlass.js:742
msgid "Downloading" msgid "Downloading"
msgstr "S'està baixant" msgstr "S'està baixant"
#: js/ui/lookingGlass.js:777 #: js/ui/lookingGlass.js:771
msgid "View Source" msgid "View Source"
msgstr "Mostra el codi font" msgstr "Mostra el codi font"
#: js/ui/lookingGlass.js:786 #: js/ui/lookingGlass.js:780
msgid "Web Page" msgid "Web Page"
msgstr "Pàgina web" msgstr "Pàgina web"
#: js/ui/main.js:274 #: js/ui/main.js:267
msgid "Logged in as a privileged user" msgid "Logged in as a privileged user"
msgstr "Sessió iniciada com a usuari privilegiat" msgstr "Sessió iniciada com a usuari privilegiat"
#: js/ui/main.js:275 #: js/ui/main.js:268
msgid "" msgid ""
"Running a session as a privileged user should be avoided for security " "Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user." "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. " "Cal evitar iniciar sessions com a usuari privilegiat per raons de seguretat. "
"Si és possible, entreu com a un usuari normal." "Si és possible, entreu com a un usuari normal."
#: js/ui/main.js:281 #: js/ui/main.js:274
msgid "Screen Lock disabled" msgid "Screen Lock disabled"
msgstr "La pantalla de bloqueig està inhabilitada" msgstr "La pantalla de bloqueig està inhabilitada"
#: js/ui/main.js:282 #: js/ui/main.js:275
msgid "Screen Locking requires the GNOME display manager." msgid "Screen Locking requires the GNOME display manager."
msgstr "El bloqueig de pantalla requereix el gestor de pantalla del GNOME." msgstr "El bloqueig de pantalla requereix el gestor de pantalla del GNOME."
@@ -1646,7 +1634,7 @@ msgstr "Vista general"
#. characters. #. characters.
#: js/ui/overview.js:107 #: js/ui/overview.js:107
msgid "Type to search" msgid "Type to search"
msgstr "Teclegeu per a cercar" msgstr "Teclegeu per començar la cerca"
#: js/ui/padOsd.js:95 #: js/ui/padOsd.js:95
msgid "New shortcut…" msgid "New shortcut…"
@@ -1686,11 +1674,11 @@ msgstr "Premeu un botó per a configurar"
#: js/ui/padOsd.js:864 #: js/ui/padOsd.js:864
msgid "Press Esc to exit" msgid "Press Esc to exit"
msgstr "Premeu Esc per a sortir" msgstr "Premeu Esc per sortir"
#: js/ui/padOsd.js:867 #: js/ui/padOsd.js:867
msgid "Press any key to exit" msgid "Press any key to exit"
msgstr "Premeu qualsevol tecla per a sortir" msgstr "Premeu qualsevol tecla per sortir"
#: js/ui/panel.js:109 #: js/ui/panel.js:109
msgid "Quit" msgid "Quit"
@@ -1702,12 +1690,12 @@ msgstr "Surt"
msgid "Activities" msgid "Activities"
msgstr "Activitats" msgstr "Activitats"
#: js/ui/panel.js:713 #: js/ui/panel.js:707
msgctxt "System menu in the top bar" msgctxt "System menu in the top bar"
msgid "System" msgid "System"
msgstr "Sistema" msgstr "Sistema"
#: js/ui/panel.js:826 #: js/ui/panel.js:820
msgid "Top Bar" msgid "Top Bar"
msgstr "Barra superior" msgstr "Barra superior"
@@ -1927,11 +1915,11 @@ msgstr "Clic secundari"
msgid "Dwell Click" msgid "Dwell Click"
msgstr "Clic en passar per sobre" msgstr "Clic en passar per sobre"
#: js/ui/status/keyboard.js:826 #: js/ui/status/keyboard.js:825
msgid "Keyboard" msgid "Keyboard"
msgstr "Teclat" msgstr "Teclat"
#: js/ui/status/keyboard.js:848 #: js/ui/status/keyboard.js:847
msgid "Show Keyboard Layout" msgid "Show Keyboard Layout"
msgstr "Mostra la disposició del teclat" msgstr "Mostra la disposició del teclat"
@@ -2345,26 +2333,22 @@ msgstr "Només l'integrat"
#. Translators: This is a time format for a date in #. Translators: This is a time format for a date in
#. long format #. long format
#: js/ui/unlockDialog.js:370 #: js/ui/unlockDialog.js:372
msgid "%A %B %-d" msgid "%A %B %-d"
msgstr "%A %-d %B" msgstr "%A %-d %B"
#: js/ui/unlockDialog.js:376 #: js/ui/unlockDialog.js:378
msgid "Swipe up to unlock" msgid "Swipe up to unlock"
msgstr "Llisqueu amunt per a desbloquejar" msgstr "Llisqueu amunt per desbloquejar"
#: js/ui/unlockDialog.js:377 #: js/ui/unlockDialog.js:379
msgid "Click or press a key to unlock" 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 #: js/ui/unlockDialog.js:552
msgid "Unlock Window" msgid "Unlock Window"
msgstr "Desbloqueja la finestra" msgstr "Desbloqueja la finestra"
#: js/ui/unlockDialog.js:558
msgid "Log in as another user"
msgstr "Entra amb un altre usuari"
#: js/ui/viewSelector.js:181 #: js/ui/viewSelector.js:181
msgid "Applications" msgid "Applications"
msgstr "Aplicacions" msgstr "Aplicacions"
@@ -2480,19 +2464,19 @@ msgstr "Tanca"
msgid "Evolution Calendar" msgid "Evolution Calendar"
msgstr "Calendari de l'Evolution" 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" msgid "Print version"
msgstr "Mostra la versió" msgstr "Mostra la versió"
#: src/main.c:464 #: src/main.c:466
msgid "Mode used by GDM for login screen" msgid "Mode used by GDM for login screen"
msgstr "El mode que utilitzarà el GDM per a la pantalla d'entrada" 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" 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" 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" msgid "List possible modes"
msgstr "Llista els modes possibles" msgstr "Llista els modes possibles"
@@ -2830,7 +2814,7 @@ msgstr "Instal·la un paquet d'extensió"
#: subprojects/extensions-tool/src/main.c:262 #: subprojects/extensions-tool/src/main.c:262
#, c-format #, c-format
msgid "Use “%s” to get detailed help.\n" 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: #. translators:
#. * The number of sound outputs on a particular device #. * The number of sound outputs on a particular device
@@ -2867,6 +2851,9 @@ msgstr "Sons del sistema"
#~ msgid "Enter Password…" #~ msgid "Enter Password…"
#~ msgstr "Introduïu la contrasenya…" #~ msgstr "Introduïu la contrasenya…"
#~ msgid "Log in as another user"
#~ msgstr "Entra amb un altre usuari"
#~ msgid "Browse in Software" #~ msgid "Browse in Software"
#~ msgstr "Navega al Programari" #~ msgstr "Navega al Programari"

2619
po/ckb.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