Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
a6783692c5 | |||
1c27b68bcc | |||
717c05a288 | |||
e68604b1aa | |||
0368ad29e9 | |||
b982ce394e | |||
025647f585 | |||
7125b726ad | |||
aebfab7207 | |||
698bd5b3a9 | |||
51e9f19f2f | |||
6d38a4a7b3 | |||
dfcc5ffb1e | |||
8b80a4cf4d | |||
01e894c028 | |||
856adfd1f1 | |||
efee3aa749 | |||
15e72da648 | |||
3f8bd1db25 | |||
3a863ee341 | |||
654a7af929 | |||
8dd9cbac7f | |||
331db650dd | |||
428d38179d | |||
fe9708ebd8 | |||
8398769321 | |||
768c08ba9d | |||
69426cbfda | |||
9f968e7378 | |||
1ab5e6973a | |||
1dea3341ec | |||
8fda054dc5 | |||
e989684602 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -60,6 +60,7 @@ src/calendar-server/evolution-calendar.desktop
|
||||
src/calendar-server/org.gnome.Shell.CalendarServer.service
|
||||
src/gnome-shell
|
||||
src/gnome-shell-calendar-server
|
||||
src/gnome-shell-extension-prefs
|
||||
src/gnome-shell-extension-tool
|
||||
src/gnome-shell-hotplug-sniffer
|
||||
src/gnome-shell-perf-helper
|
||||
|
@ -18,7 +18,7 @@ variables:
|
||||
- merge_requests
|
||||
|
||||
check_commit_log:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
@ -28,10 +28,10 @@ check_commit_log:
|
||||
- merge_requests
|
||||
|
||||
js_check:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
|
||||
stage: review
|
||||
script:
|
||||
- find js -name '*.js' -exec js68 -c -s '{}' ';' 2>&1 | tee $JS_LOG
|
||||
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
|
||||
- (! grep -q . $JS_LOG)
|
||||
<<: *only_default
|
||||
artifacts:
|
||||
@ -40,7 +40,7 @@ js_check:
|
||||
when: on_failure
|
||||
|
||||
eslint:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
|
||||
stage: review
|
||||
script:
|
||||
- ./.gitlab-ci/run-eslint.sh
|
||||
@ -51,21 +51,21 @@ eslint:
|
||||
when: always
|
||||
|
||||
potfile_check:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
|
||||
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:v2
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
|
||||
stage: review
|
||||
script:
|
||||
- ./.gitlab-ci/check-template-strings.sh
|
||||
<<: *only_default
|
||||
|
||||
build:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
|
||||
stage: build
|
||||
before_script:
|
||||
- .gitlab-ci/checkout-mutter.sh
|
||||
@ -83,7 +83,7 @@ build:
|
||||
- build
|
||||
|
||||
test:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
|
||||
stage: test
|
||||
variables:
|
||||
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
|
||||
@ -100,7 +100,7 @@ test:
|
||||
when: on_failure
|
||||
|
||||
test-pot:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
|
||||
stage: test
|
||||
before_script:
|
||||
- ninja -C mutter/build install
|
||||
@ -124,7 +124,11 @@ flatpak:
|
||||
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
|
||||
FLATPAK_MODULE: "gnome-extensions-app"
|
||||
APP_ID: "org.gnome.Extensions"
|
||||
MESON_ARGS: "$SUBPROJECT"
|
||||
extends: .flatpak
|
||||
before_script:
|
||||
- flatpak run --command=$SUBPROJECT/generate-translations.sh
|
||||
--filesystem=host org.gnome.Sdk//master
|
||||
<<: *only_default
|
||||
|
||||
nightly:
|
||||
|
@ -1,24 +0,0 @@
|
||||
# Rebuild and push with
|
||||
#
|
||||
# cd .gitlab-ci/
|
||||
# podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2 .
|
||||
# podman push registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v2
|
||||
#
|
||||
|
||||
FROM registry.fedoraproject.org/fedora:32
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(copr)' git && \
|
||||
|
||||
# For syntax checks with `find . -name '*.js' -exec js68 -c -s '{}' ';'`
|
||||
dnf install -y findutils mozjs68-devel && \
|
||||
|
||||
# For static analysis with eslint
|
||||
dnf install -y nodejs && \
|
||||
npm install -g eslint && \
|
||||
|
||||
# Shameless plug for my own tooling; useful for generating zip
|
||||
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
||||
dnf install -y gnome-extensions-tool meson && \
|
||||
|
||||
dnf clean all
|
18
.gitlab-ci/Dockerfile.extension-ci
Normal file
18
.gitlab-ci/Dockerfile.extension-ci
Normal file
@ -0,0 +1,18 @@
|
||||
FROM registry.fedoraproject.org/fedora:latest
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(copr)' git && \
|
||||
|
||||
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
|
||||
dnf install -y findutils mozjs60-devel && \
|
||||
|
||||
# For static analysis with eslint
|
||||
dnf install -y nodejs && \
|
||||
npm install -g eslint && \
|
||||
|
||||
# Shameless plug for my own tooling; useful for generating zip
|
||||
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
||||
dnf install -y gnome-extensions-tool meson && \
|
||||
|
||||
dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
@ -6,11 +6,6 @@ globs=('*.js' '*.c')
|
||||
# find source files that contain gettext keywords
|
||||
files=$(grep -lR ${globs[@]/#/--include=} '\(gettext\|[^I_)]_\)(' $srcdirs)
|
||||
|
||||
# filter out excluded files
|
||||
if [ -f po/POTFILES.skip ]; then
|
||||
files=$(for f in $files; do ! grep -q ^$f po/POTFILES.skip && echo $f; done)
|
||||
fi
|
||||
|
||||
# find those that aren't listed in POTFILES.in
|
||||
missing=$(for f in $files; do ! grep -q ^$f po/POTFILES.in && echo $f; done)
|
||||
|
||||
|
@ -18,14 +18,12 @@ run_eslint() {
|
||||
local extra_args=ARGS_$1
|
||||
local output_var=OUTPUT_$1
|
||||
local output=${!output_var}
|
||||
local cache=.eslintcache-${1,,}
|
||||
|
||||
# ensure output exists even if eslint doesn't report any errors
|
||||
mkdir -p $(dirname $output)
|
||||
touch $output
|
||||
|
||||
eslint -f unix --cache --cache-location $cache ${!extra_args} -o $output \
|
||||
js subprojects/extensions-app/js
|
||||
eslint -f unix ${!extra_args} -o $output js subprojects/extensions-app/js
|
||||
}
|
||||
|
||||
list_commit_range_additions() {
|
||||
|
131
NEWS
131
NEWS
@ -1,87 +1,60 @@
|
||||
3.37.2
|
||||
3.36.1
|
||||
======
|
||||
* Add support for "PrefersNonDefaultGPU" desktop key [Bastien; !1226]
|
||||
* Only start systemd units when running under systemd
|
||||
[Carlos, Florian; #2755, !1242, !1252]
|
||||
* Fix "ghost" media controls [Bryan; #2776]
|
||||
* Fix zombie sockets from extensions downloader [Michael; #2774]
|
||||
* Update world clocks offsets when timezone changes [Bryan; #2209]
|
||||
* Support scrolling anywhere in slider menu items [Peter; #2795]
|
||||
* Fix "Do Not Disturb" setting getting reset on startup [Florian; #2804]
|
||||
* Only allow updates for extensions that aren't cached [Florian; !1248]
|
||||
* Fix matching notifications by PID [Florian; #2592]
|
||||
* Indicate extension errors in Extensions app [Florian; #2337]
|
||||
* Add clipboard API for querying supported mimetypes [Andy; #2819]
|
||||
* Add preview to color picker [Florian; #451]
|
||||
* Improve world clocks styling [PrOF-kk; #2825]
|
||||
* Remove Frequent view from app picker [Georges; !880]
|
||||
* Fix pad OSD glitches [Carlos; !1290]
|
||||
* Expose actor tree in looking glass [Georges; !1292]
|
||||
* Fixed crashes [Jonas D., Florian; #2709, #2757]
|
||||
* Misc. bug fixes and cleanups [Florian, AsciiWolf, Michael, Piotr, Ting-Wei,
|
||||
Amr, Alexander, Bryan, Georges, Jonas D., Andy, Björn, Koki, Carlos; !1229,
|
||||
!1231, !1233, !1235, #2578, #2735, #2751, #2602, #2777, !1249, #2796, !1268,
|
||||
!1269, !1265, !1245, !1273, #2816, !1274, !1263, !1188, !1276, #2652, !1277,
|
||||
!1281, #2286, !1267, !1286, !1279, !1288, !1293, !1294, !1291]
|
||||
* 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:
|
||||
AsciiWolf, Michael Catanzaro, Björn Daase, Jonas Dreßler, Bryan Dunsmore,
|
||||
Koki Fukuda, Carlos Garnacho, Andy Holmes, Amr Ibrahim, Soslan Khubulov,
|
||||
Ting-Wei Lan, Michael Lass, Alexander Mikhaylenko, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Bastien Nocera, PrOF-kk, Peter Simonyi
|
||||
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:
|
||||
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Yuri Chornoivan [uk],
|
||||
Dušan Kazik [sk], Piotr Drąg [pl], Soslan Khubulov [os],
|
||||
Daniel Mustieles [es], Nathan Follens [nl], Bruce Cowan [en_GB],
|
||||
Florentina Mușat [ro], Milo Casagrande [it], Anders Jonsson [sv],
|
||||
Charles Monzat [fr], Danial Behzadi [fa], sicklylife [ja], Kukuh Syafaat [id],
|
||||
Jordi Mas [ca], Emin Tufan Çetin [tr], Jiri Grönroos [fi], Марко Костић [sr],
|
||||
Christian Kirbach [de], Changwoo Ryu [ko], Matej Urbančič [sl]
|
||||
|
||||
3.37.1
|
||||
======
|
||||
* Improve bluetooth submenu title [Mariana; #2340]
|
||||
* Add openPrefs() convenience method for extensions [Florian; !1163]
|
||||
* Bring back support for empty StIcons [Andre, Jonas D.; !1173, !1178]
|
||||
* Wake up screen when unlocking programmatically [Florian; !1158]
|
||||
* Improve extensions tool error reporting [Florian; #2391]
|
||||
* Improve handling of scale-factor changes [Georges; !1176]
|
||||
* Tone down weekend days with events in calendar [Jakub; #2588]
|
||||
* Fix showing bluetooth submenu when devices were set up [Florian; !1174]
|
||||
* Add support for parental controls filtering [Philip W.; !465]
|
||||
* Provide alternative extension templates [Florian; !812]
|
||||
* Improve weather section's empty state [Mariana; #2179]
|
||||
* Fix translations of folder names [Florian; #2623]
|
||||
* Drop Tweener [Jonas Å.; !1200]
|
||||
* Match ASCII alternatives of system actions [Will; #2688]
|
||||
* Fix delay on lock screen after entering wrong password [Jonas D.; #2655]
|
||||
* Use globalThis instead of window [Andy; #2322]
|
||||
* Inhibit remote access when disabled by session mode [Jonas Å.; !1210]
|
||||
* Improve calendar-server performance [Milan; #1875]
|
||||
* Add gnome-shell-extension-prefs wrapper for compatibility [Florian; !1220]
|
||||
* Fix stuck lock screen after unlock [Jonas D., Florian; #2446]
|
||||
* Fixed crashes [Jonas D., Florian, Carlos; #2584, #2625, !1223, !1218]
|
||||
* Misc. bug fixes and cleanups [Florian, Jonas Å., Marco, Andre, Georges,
|
||||
Jonas D., Jan, Philip Ch.,, Xiaoguang, Will, Jordan, Matthew, qarmin;
|
||||
!1126, !1155, !1156, !1165, !1168, !1169, #2551, #2563, !1172, !1175, !1179,
|
||||
!1160, #2562, #2578, !1184, #2559, !1186, #2607, !1191, !1194, !1199, !1203,
|
||||
#2649, #2628, !1205, !1206, !1208, !1207, !1211, !1214, !1213, !1192, !1217,
|
||||
!1219, #1615, #2691, !1094, !1177]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Philip Chimento, Milan Crha, Jonas Dreßler,
|
||||
Carlos Garnacho, Andy Holmes, Matthew Leeds, Andre Moreira Magalhaes,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Jordan Petridis,
|
||||
Mariana Picolo, Jakub Steiner, Will Thompson, Jan Tojnar, Xiaoguang Wang,
|
||||
Philip Withnall, qarmin, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Danial Behzadi [fa],
|
||||
Jiri Grönroos [fi], Ibai Oihanguren Sala [eu], Марко Костић [sr],
|
||||
Rūdolfs Mazurs [lv], Yuri Chornoivan [uk], Carmen Bianca BAKKER [eo],
|
||||
Dingzhong Chen [zh_CN], Rafael Fontenelle [pt_BR], Petr Kovář [cs],
|
||||
Asier Sarasua Garmendia [eu], Daniel Mustieles [es], Emin Tufan Çetin [tr]
|
||||
Марко Костић [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
|
||||
======
|
||||
|
@ -1,19 +1,12 @@
|
||||
<node>
|
||||
<interface name="org.gnome.Shell.CalendarServer">
|
||||
<method name="SetTimeRange">
|
||||
<arg type="x" name="since" direction="in"/>
|
||||
<arg type="x" name="until" direction="in"/>
|
||||
<arg type="b" name="force_reload" direction="in"/>
|
||||
<method name="GetEvents">
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="a(sssbxxa{sv})" direction="out" />
|
||||
</method>
|
||||
<signal name="EventsAddedOrUpdated">
|
||||
<arg type="a(ssbxxa{sv})" name="events" direction="out"/>
|
||||
</signal>
|
||||
<signal name="EventsRemoved">
|
||||
<arg type="as" name="ids" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ClientDisappeared">
|
||||
<arg type="s" name="source_uid" direction="out"/>
|
||||
</signal>
|
||||
<property name="HasCalendars" type="b" access="read" />
|
||||
<signal name="Changed" />
|
||||
</interface>
|
||||
</node>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/shell/dbus-interfaces">
|
||||
<file preprocess="xml-stripblanks">net.hadess.SensorProxy.xml</file>
|
||||
<file preprocess="xml-stripblanks">net.hadess.SwitcherooControl.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.freedesktop.Application.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.freedesktop.bolt1.Device.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.freedesktop.bolt1.Manager.xml</file>
|
||||
|
@ -6,7 +6,6 @@
|
||||
<file>checkbox-off-focused.svg</file>
|
||||
<file>checkbox-off.svg</file>
|
||||
<file>checkbox.svg</file>
|
||||
<file alias="icons/color-pick.svg">color-pick.svg</file>
|
||||
<file>dash-placeholder.svg</file>
|
||||
<file>gnome-shell.css</file>
|
||||
<file>gnome-shell-high-contrast.css</file>
|
||||
|
@ -1,94 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="5.4116011mm"
|
||||
height="5.1374583mm"
|
||||
viewBox="0 0 5.4116011 5.1374583"
|
||||
version="1.1"
|
||||
id="svg5595"
|
||||
inkscape:version="0.92.4 (unknown)"
|
||||
sodipodi:docname="color-pick.svg">
|
||||
<defs
|
||||
id="defs5589">
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
x="-0.10291173"
|
||||
width="1.2058235"
|
||||
y="-0.065432459"
|
||||
height="1.1308649"
|
||||
id="filter5601"
|
||||
style="color-interpolation-filters:sRGB">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.610872"
|
||||
id="feGaussianBlur5603" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="39.387731"
|
||||
inkscape:cy="12.554326"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata5592">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-103.12753,-146.26461)">
|
||||
<circle
|
||||
r="8.4810486"
|
||||
cy="9.82623"
|
||||
cx="10.226647"
|
||||
id="circle7584"
|
||||
style="color:#000000;display:inline;overflow:visible;opacity:0.6;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;filter:url(#filter5601)"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,103.12753,146.26461)" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.26399338;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 108.07728,148.64122 c 0,1.2393 -1.00465,2.24394 -2.24395,2.24394 -1.23929,0 -2.24716,-1.00465 -2.25221,-2.24394 l -0.009,-2.24458 2.26136,6.4e-4 c 1.2393,3.4e-4 2.24395,1.00464 2.24395,2.24394 z"
|
||||
id="path7523-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ssscss" />
|
||||
<circle
|
||||
style="color:#000000;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:#50dbb5;fill-opacity:1;stroke:none;stroke-width:0.36885914;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="path7482-1"
|
||||
cx="105.83707"
|
||||
cy="148.64352"
|
||||
r="1.844296" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.7 KiB |
@ -14,6 +14,8 @@ $app_icon_padding: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
//.app-display { spacing: 20px; }
|
||||
|
||||
/* App Icons */
|
||||
|
||||
$app_grid_fg_color: #fff;
|
||||
@ -121,11 +123,15 @@ $app_grid_fg_color: #fff;
|
||||
}
|
||||
|
||||
// Some hacks I don't even know
|
||||
.all-apps {
|
||||
.all-apps,
|
||||
.frequent-apps > StBoxLayout {
|
||||
// horizontal padding to make sure scrollbars or dash don't overlap content
|
||||
padding: 0px 88px 10px 88px;
|
||||
}
|
||||
|
||||
// Label when no frequent apps
|
||||
.no-frequent-applications-label { @extend %status_text; }
|
||||
|
||||
// shutdown and other actions in the grid
|
||||
.system-action-icon {
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
@ -133,3 +139,44 @@ $app_grid_fg_color: #fff;
|
||||
border-radius: 99px;
|
||||
icon-size: $app_icon_size * 0.5;
|
||||
}
|
||||
|
||||
/* Frequent | All toggle */
|
||||
|
||||
// container
|
||||
.app-view-controls {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
// buttons
|
||||
.app-view-control {
|
||||
padding: 4px 32px;
|
||||
margin: 0 4px;
|
||||
|
||||
&, &:hover, &:checked {
|
||||
@include button(undecorated);
|
||||
color: darken($osd_fg_color, 25%);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $osd_fg_color;
|
||||
box-shadow: inset 0 -2px darken($osd_fg_color, 25%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: inset 0 -2px $osd_fg_color;
|
||||
}
|
||||
|
||||
&:checked {
|
||||
color: $osd_fg_color;
|
||||
box-shadow: inset 0 -2px $selected_bg_color;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-right-width: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
@ -153,11 +153,9 @@
|
||||
}
|
||||
|
||||
.calendar-day-with-events {
|
||||
color: lighten($fg_color,10%);
|
||||
font-weight: bold;
|
||||
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
|
||||
&.calendar-work-day {
|
||||
color: lighten($fg_color,10%);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-other-month-day {
|
||||
@ -204,7 +202,7 @@
|
||||
.world-clocks-time {
|
||||
font-weight: bold;
|
||||
color: $fg_color;
|
||||
font-feature-settings: "tnum";
|
||||
font-feature-settings: "lnum";
|
||||
@include fontsize($base_font_size);
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
/* Looking Glass */
|
||||
|
||||
$text_fg_color: #ccc;
|
||||
|
||||
// Dialog
|
||||
#LookingGlassDialog {
|
||||
background-color: $osd_bg_color;
|
||||
@ -54,11 +52,6 @@ $text_fg_color: #ccc;
|
||||
&:hover { color: lighten($link_color, 10%); }
|
||||
&:active { color: darken($link_color, 10%); }
|
||||
}
|
||||
.actor-link {
|
||||
color: $text_fg_color;
|
||||
&:hover { color: lighten($text_fg_color, 20%); }
|
||||
&:active { color: darken($text_fg_color, 20%); }
|
||||
}
|
||||
}
|
||||
|
||||
.lg-completions-text {
|
||||
|
@ -54,10 +54,6 @@
|
||||
@extend %status_text;
|
||||
}
|
||||
|
||||
.grid-search-results {
|
||||
spacing: $base_spacing * 6;
|
||||
}
|
||||
|
||||
// Search results with icons
|
||||
.grid-search-result {
|
||||
@extend %app-well-app;
|
||||
|
@ -9,8 +9,6 @@ const { ServiceImplementation } = imports.dbusService;
|
||||
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
|
||||
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
|
||||
|
||||
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
|
||||
|
||||
var NotificationDaemon = class extends ServiceImplementation {
|
||||
constructor() {
|
||||
super(NotificationsIface, '/org/freedesktop/Notifications');
|
||||
@ -44,15 +42,7 @@ var NotificationDaemon = class extends ServiceImplementation {
|
||||
null, null);
|
||||
}
|
||||
|
||||
async NotifyAsync(params, invocation) {
|
||||
const pid = await this._getSenderPid(invocation.get_sender());
|
||||
const hints = params[6];
|
||||
|
||||
params[6] = {
|
||||
...hints,
|
||||
'sender-pid': new GLib.Variant('u', pid),
|
||||
};
|
||||
|
||||
NotifyAsync(params, invocation) {
|
||||
this._proxy.NotifyRemote(...params, (res, error) => {
|
||||
if (this._handleError(invocation, error))
|
||||
return;
|
||||
@ -87,19 +77,4 @@ var NotificationDaemon = class extends ServiceImplementation {
|
||||
invocation.return_value(new GLib.Variant('(ssss)', res));
|
||||
});
|
||||
}
|
||||
|
||||
async _getSenderPid(sender) {
|
||||
const res = await Gio.DBus.session.call(
|
||||
'org.freedesktop.DBus',
|
||||
'/',
|
||||
'org.freedesktop.DBus',
|
||||
'GetConnectionUnixProcessID',
|
||||
new GLib.Variant('(s)', [sender]),
|
||||
new GLib.VariantType('(u)'),
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
null);
|
||||
const [pid] = res.deepUnpack();
|
||||
return pid;
|
||||
}
|
||||
};
|
||||
|
@ -184,7 +184,7 @@ var AuthPrompt = GObject.registerClass({
|
||||
});
|
||||
this._defaultButtonWell.add_constraint(new Clutter.BindConstraint({
|
||||
source: this.cancelButton,
|
||||
coordinate: Clutter.BindCoordinate.WIDTH,
|
||||
coordinate: Clutter.BindCoordinate.SIZE,
|
||||
}));
|
||||
this._mainBox.add_child(this._defaultButtonWell);
|
||||
|
||||
@ -424,13 +424,7 @@ var AuthPrompt = GObject.registerClass({
|
||||
}
|
||||
|
||||
updateSensitivity(sensitive) {
|
||||
if (this._entry.reactive === sensitive)
|
||||
return;
|
||||
|
||||
this._entry.reactive = sensitive;
|
||||
|
||||
if (sensitive)
|
||||
this._entry.grab_key_focus();
|
||||
}
|
||||
|
||||
vfunc_hide() {
|
||||
|
@ -589,8 +589,8 @@ var LoginDialog = GObject.registerClass({
|
||||
return actorBox;
|
||||
}
|
||||
|
||||
vfunc_allocate(dialogBox) {
|
||||
this.set_allocation(dialogBox);
|
||||
vfunc_allocate(dialogBox, flags) {
|
||||
this.set_allocation(dialogBox, flags);
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
dialogBox = themeNode.get_content_box(dialogBox);
|
||||
@ -719,19 +719,19 @@ var LoginDialog = GObject.registerClass({
|
||||
|
||||
// Finally hand out the allocations
|
||||
if (bannerAllocation)
|
||||
this._bannerView.allocate(bannerAllocation);
|
||||
this._bannerView.allocate(bannerAllocation, flags);
|
||||
|
||||
if (authPromptAllocation)
|
||||
this._authPrompt.allocate(authPromptAllocation);
|
||||
this._authPrompt.allocate(authPromptAllocation, flags);
|
||||
|
||||
if (userSelectionAllocation)
|
||||
this._userSelectionBox.allocate(userSelectionAllocation);
|
||||
this._userSelectionBox.allocate(userSelectionAllocation, flags);
|
||||
|
||||
if (logoAllocation)
|
||||
this._logoBin.allocate(logoAllocation);
|
||||
this._logoBin.allocate(logoAllocation, flags);
|
||||
|
||||
if (sessionMenuButtonAllocation)
|
||||
this._sessionMenuButton.allocate(sessionMenuButtonAllocation);
|
||||
this._sessionMenuButton.allocate(sessionMenuButtonAllocation, flags);
|
||||
}
|
||||
|
||||
_ensureUserListLoaded() {
|
||||
@ -810,13 +810,12 @@ var LoginDialog = GObject.registerClass({
|
||||
return;
|
||||
|
||||
this._logoBin.destroy_all_children();
|
||||
const [valid, resourceScale] = this._logoBin.get_resource_scale();
|
||||
if (this._logoFile && valid) {
|
||||
if (this._logoFile && this._logoBin.resource_scale > 0) {
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
|
||||
-1, -1,
|
||||
scaleFactor,
|
||||
resourceScale));
|
||||
this._logoBin.resource_scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
|
||||
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
|
||||
|
||||
const { Clutter, Gdm, Gio, GLib } = imports.gi;
|
||||
const { Clutter, Gio, GLib } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Batch = imports.gdm.batch;
|
||||
@ -12,15 +12,6 @@ const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const SmartcardManager = imports.misc.smartcardManager;
|
||||
|
||||
Gio._promisify(Gdm.Client.prototype,
|
||||
'open_reauthentication_channel', 'open_reauthentication_channel_finish');
|
||||
Gio._promisify(Gdm.Client.prototype,
|
||||
'get_user_verifier', 'get_user_verifier_finish');
|
||||
Gio._promisify(Gdm.UserVerifierProxy.prototype,
|
||||
'call_begin_verification_for_user', 'call_begin_verification_for_user_finish');
|
||||
Gio._promisify(Gdm.UserVerifierProxy.prototype,
|
||||
'call_begin_verification', 'call_begin_verification_finish');
|
||||
|
||||
var PASSWORD_SERVICE_NAME = 'gdm-password';
|
||||
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
|
||||
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
|
||||
@ -177,12 +168,14 @@ var ShellUserVerifier = class {
|
||||
|
||||
this._checkForFingerprintReader();
|
||||
|
||||
// If possible, reauthenticate an already running session,
|
||||
// so any session specific credentials get updated appropriately
|
||||
if (userName)
|
||||
this._openReauthenticationChannel(userName);
|
||||
else
|
||||
this._getUserVerifier();
|
||||
if (userName) {
|
||||
// If possible, reauthenticate an already running session,
|
||||
// so any session specific credentials get updated appropriately
|
||||
this._client.open_reauthentication_channel(userName, this._cancellable,
|
||||
this._reauthenticationChannelOpened.bind(this));
|
||||
} else {
|
||||
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
@ -346,11 +339,10 @@ var ShellUserVerifier = class {
|
||||
this._verificationFailed(false);
|
||||
}
|
||||
|
||||
async _openReauthenticationChannel(userName) {
|
||||
_reauthenticationChannelOpened(client, result) {
|
||||
try {
|
||||
this._clearUserVerifier();
|
||||
this._userVerifier = await this._client.open_reauthentication_channel(
|
||||
userName, this._cancellable);
|
||||
this._userVerifier = client.open_reauthentication_channel_finish(result);
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
@ -359,7 +351,8 @@ var ShellUserVerifier = class {
|
||||
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
|
||||
// is no session to reauthenticate. Fall back to performing
|
||||
// verification from this login session
|
||||
this._getUserVerifier();
|
||||
client.get_user_verifier(this._cancellable,
|
||||
this._userVerifierGot.bind(this));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -373,11 +366,10 @@ var ShellUserVerifier = class {
|
||||
this._hold.release();
|
||||
}
|
||||
|
||||
async _getUserVerifier() {
|
||||
_userVerifierGot(client, result) {
|
||||
try {
|
||||
this._clearUserVerifier();
|
||||
this._userVerifier =
|
||||
await this._client.get_user_verifier(this._cancellable);
|
||||
this._userVerifier = client.get_user_verifier_finish(result);
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
@ -429,25 +421,35 @@ var ShellUserVerifier = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _startService(serviceName) {
|
||||
_startService(serviceName) {
|
||||
this._hold.acquire();
|
||||
try {
|
||||
if (this._userName) {
|
||||
await this._userVerifier.call_begin_verification_for_user(
|
||||
serviceName, this._userName, this._cancellable);
|
||||
} else {
|
||||
await this._userVerifier.call_begin_verification(
|
||||
serviceName, this._cancellable);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
this._reportInitError(this._userName
|
||||
? 'Failed to start verification for user'
|
||||
: 'Failed to start verification', e);
|
||||
return;
|
||||
if (this._userName) {
|
||||
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
|
||||
try {
|
||||
obj.call_begin_verification_for_user_finish(result);
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
this._reportInitError('Failed to start verification for user', e);
|
||||
return;
|
||||
}
|
||||
|
||||
this._hold.release();
|
||||
});
|
||||
} else {
|
||||
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
|
||||
try {
|
||||
obj.call_begin_verification_finish(result);
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
this._reportInitError('Failed to start verification', e);
|
||||
return;
|
||||
}
|
||||
|
||||
this._hold.release();
|
||||
});
|
||||
}
|
||||
this._hold.release();
|
||||
}
|
||||
|
||||
_beginVerification() {
|
||||
|
@ -23,7 +23,6 @@
|
||||
<file>misc/modemManager.js</file>
|
||||
<file>misc/objectManager.js</file>
|
||||
<file>misc/params.js</file>
|
||||
<file>misc/parentalControlsManager.js</file>
|
||||
<file>misc/permissionStore.js</file>
|
||||
<file>misc/smartcardManager.js</file>
|
||||
<file>misc/systemActions.js</file>
|
||||
@ -102,6 +101,7 @@
|
||||
<file>ui/swipeTracker.js</file>
|
||||
<file>ui/switcherPopup.js</file>
|
||||
<file>ui/switchMonitor.js</file>
|
||||
<file>ui/tweener.js</file>
|
||||
<file>ui/unlockDialog.js</file>
|
||||
<file>ui/userWidget.js</file>
|
||||
<file>ui/viewSelector.js</file>
|
||||
|
@ -6,15 +6,6 @@ const Signals = imports.signals;
|
||||
|
||||
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
||||
|
||||
Gio._promisify(IBus.Bus.prototype,
|
||||
'list_engines_async', 'list_engines_async_finish');
|
||||
Gio._promisify(IBus.Bus.prototype,
|
||||
'request_name_async', 'request_name_async_finish');
|
||||
Gio._promisify(IBus.Bus.prototype,
|
||||
'get_global_engine_async', 'get_global_engine_async_finish');
|
||||
Gio._promisify(IBus.Bus.prototype,
|
||||
'set_global_engine_async', 'set_global_engine_async_finish');
|
||||
|
||||
// Ensure runtime version matches
|
||||
_checkIBusVersion(1, 5, 2);
|
||||
|
||||
@ -111,14 +102,16 @@ var IBusManager = class {
|
||||
|
||||
_onConnected() {
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
this._initEngines();
|
||||
this._initPanelService();
|
||||
this._ibus.list_engines_async(-1, this._cancellable,
|
||||
this._initEngines.bind(this));
|
||||
this._ibus.request_name_async(IBus.SERVICE_PANEL,
|
||||
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
|
||||
this._initPanelService.bind(this));
|
||||
}
|
||||
|
||||
async _initEngines() {
|
||||
_initEngines(ibus, result) {
|
||||
try {
|
||||
const enginesList =
|
||||
await this._ibus.list_engines_async(-1, this._cancellable);
|
||||
let enginesList = this._ibus.list_engines_async_finish(result);
|
||||
for (let i = 0; i < enginesList.length; ++i) {
|
||||
let name = enginesList[i].get_name();
|
||||
this._engines.set(name, enginesList[i]);
|
||||
@ -133,10 +126,9 @@ var IBusManager = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _initPanelService() {
|
||||
_initPanelService(ibus, result) {
|
||||
try {
|
||||
await this._ibus.request_name_async(IBus.SERVICE_PANEL,
|
||||
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable);
|
||||
this._ibus.request_name_async_finish(result);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||
logError(e);
|
||||
@ -171,15 +163,19 @@ var IBusManager = class {
|
||||
this._panelService.connect('set-content-type', this._setContentType.bind(this));
|
||||
} catch (e) {
|
||||
}
|
||||
this._updateReadiness();
|
||||
|
||||
try {
|
||||
// If an engine is already active we need to get its properties
|
||||
const engine =
|
||||
await this._ibus.get_global_engine_async(-1, this._cancellable);
|
||||
// If an engine is already active we need to get its properties
|
||||
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
|
||||
let engine;
|
||||
try {
|
||||
engine = this._ibus.get_global_engine_async_finish(res);
|
||||
if (!engine)
|
||||
return;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
this._engineChanged(this._ibus, engine.get_name());
|
||||
} catch (e) {
|
||||
}
|
||||
});
|
||||
this._updateReadiness();
|
||||
}
|
||||
|
||||
_updateReadiness() {
|
||||
@ -227,7 +223,7 @@ var IBusManager = class {
|
||||
return this._engines.get(id);
|
||||
}
|
||||
|
||||
async setEngine(id, callback) {
|
||||
setEngine(id, callback) {
|
||||
// Send id even if id == this._currentEngineName
|
||||
// because 'properties-registered' signal can be emitted
|
||||
// while this._ibusSources == null on a lock screen.
|
||||
@ -237,16 +233,18 @@ var IBusManager = class {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this._ibus.set_global_engine_async(id,
|
||||
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
|
||||
this._cancellable);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
logError(e);
|
||||
}
|
||||
if (callback)
|
||||
callback();
|
||||
this._ibus.set_global_engine_async(id,
|
||||
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
|
||||
this._cancellable, (_bus, res) => {
|
||||
try {
|
||||
this._ibus.set_global_engine_async_finish(res);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
logError(e);
|
||||
}
|
||||
if (callback)
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
preloadEngines(ids) {
|
||||
|
@ -4,9 +4,6 @@ const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
|
||||
|
||||
const Keyboard = imports.ui.status.keyboard;
|
||||
|
||||
Gio._promisify(IBus.Bus.prototype,
|
||||
'create_input_context_async', 'create_input_context_async_finish');
|
||||
|
||||
var HIDE_PANEL_TIME = 50;
|
||||
|
||||
var InputMethod = GObject.registerClass(
|
||||
@ -49,11 +46,15 @@ class InputMethod extends Clutter.InputMethod {
|
||||
this._currentSource = this._inputSourceManager.currentSource;
|
||||
}
|
||||
|
||||
async _onConnected() {
|
||||
_onConnected() {
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
this._ibus.create_input_context_async('gnome-shell', -1,
|
||||
this._cancellable, this._setContext.bind(this));
|
||||
}
|
||||
|
||||
_setContext(bus, res) {
|
||||
try {
|
||||
this._context = await this._ibus.create_input_context_async(
|
||||
'gnome-shell', -1, this._cancellable);
|
||||
this._context = this._ibus.create_input_context_async_finish(res);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||
logError(e);
|
||||
|
@ -24,7 +24,8 @@ function getCompletions(text, commandHeader, globalCompletionList) {
|
||||
[expr_, base, attrHead] = matches;
|
||||
|
||||
methods = getPropertyNamesFromExpression(base, commandHeader).filter(
|
||||
attr => attr.slice(0, attrHead.length) === attrHead);
|
||||
attr => attr.slice(0, attrHead.length) == attrHead
|
||||
);
|
||||
}
|
||||
|
||||
// Look for the empty expression or partially entered words
|
||||
@ -33,7 +34,8 @@ function getCompletions(text, commandHeader, globalCompletionList) {
|
||||
if (text == '' || matches) {
|
||||
[expr_, attrHead] = matches;
|
||||
methods = globalCompletionList.filter(
|
||||
attr => attr.slice(0, attrHead.length) === attrHead);
|
||||
attr => attr.slice(0, attrHead.length) == attrHead
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
|
||||
|
||||
const { GLib, GnomeDesktop } = imports.gi;
|
||||
const { GLib, GnomeDesktop, Meta } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
@ -62,11 +62,11 @@ var KeyboardManager = class {
|
||||
return;
|
||||
|
||||
this._currentKeymap = { layouts, variants, options };
|
||||
global.backend.set_keymap(layouts, variants, options);
|
||||
Meta.get_backend().set_keymap(layouts, variants, options);
|
||||
}
|
||||
|
||||
_applyLayoutGroupIndex(idx) {
|
||||
global.backend.lock_layout_group(idx);
|
||||
Meta.get_backend().lock_layout_group(idx);
|
||||
}
|
||||
|
||||
apply(id) {
|
||||
|
@ -50,22 +50,25 @@ function canLock() {
|
||||
}
|
||||
|
||||
|
||||
async function registerSessionWithGDM() {
|
||||
function registerSessionWithGDM() {
|
||||
log("Registering session with GDM");
|
||||
try {
|
||||
await Gio.DBus.system.call(
|
||||
'org.gnome.DisplayManager',
|
||||
'/org/gnome/DisplayManager/Manager',
|
||||
'org.gnome.DisplayManager.Manager',
|
||||
'RegisterSession',
|
||||
GLib.Variant.new('(a{sv})', [{}]), null,
|
||||
Gio.DBusCallFlags.NONE, -1, null);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
|
||||
log(`Error registering session with GDM: ${e.message}`);
|
||||
else
|
||||
log('Not calling RegisterSession(): method not exported, GDM too old?');
|
||||
}
|
||||
Gio.DBus.system.call('org.gnome.DisplayManager',
|
||||
'/org/gnome/DisplayManager/Manager',
|
||||
'org.gnome.DisplayManager.Manager',
|
||||
'RegisterSession',
|
||||
GLib.Variant.new('(a{sv})', [{}]), null,
|
||||
Gio.DBusCallFlags.NONE, -1, null,
|
||||
(source, result) => {
|
||||
try {
|
||||
source.call_finish(result);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
|
||||
log(`Error registering session with GDM: ${e.message}`);
|
||||
else
|
||||
log("Not calling RegisterSession(): method not exported, GDM too old?");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let _loginManager = null;
|
||||
@ -171,19 +174,24 @@ var LoginManagerSystemd = class {
|
||||
this._proxy.SuspendRemote(true);
|
||||
}
|
||||
|
||||
async inhibit(reason, callback) {
|
||||
try {
|
||||
const inVariant = new GLib.Variant('(ssss)',
|
||||
['sleep', 'GNOME Shell', reason, 'delay']);
|
||||
const [outVariant_, fdList] =
|
||||
await this._proxy.call_with_unix_fd_list('Inhibit',
|
||||
inVariant, 0, -1, null, null);
|
||||
const [fd] = fdList.steal_fds();
|
||||
callback(new Gio.UnixInputStream({ fd }));
|
||||
} catch (e) {
|
||||
logError(e, 'Error getting systemd inhibitor');
|
||||
callback(null);
|
||||
}
|
||||
inhibit(reason, callback) {
|
||||
let inVariant = GLib.Variant.new('(ssss)',
|
||||
['sleep',
|
||||
'GNOME Shell',
|
||||
reason,
|
||||
'delay']);
|
||||
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
|
||||
(proxy, result) => {
|
||||
let fd = -1;
|
||||
try {
|
||||
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
|
||||
fd = fdList.steal_fds()[0];
|
||||
callback(new Gio.UnixInputStream({ fd }));
|
||||
} catch (e) {
|
||||
logError(e, "Error getting systemd inhibitor");
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_prepareForSleep(proxy, sender, [aboutToSuspend]) {
|
||||
|
@ -57,7 +57,9 @@ var ObjectManager = class {
|
||||
// Start out inhibiting load until at least the proxy
|
||||
// manager is loaded and the remote objects are fetched
|
||||
this._numLoadInhibitors = 1;
|
||||
this._initManagerProxy();
|
||||
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
|
||||
this._cancellable,
|
||||
this._onManagerProxyLoaded.bind(this));
|
||||
}
|
||||
|
||||
_tryToCompleteLoad() {
|
||||
@ -71,7 +73,7 @@ var ObjectManager = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _addInterface(objectPath, interfaceName, onFinished) {
|
||||
_addInterface(objectPath, interfaceName, onFinished) {
|
||||
let info = this._interfaceInfos[interfaceName];
|
||||
|
||||
if (!info) {
|
||||
@ -87,38 +89,40 @@ var ObjectManager = class {
|
||||
g_interface_info: info,
|
||||
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
|
||||
|
||||
try {
|
||||
await proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||
} catch (e) {
|
||||
logError(e, `could not initialize proxy for interface ${interfaceName}`);
|
||||
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
|
||||
try {
|
||||
initable.init_finish(result);
|
||||
} catch (e) {
|
||||
logError(e, `could not initialize proxy for interface ${interfaceName}`);
|
||||
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
let isNewObject;
|
||||
if (!this._objects[objectPath]) {
|
||||
this._objects[objectPath] = {};
|
||||
isNewObject = true;
|
||||
} else {
|
||||
isNewObject = false;
|
||||
}
|
||||
|
||||
this._objects[objectPath][interfaceName] = proxy;
|
||||
|
||||
if (!this._interfaces[interfaceName])
|
||||
this._interfaces[interfaceName] = [];
|
||||
|
||||
this._interfaces[interfaceName].push(proxy);
|
||||
|
||||
if (isNewObject)
|
||||
this.emit('object-added', objectPath);
|
||||
|
||||
this.emit('interface-added', interfaceName, proxy);
|
||||
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
let isNewObject;
|
||||
if (!this._objects[objectPath]) {
|
||||
this._objects[objectPath] = {};
|
||||
isNewObject = true;
|
||||
} else {
|
||||
isNewObject = false;
|
||||
}
|
||||
|
||||
this._objects[objectPath][interfaceName] = proxy;
|
||||
|
||||
if (!this._interfaces[interfaceName])
|
||||
this._interfaces[interfaceName] = [];
|
||||
|
||||
this._interfaces[interfaceName].push(proxy);
|
||||
|
||||
if (isNewObject)
|
||||
this.emit('object-added', objectPath);
|
||||
|
||||
this.emit('interface-added', interfaceName, proxy);
|
||||
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
});
|
||||
}
|
||||
|
||||
_removeInterface(objectPath, interfaceName) {
|
||||
@ -147,10 +151,9 @@ var ObjectManager = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _initManagerProxy() {
|
||||
_onManagerProxyLoaded(initable, result) {
|
||||
try {
|
||||
await this._managerProxy.init_async(
|
||||
GLib.PRIORITY_DEFAULT, this._cancellable);
|
||||
initable.init_finish(result);
|
||||
} catch (e) {
|
||||
logError(e, `could not initialize object manager for object ${this._serviceName}`);
|
||||
|
||||
|
@ -1,146 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
//
|
||||
// Copyright (C) 2018, 2019, 2020 Endless Mobile, Inc.
|
||||
//
|
||||
// This is a GNOME Shell component to wrap the interactions over
|
||||
// D-Bus with the malcontent library.
|
||||
//
|
||||
// Licensed under the GNU General Public License Version 2
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
/* exported getDefault */
|
||||
|
||||
const { Gio, GObject, Shell } = imports.gi;
|
||||
|
||||
// We require libmalcontent ≥ 0.6.0
|
||||
const HAVE_MALCONTENT = imports.package.checkSymbol(
|
||||
'Malcontent', '0', 'ManagerGetValueFlags');
|
||||
|
||||
var Malcontent = null;
|
||||
if (HAVE_MALCONTENT) {
|
||||
Malcontent = imports.gi.Malcontent;
|
||||
Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async', 'get_app_filter_finish');
|
||||
}
|
||||
|
||||
let _singleton = null;
|
||||
|
||||
function getDefault() {
|
||||
if (_singleton === null)
|
||||
_singleton = new ParentalControlsManager();
|
||||
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
// A manager class which provides cached access to the constructing user’s
|
||||
// parental controls settings. It’s possible for the user’s parental controls
|
||||
// to change at runtime if the Parental Controls application is used by an
|
||||
// administrator from within the user’s session.
|
||||
var ParentalControlsManager = GObject.registerClass({
|
||||
Signals: {
|
||||
'app-filter-changed': {},
|
||||
},
|
||||
}, class ParentalControlsManager extends GObject.Object {
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
this._initialized = false;
|
||||
this._disabled = false;
|
||||
this._appFilter = null;
|
||||
|
||||
this._initializeManager();
|
||||
}
|
||||
|
||||
async _initializeManager() {
|
||||
if (!HAVE_MALCONTENT) {
|
||||
log('Skipping parental controls support as it’s disabled');
|
||||
this._initialized = true;
|
||||
this.emit('app-filter-changed');
|
||||
return;
|
||||
}
|
||||
|
||||
log(`Getting parental controls for user ${Shell.util_get_uid()}`);
|
||||
try {
|
||||
const connection = await Gio.DBus.get(Gio.BusType.SYSTEM, null);
|
||||
this._manager = new Malcontent.Manager({ connection });
|
||||
this._appFilter = await this._manager.get_app_filter_async(
|
||||
Shell.util_get_uid(),
|
||||
Malcontent.ManagerGetValueFlags.NONE,
|
||||
null);
|
||||
} catch (e) {
|
||||
if (e.matches(Malcontent.ManagerError, Malcontent.ManagerError.DISABLED)) {
|
||||
log('Parental controls globally disabled');
|
||||
this._disabled = true;
|
||||
} else {
|
||||
logError(e, 'Failed to get parental controls settings');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._manager.connect('app-filter-changed', this._onAppFilterChanged.bind(this));
|
||||
|
||||
// Signal initialisation is complete.
|
||||
this._initialized = true;
|
||||
this.emit('app-filter-changed');
|
||||
}
|
||||
|
||||
async _onAppFilterChanged(manager, uid) {
|
||||
// Emit 'changed' signal only if app-filter is changed for currently logged-in user.
|
||||
let currentUid = Shell.util_get_uid();
|
||||
if (currentUid !== uid)
|
||||
return;
|
||||
|
||||
try {
|
||||
this._appFilter = await this._manager.get_app_filter_async(
|
||||
currentUid,
|
||||
Malcontent.ManagerGetValueFlags.NONE,
|
||||
null);
|
||||
this.emit('app-filter-changed');
|
||||
} catch (e) {
|
||||
// Log an error and keep the old app filter.
|
||||
logError(e, `Failed to get new MctAppFilter for uid ${Shell.util_get_uid()} on app-filter-changed`);
|
||||
}
|
||||
}
|
||||
|
||||
get initialized() {
|
||||
return this._initialized;
|
||||
}
|
||||
|
||||
// Calculate whether the given app (a Gio.DesktopAppInfo) should be shown
|
||||
// on the desktop, in search results, etc. The app should be shown if:
|
||||
// - The .desktop file doesn’t say it should be hidden.
|
||||
// - The executable from the .desktop file’s Exec line isn’t blacklisted in
|
||||
// the user’s parental controls.
|
||||
// - None of the flatpak app IDs from the X-Flatpak and the
|
||||
// X-Flatpak-RenamedFrom lines are blacklisted in the user’s parental
|
||||
// controls.
|
||||
shouldShowApp(appInfo) {
|
||||
// Quick decision?
|
||||
if (!appInfo.should_show())
|
||||
return false;
|
||||
|
||||
// Are parental controls enabled (at configure time or runtime)?
|
||||
if (!HAVE_MALCONTENT || this._disabled)
|
||||
return true;
|
||||
|
||||
// Have we finished initialising yet?
|
||||
if (!this.initialized) {
|
||||
log(`Warning: Hiding app because parental controls not yet initialised: ${appInfo.get_id()}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._appFilter.is_appinfo_allowed(appInfo);
|
||||
}
|
||||
});
|
@ -83,17 +83,13 @@ const SystemActions = GObject.registerClass({
|
||||
this._canHavePowerOff = true;
|
||||
this._canHaveSuspend = true;
|
||||
|
||||
function tokenizeKeywords(keywords) {
|
||||
return keywords.split(';').map(keyword => GLib.str_tokenize_and_fold(keyword, null)).flat(2);
|
||||
}
|
||||
|
||||
this._actions = new Map();
|
||||
this._actions.set(POWER_OFF_ACTION_ID, {
|
||||
// Translators: The name of the power-off action in search
|
||||
name: C_("search-result", "Power Off"),
|
||||
iconName: 'system-shutdown-symbolic',
|
||||
// Translators: A list of keywords that match the power-off action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('power off;shutdown;reboot;restart;halt;stop')),
|
||||
keywords: _('power off;shutdown;reboot;restart;halt;stop').split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
this._actions.set(LOCK_SCREEN_ACTION_ID, {
|
||||
@ -101,15 +97,15 @@ const SystemActions = GObject.registerClass({
|
||||
name: C_("search-result", "Lock Screen"),
|
||||
iconName: 'system-lock-screen-symbolic',
|
||||
// Translators: A list of keywords that match the lock screen action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('lock screen')),
|
||||
keywords: _("lock screen").split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
this._actions.set(LOGOUT_ACTION_ID, {
|
||||
// Translators: The name of the logout action in search
|
||||
name: C_("search-result", "Log Out"),
|
||||
iconName: 'system-log-out-symbolic',
|
||||
iconName: 'application-exit-symbolic',
|
||||
// Translators: A list of keywords that match the logout action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('logout;log out;sign off')),
|
||||
keywords: _("logout;log out;sign off").split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
this._actions.set(SUSPEND_ACTION_ID, {
|
||||
@ -117,7 +113,7 @@ const SystemActions = GObject.registerClass({
|
||||
name: C_("search-result", "Suspend"),
|
||||
iconName: 'media-playback-pause-symbolic',
|
||||
// Translators: A list of keywords that match the suspend action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('suspend;sleep')),
|
||||
keywords: _("suspend;sleep").split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
this._actions.set(SWITCH_USER_ACTION_ID, {
|
||||
@ -125,14 +121,14 @@ const SystemActions = GObject.registerClass({
|
||||
name: C_("search-result", "Switch User"),
|
||||
iconName: 'system-switch-user-symbolic',
|
||||
// Translators: A list of keywords that match the switch user action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('switch user')),
|
||||
keywords: _("switch user").split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
|
||||
name: '',
|
||||
iconName: '',
|
||||
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
|
||||
keywords: tokenizeKeywords(_('lock orientation;unlock orientation;screen;rotation')),
|
||||
keywords: _("lock orientation;unlock orientation;screen;rotation").split(/[; ]/),
|
||||
available: false,
|
||||
});
|
||||
|
||||
@ -281,7 +277,7 @@ const SystemActions = GObject.registerClass({
|
||||
|
||||
getMatchingActions(terms) {
|
||||
// terms is a list of strings
|
||||
terms = terms.map(term => GLib.str_tokenize_and_fold(term, null)[0]);
|
||||
terms = terms.map(term => term.toLowerCase());
|
||||
|
||||
let results = [];
|
||||
|
||||
|
@ -7,8 +7,6 @@ const PermissionStore = imports.misc.permissionStore;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
Gio._promisify(Geoclue.Simple, 'new', 'new_finish');
|
||||
|
||||
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
|
||||
|
||||
const WEATHER_BUS_NAME = 'org.gnome.Weather';
|
||||
@ -81,7 +79,16 @@ var WeatherClient = class {
|
||||
this._weatherApp = null;
|
||||
this._weatherProxy = null;
|
||||
|
||||
this._createWeatherProxy();
|
||||
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
|
||||
Gio.DBusProxy.new(
|
||||
Gio.DBus.session,
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
|
||||
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
|
||||
WEATHER_BUS_NAME,
|
||||
WEATHER_OBJECT_PATH,
|
||||
WEATHER_INTEGRATION_IFACE,
|
||||
null,
|
||||
this._onWeatherProxyReady.bind(this));
|
||||
|
||||
this._settings = new Gio.Settings({
|
||||
schema_id: 'org.gnome.shell.weather',
|
||||
@ -139,17 +146,9 @@ var WeatherClient = class {
|
||||
(!this._needsAuth || this._weatherAuthorized);
|
||||
}
|
||||
|
||||
async _createWeatherProxy() {
|
||||
const nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
|
||||
_onWeatherProxyReady(o, res) {
|
||||
try {
|
||||
this._weatherProxy = await Gio.DBusProxy.new(
|
||||
Gio.DBus.session,
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
|
||||
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
|
||||
WEATHER_BUS_NAME,
|
||||
WEATHER_OBJECT_PATH,
|
||||
WEATHER_INTEGRATION_IFACE,
|
||||
null);
|
||||
this._weatherProxy = Gio.DBusProxy.new_finish(res);
|
||||
} catch (e) {
|
||||
log(`Failed to create GNOME Weather proxy: ${e}`);
|
||||
return;
|
||||
@ -240,23 +239,25 @@ var WeatherClient = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _startGClueService() {
|
||||
_startGClueService() {
|
||||
if (this._gclueStarting)
|
||||
return;
|
||||
|
||||
this._gclueStarting = true;
|
||||
|
||||
try {
|
||||
this._gclueService = await Geoclue.Simple.new(
|
||||
'org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null);
|
||||
} catch (e) {
|
||||
log(`Failed to connect to Geoclue2 service: ${e.message}`);
|
||||
this._setLocation(this._mostRecentLocation);
|
||||
return;
|
||||
}
|
||||
this._gclueStarted = true;
|
||||
this._gclueService.get_client().distance_threshold = 100;
|
||||
this._updateLocationMonitoring();
|
||||
Geoclue.Simple.new('org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null,
|
||||
(o, res) => {
|
||||
try {
|
||||
this._gclueService = Geoclue.Simple.new_finish(res);
|
||||
} catch (e) {
|
||||
log(`Failed to connect to Geoclue2 service: ${e.message}`);
|
||||
this._setLocation(this._mostRecentLocation);
|
||||
return;
|
||||
}
|
||||
this._gclueStarted = true;
|
||||
this._gclueService.get_client().distance_threshold = 100;
|
||||
this._updateLocationMonitoring();
|
||||
});
|
||||
}
|
||||
|
||||
_onGClueLocationChanged() {
|
||||
|
@ -68,8 +68,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
|
||||
this._items = this._switcherList.icons;
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
super.vfunc_allocate(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
// Allocate the thumbnails
|
||||
// We try to avoid overflowing the screen so we base the resulting size on
|
||||
@ -102,7 +102,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
|
||||
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
|
||||
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
|
||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||
this._thumbnails.allocate(childBox);
|
||||
this._thumbnails.allocate(childBox, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -681,7 +681,8 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
|
||||
// Cache the window list now; we don't handle dynamic changes here,
|
||||
// and we don't want to be continually retrieving it
|
||||
appIcon.cachedWindows = allWindows.filter(
|
||||
w => windowTracker.get_window_app(w) === appIcon.app);
|
||||
w => windowTracker.get_window_app(w) == appIcon.app
|
||||
);
|
||||
if (appIcon.cachedWindows.length > 0)
|
||||
this._addIcon(appIcon);
|
||||
}
|
||||
@ -749,9 +750,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
|
||||
return super.vfunc_get_preferred_height(forWidth);
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
// Allocate the main list items
|
||||
super.vfunc_allocate(box);
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
|
||||
@ -766,7 +767,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
|
||||
childBox.x2 = childBox.x1 + arrowWidth;
|
||||
childBox.y1 = contentBox.y1 + itemBox.y2 + arrowHeight;
|
||||
childBox.y2 = childBox.y1 + arrowHeight;
|
||||
this._arrows[i].allocate(childBox);
|
||||
this._arrows[i].allocate(childBox, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1056,28 +1057,28 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
|
||||
return [minHeight, natHeight];
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
let themeNode = this.get_theme_node();
|
||||
let contentBox = themeNode.get_content_box(box);
|
||||
const labelHeight = this._label.height;
|
||||
const totalLabelHeight =
|
||||
labelHeight + themeNode.get_padding(St.Side.BOTTOM);
|
||||
|
||||
box.y2 -= totalLabelHeight;
|
||||
super.vfunc_allocate(box);
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = contentBox.x1;
|
||||
childBox.x2 = contentBox.x2;
|
||||
childBox.y2 = contentBox.y2;
|
||||
childBox.y1 = childBox.y2 - this._label.height;
|
||||
this._label.allocate(childBox, flags);
|
||||
|
||||
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
|
||||
childBox.x1 = box.x1;
|
||||
childBox.x2 = box.x2;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y2 - totalLabelHeight;
|
||||
super.vfunc_allocate(childBox, flags);
|
||||
|
||||
// Hooking up the parent vfunc will call this.set_allocation() with
|
||||
// the height without the label height, so call it again with the
|
||||
// correct size here.
|
||||
box.y2 += totalLabelHeight;
|
||||
this.set_allocation(box);
|
||||
|
||||
const childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = contentBox.x1;
|
||||
childBox.x2 = contentBox.x2;
|
||||
childBox.y2 = contentBox.y2;
|
||||
childBox.y1 = childBox.y2 - labelHeight;
|
||||
this._label.allocate(childBox);
|
||||
this.set_allocation(box, flags);
|
||||
}
|
||||
|
||||
highlight(index, justOutline) {
|
||||
|
@ -10,7 +10,6 @@ const GrabHelper = imports.ui.grabHelper;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const PageIndicators = imports.ui.pageIndicators;
|
||||
const ParentalControlsManager = imports.misc.parentalControlsManager;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Search = imports.ui.search;
|
||||
const SwipeTracker = imports.ui.swipeTracker;
|
||||
@ -18,6 +17,8 @@ const Params = imports.misc.params;
|
||||
const Util = imports.misc.util;
|
||||
const SystemActions = imports.misc.systemActions;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
var MENU_POPUP_TIMEOUT = 600;
|
||||
var MAX_COLUMNS = 6;
|
||||
var MIN_COLUMNS = 4;
|
||||
@ -29,11 +30,12 @@ var INACTIVE_GRID_OPACITY = 77;
|
||||
var INACTIVE_GRID_OPACITY_ANIMATION_TIME = 240;
|
||||
var FOLDER_SUBICON_FRACTION = .4;
|
||||
|
||||
var MIN_FREQUENT_APPS_COUNT = 3;
|
||||
|
||||
var VIEWS_SWITCH_TIME = 400;
|
||||
var VIEWS_SWITCH_ANIMATION_DELAY = 100;
|
||||
|
||||
var PAGE_SWITCH_TIME = 250;
|
||||
var SCROLL_TIMEOUT_TIME = 150;
|
||||
|
||||
var APP_ICON_SCALE_IN_TIME = 500;
|
||||
var APP_ICON_SCALE_IN_DELAY = 700;
|
||||
@ -43,6 +45,11 @@ const FOLDER_DIALOG_ANIMATION_TIME = 200;
|
||||
const OVERSHOOT_THRESHOLD = 20;
|
||||
const OVERSHOOT_TIMEOUT = 1000;
|
||||
|
||||
const SWITCHEROO_BUS_NAME = 'net.hadess.SwitcherooControl';
|
||||
const SWITCHEROO_OBJECT_PATH = '/net/hadess/SwitcherooControl';
|
||||
|
||||
const SwitcherooProxyInterface = loadInterfaceXML('net.hadess.SwitcherooControl');
|
||||
const SwitcherooProxy = Gio.DBusProxy.makeProxyWrapper(SwitcherooProxyInterface);
|
||||
let discreteGpuAvailable = false;
|
||||
|
||||
function _getCategories(info) {
|
||||
@ -107,8 +114,7 @@ function _findBestFolderName(apps) {
|
||||
}, commonCategories);
|
||||
|
||||
for (let category of commonCategories) {
|
||||
const directory = '%s.directory'.format(category);
|
||||
const translated = Shell.util_get_translated_folder_name(directory);
|
||||
let translated = Shell.util_get_translated_folder_name(category);
|
||||
if (translated !== null)
|
||||
return translated;
|
||||
}
|
||||
@ -138,7 +144,11 @@ var BaseAppView = GObject.registerClass({
|
||||
padWithSpacing: true,
|
||||
}, true);
|
||||
|
||||
this._grid = new IconGrid.IconGrid(gridParams);
|
||||
if (this.use_pagination)
|
||||
this._grid = new IconGrid.PaginatedIconGrid(gridParams);
|
||||
else
|
||||
this._grid = new IconGrid.IconGrid(gridParams);
|
||||
|
||||
this._grid.connect('child-focused', (grid, actor) => {
|
||||
this._childFocused(actor);
|
||||
});
|
||||
@ -151,12 +161,6 @@ var BaseAppView = GObject.registerClass({
|
||||
this._animateLaterId = 0;
|
||||
this._viewLoadedHandlerId = 0;
|
||||
this._viewIsReady = false;
|
||||
|
||||
// Filter the apps through the user’s parental controls.
|
||||
this._parentalControlsManager = ParentalControlsManager.getDefault();
|
||||
this._parentalControlsManager.connect('app-filter-changed', () => {
|
||||
this._redisplay();
|
||||
});
|
||||
}
|
||||
|
||||
_childFocused(_actor) {
|
||||
@ -320,46 +324,24 @@ var BaseAppView = GObject.registerClass({
|
||||
}
|
||||
});
|
||||
|
||||
var AppDisplay = GObject.registerClass(
|
||||
class AppDisplay extends BaseAppView {
|
||||
var AllView = GObject.registerClass({
|
||||
}, class AllView extends BaseAppView {
|
||||
_init() {
|
||||
super._init({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
use_pagination: true,
|
||||
});
|
||||
|
||||
this._grid._delegate = this;
|
||||
|
||||
this._stack = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
});
|
||||
this.add_actor(this._stack);
|
||||
|
||||
let box = new St.BoxLayout({
|
||||
vertical: true,
|
||||
y_align: Clutter.ActorAlign.START,
|
||||
});
|
||||
box.add_child(this._grid);
|
||||
|
||||
this._scrollView = new St.ScrollView({
|
||||
style_class: 'all-apps',
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
reactive: true,
|
||||
});
|
||||
this._scrollView.add_actor(box);
|
||||
this._stack.add_actor(this._scrollView);
|
||||
|
||||
this._eventBlocker = new St.Widget({
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
reactive: true,
|
||||
visible: false,
|
||||
});
|
||||
this._stack.add_actor(this._eventBlocker);
|
||||
this.add_actor(this._scrollView);
|
||||
this._grid._delegate = this;
|
||||
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.EXTERNAL);
|
||||
@ -380,7 +362,24 @@ class AppDisplay extends BaseAppView {
|
||||
|
||||
this._folderIcons = [];
|
||||
|
||||
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
let box = new St.BoxLayout({
|
||||
vertical: true,
|
||||
y_align: Clutter.ActorAlign.START,
|
||||
});
|
||||
|
||||
this._grid.currentPage = 0;
|
||||
this._stack.add_actor(this._grid);
|
||||
this._eventBlocker = new St.Widget({
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
reactive: true,
|
||||
visible: false,
|
||||
});
|
||||
this._stack.add_actor(this._eventBlocker);
|
||||
|
||||
box.add_actor(this._stack);
|
||||
this._scrollView.add_actor(box);
|
||||
|
||||
this._scrollView.connect('scroll-event', this._onScroll.bind(this));
|
||||
|
||||
@ -433,29 +432,6 @@ class AppDisplay extends BaseAppView {
|
||||
Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._switcherooNotifyId = global.connect('notify::switcheroo-control',
|
||||
() => this._updateDiscreteGpuAvailable());
|
||||
this._updateDiscreteGpuAvailable();
|
||||
}
|
||||
|
||||
_updateDiscreteGpuAvailable() {
|
||||
this._switcherooProxy = global.get_switcheroo_control();
|
||||
if (this._switcherooProxy) {
|
||||
let prop = this._switcherooProxy.get_cached_property('HasDualGpu');
|
||||
discreteGpuAvailable = prop ? prop.unpack() : false;
|
||||
} else {
|
||||
discreteGpuAvailable = false;
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
box = this.get_theme_node().get_content_box(box);
|
||||
let availWidth = box.get_width();
|
||||
let availHeight = box.get_height();
|
||||
this.adaptToSize(availWidth, availHeight);
|
||||
|
||||
super.vfunc_allocate(box);
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
@ -538,7 +514,7 @@ class AppDisplay extends BaseAppView {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return this._parentalControlsManager.shouldShowApp(appInfo);
|
||||
return appInfo.should_show();
|
||||
});
|
||||
|
||||
let apps = this._appInfoList.map(app => app.get_id());
|
||||
@ -648,7 +624,7 @@ class AppDisplay extends BaseAppView {
|
||||
|
||||
this._grid.currentPage = pageNumber;
|
||||
|
||||
// Animate the change between pages.
|
||||
// Tween the change between pages.
|
||||
this._adjustment.ease(this._grid.getPageY(this._grid.currentPage), {
|
||||
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
||||
duration: animate ? PAGE_SWITCH_TIME : 0,
|
||||
@ -675,11 +651,12 @@ class AppDisplay extends BaseAppView {
|
||||
|
||||
this._canScroll = false;
|
||||
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
|
||||
SCROLL_TIMEOUT_TIME, () => {
|
||||
PAGE_SWITCH_TIME, () => {
|
||||
this._canScroll = true;
|
||||
this._scrollTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
@ -970,6 +947,301 @@ class AppDisplay extends BaseAppView {
|
||||
}
|
||||
});
|
||||
|
||||
var FrequentView = GObject.registerClass(
|
||||
class FrequentView extends BaseAppView {
|
||||
_init() {
|
||||
super._init({
|
||||
style_class: 'frequent-apps',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
}, { fillParent: true });
|
||||
|
||||
this._noFrequentAppsLabel = new St.Label({ text: _("Frequently used applications will appear here"),
|
||||
style_class: 'no-frequent-applications-label',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
y_expand: true });
|
||||
|
||||
this._grid.y_expand = true;
|
||||
|
||||
this.add_actor(this._grid);
|
||||
this.add_actor(this._noFrequentAppsLabel);
|
||||
this._noFrequentAppsLabel.hide();
|
||||
|
||||
this._usage = Shell.AppUsage.get_default();
|
||||
}
|
||||
|
||||
vfunc_map() {
|
||||
this._redisplay();
|
||||
super.vfunc_map();
|
||||
}
|
||||
|
||||
hasUsefulData() {
|
||||
return this._usage.get_most_used().length >= MIN_FREQUENT_APPS_COUNT;
|
||||
}
|
||||
|
||||
_compareItems() {
|
||||
// The FrequentView does not need to be sorted alphabetically
|
||||
return 0;
|
||||
}
|
||||
|
||||
_loadApps() {
|
||||
let apps = [];
|
||||
let mostUsed = this._usage.get_most_used();
|
||||
let hasUsefulData = this.hasUsefulData();
|
||||
this._noFrequentAppsLabel.visible = !hasUsefulData;
|
||||
if (!hasUsefulData)
|
||||
return [];
|
||||
|
||||
// Allow dragging of the icon only if the Dash would accept a drop to
|
||||
// change favorite-apps. There are no other possible drop targets from
|
||||
// the app picker, so there's no other need for a drag to start,
|
||||
// at least on single-monitor setups.
|
||||
// This also disables drag-to-launch on multi-monitor setups,
|
||||
// but we hope that is not used much.
|
||||
let favoritesWritable = global.settings.is_writable('favorite-apps');
|
||||
|
||||
for (let i = 0; i < mostUsed.length; i++) {
|
||||
if (!mostUsed[i].get_app_info().should_show())
|
||||
continue;
|
||||
let appIcon = this._items.get(mostUsed[i].get_id());
|
||||
if (!appIcon) {
|
||||
appIcon = new AppIcon(mostUsed[i], {
|
||||
isDraggable: favoritesWritable,
|
||||
});
|
||||
}
|
||||
apps.push(appIcon);
|
||||
}
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
// Called before allocation to calculate dynamic spacing
|
||||
adaptToSize(width, height) {
|
||||
let box = new Clutter.ActorBox();
|
||||
box.x1 = box.y1 = 0;
|
||||
box.x2 = width;
|
||||
box.y2 = height;
|
||||
box = this.get_theme_node().get_content_box(box);
|
||||
box = this._grid.get_theme_node().get_content_box(box);
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
this._grid.adaptToSize(availWidth, availHeight);
|
||||
}
|
||||
});
|
||||
|
||||
var Views = {
|
||||
FREQUENT: 0,
|
||||
ALL: 1,
|
||||
};
|
||||
|
||||
var ControlsBoxLayout = GObject.registerClass(
|
||||
class ControlsBoxLayout extends Clutter.BoxLayout {
|
||||
/*
|
||||
* Override the BoxLayout behavior to use the maximum preferred width of all
|
||||
* buttons for each child
|
||||
*/
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
let maxMinWidth = 0;
|
||||
let maxNaturalWidth = 0;
|
||||
for (let child = container.get_first_child();
|
||||
child;
|
||||
child = child.get_next_sibling()) {
|
||||
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
|
||||
maxMinWidth = Math.max(maxMinWidth, minWidth);
|
||||
maxNaturalWidth = Math.max(maxNaturalWidth, natWidth);
|
||||
}
|
||||
let childrenCount = container.get_n_children();
|
||||
let totalSpacing = this.spacing * (childrenCount - 1);
|
||||
return [maxMinWidth * childrenCount + totalSpacing,
|
||||
maxNaturalWidth * childrenCount + totalSpacing];
|
||||
}
|
||||
});
|
||||
|
||||
var ViewStackLayout = GObject.registerClass({
|
||||
Signals: { 'allocated-size-changed': { param_types: [GObject.TYPE_INT,
|
||||
GObject.TYPE_INT] } },
|
||||
}, class ViewStackLayout extends Clutter.BinLayout {
|
||||
vfunc_allocate(actor, box, flags) {
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
// Prepare children of all views for the upcoming allocation, calculate all
|
||||
// the needed values to adapt available size
|
||||
this.emit('allocated-size-changed', availWidth, availHeight);
|
||||
super.vfunc_allocate(actor, box, flags);
|
||||
}
|
||||
});
|
||||
|
||||
var AppDisplay = GObject.registerClass(
|
||||
class AppDisplay extends St.BoxLayout {
|
||||
_init() {
|
||||
super._init({
|
||||
style_class: 'app-display',
|
||||
vertical: true,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
});
|
||||
|
||||
this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' });
|
||||
this._privacySettings.connect('changed::remember-app-usage',
|
||||
this._updateFrequentVisibility.bind(this));
|
||||
|
||||
this._views = [];
|
||||
|
||||
let view, button;
|
||||
view = new FrequentView();
|
||||
button = new St.Button({ label: _("Frequent"),
|
||||
style_class: 'app-view-control button',
|
||||
can_focus: true,
|
||||
x_expand: true });
|
||||
this._views[Views.FREQUENT] = { view, 'control': button };
|
||||
|
||||
view = new AllView();
|
||||
button = new St.Button({ label: _("All"),
|
||||
style_class: 'app-view-control button',
|
||||
can_focus: true,
|
||||
x_expand: true });
|
||||
this._views[Views.ALL] = { view, 'control': button };
|
||||
|
||||
this._viewStackLayout = new ViewStackLayout();
|
||||
this._viewStack = new St.Widget({ x_expand: true, y_expand: true,
|
||||
layout_manager: this._viewStackLayout });
|
||||
this._viewStackLayout.connect('allocated-size-changed', this._onAllocatedSizeChanged.bind(this));
|
||||
this.add_actor(this._viewStack);
|
||||
let layout = new ControlsBoxLayout({ homogeneous: true });
|
||||
this._controls = new St.Widget({
|
||||
style_class: 'app-view-controls',
|
||||
layout_manager: layout,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
this._controls.connect('notify::mapped', () => {
|
||||
// controls are faded either with their parent or
|
||||
// explicitly in animate(); we can't know how they'll be
|
||||
// shown next, so make sure to restore their opacity
|
||||
// when they are hidden
|
||||
if (this._controls.mapped)
|
||||
return;
|
||||
|
||||
this._controls.remove_all_transitions();
|
||||
this._controls.opacity = 255;
|
||||
});
|
||||
|
||||
layout.hookup_style(this._controls);
|
||||
this.add_actor(new St.Bin({ child: this._controls }));
|
||||
|
||||
for (let i = 0; i < this._views.length; i++) {
|
||||
this._viewStack.add_actor(this._views[i].view);
|
||||
this._controls.add_actor(this._views[i].control);
|
||||
|
||||
let viewIndex = i;
|
||||
this._views[i].control.connect('clicked', () => {
|
||||
this._showView(viewIndex);
|
||||
global.settings.set_uint('app-picker-view', viewIndex);
|
||||
});
|
||||
}
|
||||
let initialView = Math.min(global.settings.get_uint('app-picker-view'),
|
||||
this._views.length - 1);
|
||||
let frequentUseful = this._views[Views.FREQUENT].view.hasUsefulData();
|
||||
if (initialView == Views.FREQUENT && !frequentUseful)
|
||||
initialView = Views.ALL;
|
||||
this._showView(initialView);
|
||||
this._updateFrequentVisibility();
|
||||
|
||||
Gio.DBus.system.watch_name(SWITCHEROO_BUS_NAME,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
this._switcherooProxyAppeared.bind(this),
|
||||
() => {
|
||||
this._switcherooProxy = null;
|
||||
this._updateDiscreteGpuAvailable();
|
||||
});
|
||||
}
|
||||
|
||||
_updateDiscreteGpuAvailable() {
|
||||
if (!this._switcherooProxy)
|
||||
discreteGpuAvailable = false;
|
||||
else
|
||||
discreteGpuAvailable = this._switcherooProxy.HasDualGpu;
|
||||
}
|
||||
|
||||
_switcherooProxyAppeared() {
|
||||
this._switcherooProxy = new SwitcherooProxy(Gio.DBus.system, SWITCHEROO_BUS_NAME, SWITCHEROO_OBJECT_PATH,
|
||||
(proxy, error) => {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
this._updateDiscreteGpuAvailable();
|
||||
});
|
||||
}
|
||||
|
||||
animate(animationDirection, onComplete) {
|
||||
let currentView = this._views.filter(v => v.control.has_style_pseudo_class('checked')).pop().view;
|
||||
|
||||
// Animate controls opacity using iconGrid animation time, since
|
||||
// it will be the time the AllView or FrequentView takes to show
|
||||
// it entirely.
|
||||
let finalOpacity;
|
||||
if (animationDirection == IconGrid.AnimationDirection.IN) {
|
||||
this._controls.opacity = 0;
|
||||
finalOpacity = 255;
|
||||
} else {
|
||||
finalOpacity = 0;
|
||||
}
|
||||
|
||||
this._controls.ease({
|
||||
opacity: finalOpacity,
|
||||
duration: IconGrid.ANIMATION_TIME_IN,
|
||||
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
|
||||
});
|
||||
|
||||
currentView.animate(animationDirection, onComplete);
|
||||
}
|
||||
|
||||
_showView(activeIndex) {
|
||||
for (let i = 0; i < this._views.length; i++) {
|
||||
if (i == activeIndex)
|
||||
this._views[i].control.add_style_pseudo_class('checked');
|
||||
else
|
||||
this._views[i].control.remove_style_pseudo_class('checked');
|
||||
|
||||
let animationDirection = i == activeIndex
|
||||
? IconGrid.AnimationDirection.IN
|
||||
: IconGrid.AnimationDirection.OUT;
|
||||
this._views[i].view.animateSwitch(animationDirection);
|
||||
}
|
||||
}
|
||||
|
||||
_updateFrequentVisibility() {
|
||||
let enabled = this._privacySettings.get_boolean('remember-app-usage');
|
||||
this._views[Views.FREQUENT].control.visible = enabled;
|
||||
|
||||
let visibleViews = this._views.filter(v => v.control.visible);
|
||||
this._controls.visible = visibleViews.length > 1;
|
||||
|
||||
if (!enabled && this._views[Views.FREQUENT].view.visible)
|
||||
this._showView(Views.ALL);
|
||||
}
|
||||
|
||||
selectApp(id) {
|
||||
this._showView(Views.ALL);
|
||||
this._views[Views.ALL].view.selectApp(id);
|
||||
}
|
||||
|
||||
_onAllocatedSizeChanged(actor, width, height) {
|
||||
let box = new Clutter.ActorBox();
|
||||
box.x1 = box.y1 = 0;
|
||||
box.x2 = width;
|
||||
box.y2 = height;
|
||||
box = this._viewStack.get_theme_node().get_content_box(box);
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
for (let i = 0; i < this._views.length; i++)
|
||||
this._views[i].view.adaptToSize(availWidth, availHeight);
|
||||
}
|
||||
});
|
||||
|
||||
var AppSearchProvider = class AppSearchProvider {
|
||||
constructor() {
|
||||
this._appSys = Shell.AppSystem.get_default();
|
||||
@ -978,8 +1250,6 @@ var AppSearchProvider = class AppSearchProvider {
|
||||
this.canLaunchSearch = false;
|
||||
|
||||
this._systemActions = new SystemActions.getDefault();
|
||||
|
||||
this._parentalControlsManager = ParentalControlsManager.getDefault();
|
||||
}
|
||||
|
||||
getResultMetas(apps, callback) {
|
||||
@ -1014,30 +1284,18 @@ var AppSearchProvider = class AppSearchProvider {
|
||||
}
|
||||
|
||||
getInitialResultSet(terms, callback, _cancellable) {
|
||||
// Defer until the parental controls manager is initialised, so the
|
||||
// results can be filtered correctly.
|
||||
if (!this._parentalControlsManager.initialized) {
|
||||
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
|
||||
if (this._parentalControlsManager.initialized) {
|
||||
this._parentalControlsManager.disconnect(initializedId);
|
||||
this.getInitialResultSet(terms, callback, _cancellable);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let query = terms.join(' ');
|
||||
let groups = Shell.AppSystem.search(query);
|
||||
let usage = Shell.AppUsage.get_default();
|
||||
let results = [];
|
||||
|
||||
groups.forEach(group => {
|
||||
group = group.filter(appID => {
|
||||
const app = this._appSys.lookup_app(appID);
|
||||
return app && this._parentalControlsManager.shouldShowApp(app.app_info);
|
||||
return app && app.app_info.should_show();
|
||||
});
|
||||
results = results.concat(group.sort(
|
||||
(a, b) => usage.compare(a, b)));
|
||||
(a, b) => usage.compare(a, b)
|
||||
));
|
||||
});
|
||||
|
||||
results = results.concat(this._systemActions.getMatchingActions(terms));
|
||||
@ -1172,7 +1430,7 @@ class FolderView extends BaseAppView {
|
||||
if (!app)
|
||||
return;
|
||||
|
||||
if (!this._parentalControlsManager.shouldShowApp(app.get_app_info()))
|
||||
if (!app.get_app_info().should_show())
|
||||
return;
|
||||
|
||||
if (apps.some(appIcon => appIcon.id == appId))
|
||||
@ -1358,7 +1616,7 @@ var FolderIcon = GObject.registerClass({
|
||||
return false;
|
||||
|
||||
let view = _getViewFromIcon(source);
|
||||
if (!view || !(view instanceof AppDisplay))
|
||||
if (!view || !(view instanceof AllView))
|
||||
return false;
|
||||
|
||||
if (this._folder.get_strv('apps').includes(source.id))
|
||||
@ -1680,7 +1938,7 @@ var AppFolderDialog = GObject.registerClass({
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
contentBox = this._viewBox.get_theme_node().get_content_box(contentBox);
|
||||
|
||||
@ -1693,7 +1951,7 @@ var AppFolderDialog = GObject.registerClass({
|
||||
|
||||
this._view._grid.topPadding = 0;
|
||||
|
||||
super.vfunc_allocate(box);
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
// We can only start zooming after receiving an allocation
|
||||
if (this._needsZoomAndFade)
|
||||
@ -1918,7 +2176,7 @@ var AppIcon = GObject.registerClass({
|
||||
}
|
||||
|
||||
vfunc_leave_event(crossingEvent) {
|
||||
const ret = super.vfunc_leave_event(crossingEvent);
|
||||
let ret = super.vfunc_leave_event(crossingEvent);
|
||||
|
||||
this.fake_release();
|
||||
this._removeMenuTimeout();
|
||||
@ -1926,22 +2184,22 @@ var AppIcon = GObject.registerClass({
|
||||
}
|
||||
|
||||
vfunc_button_press_event(buttonEvent) {
|
||||
const ret = super.vfunc_button_press_event(buttonEvent);
|
||||
super.vfunc_button_press_event(buttonEvent);
|
||||
if (buttonEvent.button == 1) {
|
||||
this._setPopupTimeout();
|
||||
} else if (buttonEvent.button == 3) {
|
||||
this.popupMenu();
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return ret;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
vfunc_touch_event(touchEvent) {
|
||||
const ret = super.vfunc_touch_event(touchEvent);
|
||||
super.vfunc_touch_event(touchEvent);
|
||||
if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN)
|
||||
this._setPopupTimeout();
|
||||
|
||||
return ret;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
vfunc_clicked(button) {
|
||||
@ -2110,7 +2368,7 @@ var AppIcon = GObject.registerClass({
|
||||
|
||||
return source != this &&
|
||||
(source instanceof this.constructor) &&
|
||||
(view instanceof AppDisplay);
|
||||
(view instanceof AllView);
|
||||
}
|
||||
|
||||
_setHoveringByDnd(hovering) {
|
||||
@ -2211,12 +2469,14 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
|
||||
this.removeAll();
|
||||
|
||||
let windows = this._source.app.get_windows().filter(
|
||||
w => !w.skip_taskbar);
|
||||
w => !w.skip_taskbar
|
||||
);
|
||||
|
||||
if (windows.length > 0) {
|
||||
this.addMenuItem(
|
||||
/* Translators: This is the heading of a list of open windows */
|
||||
new PopupMenu.PopupSeparatorMenuItem(_('Open Windows')));
|
||||
new PopupMenu.PopupSeparatorMenuItem(_("Open Windows"))
|
||||
);
|
||||
}
|
||||
|
||||
windows.forEach(window => {
|
||||
@ -2246,16 +2506,10 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
|
||||
|
||||
if (discreteGpuAvailable &&
|
||||
this._source.app.state == Shell.AppState.STOPPED) {
|
||||
const appPrefersNonDefaultGPU = appInfo.get_boolean('PrefersNonDefaultGPU');
|
||||
const gpuPref = appPrefersNonDefaultGPU
|
||||
? Shell.AppLaunchGpu.DEFAULT
|
||||
: Shell.AppLaunchGpu.DISCRETE;
|
||||
this._onGpuMenuItem = this._appendMenuItem(appPrefersNonDefaultGPU
|
||||
? _('Launch using Integrated Graphics Card')
|
||||
: _('Launch using Discrete Graphics Card'));
|
||||
this._onGpuMenuItem.connect('activate', () => {
|
||||
this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
|
||||
this._onDiscreteGpuMenuItem.connect('activate', () => {
|
||||
this._source.animateLaunch();
|
||||
this._source.app.launch(0, -1, gpuPref);
|
||||
this._source.app.launch(0, -1, true);
|
||||
this.emit('activate-window', null);
|
||||
});
|
||||
}
|
||||
@ -2297,18 +2551,19 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
|
||||
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
|
||||
this._appendSeparator();
|
||||
let item = this._appendMenuItem(_("Show Details"));
|
||||
item.connect('activate', async () => {
|
||||
item.connect('activate', () => {
|
||||
let id = this._source.app.get_id();
|
||||
let args = GLib.Variant.new('(ss)', [id, '']);
|
||||
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
|
||||
bus.call(
|
||||
'org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions', 'Activate',
|
||||
new GLib.Variant.new(
|
||||
'(sava{sv})', ['details', [args], null]),
|
||||
null, 0, -1, null);
|
||||
Main.overview.hide();
|
||||
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
|
||||
let bus = Gio.DBus.get_finish(res);
|
||||
bus.call('org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions', 'Activate',
|
||||
GLib.Variant.new('(sava{sv})',
|
||||
['details', [args], null]),
|
||||
null, 0, -1, null);
|
||||
Main.overview.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
/* exported getAppFavorites */
|
||||
|
||||
const Shell = imports.gi.Shell;
|
||||
const ParentalControlsManager = imports.misc.parentalControlsManager;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
@ -13,7 +12,6 @@ const RENAMED_DESKTOP_IDS = {
|
||||
'cheese.desktop': 'org.gnome.Cheese.desktop',
|
||||
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
|
||||
'empathy.desktop': 'org.gnome.Empathy.desktop',
|
||||
'eog.desktop': 'org.gnome.eog.desktop',
|
||||
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
|
||||
'evolution.desktop': 'org.gnome.Evolution.desktop',
|
||||
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
|
||||
@ -66,13 +64,6 @@ const RENAMED_DESKTOP_IDS = {
|
||||
|
||||
class AppFavorites {
|
||||
constructor() {
|
||||
// Filter the apps through the user’s parental controls.
|
||||
this._parentalControlsManager = ParentalControlsManager.getDefault();
|
||||
this._parentalControlsManager.connect('app-filter-changed', () => {
|
||||
this.reload();
|
||||
this.emit('changed');
|
||||
});
|
||||
|
||||
this.FAVORITE_APPS_KEY = 'favorite-apps';
|
||||
this._favorites = {};
|
||||
global.settings.connect('changed::%s'.format(this.FAVORITE_APPS_KEY), this._onFavsChanged.bind(this));
|
||||
@ -104,7 +95,7 @@ class AppFavorites {
|
||||
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
|
||||
|
||||
let apps = ids.map(id => appSys.lookup_app(id))
|
||||
.filter(app => app !== null && this._parentalControlsManager.shouldShowApp(app.app_info));
|
||||
.filter(app => app != null);
|
||||
this._favorites = {};
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
@ -143,9 +134,6 @@ class AppFavorites {
|
||||
if (!app)
|
||||
return false;
|
||||
|
||||
if (!this._parentalControlsManager.shouldShowApp(app.app_info))
|
||||
return false;
|
||||
|
||||
let ids = this._getIds();
|
||||
if (pos == -1)
|
||||
ids.push(appId);
|
||||
|
@ -147,8 +147,9 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
|
||||
_onDeviceSelected(dialog, device) {
|
||||
let connection = this._dbusImpl.get_connection();
|
||||
let info = this._dbusImpl.get_info();
|
||||
const deviceName = Object.keys(AudioDevice)
|
||||
.filter(dev => AudioDevice[dev] === device)[0].toLowerCase();
|
||||
let deviceName = Object.keys(AudioDevice).filter(
|
||||
dev => AudioDevice[dev] == device
|
||||
)[0].toLowerCase();
|
||||
connection.emit_signal(this._audioSelectionDialog._sender,
|
||||
this._dbusImpl.get_object_path(),
|
||||
info ? info.name : null,
|
||||
|
@ -30,8 +30,8 @@ var BarLevel = GObject.registerClass({
|
||||
accessible_role: Atk.Role.LEVEL_BAR,
|
||||
};
|
||||
super._init(Object.assign(defaultParams, params));
|
||||
this.connect('notify::allocation', () => {
|
||||
this._barLevelWidth = this.allocation.get_width();
|
||||
this.connect('allocation-changed', (actor, box) => {
|
||||
this._barLevelWidth = box.get_width();
|
||||
});
|
||||
|
||||
this._customAccessible = St.GenericAccessible.new_for_actor(this);
|
||||
|
@ -196,13 +196,8 @@ var BoxPointer = GObject.registerClass({
|
||||
return themeNode.adjust_preferred_height(...height);
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
if (this._sourceActor && this._sourceActor.mapped) {
|
||||
this._reposition(box);
|
||||
this._updateFlip(box);
|
||||
}
|
||||
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||
@ -214,7 +209,7 @@ var BoxPointer = GObject.registerClass({
|
||||
childBox.y1 = 0;
|
||||
childBox.x2 = availWidth;
|
||||
childBox.y2 = availHeight;
|
||||
this._border.allocate(childBox);
|
||||
this._border.allocate(childBox, flags);
|
||||
|
||||
childBox.x1 = borderWidth;
|
||||
childBox.y1 = borderWidth;
|
||||
@ -234,7 +229,13 @@ var BoxPointer = GObject.registerClass({
|
||||
childBox.x2 -= rise;
|
||||
break;
|
||||
}
|
||||
this.bin.allocate(childBox);
|
||||
this.bin.allocate(childBox, flags);
|
||||
|
||||
if (this._sourceActor && this._sourceActor.mapped) {
|
||||
this._reposition(box);
|
||||
this._updateFlip(box);
|
||||
this.set_allocation(box, flags);
|
||||
}
|
||||
}
|
||||
|
||||
_drawBorder(area) {
|
||||
|
@ -199,52 +199,46 @@ class DBusEventSource extends EventSourceBase {
|
||||
|
||||
this._initialized = false;
|
||||
this._dbusProxy = new CalendarServer();
|
||||
this._initProxy();
|
||||
}
|
||||
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
|
||||
let loaded = false;
|
||||
|
||||
async _initProxy() {
|
||||
let loaded = false;
|
||||
|
||||
try {
|
||||
await this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null);
|
||||
loaded = true;
|
||||
} catch (e) {
|
||||
// Ignore timeouts and install signals as normal, because with high
|
||||
// probability the service will appear later on, and we will get a
|
||||
// NameOwnerChanged which will finish loading
|
||||
//
|
||||
// (But still _initialized to false, because the proxy does not know
|
||||
// about the HasCalendars property and would cause an exception trying
|
||||
// to read it)
|
||||
if (!e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
|
||||
log('Error loading calendars: %s'.format(e.message));
|
||||
return;
|
||||
try {
|
||||
this._dbusProxy.init_finish(result);
|
||||
loaded = true;
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
|
||||
// Ignore timeouts and install signals as normal, because with high
|
||||
// probability the service will appear later on, and we will get a
|
||||
// NameOwnerChanged which will finish loading
|
||||
//
|
||||
// (But still _initialized to false, because the proxy does not know
|
||||
// about the HasCalendars property and would cause an exception trying
|
||||
// to read it)
|
||||
} else {
|
||||
log('Error loading calendars: %s'.format(e.message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._dbusProxy.connectSignal('EventsAddedOrUpdated',
|
||||
this._onEventsAddedOrUpdated.bind(this));
|
||||
this._dbusProxy.connectSignal('EventsRemoved',
|
||||
this._onEventsRemoved.bind(this));
|
||||
this._dbusProxy.connectSignal('ClientDisappeared',
|
||||
this._onClientDisappeared.bind(this));
|
||||
this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
|
||||
|
||||
this._dbusProxy.connect('notify::g-name-owner', () => {
|
||||
if (this._dbusProxy.g_name_owner)
|
||||
this._dbusProxy.connect('notify::g-name-owner', () => {
|
||||
if (this._dbusProxy.g_name_owner)
|
||||
this._onNameAppeared();
|
||||
else
|
||||
this._onNameVanished();
|
||||
});
|
||||
|
||||
this._dbusProxy.connect('g-properties-changed', () => {
|
||||
this.notify('has-calendars');
|
||||
});
|
||||
|
||||
this._initialized = loaded;
|
||||
if (loaded) {
|
||||
this.notify('has-calendars');
|
||||
this._onNameAppeared();
|
||||
else
|
||||
this._onNameVanished();
|
||||
}
|
||||
});
|
||||
|
||||
this._dbusProxy.connect('g-properties-changed', () => {
|
||||
this.notify('has-calendars');
|
||||
});
|
||||
|
||||
this._initialized = loaded;
|
||||
if (loaded) {
|
||||
this.notify('has-calendars');
|
||||
this._onNameAppeared();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
@ -263,7 +257,7 @@ class DBusEventSource extends EventSourceBase {
|
||||
}
|
||||
|
||||
_resetCache() {
|
||||
this._events = new Map();
|
||||
this._events = [];
|
||||
this._lastRequestBegin = null;
|
||||
this._lastRequestEnd = null;
|
||||
}
|
||||
@ -279,47 +273,28 @@ class DBusEventSource extends EventSourceBase {
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
|
||||
const [appointments = []] = argArray;
|
||||
let changed = false;
|
||||
_onChanged() {
|
||||
this._loadEvents(false);
|
||||
}
|
||||
|
||||
_onEventsReceived(results, _error) {
|
||||
let newEvents = [];
|
||||
let appointments = results[0] || [];
|
||||
for (let n = 0; n < appointments.length; n++) {
|
||||
const [id, summary, allDay, startTime, endTime] = appointments[n];
|
||||
const date = new Date(startTime * 1000);
|
||||
const end = new Date(endTime * 1000);
|
||||
let a = appointments[n];
|
||||
let date = new Date(a[4] * 1000);
|
||||
let end = new Date(a[5] * 1000);
|
||||
let id = a[0];
|
||||
let summary = a[1];
|
||||
let allDay = a[3];
|
||||
let event = new CalendarEvent(id, date, end, summary, allDay);
|
||||
this._events.set(event.id, event);
|
||||
|
||||
changed = true;
|
||||
newEvents.push(event);
|
||||
}
|
||||
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
|
||||
|
||||
if (changed)
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
|
||||
const [ids = []] = argArray;
|
||||
|
||||
let changed = false;
|
||||
for (const id of ids)
|
||||
changed |= this._events.delete(id);
|
||||
|
||||
if (changed)
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_onClientDisappeared(dbusProxy, nameOwner, argArray) {
|
||||
let [sourceUid = ''] = argArray;
|
||||
sourceUid += '\n';
|
||||
|
||||
let changed = false;
|
||||
for (const id of this._events.keys()) {
|
||||
if (id.startsWith(sourceUid))
|
||||
changed |= this._events.delete(id);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
this.emit('changed');
|
||||
this._events = newEvents;
|
||||
this._isLoading = false;
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_loadEvents(forceReload) {
|
||||
@ -328,38 +303,33 @@ class DBusEventSource extends EventSourceBase {
|
||||
return;
|
||||
|
||||
if (this._curRequestBegin && this._curRequestEnd) {
|
||||
if (forceReload) {
|
||||
this._events.clear();
|
||||
this.emit('changed');
|
||||
}
|
||||
this._dbusProxy.SetTimeRangeRemote(
|
||||
this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload,
|
||||
Gio.DBusCallFlags.NONE);
|
||||
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload,
|
||||
this._onEventsReceived.bind(this),
|
||||
Gio.DBusCallFlags.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
requestRange(begin, end) {
|
||||
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
|
||||
this._isLoading = true;
|
||||
this._lastRequestBegin = begin;
|
||||
this._lastRequestEnd = end;
|
||||
this._curRequestBegin = begin;
|
||||
this._curRequestEnd = end;
|
||||
this._loadEvents(true);
|
||||
}
|
||||
}
|
||||
|
||||
*_getFilteredEvents(begin, end) {
|
||||
for (const event of this._events.values()) {
|
||||
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
|
||||
yield event;
|
||||
this._loadEvents(false);
|
||||
}
|
||||
}
|
||||
|
||||
getEvents(begin, end) {
|
||||
let result = [...this._getFilteredEvents(begin, end)];
|
||||
let result = [];
|
||||
for (let n = 0; n < this._events.length; n++) {
|
||||
let event = this._events[n];
|
||||
|
||||
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
|
||||
result.push(event);
|
||||
}
|
||||
result.sort((event1, event2) => {
|
||||
// sort events by end time on ending day
|
||||
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
|
||||
@ -373,8 +343,12 @@ class DBusEventSource extends EventSourceBase {
|
||||
let dayBegin = _getBeginningOfDay(day);
|
||||
let dayEnd = _getEndOfDay(day);
|
||||
|
||||
const { done } = this._getFilteredEvents(dayBegin, dayEnd).next();
|
||||
return !done;
|
||||
let events = this.getEvents(dayBegin, dayEnd);
|
||||
|
||||
if (events.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@ -726,11 +700,12 @@ var Calendar = GObject.registerClass({
|
||||
var EventMessage = GObject.registerClass(
|
||||
class EventMessage extends MessageList.Message {
|
||||
_init(event, date) {
|
||||
super._init('', '');
|
||||
super._init('', event.summary);
|
||||
|
||||
this._event = event;
|
||||
this._date = date;
|
||||
|
||||
this.update(event);
|
||||
this.setTitle(this._formatEventTime());
|
||||
|
||||
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
|
||||
this.setIcon(this._icon);
|
||||
@ -742,13 +717,6 @@ class EventMessage extends MessageList.Message {
|
||||
super.vfunc_style_changed();
|
||||
}
|
||||
|
||||
update(event) {
|
||||
this._event = event;
|
||||
|
||||
this.setTitle(this._formatEventTime());
|
||||
this.setBody(event.summary);
|
||||
}
|
||||
|
||||
_formatEventTime() {
|
||||
let periodBegin = _getBeginningOfDay(this._date);
|
||||
let periodEnd = _getEndOfDay(this._date);
|
||||
@ -906,7 +874,7 @@ class EventsSection extends MessageList.MessageListSection {
|
||||
}
|
||||
|
||||
_reloadEvents() {
|
||||
if (this._eventSource.isLoading || this._reloading)
|
||||
if (this._eventSource.isLoading)
|
||||
return;
|
||||
|
||||
this._reloading = true;
|
||||
@ -932,7 +900,6 @@ class EventsSection extends MessageList.MessageListSection {
|
||||
this._messageById.set(event.id, message);
|
||||
this.addMessage(message, false);
|
||||
} else {
|
||||
message.update(event);
|
||||
this.moveMessage(message, i, false);
|
||||
}
|
||||
}
|
||||
@ -1199,8 +1166,8 @@ class CalendarMessageList extends St.Widget {
|
||||
child: this._dndSwitch,
|
||||
label_actor: dndLabel,
|
||||
});
|
||||
this._dndSwitch.bind_property('state',
|
||||
this._dndButton, 'checked',
|
||||
this._dndButton.bind_property('checked',
|
||||
this._dndSwitch, 'state',
|
||||
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
|
||||
hbox.add_child(this._dndButton);
|
||||
|
||||
|
@ -13,13 +13,17 @@ var ComponentManager = class {
|
||||
_sessionUpdated() {
|
||||
let newEnabledComponents = Main.sessionMode.components;
|
||||
|
||||
newEnabledComponents
|
||||
.filter(name => !this._enabledComponents.includes(name))
|
||||
.forEach(name => this._enableComponent(name));
|
||||
newEnabledComponents.filter(
|
||||
name => !this._enabledComponents.includes(name)
|
||||
).forEach(name => {
|
||||
this._enableComponent(name);
|
||||
});
|
||||
|
||||
this._enabledComponents
|
||||
.filter(name => !newEnabledComponents.includes(name))
|
||||
.forEach(name => this._disableComponent(name));
|
||||
this._enabledComponents.filter(
|
||||
name => !newEnabledComponents.includes(name)
|
||||
).forEach(name => {
|
||||
this._disableComponent(name);
|
||||
});
|
||||
|
||||
this._enabledComponents = newEnabledComponents;
|
||||
}
|
||||
|
@ -125,7 +125,8 @@ var ContentTypeDiscoverer = class {
|
||||
_emitCallback(mount, contentTypes = []) {
|
||||
// we're not interested in win32 software content types here
|
||||
contentTypes = contentTypes.filter(
|
||||
type => type !== 'x-content/win32-software');
|
||||
type => type != 'x-content/win32-software'
|
||||
);
|
||||
|
||||
let apps = [];
|
||||
contentTypes.forEach(type => {
|
||||
|
@ -10,7 +10,6 @@ const MessageTray = imports.ui.messageTray;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
|
||||
Gio._promisify(Shell.NetworkAgent.prototype, 'init_async', 'init_finish');
|
||||
Gio._promisify(Shell.NetworkAgent.prototype,
|
||||
'search_vpn_plugin', 'search_vpn_plugin_finish');
|
||||
|
||||
@ -483,37 +482,39 @@ var VPNRequestHandler = class {
|
||||
}
|
||||
}
|
||||
|
||||
async _readStdoutOldStyle() {
|
||||
const [line, len_] =
|
||||
await this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null);
|
||||
_readStdoutOldStyle() {
|
||||
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
|
||||
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
|
||||
|
||||
if (line === null) {
|
||||
// end of file
|
||||
this._stdout.close(null);
|
||||
return;
|
||||
}
|
||||
if (line == null) {
|
||||
// end of file
|
||||
this._stdout.close(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this._vpnChildProcessLineOldStyle(line);
|
||||
this._vpnChildProcessLineOldStyle(line);
|
||||
|
||||
// try to read more!
|
||||
this._readStdoutOldStyle();
|
||||
// try to read more!
|
||||
this._readStdoutOldStyle();
|
||||
});
|
||||
}
|
||||
|
||||
async _readStdoutNewStyle() {
|
||||
const cnt =
|
||||
await this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null);
|
||||
_readStdoutNewStyle() {
|
||||
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
|
||||
let cnt = this._dataStdout.fill_finish(result);
|
||||
|
||||
if (cnt === 0) {
|
||||
// end of file
|
||||
this._showNewStyleDialog();
|
||||
if (cnt == 0) {
|
||||
// end of file
|
||||
this._showNewStyleDialog();
|
||||
|
||||
this._stdout.close(null);
|
||||
return;
|
||||
}
|
||||
this._stdout.close(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to read more
|
||||
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
|
||||
this._readStdoutNewStyle();
|
||||
// Try to read more
|
||||
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
|
||||
this._readStdoutNewStyle();
|
||||
});
|
||||
}
|
||||
|
||||
_showNewStyleDialog() {
|
||||
@ -620,17 +621,15 @@ var NetworkAgent = class {
|
||||
this._native.connect('cancel-request', this._cancelRequest.bind(this));
|
||||
|
||||
this._initialized = false;
|
||||
this._initNative();
|
||||
}
|
||||
|
||||
async _initNative() {
|
||||
try {
|
||||
await this._native.init_async(GLib.PRIORITY_DEFAULT, null);
|
||||
this._initialized = true;
|
||||
} catch (e) {
|
||||
this._native = null;
|
||||
logError(e, 'error initializing the NetworkManager Agent');
|
||||
}
|
||||
this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
|
||||
try {
|
||||
this._native.init_finish(res);
|
||||
this._initialized = true;
|
||||
} catch (e) {
|
||||
this._native = null;
|
||||
logError(e, 'error initializing the NetworkManager Agent');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
enable() {
|
||||
|
@ -327,16 +327,12 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
}
|
||||
|
||||
let resetDialog = () => {
|
||||
this._sessionRequestTimeoutId = 0;
|
||||
|
||||
if (this.state != ModalDialog.State.OPENED)
|
||||
return GLib.SOURCE_REMOVE;
|
||||
return;
|
||||
|
||||
this._passwordEntry.hide();
|
||||
this._cancelButton.grab_key_focus();
|
||||
this._okButton.reactive = false;
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
};
|
||||
|
||||
if (delay) {
|
||||
|
@ -7,14 +7,6 @@ var Tpl = null;
|
||||
var Tp = null;
|
||||
try {
|
||||
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
|
||||
|
||||
Gio._promisify(Tp.Channel.prototype, 'close_async', 'close_finish');
|
||||
Gio._promisify(Tp.Channel.prototype,
|
||||
'send_message_async', 'send_message_finish');
|
||||
Gio._promisify(Tp.ChannelDispatchOperation.prototype,
|
||||
'claim_with_async', 'claim_with_finish');
|
||||
Gio._promisify(Tpl.LogManager.prototype,
|
||||
'get_filtered_events_async', 'get_filtered_events_finish');
|
||||
} catch (e) {
|
||||
log('Telepathy is not available, chat integration will be disabled.');
|
||||
}
|
||||
@ -223,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
|
||||
|
||||
// We can only handle text channel, so close any other channel
|
||||
if (!(channel instanceof Tp.TextChannel)) {
|
||||
channel.close_async();
|
||||
channel.close_async(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -269,7 +261,7 @@ class TelepathyClient extends Tp.BaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
async _approveTextChannel(account, conn, channel, dispatchOp, context) {
|
||||
_approveTextChannel(account, conn, channel, dispatchOp, context) {
|
||||
let [targetHandle_, targetHandleType] = channel.get_handle();
|
||||
|
||||
if (targetHandleType != Tp.HandleType.CONTACT) {
|
||||
@ -278,15 +270,17 @@ class TelepathyClient extends Tp.BaseClient {
|
||||
return;
|
||||
}
|
||||
|
||||
context.accept();
|
||||
|
||||
// Approve private text channels right away as we are going to handle it
|
||||
try {
|
||||
await dispatchOp.claim_with_async(this);
|
||||
this._handlingChannels(account, conn, [channel], false);
|
||||
} catch (err) {
|
||||
log('Failed to Claim channel: %s'.format(err.toString()));
|
||||
}
|
||||
dispatchOp.claim_with_async(this, (o, result) => {
|
||||
try {
|
||||
dispatchOp.claim_with_finish(result);
|
||||
this._handlingChannels(account, conn, [channel], false);
|
||||
} catch (err) {
|
||||
log('Failed to Claim channel: %s'.format(err.toString()));
|
||||
}
|
||||
});
|
||||
|
||||
context.accept();
|
||||
}
|
||||
|
||||
_delegatedChannelsCb(_client, _channels) {
|
||||
@ -447,14 +441,17 @@ class ChatSource extends MessageTray.Source {
|
||||
}
|
||||
}
|
||||
|
||||
async _getLogMessages() {
|
||||
_getLogMessages() {
|
||||
let logManager = Tpl.LogManager.dup_singleton();
|
||||
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
|
||||
|
||||
const [events] = await logManager.get_filtered_events_async(
|
||||
this._account, entity,
|
||||
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
|
||||
null);
|
||||
logManager.get_filtered_events_async(this._account, entity,
|
||||
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
|
||||
null, this._displayPendingMessages.bind(this));
|
||||
}
|
||||
|
||||
_displayPendingMessages(logManager, result) {
|
||||
let [success_, events] = logManager.get_filtered_events_finish(result);
|
||||
|
||||
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
|
||||
this._ensureNotification();
|
||||
@ -512,7 +509,9 @@ class ChatSource extends MessageTray.Source {
|
||||
this._ackMessages();
|
||||
// The chat box has been destroyed so it can't
|
||||
// handle the channel any more.
|
||||
this._channel.close_async();
|
||||
this._channel.close_async((channel, result) => {
|
||||
channel.close_finish(result);
|
||||
});
|
||||
} else {
|
||||
// Don't indicate any unread messages when the notification
|
||||
// that represents them has been destroyed.
|
||||
@ -610,7 +609,9 @@ class ChatSource extends MessageTray.Source {
|
||||
}
|
||||
|
||||
let msg = Tp.ClientMessage.new_text(type, text);
|
||||
this._channel.send_message_async(msg, 0);
|
||||
this._channel.send_message_async(msg, 0, (src, result) => {
|
||||
this._channel.send_message_finish(result);
|
||||
});
|
||||
}
|
||||
|
||||
setChatState(state) {
|
||||
|
@ -292,11 +292,11 @@ class DashActor extends St.Widget {
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
let availWidth = contentBox.x2 - contentBox.x1;
|
||||
|
||||
this.set_allocation(box);
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let [appIcons, showAppsButton] = this.get_children();
|
||||
let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
|
||||
@ -306,11 +306,11 @@ class DashActor extends St.Widget {
|
||||
childBox.y1 = contentBox.y1;
|
||||
childBox.x2 = contentBox.x2;
|
||||
childBox.y2 = contentBox.y2 - showAppsNatHeight;
|
||||
appIcons.allocate(childBox);
|
||||
appIcons.allocate(childBox, flags);
|
||||
|
||||
childBox.y1 = contentBox.y2 - showAppsNatHeight;
|
||||
childBox.y2 = contentBox.y2;
|
||||
showAppsButton.allocate(childBox);
|
||||
showAppsButton.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
@ -815,12 +815,7 @@ var Dash = GObject.registerClass({
|
||||
else
|
||||
pos = 0; // always insert at the top when dash is empty
|
||||
|
||||
// Put the placeholder after the last favorite if we are not
|
||||
// in the favorites zone
|
||||
if (pos > numFavorites)
|
||||
pos = numFavorites;
|
||||
|
||||
if (pos !== this._dragPlaceholderPos && this._animatingPlaceholdersCount === 0) {
|
||||
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
|
||||
this._dragPlaceholderPos = pos;
|
||||
|
||||
// Don't allow positioning before or after self
|
||||
@ -848,6 +843,11 @@ var Dash = GObject.registerClass({
|
||||
this._dragPlaceholder.show(fadeIn);
|
||||
}
|
||||
|
||||
// Remove the drag placeholder if we are not in the
|
||||
// "favorites zone"
|
||||
if (pos > numFavorites)
|
||||
this._clearDragPlaceholder();
|
||||
|
||||
if (!this._dragPlaceholder)
|
||||
return DND.DragMotionResult.NO_DROP;
|
||||
|
||||
|
@ -94,7 +94,6 @@ class WorldClocksSection extends St.Button {
|
||||
});
|
||||
this._clock = new GnomeDesktop.WallClock();
|
||||
this._clockNotifyId = 0;
|
||||
this._tzNotifyId = 0;
|
||||
|
||||
this._locations = [];
|
||||
|
||||
@ -167,6 +166,8 @@ class WorldClocksSection extends St.Button {
|
||||
layout.attach(header, 0, 0, 2, 1);
|
||||
this.label_actor = header;
|
||||
|
||||
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
|
||||
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i].location;
|
||||
|
||||
@ -179,8 +180,21 @@ class WorldClocksSection extends St.Button {
|
||||
|
||||
let time = new St.Label({ style_class: 'world-clocks-time' });
|
||||
|
||||
const utcOffset = this._getTimeAtLocation(l).get_utc_offset();
|
||||
const offsetCurrentTz = utcOffset - localOffset;
|
||||
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
|
||||
const offsetMinutes =
|
||||
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
|
||||
GLib.TIME_SPAN_MINUTE;
|
||||
|
||||
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
|
||||
const text = offsetMinutes === 0
|
||||
? '%s%d'.format(prefix, offsetHours)
|
||||
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
|
||||
|
||||
const tz = new St.Label({
|
||||
style_class: 'world-clocks-timezone',
|
||||
text,
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
@ -198,65 +212,32 @@ class WorldClocksSection extends St.Button {
|
||||
layout.attach(tz, 2, i + 1, 1, 1);
|
||||
}
|
||||
|
||||
this._locations[i].timeLabel = time;
|
||||
this._locations[i].tzLabel = tz;
|
||||
this._locations[i].actor = time;
|
||||
}
|
||||
|
||||
if (this._grid.get_n_children() > 1) {
|
||||
if (!this._clockNotifyId) {
|
||||
this._clockNotifyId =
|
||||
this._clock.connect('notify::clock', this._updateTimeLabels.bind(this));
|
||||
this._clock.connect('notify::clock', this._updateLabels.bind(this));
|
||||
}
|
||||
if (!this._tzNotifyId) {
|
||||
this._tzNotifyId =
|
||||
this._clock.connect('notify::timezone', this._updateTimezoneLabels.bind(this));
|
||||
}
|
||||
this._updateTimeLabels();
|
||||
this._updateTimezoneLabels();
|
||||
this._updateLabels();
|
||||
} else {
|
||||
if (this._clockNotifyId)
|
||||
this._clock.disconnect(this._clockNotifyId);
|
||||
this._clockNotifyId = 0;
|
||||
|
||||
if (this._tzNotifyId)
|
||||
this._clock.disconnect(this._tzNotifyId);
|
||||
this._tzNotifyId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_getTimezoneOffsetAtLocation(location) {
|
||||
const localOffset = GLib.DateTime.new_now_local().get_utc_offset();
|
||||
const utcOffset = this._getTimeAtLocation(location).get_utc_offset();
|
||||
const offsetCurrentTz = utcOffset - localOffset;
|
||||
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
|
||||
const offsetMinutes =
|
||||
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
|
||||
GLib.TIME_SPAN_MINUTE;
|
||||
|
||||
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
|
||||
const text = offsetMinutes === 0
|
||||
? '%s%d'.format(prefix, offsetHours)
|
||||
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
|
||||
return text;
|
||||
}
|
||||
|
||||
_getTimeAtLocation(location) {
|
||||
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
|
||||
return GLib.DateTime.new_now(tz);
|
||||
}
|
||||
|
||||
_updateTimeLabels() {
|
||||
_updateLabels() {
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i];
|
||||
let now = this._getTimeAtLocation(l.location);
|
||||
l.timeLabel.text = Util.formatTime(now, { timeOnly: true });
|
||||
}
|
||||
}
|
||||
|
||||
_updateTimezoneLabels() {
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i];
|
||||
l.tzLabel.text = this._getTimezoneOffsetAtLocation(l.location);
|
||||
l.actor.text = Util.formatTime(now, { timeOnly: true });
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,13 +281,13 @@ class WeatherSection extends St.Button {
|
||||
this.child = box;
|
||||
|
||||
let titleBox = new St.BoxLayout({ style_class: 'weather-header-box' });
|
||||
this._titleLabel = new St.Label({
|
||||
titleBox.add_child(new St.Label({
|
||||
style_class: 'weather-header',
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
x_expand: true,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
});
|
||||
titleBox.add_child(this._titleLabel);
|
||||
text: _('Weather'),
|
||||
}));
|
||||
box.add_child(titleBox);
|
||||
|
||||
this._titleLocation = new St.Label({
|
||||
@ -433,8 +414,10 @@ class WeatherSection extends St.Button {
|
||||
_updateForecasts() {
|
||||
this._forecastGrid.destroy_all_children();
|
||||
|
||||
if (!this._weatherClient.hasLocation)
|
||||
if (!this._weatherClient.hasLocation) {
|
||||
this._setStatusLabel(_("Select a location…"));
|
||||
return;
|
||||
}
|
||||
|
||||
const { info } = this._weatherClient;
|
||||
this._titleLocation.text = this._findBestLocationName(info.location);
|
||||
@ -461,12 +444,6 @@ class WeatherSection extends St.Button {
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
if (this._weatherClient.hasLocation)
|
||||
this._titleLabel.text = _('Weather');
|
||||
else
|
||||
this._titleLabel.text = _('Select weather location…');
|
||||
|
||||
this._forecastGrid.visible = this._weatherClient.hasLocation;
|
||||
this._titleLocation.visible = this._weatherClient.hasLocation;
|
||||
|
||||
this._updateForecasts();
|
||||
@ -485,6 +462,7 @@ class MessagesIndicator extends St.Icon {
|
||||
|
||||
this._sources = [];
|
||||
this._count = 0;
|
||||
this._doNotDisturb = false;
|
||||
|
||||
this._settings = new Gio.Settings({
|
||||
schema_id: 'org.gnome.desktop.notifications',
|
||||
@ -565,8 +543,8 @@ class FreezableBinLayout extends Clutter.BinLayout {
|
||||
return this._savedHeight;
|
||||
}
|
||||
|
||||
vfunc_allocate(container, allocation) {
|
||||
super.vfunc_allocate(container, allocation);
|
||||
vfunc_allocate(container, allocation, flags) {
|
||||
super.vfunc_allocate(container, allocation, flags);
|
||||
|
||||
let [width, height] = allocation.get_size();
|
||||
this._savedWidth = [width, width];
|
||||
|
@ -278,7 +278,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
|
||||
}
|
||||
|
||||
async _onPkOfflineProxyCreated(proxy, error) {
|
||||
_onPkOfflineProxyCreated(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
@ -293,12 +293,15 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
|
||||
}
|
||||
|
||||
// It only makes sense to check for this permission if PackageKit is available.
|
||||
try {
|
||||
this._updatesPermission = await Polkit.Permission.new(
|
||||
'org.freedesktop.packagekit.trigger-offline-update', null, null);
|
||||
} catch (e) {
|
||||
log('No permission to trigger offline updates: %s'.format(e.toString()));
|
||||
}
|
||||
Polkit.Permission.new(
|
||||
'org.freedesktop.packagekit.trigger-offline-update', null, null,
|
||||
(source, res) => {
|
||||
try {
|
||||
this._updatesPermission = Polkit.Permission.new_finish(res);
|
||||
} catch (e) {
|
||||
log('No permission to trigger offline updates: %s'.format(e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
|
@ -10,20 +10,11 @@ imports.gi.versions.Gtk = '3.0';
|
||||
imports.gi.versions.TelepathyGLib = '0.12';
|
||||
imports.gi.versions.TelepathyLogger = '0.2';
|
||||
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Gettext = imports.gettext;
|
||||
const System = imports.system;
|
||||
|
||||
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
|
||||
Gio._promisify(Gio.DataInputStream.prototype,
|
||||
'read_line_async', 'read_line_finish');
|
||||
Gio._promisify(Gio.DBus, 'get', 'get_finish');
|
||||
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
|
||||
Gio._promisify(Gio.DBusProxy, 'new', 'new_finish');
|
||||
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
|
||||
Gio._promisify(Gio.DBusProxy.prototype,
|
||||
'call_with_unix_fd_list', 'call_with_unix_fd_list_finish');
|
||||
Gio._promisify(Polkit.Permission, 'new', 'new_finish');
|
||||
|
||||
let _localTimeZone = null;
|
||||
|
||||
@ -245,15 +236,16 @@ function _loggingFunc(...args) {
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Add some bindings to the global JS namespace
|
||||
globalThis.global = Shell.Global.get();
|
||||
// Add some bindings to the global JS namespace; (gjs keeps the web
|
||||
// browser convention of having that namespace be called 'window'.)
|
||||
window.global = Shell.Global.get();
|
||||
|
||||
globalThis.log = _loggingFunc;
|
||||
window.log = _loggingFunc;
|
||||
|
||||
globalThis._ = Gettext.gettext;
|
||||
globalThis.C_ = Gettext.pgettext;
|
||||
globalThis.ngettext = Gettext.ngettext;
|
||||
globalThis.N_ = s => s;
|
||||
window._ = Gettext.gettext;
|
||||
window.C_ = Gettext.pgettext;
|
||||
window.ngettext = Gettext.ngettext;
|
||||
window.N_ = s => s;
|
||||
|
||||
GObject.gtypeNameBasedOnJSPath = true;
|
||||
|
||||
@ -285,11 +277,6 @@ function init() {
|
||||
_easeActorProperty(this, 'value', target, params);
|
||||
};
|
||||
|
||||
Clutter.Actor.prototype[Symbol.iterator] = function* () {
|
||||
for (let c = this.get_first_child(); c; c = c.get_next_sibling())
|
||||
yield c;
|
||||
};
|
||||
|
||||
Clutter.Actor.prototype.toString = function () {
|
||||
return St.describe_actor(this);
|
||||
};
|
||||
@ -360,7 +347,9 @@ function init() {
|
||||
|
||||
// OK, now things are initialized enough that we can import shell JS
|
||||
const Format = imports.format;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
Tweener.init();
|
||||
String.prototype.format = Format.format;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
|
||||
});
|
||||
|
||||
function init() {
|
||||
_httpSession = new Soup.Session({ ssl_use_system_ca_file: true });
|
||||
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
|
||||
|
||||
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
|
||||
// _httpSession.add_feature(new Soup.ProxyResolverDefault());
|
||||
|
@ -26,7 +26,6 @@ var ExtensionManager = class {
|
||||
this._updateNotified = false;
|
||||
|
||||
this._extensions = new Map();
|
||||
this._unloadedExtensions = new Map();
|
||||
this._enabledExtensions = [];
|
||||
this._extensionOrder = [];
|
||||
|
||||
@ -103,18 +102,18 @@ var ExtensionManager = class {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
extension.stateObj.disable();
|
||||
} catch (e) {
|
||||
this.logExtensionError(uuid, e);
|
||||
}
|
||||
|
||||
if (extension.stylesheet) {
|
||||
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
||||
theme.unload_stylesheet(extension.stylesheet);
|
||||
delete extension.stylesheet;
|
||||
}
|
||||
|
||||
try {
|
||||
extension.stateObj.disable();
|
||||
} catch (e) {
|
||||
this.logExtensionError(uuid, e);
|
||||
}
|
||||
|
||||
for (let i = 0; i < order.length; i++) {
|
||||
let otherUuid = order[i];
|
||||
try {
|
||||
@ -230,7 +229,8 @@ var ExtensionManager = class {
|
||||
null,
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
null);
|
||||
null,
|
||||
(conn, res) => conn.call_finish(res));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -260,8 +260,7 @@ var ExtensionManager = class {
|
||||
if (!extension)
|
||||
return;
|
||||
|
||||
const message = error instanceof Error
|
||||
? error.message : error.toString();
|
||||
let message = error.toString();
|
||||
|
||||
extension.error = message;
|
||||
extension.state = ExtensionState.ERROR;
|
||||
@ -270,7 +269,6 @@ var ExtensionManager = class {
|
||||
extension.errors.push(message);
|
||||
|
||||
logError(error, 'Extension %s'.format(uuid));
|
||||
this._updateCanChange(extension);
|
||||
this.emit('extension-state-changed', extension);
|
||||
}
|
||||
|
||||
@ -320,14 +318,6 @@ var ExtensionManager = class {
|
||||
return extension;
|
||||
}
|
||||
|
||||
_canLoad(extension) {
|
||||
if (!this._unloadedExtensions.has(extension.uuid))
|
||||
return true;
|
||||
|
||||
const version = this._unloadedExtensions.get(extension.uuid);
|
||||
return extension.metadata.version === version;
|
||||
}
|
||||
|
||||
loadExtension(extension) {
|
||||
// Default to error, we set success as the last step
|
||||
extension.state = ExtensionState.ERROR;
|
||||
@ -336,9 +326,6 @@ var ExtensionManager = class {
|
||||
|
||||
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
|
||||
extension.state = ExtensionState.OUT_OF_DATE;
|
||||
} else if (!this._canLoad(extension)) {
|
||||
this.logExtensionError(extension.uuid, new Error(
|
||||
'A different version was loaded previously. You need to log out for changes to take effect.'));
|
||||
} else {
|
||||
let enabled = this._enabledExtensions.includes(extension.uuid);
|
||||
if (enabled) {
|
||||
@ -349,8 +336,6 @@ var ExtensionManager = class {
|
||||
} else {
|
||||
extension.state = ExtensionState.INITIALIZED;
|
||||
}
|
||||
|
||||
this._unloadedExtensions.delete(extension.uuid);
|
||||
}
|
||||
|
||||
this._updateCanChange(extension);
|
||||
@ -358,22 +343,15 @@ var ExtensionManager = class {
|
||||
}
|
||||
|
||||
unloadExtension(extension) {
|
||||
const { uuid, type } = extension;
|
||||
|
||||
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
|
||||
// but it will be removed on next reboot, and hopefully nothing
|
||||
// broke too much.
|
||||
this._callExtensionDisable(uuid);
|
||||
this._callExtensionDisable(extension.uuid);
|
||||
|
||||
extension.state = ExtensionState.UNINSTALLED;
|
||||
this.emit('extension-state-changed', extension);
|
||||
|
||||
// If we did install an importer, it is now cached and it's
|
||||
// impossible to load a different version
|
||||
if (type === ExtensionType.PER_USER && extension.imports)
|
||||
this._unloadedExtensions.set(uuid, extension.metadata.version);
|
||||
|
||||
this._extensions.delete(uuid);
|
||||
this._extensions.delete(extension.uuid);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -486,15 +464,19 @@ var ExtensionManager = class {
|
||||
|
||||
// Find and enable all the newly enabled extensions: UUIDs found in the
|
||||
// new setting, but not in the old one.
|
||||
newEnabledExtensions
|
||||
.filter(uuid => !this._enabledExtensions.includes(uuid))
|
||||
.forEach(uuid => this._callExtensionEnable(uuid));
|
||||
newEnabledExtensions.filter(
|
||||
uuid => !this._enabledExtensions.includes(uuid)
|
||||
).forEach(uuid => {
|
||||
this._callExtensionEnable(uuid);
|
||||
});
|
||||
|
||||
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||
// old setting, but not in the new one.
|
||||
this._extensionOrder
|
||||
.filter(uuid => !newEnabledExtensions.includes(uuid))
|
||||
.reverse().forEach(uuid => this._callExtensionDisable(uuid));
|
||||
this._extensionOrder.filter(
|
||||
uuid => !newEnabledExtensions.includes(uuid)
|
||||
).reverse().forEach(uuid => {
|
||||
this._callExtensionDisable(uuid);
|
||||
});
|
||||
|
||||
this._enabledExtensions = newEnabledExtensions;
|
||||
}
|
||||
|
@ -114,11 +114,8 @@ class BaseIcon extends St.Bin {
|
||||
if (this._setSizeManually) {
|
||||
size = this.iconSize;
|
||||
} else {
|
||||
const { scaleFactor } =
|
||||
St.ThemeContext.get_for_stage(global.stage);
|
||||
|
||||
let [found, len] = node.lookup_length('icon-size', false);
|
||||
size = found ? len / scaleFactor : ICON_SIZE;
|
||||
size = found ? len : ICON_SIZE;
|
||||
}
|
||||
|
||||
if (this.iconSize == size && this._iconBin.child)
|
||||
@ -197,9 +194,9 @@ function zoomOutActorAtPos(actor, x, y) {
|
||||
});
|
||||
}
|
||||
|
||||
function animateIconPosition(icon, box, nChangedIcons) {
|
||||
function animateIconPosition(icon, box, flags, nChangedIcons) {
|
||||
if (!icon.has_allocation() || icon.allocation.equal(box) || icon.opacity === 0) {
|
||||
icon.allocate(box);
|
||||
icon.allocate(box, flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -207,7 +204,7 @@ function animateIconPosition(icon, box, nChangedIcons) {
|
||||
icon.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
|
||||
icon.set_easing_delay(nChangedIcons * ICON_POSITION_DELAY);
|
||||
|
||||
icon.allocate(box);
|
||||
icon.allocate(box, flags);
|
||||
|
||||
icon.restore_easing_state();
|
||||
|
||||
@ -226,6 +223,7 @@ var IconGrid = GObject.registerClass({
|
||||
columnLimit: null,
|
||||
minRows: 1,
|
||||
minColumns: 1,
|
||||
fillParent: false,
|
||||
xAlign: St.Align.MIDDLE,
|
||||
padWithSpacing: false });
|
||||
this._rowLimit = params.rowLimit;
|
||||
@ -233,6 +231,7 @@ var IconGrid = GObject.registerClass({
|
||||
this._minRows = params.minRows;
|
||||
this._minColumns = params.minColumns;
|
||||
this._xAlign = params.xAlign;
|
||||
this._fillParent = params.fillParent;
|
||||
this._padWithSpacing = params.padWithSpacing;
|
||||
|
||||
this.topPadding = 0;
|
||||
@ -240,12 +239,6 @@ var IconGrid = GObject.registerClass({
|
||||
this.rightPadding = 0;
|
||||
this.leftPadding = 0;
|
||||
|
||||
this._nPages = 0;
|
||||
this.currentPage = 0;
|
||||
this._rowsPerPage = 0;
|
||||
this._spaceBetweenPages = 0;
|
||||
this._childrenPerPage = 0;
|
||||
|
||||
this._updateIconSizesLaterId = 0;
|
||||
|
||||
this._items = [];
|
||||
@ -301,6 +294,11 @@ var IconGrid = GObject.registerClass({
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(_forHeight) {
|
||||
if (this._fillParent)
|
||||
// Ignore all size requests of children and request a size of 0;
|
||||
// later we'll allocate as many children as fit the parent
|
||||
return [0, 0];
|
||||
|
||||
let nChildren = this.get_n_children();
|
||||
let nColumns = this._colLimit
|
||||
? Math.min(this._colLimit, nChildren)
|
||||
@ -319,23 +317,52 @@ var IconGrid = GObject.registerClass({
|
||||
return this.get_children().filter(actor => actor.visible);
|
||||
}
|
||||
|
||||
_availableHeightPerPageForItems() {
|
||||
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
if (this._fillParent)
|
||||
// Ignore all size requests of children and request a size of 0;
|
||||
// later we'll allocate as many children as fit the parent
|
||||
return [0, 0];
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
let children = this._getVisibleChildren();
|
||||
let nColumns;
|
||||
|
||||
forWidth = themeNode.adjust_for_width(forWidth);
|
||||
|
||||
if (forWidth < 0)
|
||||
nColumns = children.length;
|
||||
else
|
||||
[nColumns] = this._computeLayout(forWidth);
|
||||
|
||||
let nRows;
|
||||
if (nColumns > 0)
|
||||
nRows = Math.ceil(children.length / nColumns);
|
||||
else
|
||||
nRows = 0;
|
||||
if (this._rowLimit)
|
||||
nRows = Math.min(nRows, this._rowLimit);
|
||||
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
|
||||
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
|
||||
|
||||
return themeNode.adjust_preferred_height(height, height);
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height() {
|
||||
const height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
|
||||
return [height, height];
|
||||
}
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
vfunc_allocate(box) {
|
||||
if (this._childrenPerPage === 0)
|
||||
log('computePages() must be called before allocate(); pagination will not work.');
|
||||
let themeNode = this.get_theme_node();
|
||||
box = themeNode.get_content_box(box);
|
||||
|
||||
this.set_allocation(box);
|
||||
if (this._fillParent) {
|
||||
// Reset the passed in box to fill the parent
|
||||
let parentBox = this.get_parent().allocation;
|
||||
let gridBox = themeNode.get_content_box(parentBox);
|
||||
box = themeNode.get_content_box(gridBox);
|
||||
}
|
||||
|
||||
let children = this._getVisibleChildren();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
let spacing = this._getSpacing();
|
||||
let [nColumns, usedWidth] = this._computeLayout(availWidth);
|
||||
|
||||
@ -351,27 +378,34 @@ var IconGrid = GObject.registerClass({
|
||||
leftEmptySpace = availWidth - usedWidth;
|
||||
}
|
||||
|
||||
let animating = this._clonesAnimating.length > 0;
|
||||
let x = box.x1 + leftEmptySpace + this.leftPadding;
|
||||
let y = box.y1 + this.topPadding;
|
||||
let columnIndex = 0;
|
||||
|
||||
let rowIndex = 0;
|
||||
let nChangedIcons = 0;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let childBox = this._calculateChildBox(children[i], x, y, box);
|
||||
|
||||
if (animateIconPosition(children[i], childBox, nChangedIcons))
|
||||
nChangedIcons++;
|
||||
if (this._rowLimit && rowIndex >= this._rowLimit ||
|
||||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
|
||||
children[i].opacity = 0;
|
||||
} else {
|
||||
if (!animating)
|
||||
children[i].opacity = 255;
|
||||
|
||||
children[i].show();
|
||||
if (animateIconPosition(children[i], childBox, flags, nChangedIcons))
|
||||
nChangedIcons++;
|
||||
}
|
||||
|
||||
columnIndex++;
|
||||
if (columnIndex === nColumns)
|
||||
if (columnIndex == nColumns) {
|
||||
columnIndex = 0;
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
if (columnIndex == 0) {
|
||||
y += this._getVItemSize() + spacing;
|
||||
if ((i + 1) % this._childrenPerPage === 0)
|
||||
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
|
||||
x = box.x1 + leftEmptySpace + this.leftPadding;
|
||||
} else {
|
||||
x += this._getHItemSize() + spacing;
|
||||
@ -423,11 +457,7 @@ var IconGrid = GObject.registerClass({
|
||||
* set of items to be animated.
|
||||
*/
|
||||
_getChildrenToAnimate() {
|
||||
const children = this._getVisibleChildren().filter(child => child.opacity > 0);
|
||||
const firstIndex = this._childrenPerPage * this.currentPage;
|
||||
const lastIndex = firstIndex + this._childrenPerPage;
|
||||
|
||||
return children.slice(firstIndex, lastIndex);
|
||||
return this._getVisibleChildren().filter(child => child.opacity > 0);
|
||||
}
|
||||
|
||||
_resetAnimationActors() {
|
||||
@ -703,6 +733,16 @@ var IconGrid = GObject.registerClass({
|
||||
return usedWidth + this.leftPadding + this.rightPadding;
|
||||
}
|
||||
|
||||
removeAll() {
|
||||
this._items = [];
|
||||
this.remove_all_children();
|
||||
}
|
||||
|
||||
destroyAll() {
|
||||
this._items = [];
|
||||
this.destroy_all_children();
|
||||
}
|
||||
|
||||
addItem(item, index) {
|
||||
if (!(item.icon instanceof BaseIcon))
|
||||
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
|
||||
@ -718,6 +758,14 @@ var IconGrid = GObject.registerClass({
|
||||
this.remove_child(item);
|
||||
}
|
||||
|
||||
getItemAtIndex(index) {
|
||||
return this.get_child_at_index(index);
|
||||
}
|
||||
|
||||
visibleItemsCount() {
|
||||
return this.get_children().filter(c => c.is_visible()).length;
|
||||
}
|
||||
|
||||
setSpacing(spacing) {
|
||||
this._fixedSpacing = spacing;
|
||||
}
|
||||
@ -767,24 +815,6 @@ var IconGrid = GObject.registerClass({
|
||||
this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
|
||||
}
|
||||
|
||||
_computePages(availWidthPerPage, availHeightPerPage) {
|
||||
const [nColumns] = this._computeLayout(availWidthPerPage);
|
||||
const children = this._getVisibleChildren();
|
||||
let nRows;
|
||||
if (nColumns > 0)
|
||||
nRows = Math.ceil(children.length / nColumns);
|
||||
else
|
||||
nRows = 0;
|
||||
if (this._rowLimit)
|
||||
nRows = Math.min(nRows, this._rowLimit);
|
||||
|
||||
// We want to contain the grid inside the parent box with padding
|
||||
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
|
||||
this._nPages = Math.ceil(nRows / this._rowsPerPage);
|
||||
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
|
||||
this._childrenPerPage = nColumns * this._rowsPerPage;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function must to be called before iconGrid allocation,
|
||||
* to know how much spacing can the grid has
|
||||
@ -810,7 +840,6 @@ var IconGrid = GObject.registerClass({
|
||||
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
this._updateIconSizes.bind(this));
|
||||
}
|
||||
this._computePages(availWidth, availHeight);
|
||||
}
|
||||
|
||||
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
|
||||
@ -823,6 +852,116 @@ var IconGrid = GObject.registerClass({
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
});
|
||||
|
||||
var PaginatedIconGrid = GObject.registerClass(
|
||||
class PaginatedIconGrid extends IconGrid {
|
||||
_init(params) {
|
||||
super._init(params);
|
||||
this._nPages = 0;
|
||||
this.currentPage = 0;
|
||||
this._rowsPerPage = 0;
|
||||
this._spaceBetweenPages = 0;
|
||||
this._childrenPerPage = 0;
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(_forWidth) {
|
||||
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
|
||||
return [height, height];
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
if (this._childrenPerPage == 0)
|
||||
log('computePages() must be called before allocate(); pagination will not work.');
|
||||
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
if (this._fillParent) {
|
||||
// Reset the passed in box to fill the parent
|
||||
let parentBox = this.get_parent().allocation;
|
||||
let gridBox = this.get_theme_node().get_content_box(parentBox);
|
||||
box = this.get_theme_node().get_content_box(gridBox);
|
||||
}
|
||||
let children = this._getVisibleChildren();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let spacing = this._getSpacing();
|
||||
let [nColumns, usedWidth] = this._computeLayout(availWidth);
|
||||
|
||||
let leftEmptySpace;
|
||||
switch (this._xAlign) {
|
||||
case St.Align.START:
|
||||
leftEmptySpace = 0;
|
||||
break;
|
||||
case St.Align.MIDDLE:
|
||||
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
|
||||
break;
|
||||
case St.Align.END:
|
||||
leftEmptySpace = availWidth - usedWidth;
|
||||
}
|
||||
|
||||
let x = box.x1 + leftEmptySpace + this.leftPadding;
|
||||
let y = box.y1 + this.topPadding;
|
||||
let columnIndex = 0;
|
||||
|
||||
let nChangedIcons = 0;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let childBox = this._calculateChildBox(children[i], x, y, box);
|
||||
|
||||
if (animateIconPosition(children[i], childBox, flags, nChangedIcons))
|
||||
nChangedIcons++;
|
||||
|
||||
children[i].show();
|
||||
|
||||
columnIndex++;
|
||||
if (columnIndex == nColumns)
|
||||
columnIndex = 0;
|
||||
|
||||
if (columnIndex == 0) {
|
||||
y += this._getVItemSize() + spacing;
|
||||
if ((i + 1) % this._childrenPerPage == 0)
|
||||
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
|
||||
x = box.x1 + leftEmptySpace + this.leftPadding;
|
||||
} else {
|
||||
x += this._getHItemSize() + spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Overridden from IconGrid
|
||||
_getChildrenToAnimate() {
|
||||
let children = super._getChildrenToAnimate();
|
||||
let firstIndex = this._childrenPerPage * this.currentPage;
|
||||
let lastIndex = firstIndex + this._childrenPerPage;
|
||||
|
||||
return children.slice(firstIndex, lastIndex);
|
||||
}
|
||||
|
||||
_computePages(availWidthPerPage, availHeightPerPage) {
|
||||
let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage);
|
||||
let nRows;
|
||||
let children = this._getVisibleChildren();
|
||||
if (nColumns > 0)
|
||||
nRows = Math.ceil(children.length / nColumns);
|
||||
else
|
||||
nRows = 0;
|
||||
if (this._rowLimit)
|
||||
nRows = Math.min(nRows, this._rowLimit);
|
||||
|
||||
// We want to contain the grid inside the parent box with padding
|
||||
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
|
||||
this._nPages = Math.ceil(nRows / this._rowsPerPage);
|
||||
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
|
||||
this._childrenPerPage = nColumns * this._rowsPerPage;
|
||||
}
|
||||
|
||||
adaptToSize(availWidth, availHeight) {
|
||||
super.adaptToSize(availWidth, availHeight);
|
||||
this._computePages(availWidth, availHeight);
|
||||
}
|
||||
|
||||
_availableHeightPerPageForItems() {
|
||||
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
|
||||
}
|
||||
|
||||
nPages() {
|
||||
return this._nPages;
|
||||
|
@ -61,7 +61,7 @@ class AspectContainer extends St.Widget {
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
if (box.get_width() > 0 && box.get_height() > 0) {
|
||||
let sizeRatio = box.get_width() / box.get_height();
|
||||
|
||||
@ -79,7 +79,7 @@ class AspectContainer extends St.Widget {
|
||||
}
|
||||
}
|
||||
|
||||
super.vfunc_allocate(box);
|
||||
super.vfunc_allocate(box, flags);
|
||||
}
|
||||
});
|
||||
|
||||
@ -722,7 +722,7 @@ var EmojiPager = GObject.registerClass({
|
||||
|
||||
_onPan(action) {
|
||||
let [dist_, dx, dy_] = action.get_motion_delta(0);
|
||||
this.delta += dx;
|
||||
this.delta = this.delta + dx;
|
||||
|
||||
if (this._currentKey != null) {
|
||||
this._currentKey.cancel();
|
||||
@ -935,7 +935,8 @@ var EmojiSelection = GObject.registerClass({
|
||||
this.add_child(this._emojiPager);
|
||||
|
||||
this._pageIndicator = new PageIndicators.PageIndicators(
|
||||
Clutter.Orientation.HORIZONTAL);
|
||||
Clutter.Orientation.HORIZONTAL
|
||||
);
|
||||
this.add_child(this._pageIndicator);
|
||||
this._pageIndicator.setReactive(false);
|
||||
|
||||
@ -1118,7 +1119,7 @@ var KeyboardManager = class KeyBoardManager {
|
||||
this._seat.connect('notify::touch-mode', this._syncEnabled.bind(this));
|
||||
|
||||
this._lastDevice = null;
|
||||
global.backend.connect('last-device-changed', (backend, device) => {
|
||||
Meta.get_backend().connect('last-device-changed', (backend, device) => {
|
||||
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
|
||||
return;
|
||||
|
||||
@ -1256,10 +1257,6 @@ class Keyboard extends St.BoxLayout {
|
||||
return this._keyboardVisible && super.visible;
|
||||
}
|
||||
|
||||
set visible(visible) {
|
||||
super.visible = visible;
|
||||
}
|
||||
|
||||
_onFocusPositionChanged(focusTracker) {
|
||||
let rect = focusTracker.getCurrentRect();
|
||||
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
|
||||
|
@ -246,7 +246,7 @@ var LayoutManager = GObject.registerClass({
|
||||
vertical: true });
|
||||
this.addChrome(this.panelBox, { affectsStruts: true,
|
||||
trackFullscreen: true });
|
||||
this.panelBox.connect('notify::allocation',
|
||||
this.panelBox.connect('allocation-changed',
|
||||
this._panelBoxChanged.bind(this));
|
||||
|
||||
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
|
||||
|
@ -27,11 +27,13 @@ var RadialShaderEffect = GObject.registerClass({
|
||||
'brightness': GObject.ParamSpec.float(
|
||||
'brightness', 'brightness', 'brightness',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0, 1, 1),
|
||||
0, 1, 1
|
||||
),
|
||||
'sharpness': GObject.ParamSpec.float(
|
||||
'sharpness', 'sharpness', 'sharpness',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0, 1, 0),
|
||||
0, 1, 0
|
||||
),
|
||||
},
|
||||
}, class RadialShaderEffect extends Shell.GLSLEffect {
|
||||
_init(params) {
|
||||
|
@ -37,9 +37,10 @@ const LG_ANIMATION_TIME = 500;
|
||||
|
||||
function _getAutoCompleteGlobalKeywords() {
|
||||
const keywords = ['true', 'false', 'null', 'new'];
|
||||
// Don't add the private properties of globalThis (i.e., ones starting with '_')
|
||||
const windowProperties = Object.getOwnPropertyNames(globalThis).filter(
|
||||
a => a.charAt(0) !== '_');
|
||||
// Don't add the private properties of window (i.e., ones starting with '_')
|
||||
const windowProperties = Object.getOwnPropertyNames(window).filter(
|
||||
a => a.charAt(0) != '_'
|
||||
);
|
||||
const headerProperties = JsParse.getDeclaredConstants(commandHeader);
|
||||
|
||||
return keywords.concat(windowProperties).concat(headerProperties);
|
||||
@ -554,8 +555,8 @@ var Inspector = GObject.registerClass({
|
||||
this._lookingGlass = lookingGlass;
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
if (!this._eventHandler)
|
||||
return;
|
||||
@ -570,7 +571,7 @@ var Inspector = GObject.registerClass({
|
||||
childBox.x2 = childBox.x1 + natWidth;
|
||||
childBox.y1 = primary.y + Math.floor((primary.height - natHeight) / 2);
|
||||
childBox.y2 = childBox.y1 + natHeight;
|
||||
this._eventHandler.allocate(childBox);
|
||||
this._eventHandler.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
_close() {
|
||||
@ -802,191 +803,6 @@ var Extensions = GObject.registerClass({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var ActorLink = GObject.registerClass({
|
||||
Signals: {
|
||||
'inspect-actor': {},
|
||||
},
|
||||
}, class ActorLink extends St.Button {
|
||||
_init(actor) {
|
||||
this._arrow = new St.Icon({
|
||||
icon_name: 'pan-end-symbolic',
|
||||
icon_size: 8,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
|
||||
});
|
||||
|
||||
const label = new St.Label({
|
||||
text: actor.toString(),
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
});
|
||||
|
||||
const inspectButton = new St.Button({
|
||||
child: new St.Icon({
|
||||
icon_name: 'insert-object-symbolic',
|
||||
icon_size: 12,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
}),
|
||||
reactive: true,
|
||||
x_expand: true,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
inspectButton.connect('clicked', () => this.emit('inspect-actor'));
|
||||
|
||||
const box = new St.BoxLayout();
|
||||
box.add_child(this._arrow);
|
||||
box.add_child(label);
|
||||
box.add_child(inspectButton);
|
||||
|
||||
super._init({
|
||||
reactive: true,
|
||||
track_hover: true,
|
||||
toggle_mode: true,
|
||||
style_class: 'actor-link',
|
||||
child: box,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
});
|
||||
|
||||
this._actor = actor;
|
||||
}
|
||||
|
||||
vfunc_clicked() {
|
||||
this._arrow.ease({
|
||||
rotation_angle_z: this.checked ? 90 : 0,
|
||||
duration: 250,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var ActorTreeViewer = GObject.registerClass(
|
||||
class ActorTreeViewer extends St.BoxLayout {
|
||||
_init(lookingGlass) {
|
||||
super._init();
|
||||
|
||||
this._lookingGlass = lookingGlass;
|
||||
this._actorData = new Map();
|
||||
}
|
||||
|
||||
_showActorChildren(actor) {
|
||||
const data = this._actorData.get(actor);
|
||||
if (!data || data.visible)
|
||||
return;
|
||||
|
||||
data.visible = true;
|
||||
data.actorAddedId = actor.connect('actor-added', (container, child) => {
|
||||
this._addActor(data.children, child);
|
||||
});
|
||||
data.actorRemovedId = actor.connect('actor-removed', (container, child) => {
|
||||
this._removeActor(child);
|
||||
});
|
||||
|
||||
for (let child of actor)
|
||||
this._addActor(data.children, child);
|
||||
}
|
||||
|
||||
_hideActorChildren(actor) {
|
||||
const data = this._actorData.get(actor);
|
||||
if (!data || !data.visible)
|
||||
return;
|
||||
|
||||
for (let child of actor)
|
||||
this._removeActor(child);
|
||||
|
||||
data.visible = false;
|
||||
if (data.actorAddedId > 0) {
|
||||
actor.disconnect(data.actorAddedId);
|
||||
data.actorAddedId = 0;
|
||||
}
|
||||
if (data.actorRemovedId > 0) {
|
||||
actor.disconnect(data.actorRemovedId);
|
||||
data.actorRemovedId = 0;
|
||||
}
|
||||
data.children.remove_all_children();
|
||||
}
|
||||
|
||||
_addActor(container, actor) {
|
||||
if (this._actorData.has(actor))
|
||||
return;
|
||||
|
||||
if (actor === this._lookingGlass)
|
||||
return;
|
||||
|
||||
const button = new ActorLink(actor);
|
||||
button.connect('notify::checked', () => {
|
||||
this._lookingGlass.setBorderPaintTarget(actor);
|
||||
if (button.checked)
|
||||
this._showActorChildren(actor);
|
||||
else
|
||||
this._hideActorChildren(actor);
|
||||
});
|
||||
button.connect('inspect-actor', () => {
|
||||
this._lookingGlass.inspectObject(actor, button);
|
||||
});
|
||||
|
||||
const mainContainer = new St.BoxLayout({ vertical: true });
|
||||
const childrenContainer = new St.BoxLayout({
|
||||
vertical: true,
|
||||
style: 'padding: 0 0 0 18px',
|
||||
});
|
||||
|
||||
mainContainer.add_child(button);
|
||||
mainContainer.add_child(childrenContainer);
|
||||
|
||||
this._actorData.set(actor, {
|
||||
button,
|
||||
container: mainContainer,
|
||||
children: childrenContainer,
|
||||
visible: false,
|
||||
actorAddedId: 0,
|
||||
actorRemovedId: 0,
|
||||
actorDestroyedId: actor.connect('destroy', () => this._removeActor(actor)),
|
||||
});
|
||||
|
||||
let belowChild = null;
|
||||
const nextSibling = actor.get_next_sibling();
|
||||
if (nextSibling && this._actorData.has(nextSibling))
|
||||
belowChild = this._actorData.get(nextSibling).container;
|
||||
|
||||
container.insert_child_above(mainContainer, belowChild);
|
||||
}
|
||||
|
||||
_removeActor(actor) {
|
||||
const data = this._actorData.get(actor);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
for (let child of actor)
|
||||
this._removeActor(child);
|
||||
|
||||
if (data.actorAddedId > 0) {
|
||||
actor.disconnect(data.actorAddedId);
|
||||
data.actorAddedId = 0;
|
||||
}
|
||||
if (data.actorRemovedId > 0) {
|
||||
actor.disconnect(data.actorRemovedId);
|
||||
data.actorRemovedId = 0;
|
||||
}
|
||||
if (data.actorDestroyedId > 0) {
|
||||
actor.disconnect(data.actorDestroyedId);
|
||||
data.actorDestroyedId = 0;
|
||||
}
|
||||
data.container.destroy();
|
||||
this._actorData.delete(actor);
|
||||
}
|
||||
|
||||
vfunc_map() {
|
||||
super.vfunc_map();
|
||||
this._addActor(this, global.stage);
|
||||
}
|
||||
|
||||
vfunc_unmap() {
|
||||
super.vfunc_unmap();
|
||||
this._removeActor(global.stage);
|
||||
}
|
||||
});
|
||||
|
||||
var LookingGlass = GObject.registerClass(
|
||||
class LookingGlass extends St.BoxLayout {
|
||||
_init() {
|
||||
@ -1018,9 +834,9 @@ class LookingGlass extends St.BoxLayout {
|
||||
Main.uiGroup.add_actor(this);
|
||||
Main.uiGroup.set_child_below_sibling(this,
|
||||
Main.layoutManager.panelBox);
|
||||
Main.layoutManager.panelBox.connect('notify::allocation',
|
||||
Main.layoutManager.panelBox.connect('allocation-changed',
|
||||
this._queueResize.bind(this));
|
||||
Main.layoutManager.keyboardBox.connect('notify::allocation',
|
||||
Main.layoutManager.keyboardBox.connect('allocation-changed',
|
||||
this._queueResize.bind(this));
|
||||
|
||||
this._objInspector = new ObjInspector(this);
|
||||
@ -1102,9 +918,6 @@ class LookingGlass extends St.BoxLayout {
|
||||
this._extensions = new Extensions(this);
|
||||
notebook.appendPage('Extensions', this._extensions);
|
||||
|
||||
this._actorTreeViewer = new ActorTreeViewer(this);
|
||||
notebook.appendPage('Actors', this._actorTreeViewer);
|
||||
|
||||
this._entry.clutter_text.connect('activate', (o, _e) => {
|
||||
// Hide any completions we are currently showing
|
||||
this._hideCompletions();
|
||||
|
@ -643,7 +643,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setClampScrollingAtEdges(
|
||||
!this._settings.get_boolean(CLAMP_MODE_KEY));
|
||||
!this._settings.get_boolean(CLAMP_MODE_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,7 +652,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setMouseTrackingMode(
|
||||
this._settings.get_enum(MOUSE_TRACKING_KEY));
|
||||
this._settings.get_enum(MOUSE_TRACKING_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,7 +661,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setFocusTrackingMode(
|
||||
this._settings.get_enum(FOCUS_TRACKING_KEY));
|
||||
this._settings.get_enum(FOCUS_TRACKING_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,7 +670,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setCaretTrackingMode(
|
||||
this._settings.get_enum(CARET_TRACKING_KEY));
|
||||
this._settings.get_enum(CARET_TRACKING_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,7 +679,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setInvertLightness(
|
||||
this._settings.get_boolean(INVERT_LIGHTNESS_KEY));
|
||||
this._settings.get_boolean(INVERT_LIGHTNESS_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,7 +688,8 @@ var Magnifier = class Magnifier {
|
||||
// Applies only to the first zoom region.
|
||||
if (this._zoomRegions.length) {
|
||||
this._zoomRegions[0].setColorSaturation(
|
||||
this._settings.get_double(COLOR_SATURATION_KEY));
|
||||
this._settings.get_double(COLOR_SATURATION_KEY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1935,8 +1941,9 @@ var MagShaderEffects = class MagShaderEffects {
|
||||
// it modifies the brightness and/or contrast.
|
||||
let [cRed, cGreen, cBlue] = this._brightnessContrast.get_contrast();
|
||||
this._brightnessContrast.set_enabled(
|
||||
bRed !== NO_CHANGE || bGreen !== NO_CHANGE || bBlue !== NO_CHANGE ||
|
||||
cRed !== NO_CHANGE || cGreen !== NO_CHANGE || cBlue !== NO_CHANGE);
|
||||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE ||
|
||||
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1963,7 +1970,8 @@ var MagShaderEffects = class MagShaderEffects {
|
||||
// a null first argument.
|
||||
let [bRed, bGreen, bBlue] = this._brightnessContrast.get_brightness();
|
||||
this._brightnessContrast.set_enabled(
|
||||
cRed !== NO_CHANGE || cGreen !== NO_CHANGE || cBlue !== NO_CHANGE ||
|
||||
bRed !== NO_CHANGE || bGreen !== NO_CHANGE || bBlue !== NO_CHANGE);
|
||||
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
|
||||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -46,7 +46,6 @@ const XdndHandler = imports.ui.xdndHandler;
|
||||
const KbdA11yDialog = imports.ui.kbdA11yDialog;
|
||||
const LocatePointer = imports.ui.locatePointer;
|
||||
const PointerA11yTimeout = imports.ui.pointerA11yTimeout;
|
||||
const ParentalControlsManager = imports.misc.parentalControlsManager;
|
||||
|
||||
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
|
||||
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
|
||||
@ -97,8 +96,6 @@ let _oskResource = null;
|
||||
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
|
||||
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
|
||||
|
||||
let _remoteAccessInhibited = false;
|
||||
|
||||
function _sessionUpdated() {
|
||||
if (sessionMode.isPrimary)
|
||||
_loadDefaultStylesheet();
|
||||
@ -123,23 +120,12 @@ function _sessionUpdated() {
|
||||
if (lookingGlass)
|
||||
lookingGlass.close();
|
||||
}
|
||||
|
||||
let remoteAccessController = global.backend.get_remote_access_controller();
|
||||
if (remoteAccessController) {
|
||||
if (sessionMode.allowScreencast && _remoteAccessInhibited) {
|
||||
remoteAccessController.uninhibit_remote_access();
|
||||
_remoteAccessInhibited = false;
|
||||
} else if (!sessionMode.allowScreencast && !_remoteAccessInhibited) {
|
||||
remoteAccessController.inhibit_remote_access();
|
||||
_remoteAccessInhibited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
// These are here so we don't break compatibility.
|
||||
global.logError = globalThis.log;
|
||||
global.log = globalThis.log;
|
||||
global.logError = window.log;
|
||||
global.log = window.log;
|
||||
|
||||
// Chain up async errors reported from C
|
||||
global.connect('notify-error', (global, msg, detail) => {
|
||||
@ -154,10 +140,6 @@ function start() {
|
||||
sessionMode.connect('updated', _sessionUpdated);
|
||||
|
||||
St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
|
||||
|
||||
// Initialize ParentalControlsManager before the UI
|
||||
ParentalControlsManager.getDefault();
|
||||
|
||||
_initializeUI();
|
||||
|
||||
shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
|
||||
@ -539,9 +521,7 @@ function pushModal(actor, params) {
|
||||
let prevFocusDestroyId;
|
||||
if (prevFocus != null) {
|
||||
prevFocusDestroyId = prevFocus.connect('destroy', () => {
|
||||
const index = modalActorFocusStack.findIndex(
|
||||
record => record.prevFocus === prevFocus);
|
||||
|
||||
let index = _findModal(actor);
|
||||
if (index >= 0)
|
||||
modalActorFocusStack[index].prevFocus = null;
|
||||
});
|
||||
@ -817,7 +797,7 @@ function showRestartMessage(message) {
|
||||
|
||||
var AnimationsSettings = class {
|
||||
constructor() {
|
||||
let backend = global.backend;
|
||||
let backend = Meta.get_backend();
|
||||
if (!backend.is_rendering_hardware_accelerated()) {
|
||||
St.Settings.get().inhibit_animations();
|
||||
return;
|
||||
|
@ -285,12 +285,12 @@ var LabelExpanderLayout = GObject.registerClass({
|
||||
return [min, nat];
|
||||
}
|
||||
|
||||
vfunc_allocate(container, box) {
|
||||
vfunc_allocate(container, box, flags) {
|
||||
for (let i = 0; i < container.get_n_children(); i++) {
|
||||
let child = container.get_child_at_index(i);
|
||||
|
||||
if (child.visible)
|
||||
child.allocate(box);
|
||||
child.allocate(box, flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -136,22 +136,29 @@ var FocusGrabber = class FocusGrabber {
|
||||
var NotificationPolicy = GObject.registerClass({
|
||||
Properties: {
|
||||
'enable': GObject.ParamSpec.boolean(
|
||||
'enable', 'enable', 'enable', GObject.ParamFlags.READABLE, true),
|
||||
'enable', 'enable', 'enable',
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
true),
|
||||
'enable-sound': GObject.ParamSpec.boolean(
|
||||
'enable-sound', 'enable-sound', 'enable-sound',
|
||||
GObject.ParamFlags.READABLE, true),
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
true),
|
||||
'show-banners': GObject.ParamSpec.boolean(
|
||||
'show-banners', 'show-banners', 'show-banners',
|
||||
GObject.ParamFlags.READABLE, true),
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
true),
|
||||
'force-expanded': GObject.ParamSpec.boolean(
|
||||
'force-expanded', 'force-expanded', 'force-expanded',
|
||||
GObject.ParamFlags.READABLE, false),
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
false),
|
||||
'show-in-lock-screen': GObject.ParamSpec.boolean(
|
||||
'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
|
||||
GObject.ParamFlags.READABLE, false),
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
false),
|
||||
'details-in-lock-screen': GObject.ParamSpec.boolean(
|
||||
'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
|
||||
GObject.ParamFlags.READABLE, false),
|
||||
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
|
||||
false),
|
||||
},
|
||||
}, class NotificationPolicy extends GObject.Object {
|
||||
// Do nothing for the default policy. These methods are only useful for the
|
||||
@ -162,28 +169,24 @@ var NotificationPolicy = GObject.registerClass({
|
||||
this.run_dispose();
|
||||
}
|
||||
|
||||
get enable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get enableSound() {
|
||||
return true;
|
||||
return this.enable_sound;
|
||||
}
|
||||
|
||||
get showBanners() {
|
||||
return true;
|
||||
return this.show_banners;
|
||||
}
|
||||
|
||||
get forceExpanded() {
|
||||
return false;
|
||||
return this.force_expanded;
|
||||
}
|
||||
|
||||
get showInLockScreen() {
|
||||
return false;
|
||||
return this.show_in_lock_screen;
|
||||
}
|
||||
|
||||
get detailsInLockScreen() {
|
||||
return false;
|
||||
return this.details_in_lock_screen;
|
||||
}
|
||||
});
|
||||
|
||||
@ -686,8 +689,8 @@ class SourceActorWithLabel extends SourceActor {
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
super.vfunc_allocate(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
@ -707,7 +710,7 @@ class SourceActorWithLabel extends SourceActor {
|
||||
childBox.y1 = box.y2 - naturalHeight;
|
||||
childBox.y2 = box.y2;
|
||||
|
||||
this._counterBin.allocate(childBox);
|
||||
this._counterBin.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
_updateCount() {
|
||||
@ -1164,7 +1167,8 @@ var MessageTray = GObject.registerClass({
|
||||
this._onNotificationDestroy.bind(this));
|
||||
this._notificationQueue.push(notification);
|
||||
this._notificationQueue.sort(
|
||||
(n1, n2) => n2.urgency - n1.urgency);
|
||||
(n1, n2) => n2.urgency - n1.urgency
|
||||
);
|
||||
this.emit('queue-changed');
|
||||
}
|
||||
}
|
||||
|
@ -173,11 +173,6 @@ var MprisPlayer = class MprisPlayer {
|
||||
if (!this._mprisProxy.g_name_owner)
|
||||
this._close();
|
||||
});
|
||||
// It is possible for the bus to disappear before the previous signal
|
||||
// is connected, so we must ensure that the bus still exists at this
|
||||
// point.
|
||||
if (!this._mprisProxy.g_name_owner)
|
||||
this._close();
|
||||
}
|
||||
|
||||
_onPlayerProxyReady() {
|
||||
|
@ -10,6 +10,13 @@ const Params = imports.misc.params;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
// Should really be defined in Gio.js
|
||||
const BusIface = loadInterfaceXML('org.freedesktop.DBus');
|
||||
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
|
||||
function Bus() {
|
||||
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
|
||||
}
|
||||
|
||||
const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
|
||||
|
||||
var NotificationClosedReason = {
|
||||
@ -42,7 +49,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
|
||||
this._sources = [];
|
||||
this._senderToPid = {};
|
||||
this._notifications = {};
|
||||
this._busProxy = new Bus();
|
||||
|
||||
this._nextNotificationId = 1;
|
||||
|
||||
@ -107,9 +116,12 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
||||
//
|
||||
// If no existing source is found, a new source is created as long as
|
||||
// pid is provided.
|
||||
//
|
||||
// Either a pid or ndata.notification is needed to retrieve or
|
||||
// create a source.
|
||||
_getSource(title, pid, ndata, sender) {
|
||||
if (!pid && !(ndata && ndata.notification))
|
||||
throw new Error('Either a pid or ndata.notification is needed');
|
||||
return null;
|
||||
|
||||
// We use notification's source for the notifications we still have
|
||||
// around that are getting replaced because we don't keep sources
|
||||
@ -206,10 +218,42 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
||||
this._notifications[id] = ndata;
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
let pid = hints['sender-pid'];
|
||||
let pid = this._senderToPid[sender];
|
||||
|
||||
let source = this._getSource(appName, pid, ndata, sender, null);
|
||||
this._notifyForSource(source, ndata);
|
||||
|
||||
if (source) {
|
||||
this._notifyForSource(source, ndata);
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
}
|
||||
|
||||
if (replacesId) {
|
||||
// There's already a pending call to GetConnectionUnixProcessID,
|
||||
// which will see the new notification data when it finishes,
|
||||
// so we don't have to do anything.
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
}
|
||||
|
||||
this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => {
|
||||
// The app may have updated or removed the notification
|
||||
ndata = this._notifications[id];
|
||||
if (!ndata)
|
||||
return;
|
||||
|
||||
if (excp) {
|
||||
logError(excp, 'Call to GetConnectionUnixProcessID failed');
|
||||
return;
|
||||
}
|
||||
|
||||
[pid] = result;
|
||||
source = this._getSource(appName, pid, ndata, sender, null);
|
||||
|
||||
this._senderToPid[sender] = pid;
|
||||
source.connect('destroy', () => {
|
||||
delete this._senderToPid[sender];
|
||||
});
|
||||
this._notifyForSource(source, ndata);
|
||||
});
|
||||
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
}
|
||||
@ -373,11 +417,12 @@ var FdoNotificationDaemonSource = GObject.registerClass(
|
||||
class FdoNotificationDaemonSource extends MessageTray.Source {
|
||||
_init(title, pid, sender, appId) {
|
||||
this.pid = pid;
|
||||
this.initialTitle = title;
|
||||
this.app = this._getApp(appId);
|
||||
|
||||
super._init(title);
|
||||
|
||||
this.initialTitle = title;
|
||||
|
||||
if (this.app)
|
||||
this.title = this.app.get_name();
|
||||
else
|
||||
@ -425,20 +470,19 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
|
||||
}
|
||||
|
||||
_getApp(appId) {
|
||||
const appSys = Shell.AppSystem.get_default();
|
||||
let app;
|
||||
|
||||
app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
|
||||
if (app != null)
|
||||
return app;
|
||||
|
||||
if (appId)
|
||||
app = appSys.lookup_app('%s.desktop'.format(appId));
|
||||
if (appId) {
|
||||
app = Shell.AppSystem.get_default().lookup_app('%s.desktop'.format(appId));
|
||||
if (app != null)
|
||||
return app;
|
||||
}
|
||||
|
||||
if (!app)
|
||||
app = appSys.lookup_app('%s.desktop'.format(this.initialTitle));
|
||||
|
||||
return app;
|
||||
return null;
|
||||
}
|
||||
|
||||
setTitle(title) {
|
||||
|
@ -400,7 +400,8 @@ var Overview = class {
|
||||
|
||||
_getDesktopClone() {
|
||||
let windows = global.get_window_actors().filter(
|
||||
w => w.meta_window.get_window_type() === Meta.WindowType.DESKTOP);
|
||||
w => w.meta_window.get_window_type() == Meta.WindowType.DESKTOP
|
||||
);
|
||||
if (windows.length == 0)
|
||||
return null;
|
||||
|
||||
|
@ -51,7 +51,7 @@ var SlideLayout = GObject.registerClass({
|
||||
return [minWidth, natWidth];
|
||||
}
|
||||
|
||||
vfunc_allocate(container, box) {
|
||||
vfunc_allocate(container, box, flags) {
|
||||
let child = container.get_first_child();
|
||||
|
||||
let availWidth = Math.round(box.x2 - box.x1);
|
||||
@ -72,7 +72,7 @@ var SlideLayout = GObject.registerClass({
|
||||
actorBox.y1 = box.y1;
|
||||
actorBox.y2 = actorBox.y1 + availHeight;
|
||||
|
||||
child.allocate(actorBox);
|
||||
child.allocate(actorBox, flags);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
@ -394,10 +394,10 @@ class DashSpacer extends St.Widget {
|
||||
});
|
||||
|
||||
var ControlsLayout = GObject.registerClass({
|
||||
Signals: { 'allocation-changed': {} },
|
||||
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
|
||||
}, class ControlsLayout extends Clutter.BinLayout {
|
||||
vfunc_allocate(container, box) {
|
||||
super.vfunc_allocate(container, box);
|
||||
vfunc_allocate(container, box, flags) {
|
||||
super.vfunc_allocate(container, box, flags);
|
||||
this.emit('allocation-changed');
|
||||
}
|
||||
});
|
||||
@ -473,7 +473,6 @@ class ControlsManager extends St.Widget {
|
||||
|
||||
// A workspace might have been inserted or removed before the active
|
||||
// one, causing the adjustment to go out of sync, so update the value
|
||||
this._workspaceAdjustment.remove_transition('value');
|
||||
this._workspaceAdjustment.value = activeIndex;
|
||||
}
|
||||
|
||||
|
161
js/ui/padOsd.js
161
js/ui/padOsd.js
@ -2,7 +2,7 @@
|
||||
/* exported PadOsd, PadOsdService */
|
||||
|
||||
const { Atk, Clutter, GDesktopEnums, Gio,
|
||||
GLib, GObject, Gtk, Meta, Pango, Rsvg, St } = imports.gi;
|
||||
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
@ -329,7 +329,6 @@ var PadDiagram = GObject.registerClass({
|
||||
|
||||
this._imagePath = imagePath;
|
||||
this._handle = this._composeStyledDiagram();
|
||||
this._initLabels();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
@ -344,26 +343,6 @@ var PadDiagram = GObject.registerClass({
|
||||
this.add_actor(actor);
|
||||
}
|
||||
|
||||
_initLabels() {
|
||||
let i = 0;
|
||||
for (i = 0; ; i++) {
|
||||
if (!this._addLabel(Meta.PadActionType.BUTTON, i))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (!this._addLabel(Meta.PadActionType.RING, i, CW) ||
|
||||
!this._addLabel(Meta.PadActionType.RING, i, CCW))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (!this._addLabel(Meta.PadActionType.STRIP, i, UP) ||
|
||||
!this._addLabel(Meta.PadActionType.STRIP, i, DOWN))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_wrappingSvgHeader() {
|
||||
return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
|
||||
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
|
||||
@ -383,8 +362,10 @@ var PadDiagram = GObject.registerClass({
|
||||
|
||||
for (let i = 0; i < this._activeButtons.length; i++) {
|
||||
let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
|
||||
css += '.%s.Leader { stroke: %s !important; }'.format(ch, ACTIVE_COLOR);
|
||||
css += '.%s.Button { stroke: %s !important; fill: %s !important; }'.format(ch, ACTIVE_COLOR, ACTIVE_COLOR);
|
||||
css += '.%s {'.format(ch);
|
||||
css += ' stroke: %s !important;'.format(ACTIVE_COLOR);
|
||||
css += ' fill: %s !important;'.format(ACTIVE_COLOR);
|
||||
css += '}';
|
||||
}
|
||||
|
||||
return css;
|
||||
@ -409,6 +390,9 @@ var PadDiagram = GObject.registerClass({
|
||||
}
|
||||
|
||||
_updateDiagramScale() {
|
||||
if (this._handle == null)
|
||||
return;
|
||||
|
||||
[this._actorWidth, this._actorHeight] = this.get_size();
|
||||
let dimensions = this._handle.get_dimensions();
|
||||
let scaleX = this._actorWidth / dimensions.width;
|
||||
@ -421,11 +405,6 @@ var PadDiagram = GObject.registerClass({
|
||||
let [, natWidth] = child.get_preferred_width(natHeight);
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
// I miss Cairo.Matrix
|
||||
let dimensions = this._handle.get_dimensions();
|
||||
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
|
||||
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
|
||||
|
||||
if (direction == LTR) {
|
||||
childBox.x1 = x;
|
||||
childBox.x2 = x + natWidth;
|
||||
@ -436,23 +415,22 @@ var PadDiagram = GObject.registerClass({
|
||||
|
||||
childBox.y1 = y - natHeight / 2;
|
||||
childBox.y2 = y + natHeight / 2;
|
||||
child.allocate(childBox);
|
||||
child.allocate(childBox, 0);
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
super.vfunc_allocate(box);
|
||||
if (this._handle === null)
|
||||
return;
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
super.vfunc_allocate(box, flags);
|
||||
this._updateDiagramScale();
|
||||
|
||||
for (let i = 0; i < this._labels.length; i++) {
|
||||
const { label, x, y, arrangement } = this._labels[i];
|
||||
let [label, action, idx, dir] = this._labels[i];
|
||||
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
|
||||
this._allocateChild(label, x, y, arrangement);
|
||||
}
|
||||
|
||||
if (this._editorActor && this._curEdited) {
|
||||
const { x, y, arrangement } = this._curEdited;
|
||||
let [label_, action, idx, dir] = this._curEdited;
|
||||
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
|
||||
this._allocateChild(this._editorActor, x, y, arrangement);
|
||||
}
|
||||
}
|
||||
@ -479,6 +457,17 @@ var PadDiagram = GObject.registerClass({
|
||||
cr.$dispose();
|
||||
}
|
||||
|
||||
_transformPoint(x, y) {
|
||||
if (this._handle == null || this._scale == null)
|
||||
return [x, y];
|
||||
|
||||
// I miss Cairo.Matrix
|
||||
let dimensions = this._handle.get_dimensions();
|
||||
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
|
||||
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
|
||||
return [Math.round(x), Math.round(y)];
|
||||
}
|
||||
|
||||
_getItemLabelCoords(labelName, leaderName) {
|
||||
if (this._handle == null)
|
||||
return [false];
|
||||
@ -506,39 +495,44 @@ var PadDiagram = GObject.registerClass({
|
||||
pos.y = this._imageHeight - pos.y;
|
||||
}
|
||||
|
||||
return [true, pos.x, pos.y, direction];
|
||||
let [x, y] = this._transformPoint(pos.x, pos.y);
|
||||
|
||||
return [true, x, y, direction];
|
||||
}
|
||||
|
||||
_getButtonLabels(button) {
|
||||
getButtonLabelCoords(button) {
|
||||
let ch = String.fromCharCode('A'.charCodeAt() + button);
|
||||
let labelName = 'Label%s'.format(ch);
|
||||
let leaderName = 'Leader%s'.format(ch);
|
||||
return [labelName, leaderName];
|
||||
|
||||
return this._getItemLabelCoords(labelName, leaderName);
|
||||
}
|
||||
|
||||
_getRingLabels(number, dir) {
|
||||
getRingLabelCoords(number, dir) {
|
||||
let numStr = number > 0 ? (number + 1).toString() : '';
|
||||
let dirStr = dir == CW ? 'CW' : 'CCW';
|
||||
let labelName = 'LabelRing%s%s'.format(numStr, dirStr);
|
||||
let leaderName = 'LeaderRing%s%s'.format(numStr, dirStr);
|
||||
return [labelName, leaderName];
|
||||
|
||||
return this._getItemLabelCoords(labelName, leaderName);
|
||||
}
|
||||
|
||||
_getStripLabels(number, dir) {
|
||||
getStripLabelCoords(number, dir) {
|
||||
let numStr = number > 0 ? (number + 1).toString() : '';
|
||||
let dirStr = dir == UP ? 'Up' : 'Down';
|
||||
let labelName = 'LabelStrip%s%s'.format(numStr, dirStr);
|
||||
let leaderName = 'LeaderStrip%s%s'.format(numStr, dirStr);
|
||||
return [labelName, leaderName];
|
||||
|
||||
return this._getItemLabelCoords(labelName, leaderName);
|
||||
}
|
||||
|
||||
_getLabelCoords(action, idx, dir) {
|
||||
getLabelCoords(action, idx, dir) {
|
||||
if (action == Meta.PadActionType.BUTTON)
|
||||
return this._getItemLabelCoords(...this._getButtonLabels(idx));
|
||||
return this.getButtonLabelCoords(idx);
|
||||
else if (action == Meta.PadActionType.RING)
|
||||
return this._getItemLabelCoords(...this._getRingLabels(idx, dir));
|
||||
return this.getRingLabelCoords(idx, dir);
|
||||
else if (action == Meta.PadActionType.STRIP)
|
||||
return this._getItemLabelCoords(...this._getStripLabels(idx, dir));
|
||||
return this.getStripLabelCoords(idx, dir);
|
||||
|
||||
return [false];
|
||||
}
|
||||
@ -563,30 +557,26 @@ var PadDiagram = GObject.registerClass({
|
||||
this._invalidateSvg();
|
||||
}
|
||||
|
||||
_addLabel(action, idx, dir) {
|
||||
let [found, x, y, arrangement] = this._getLabelCoords(action, idx, dir);
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
let label = new St.Label();
|
||||
this._labels.push({ label, action, idx, dir, x, y, arrangement });
|
||||
addLabel(label, type, idx, dir) {
|
||||
this._labels.push([label, type, idx, dir]);
|
||||
this.add_actor(label);
|
||||
return true;
|
||||
}
|
||||
|
||||
updateLabels(getText) {
|
||||
for (let i = 0; i < this._labels.length; i++) {
|
||||
const { label, action, idx, dir } = this._labels[i];
|
||||
let [label, action, idx, dir] = this._labels[i];
|
||||
let str = getText(action, idx, dir);
|
||||
label.set_text(str);
|
||||
}
|
||||
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
_applyLabel(label, action, idx, dir, str) {
|
||||
if (str !== null)
|
||||
if (str != null) {
|
||||
label.set_text(str);
|
||||
|
||||
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
|
||||
this._allocateChild(label, x, y, arrangement);
|
||||
}
|
||||
label.show();
|
||||
}
|
||||
|
||||
@ -594,20 +584,18 @@ var PadDiagram = GObject.registerClass({
|
||||
this._editorActor.hide();
|
||||
|
||||
if (this._prevEdited) {
|
||||
const { label, action, idx, dir } = this._prevEdited;
|
||||
let [label, action, idx, dir] = this._prevEdited;
|
||||
this._applyLabel(label, action, idx, dir, str);
|
||||
this._prevEdited = null;
|
||||
}
|
||||
|
||||
if (this._curEdited) {
|
||||
const { label, action, idx, dir } = this._curEdited;
|
||||
let [label, action, idx, dir] = this._curEdited;
|
||||
this._applyLabel(label, action, idx, dir, str);
|
||||
if (continues)
|
||||
this._prevEdited = this._curEdited;
|
||||
this._curEdited = null;
|
||||
}
|
||||
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
startEdition(action, idx, dir) {
|
||||
@ -617,19 +605,21 @@ var PadDiagram = GObject.registerClass({
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._labels.length; i++) {
|
||||
if (action == this._labels[i].action &&
|
||||
idx == this._labels[i].idx && dir == this._labels[i].dir) {
|
||||
let [label, itemAction, itemIdx, itemDir] = this._labels[i];
|
||||
if (action == itemAction && idx == itemIdx && dir == itemDir) {
|
||||
this._curEdited = this._labels[i];
|
||||
editedLabel = this._curEdited.label;
|
||||
editedLabel = label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._curEdited == null)
|
||||
return;
|
||||
let [found] = this.getLabelCoords(action, idx, dir);
|
||||
if (!found)
|
||||
return;
|
||||
this._editorActor.show();
|
||||
editedLabel.hide();
|
||||
this.queue_relayout();
|
||||
}
|
||||
});
|
||||
|
||||
@ -703,7 +693,6 @@ var PadOsd = GObject.registerClass({
|
||||
|
||||
this._titleLabel = new St.Label({ style: 'font-side: larger; font-weight: bold;',
|
||||
x_align: Clutter.ActorAlign.CENTER });
|
||||
this._titleLabel.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
|
||||
this._titleLabel.clutter_text.set_text(padDevice.get_device_name());
|
||||
labelBox.add_actor(this._titleLabel);
|
||||
|
||||
@ -721,7 +710,31 @@ var PadOsd = GObject.registerClass({
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
this.add_actor(this._padDiagram);
|
||||
this._updateActionLabels();
|
||||
|
||||
// FIXME: Fix num buttons.
|
||||
let i = 0;
|
||||
for (i = 0; i < 50; i++) {
|
||||
let [found] = this._padDiagram.getButtonLabelCoords(i);
|
||||
if (!found)
|
||||
break;
|
||||
this._createLabel(Meta.PadActionType.BUTTON, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < padDevice.get_n_rings(); i++) {
|
||||
let [found] = this._padDiagram.getRingLabelCoords(i, CW);
|
||||
if (!found)
|
||||
break;
|
||||
this._createLabel(Meta.PadActionType.RING, i, CW);
|
||||
this._createLabel(Meta.PadActionType.RING, i, CCW);
|
||||
}
|
||||
|
||||
for (i = 0; i < padDevice.get_n_strips(); i++) {
|
||||
let [found] = this._padDiagram.getStripLabelCoords(i, UP);
|
||||
if (!found)
|
||||
break;
|
||||
this._createLabel(Meta.PadActionType.STRIP, i, UP);
|
||||
this._createLabel(Meta.PadActionType.STRIP, i, DOWN);
|
||||
}
|
||||
|
||||
let buttonBox = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
@ -774,6 +787,11 @@ var PadOsd = GObject.registerClass({
|
||||
return str ? str : _("None");
|
||||
}
|
||||
|
||||
_createLabel(type, number, dir) {
|
||||
let label = new St.Label({ text: this._getActionText(type, number) });
|
||||
this._padDiagram.addLabel(label, type, number, dir);
|
||||
}
|
||||
|
||||
_updateActionLabels() {
|
||||
this._padDiagram.updateLabels(this._getActionText.bind(this));
|
||||
}
|
||||
@ -849,7 +867,8 @@ var PadOsd = GObject.registerClass({
|
||||
this._tipLabel.set_text(_("Press any key to exit"));
|
||||
}
|
||||
|
||||
this._titleLabel.set_text(title);
|
||||
this._titleLabel.clutter_text.set_markup(
|
||||
'<span size="larger"><b>%s</b></span>'.format(title));
|
||||
}
|
||||
|
||||
_isEditedAction(type, number, dir) {
|
||||
|
@ -90,16 +90,18 @@ class AppMenu extends PopupMenu.PopupMenu {
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._detailsItem = this.addAction(_('Show Details'), async () => {
|
||||
this._detailsItem = this.addAction(_("Show Details"), () => {
|
||||
let id = this._app.get_id();
|
||||
let args = GLib.Variant.new('(ss)', [id, '']);
|
||||
const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
|
||||
bus.call(
|
||||
'org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions', 'Activate',
|
||||
new GLib.Variant('(sava{sv})', ['details', [args], null]),
|
||||
null, 0, -1, null);
|
||||
Gio.DBus.get(Gio.BusType.SESSION, null, (o, res) => {
|
||||
let bus = Gio.DBus.get_finish(res);
|
||||
bus.call('org.gnome.Software',
|
||||
'/org/gnome/Software',
|
||||
'org.gtk.Actions', 'Activate',
|
||||
GLib.Variant.new('(sava{sv})',
|
||||
['details', [args], null]),
|
||||
null, 0, -1, null);
|
||||
});
|
||||
});
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
@ -214,10 +216,7 @@ var AppMenuButton = GObject.registerClass({
|
||||
this._onIconThemeChanged.bind(this));
|
||||
|
||||
let iconEffect = new Clutter.DesaturateEffect();
|
||||
this._iconBox = new St.Bin({
|
||||
style_class: 'app-menu-icon',
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
this._iconBox = new St.Bin({ style_class: 'app-menu-icon' });
|
||||
this._iconBox.add_effect(iconEffect);
|
||||
this._container.add_actor(this._iconBox);
|
||||
|
||||
@ -284,7 +283,7 @@ var AppMenuButton = GObject.registerClass({
|
||||
this.remove_all_transitions();
|
||||
this.ease({
|
||||
opacity: 0,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
mode: Clutter.Animation.EASE_OUT_QUAD,
|
||||
duration: Overview.ANIMATION_TIME,
|
||||
onComplete: () => this.hide(),
|
||||
});
|
||||
@ -842,8 +841,8 @@ class Panel extends St.Widget {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let allocWidth = box.x2 - box.x1;
|
||||
let allocHeight = box.y2 - box.y1;
|
||||
@ -879,13 +878,13 @@ class Panel extends St.Widget {
|
||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
||||
leftNaturalWidth);
|
||||
}
|
||||
this._leftBox.allocate(childBox);
|
||||
this._leftBox.allocate(childBox, flags);
|
||||
|
||||
childBox.x1 = Math.ceil(sideWidth);
|
||||
childBox.y1 = 0;
|
||||
childBox.x2 = childBox.x1 + centerWidth;
|
||||
childBox.y2 = allocHeight;
|
||||
this._centerBox.allocate(childBox);
|
||||
this._centerBox.allocate(childBox, flags);
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = allocHeight;
|
||||
@ -899,7 +898,7 @@ class Panel extends St.Widget {
|
||||
0);
|
||||
childBox.x2 = allocWidth;
|
||||
}
|
||||
this._rightBox.allocate(childBox);
|
||||
this._rightBox.allocate(childBox, flags);
|
||||
|
||||
let cornerWidth, cornerHeight;
|
||||
|
||||
@ -909,7 +908,7 @@ class Panel extends St.Widget {
|
||||
childBox.x2 = cornerWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._leftCorner.allocate(childBox);
|
||||
this._leftCorner.allocate(childBox, flags);
|
||||
|
||||
[, cornerWidth] = this._rightCorner.get_preferred_width(-1);
|
||||
[, cornerHeight] = this._rightCorner.get_preferred_height(-1);
|
||||
@ -917,7 +916,7 @@ class Panel extends St.Widget {
|
||||
childBox.x2 = allocWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._rightCorner.allocate(childBox);
|
||||
this._rightCorner.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
_tryDragWindow(event) {
|
||||
@ -1156,9 +1155,10 @@ class Panel extends St.Widget {
|
||||
|
||||
_getDraggableWindowForPosition(stageX) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
const windows = workspaceManager.get_active_workspace().list_windows();
|
||||
const allWindowsByStacking =
|
||||
global.display.sort_windows_by_stacking(windows).reverse();
|
||||
let workspace = workspaceManager.get_active_workspace();
|
||||
let allWindowsByStacking = global.display.sort_windows_by_stacking(
|
||||
workspace.list_windows()
|
||||
).reverse();
|
||||
|
||||
return allWindowsByStacking.find(metaWindow => {
|
||||
let rect = metaWindow.get_frame_rect();
|
||||
|
@ -59,8 +59,8 @@ class ButtonBox extends St.Widget {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let child = this.get_first_child();
|
||||
if (!child)
|
||||
@ -83,7 +83,7 @@ class ButtonBox extends St.Widget {
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = availHeight;
|
||||
|
||||
child.allocate(childBox);
|
||||
child.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
|
@ -204,7 +204,7 @@ var RemoteSearchProvider = class {
|
||||
g_interface_info: proxyInfo,
|
||||
g_interface_name: proxyInfo.name,
|
||||
gFlags });
|
||||
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null);
|
||||
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
|
||||
|
||||
this.appInfo = appInfo;
|
||||
this.id = appInfo.get_id();
|
||||
|
@ -198,7 +198,7 @@ var ScreenShield = class {
|
||||
let lockEnabled = this._settings.get_boolean(LOCK_ENABLED_KEY);
|
||||
let lockLocked = this._lockSettings.get_boolean(DISABLE_LOCK_KEY);
|
||||
let inhibit = this._loginSession && this._loginSession.Active &&
|
||||
!this._isActive && lockEnabled && !lockLocked && Main.sessionMode.unlockDialog;
|
||||
!this._isActive && lockEnabled && !lockLocked;
|
||||
if (inhibit) {
|
||||
this._loginManager.inhibit(_("GNOME needs to lock the screen"),
|
||||
inhibitor => {
|
||||
@ -345,7 +345,7 @@ var ScreenShield = class {
|
||||
this._lockDialogGroup.remove_all_transitions();
|
||||
|
||||
if (animate) {
|
||||
// Animate the lock screen out of screen
|
||||
// Tween the lock screen out of screen
|
||||
// if velocity is not specified (i.e. we come here from pressing ESC),
|
||||
// use the same speed regardless of original position
|
||||
// if velocity is specified, it's in pixels per milliseconds
|
||||
@ -561,8 +561,7 @@ var ScreenShield = class {
|
||||
if (this._activationTime == 0)
|
||||
this._activationTime = GLib.get_monotonic_time();
|
||||
|
||||
if (!this._ensureUnlockDialog(true))
|
||||
return;
|
||||
this._ensureUnlockDialog(true);
|
||||
|
||||
this.actor.show();
|
||||
|
||||
|
@ -1,19 +1,12 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported ScreenshotService */
|
||||
|
||||
const { Clutter, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
|
||||
const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const GrabHelper = imports.ui.grabHelper;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
Gio._promisify(Shell.Screenshot.prototype, 'pick_color', 'pick_color_finish');
|
||||
Gio._promisify(Shell.Screenshot.prototype, 'screenshot', 'screenshot_finish');
|
||||
Gio._promisify(Shell.Screenshot.prototype,
|
||||
'screenshot_window', 'screenshot_window_finish');
|
||||
Gio._promisify(Shell.Screenshot.prototype,
|
||||
'screenshot_area', 'screenshot_area_finish');
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
const ScreenshotIface = loadInterfaceXML('org.gnome.Shell.Screenshot');
|
||||
@ -37,9 +30,7 @@ var ScreenshotService = class {
|
||||
|
||||
let sender = invocation.get_sender();
|
||||
if (this._screenShooter.has(sender) || lockedDown) {
|
||||
invocation.return_error_literal(
|
||||
Gio.IOErrorEnum, Gio.IOErrorEnum.BUSY,
|
||||
'There is an ongoing operation for this sender');
|
||||
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -165,7 +156,7 @@ var ScreenshotService = class {
|
||||
return [x, y, width, height];
|
||||
}
|
||||
|
||||
async ScreenshotAreaAsync(params, invocation) {
|
||||
ScreenshotAreaAsync(params, invocation) {
|
||||
let [x, y, width, height, flash, filename] = params;
|
||||
[x, y, width, height] = this._scaleArea(x, y, width, height);
|
||||
if (!this._checkArea(x, y, width, height)) {
|
||||
@ -182,17 +173,21 @@ var ScreenshotService = class {
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
try {
|
||||
let [area] =
|
||||
await screenshot.screenshot_area(x, y, width, height, stream);
|
||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
screenshot.screenshot_area(x, y, width, height, stream,
|
||||
(o, res) => {
|
||||
try {
|
||||
let [success_, area] =
|
||||
screenshot.screenshot_area_finish(res);
|
||||
this._onScreenshotComplete(
|
||||
area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async ScreenshotWindowAsync(params, invocation) {
|
||||
ScreenshotWindowAsync(params, invocation) {
|
||||
let [includeFrame, includeCursor, flash, filename] = params;
|
||||
let screenshot = this._createScreenshot(invocation);
|
||||
if (!screenshot)
|
||||
@ -202,17 +197,21 @@ var ScreenshotService = class {
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
try {
|
||||
let [area] =
|
||||
await screenshot.screenshot_window(includeFrame, includeCursor, stream);
|
||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
screenshot.screenshot_window(includeFrame, includeCursor, stream,
|
||||
(o, res) => {
|
||||
try {
|
||||
let [success_, area] =
|
||||
screenshot.screenshot_window_finish(res);
|
||||
this._onScreenshotComplete(
|
||||
area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async ScreenshotAsync(params, invocation) {
|
||||
ScreenshotAsync(params, invocation) {
|
||||
let [includeCursor, flash, filename] = params;
|
||||
let screenshot = this._createScreenshot(invocation);
|
||||
if (!screenshot)
|
||||
@ -222,13 +221,18 @@ var ScreenshotService = class {
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
try {
|
||||
let [area] = await screenshot.screenshot(includeCursor, stream);
|
||||
this._onScreenshotComplete(area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
screenshot.screenshot(includeCursor, stream,
|
||||
(o, res) => {
|
||||
try {
|
||||
let [success_, area] =
|
||||
screenshot.screenshot_finish(res);
|
||||
this._onScreenshotComplete(
|
||||
area, stream, file, flash, invocation);
|
||||
} catch (e) {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async SelectAreaAsync(params, invocation) {
|
||||
@ -261,28 +265,31 @@ var ScreenshotService = class {
|
||||
}
|
||||
|
||||
async PickColorAsync(params, invocation) {
|
||||
const screenshot = this._createScreenshot(invocation, false);
|
||||
if (!screenshot)
|
||||
return;
|
||||
|
||||
const pickPixel = new PickPixel(screenshot);
|
||||
let pickPixel = new PickPixel();
|
||||
try {
|
||||
const color = await pickPixel.pickAsync();
|
||||
const { red, green, blue } = color;
|
||||
const retval = GLib.Variant.new('(a{sv})', [{
|
||||
color: GLib.Variant.new('(ddd)', [
|
||||
red / 255.0,
|
||||
green / 255.0,
|
||||
blue / 255.0,
|
||||
]),
|
||||
}]);
|
||||
invocation.return_value(retval);
|
||||
const coords = await pickPixel.pickAsync();
|
||||
|
||||
let screenshot = this._createScreenshot(invocation, false);
|
||||
if (!screenshot)
|
||||
return;
|
||||
|
||||
screenshot.pick_color(coords.x, coords.y, (_o, res) => {
|
||||
let [success_, color] = screenshot.pick_color_finish(res);
|
||||
let { red, green, blue } = color;
|
||||
let retval = GLib.Variant.new('(a{sv})', [{
|
||||
color: GLib.Variant.new('(ddd)', [
|
||||
red / 255.0,
|
||||
green / 255.0,
|
||||
blue / 255.0,
|
||||
]),
|
||||
}]);
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
invocation.return_value(retval);
|
||||
});
|
||||
} catch (e) {
|
||||
invocation.return_error_literal(
|
||||
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
|
||||
'Operation was cancelled');
|
||||
} finally {
|
||||
this._removeShooterForSender(invocation.get_sender());
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -380,145 +387,12 @@ class SelectArea extends St.Widget {
|
||||
}
|
||||
});
|
||||
|
||||
var RecolorEffect = GObject.registerClass({
|
||||
Properties: {
|
||||
color: GObject.ParamSpec.boxed(
|
||||
'color', 'color', 'replacement color',
|
||||
GObject.ParamFlags.WRITABLE,
|
||||
Clutter.Color.$gtype),
|
||||
chroma: GObject.ParamSpec.boxed(
|
||||
'chroma', 'chroma', 'color to replace',
|
||||
GObject.ParamFlags.WRITABLE,
|
||||
Clutter.Color.$gtype),
|
||||
threshold: GObject.ParamSpec.float(
|
||||
'threshold', 'threshold', 'threshold',
|
||||
GObject.ParamFlags.WRITABLE,
|
||||
0.0, 1.0, 0.0),
|
||||
smoothing: GObject.ParamSpec.float(
|
||||
'smoothing', 'smoothing', 'smoothing',
|
||||
GObject.ParamFlags.WRITABLE,
|
||||
0.0, 1.0, 0.0),
|
||||
},
|
||||
}, class RecolorEffect extends Shell.GLSLEffect {
|
||||
_init(params) {
|
||||
this._color = new Clutter.Color();
|
||||
this._chroma = new Clutter.Color();
|
||||
this._threshold = 0;
|
||||
this._smoothing = 0;
|
||||
|
||||
this._colorLocation = null;
|
||||
this._chromaLocation = null;
|
||||
this._thresholdLocation = null;
|
||||
this._smoothingLocation = null;
|
||||
|
||||
super._init(params);
|
||||
|
||||
this._colorLocation = this.get_uniform_location('recolor_color');
|
||||
this._chromaLocation = this.get_uniform_location('chroma_color');
|
||||
this._thresholdLocation = this.get_uniform_location('threshold');
|
||||
this._smoothingLocation = this.get_uniform_location('smoothing');
|
||||
|
||||
this._updateColorUniform(this._colorLocation, this._color);
|
||||
this._updateColorUniform(this._chromaLocation, this._chroma);
|
||||
this._updateFloatUniform(this._thresholdLocation, this._threshold);
|
||||
this._updateFloatUniform(this._smoothingLocation, this._smoothing);
|
||||
}
|
||||
|
||||
_updateColorUniform(location, color) {
|
||||
if (!location)
|
||||
return;
|
||||
|
||||
this.set_uniform_float(location,
|
||||
3, [color.red / 255, color.green / 255, color.blue / 255]);
|
||||
this.queue_repaint();
|
||||
}
|
||||
|
||||
_updateFloatUniform(location, value) {
|
||||
if (!location)
|
||||
return;
|
||||
|
||||
this.set_uniform_float(location, 1, [value]);
|
||||
this.queue_repaint();
|
||||
}
|
||||
|
||||
set color(c) {
|
||||
if (this._color.equal(c))
|
||||
return;
|
||||
|
||||
this._color = c;
|
||||
this.notify('color');
|
||||
|
||||
this._updateColorUniform(this._colorLocation, this._color);
|
||||
}
|
||||
|
||||
set chroma(c) {
|
||||
if (this._chroma.equal(c))
|
||||
return;
|
||||
|
||||
this._chroma = c;
|
||||
this.notify('chroma');
|
||||
|
||||
this._updateColorUniform(this._chromaLocation, this._chroma);
|
||||
}
|
||||
|
||||
set threshold(value) {
|
||||
if (this._threshold === value)
|
||||
return;
|
||||
|
||||
this._threshold = value;
|
||||
this.notify('threshold');
|
||||
|
||||
this._updateFloatUniform(this._thresholdLocation, this._threshold);
|
||||
}
|
||||
|
||||
set smoothing(value) {
|
||||
if (this._smoothing === value)
|
||||
return;
|
||||
|
||||
this._smoothing = value;
|
||||
this.notify('smoothing');
|
||||
|
||||
this._updateFloatUniform(this._smoothingLocation, this._smoothing);
|
||||
}
|
||||
|
||||
vfunc_build_pipeline() {
|
||||
// Conversion parameters from https://en.wikipedia.org/wiki/YCbCr
|
||||
const decl = `
|
||||
vec3 rgb2yCrCb(vec3 c) { \n
|
||||
float y = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b; \n
|
||||
float cr = 0.7133 * (c.r - y); \n
|
||||
float cb = 0.5643 * (c.b - y); \n
|
||||
return vec3(y, cr, cb); \n
|
||||
} \n
|
||||
\n
|
||||
uniform vec3 chroma_color; \n
|
||||
uniform vec3 recolor_color; \n
|
||||
uniform float threshold; \n
|
||||
uniform float smoothing; \n`;
|
||||
const src = `
|
||||
vec3 mask = rgb2yCrCb(chroma_color.rgb); \n
|
||||
vec3 yCrCb = rgb2yCrCb(cogl_color_out.rgb); \n
|
||||
float blend = \n
|
||||
smoothstep(threshold, \n
|
||||
threshold + smoothing, \n
|
||||
distance(yCrCb.gb, mask.gb)); \n
|
||||
cogl_color_out.rgb = \n
|
||||
mix(recolor_color, cogl_color_out.rgb, blend); \n`;
|
||||
|
||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, src, false);
|
||||
}
|
||||
});
|
||||
|
||||
var PickPixel = GObject.registerClass(
|
||||
class PickPixel extends St.Widget {
|
||||
_init(screenshot) {
|
||||
_init() {
|
||||
super._init({ visible: false, reactive: true });
|
||||
|
||||
this._screenshot = screenshot;
|
||||
|
||||
this._result = null;
|
||||
this._color = null;
|
||||
this._inPick = false;
|
||||
|
||||
Main.uiGroup.add_actor(this);
|
||||
|
||||
@ -527,44 +401,16 @@ class PickPixel extends St.Widget {
|
||||
let constraint = new Clutter.BindConstraint({ source: global.stage,
|
||||
coordinate: Clutter.BindCoordinate.ALL });
|
||||
this.add_constraint(constraint);
|
||||
|
||||
const action = new Clutter.ClickAction();
|
||||
action.connect('clicked', async () => {
|
||||
await this._pickColor(...action.get_coords());
|
||||
this._result = this._color;
|
||||
this._grabHelper.ungrab();
|
||||
});
|
||||
this.add_action(action);
|
||||
|
||||
this._recolorEffect = new RecolorEffect({
|
||||
chroma: new Clutter.Color({
|
||||
red: 80,
|
||||
green: 219,
|
||||
blue: 181,
|
||||
}),
|
||||
threshold: 0.04,
|
||||
smoothing: 0.07,
|
||||
});
|
||||
this._previewCursor = new St.Icon({
|
||||
icon_name: 'color-pick',
|
||||
icon_size: Meta.prefs_get_cursor_size(),
|
||||
effect: this._recolorEffect,
|
||||
visible: false,
|
||||
});
|
||||
Main.uiGroup.add_actor(this._previewCursor);
|
||||
}
|
||||
|
||||
async pickAsync() {
|
||||
global.display.set_cursor(Meta.Cursor.BLANK);
|
||||
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
|
||||
Main.uiGroup.set_child_above_sibling(this, null);
|
||||
this.show();
|
||||
|
||||
this._pickColor(...global.get_pointer());
|
||||
|
||||
await this._grabHelper.grabAsync({ actor: this });
|
||||
|
||||
global.display.set_cursor(Meta.Cursor.DEFAULT);
|
||||
this._previewCursor.destroy();
|
||||
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
|
||||
this.destroy();
|
||||
@ -574,25 +420,10 @@ class PickPixel extends St.Widget {
|
||||
return this._result;
|
||||
}
|
||||
|
||||
async _pickColor(x, y) {
|
||||
if (this._inPick)
|
||||
return;
|
||||
|
||||
this._inPick = true;
|
||||
this._previewCursor.set_position(x, y);
|
||||
[this._color] = await this._screenshot.pick_color(x, y);
|
||||
this._inPick = false;
|
||||
|
||||
if (!this._color)
|
||||
return;
|
||||
|
||||
this._recolorEffect.color = this._color;
|
||||
this._previewCursor.show();
|
||||
}
|
||||
|
||||
vfunc_motion_event(motionEvent) {
|
||||
const { x, y } = motionEvent;
|
||||
this._pickColor(x, y);
|
||||
vfunc_button_release_event(buttonEvent) {
|
||||
let { x, y } = buttonEvent;
|
||||
this._result = new Graphene.Point({ x, y });
|
||||
this._grabHelper.ungrab();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
});
|
||||
|
165
js/ui/search.js
165
js/ui/search.js
@ -6,17 +6,17 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const ParentalControlsManager = imports.misc.parentalControlsManager;
|
||||
const RemoteSearch = imports.ui.remoteSearch;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
|
||||
|
||||
var MAX_LIST_SEARCH_RESULTS_ROWS = 5;
|
||||
var MAX_GRID_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
var MaxWidthBox = GObject.registerClass(
|
||||
class MaxWidthBox extends St.BoxLayout {
|
||||
vfunc_allocate(box) {
|
||||
vfunc_allocate(box, flags) {
|
||||
let themeNode = this.get_theme_node();
|
||||
let maxWidth = themeNode.get_max_width();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
@ -28,7 +28,7 @@ class MaxWidthBox extends St.BoxLayout {
|
||||
adjustedBox.x2 -= Math.floor(excessWidth / 2);
|
||||
}
|
||||
|
||||
super.vfunc_allocate(adjustedBox);
|
||||
super.vfunc_allocate(adjustedBox, flags);
|
||||
}
|
||||
});
|
||||
|
||||
@ -219,7 +219,8 @@ var SearchResultsBase = GObject.registerClass({
|
||||
|
||||
_ensureResultActors(results, callback) {
|
||||
let metasNeeded = results.filter(
|
||||
resultId => this._resultDisplays[resultId] === undefined);
|
||||
resultId => this._resultDisplays[resultId] === undefined
|
||||
);
|
||||
|
||||
if (metasNeeded.length === 0) {
|
||||
callback(true);
|
||||
@ -348,140 +349,18 @@ class ListSearchResults extends SearchResultsBase {
|
||||
}
|
||||
});
|
||||
|
||||
var GridSearchResultsLayout = GObject.registerClass({
|
||||
Properties: {
|
||||
'spacing': GObject.ParamSpec.int('spacing', 'Spacing', 'Spacing',
|
||||
GObject.ParamFlags.READWRITE, 0, GLib.MAXINT32, 0),
|
||||
},
|
||||
}, class GridSearchResultsLayout extends Clutter.LayoutManager {
|
||||
_init() {
|
||||
super._init();
|
||||
this._spacing = 0;
|
||||
}
|
||||
|
||||
vfunc_set_container(container) {
|
||||
this._container = container;
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
let minWidth = 0;
|
||||
let natWidth = 0;
|
||||
let first = true;
|
||||
|
||||
for (let child of container) {
|
||||
if (!child.visible)
|
||||
continue;
|
||||
|
||||
const [childMinWidth, childNatWidth] = child.get_preferred_width(forHeight);
|
||||
|
||||
minWidth = Math.max(minWidth, childMinWidth);
|
||||
natWidth += childNatWidth;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
natWidth += this._spacing;
|
||||
}
|
||||
|
||||
return [minWidth, natWidth];
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(container, forWidth) {
|
||||
let minHeight = 0;
|
||||
let natHeight = 0;
|
||||
|
||||
for (let child of container) {
|
||||
if (!child.visible)
|
||||
continue;
|
||||
|
||||
const [childMinHeight, childNatHeight] = child.get_preferred_height(forWidth);
|
||||
|
||||
minHeight = Math.max(minHeight, childMinHeight);
|
||||
natHeight = Math.max(natHeight, childNatHeight);
|
||||
}
|
||||
|
||||
return [minHeight, natHeight];
|
||||
}
|
||||
|
||||
vfunc_allocate(container, box) {
|
||||
const width = box.get_width();
|
||||
|
||||
const childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = 0;
|
||||
childBox.y1 = 0;
|
||||
|
||||
let first = true;
|
||||
for (let child of container) {
|
||||
if (!child.visible)
|
||||
continue;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
childBox.x1 += this._spacing;
|
||||
|
||||
const [childWidth] = child.get_preferred_width(-1);
|
||||
const [childHeight] = child.get_preferred_height(-1);
|
||||
childBox.set_size(childWidth, childHeight);
|
||||
|
||||
if (childBox.x1 + childWidth > width)
|
||||
return;
|
||||
|
||||
child.allocate(childBox);
|
||||
|
||||
childBox.x1 += childWidth;
|
||||
}
|
||||
}
|
||||
|
||||
columnsForWidth(width) {
|
||||
if (!this._container)
|
||||
return -1;
|
||||
|
||||
const [minWidth] = this.get_preferred_width(this._container, -1);
|
||||
|
||||
if (minWidth === 0)
|
||||
return -1;
|
||||
|
||||
let nCols = 0;
|
||||
while (width > minWidth) {
|
||||
width -= minWidth;
|
||||
if (nCols > 0)
|
||||
width -= this._spacing;
|
||||
nCols++;
|
||||
}
|
||||
|
||||
return nCols;
|
||||
}
|
||||
|
||||
get spacing() {
|
||||
return this._spacing;
|
||||
}
|
||||
|
||||
set spacing(v) {
|
||||
if (this._spacing === v)
|
||||
return;
|
||||
this._spacing = v;
|
||||
this.layout_changed();
|
||||
}
|
||||
});
|
||||
|
||||
var GridSearchResults = GObject.registerClass(
|
||||
class GridSearchResults extends SearchResultsBase {
|
||||
_init(provider, resultsView) {
|
||||
super._init(provider, resultsView);
|
||||
|
||||
this._grid = new St.Widget({ style_class: 'grid-search-results' });
|
||||
this._grid.layout_manager = new GridSearchResultsLayout();
|
||||
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
|
||||
this._grid.connect('style-changed', () => {
|
||||
const node = this._grid.get_theme_node();
|
||||
this._grid.layout_manager.spacing = node.get_length('spacing');
|
||||
});
|
||||
this._bin = new St.Bin({ x_align: Clutter.ActorAlign.CENTER });
|
||||
this._bin.set_child(this._grid);
|
||||
|
||||
this._resultDisplayBin.set_child(new St.Bin({
|
||||
child: this._grid,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
}));
|
||||
this._resultDisplayBin.set_child(this._bin);
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
@ -521,11 +400,12 @@ class GridSearchResults extends SearchResultsBase {
|
||||
if (width == 0)
|
||||
return -1;
|
||||
|
||||
return this._grid.layout_manager.columnsForWidth(width);
|
||||
let nCols = this._grid.columnsForWidth(width);
|
||||
return nCols * this._grid.getRowLimit();
|
||||
}
|
||||
|
||||
_clearResultDisplay() {
|
||||
this._grid.remove_all_children();
|
||||
this._grid.removeAll();
|
||||
}
|
||||
|
||||
_createResultDisplay(meta) {
|
||||
@ -534,15 +414,14 @@ class GridSearchResults extends SearchResultsBase {
|
||||
}
|
||||
|
||||
_addItem(display) {
|
||||
this._grid.add_child(display);
|
||||
this._grid.addItem(display);
|
||||
}
|
||||
|
||||
getFirstResult() {
|
||||
for (let child of this._grid) {
|
||||
if (child.visible)
|
||||
return child;
|
||||
}
|
||||
return null;
|
||||
if (this._grid.visibleItemsCount() > 0)
|
||||
return this._grid.getItemAtIndex(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@ -552,9 +431,6 @@ var SearchResultsView = GObject.registerClass({
|
||||
_init() {
|
||||
super._init({ name: 'searchResults', vertical: true });
|
||||
|
||||
this._parentalControlsManager = ParentalControlsManager.getDefault();
|
||||
this._parentalControlsManager.connect('app-filter-changed', this._reloadRemoteProviders.bind(this));
|
||||
|
||||
this._content = new MaxWidthBox({
|
||||
name: 'searchResultsContent',
|
||||
vertical: true,
|
||||
@ -629,11 +505,6 @@ var SearchResultsView = GObject.registerClass({
|
||||
|
||||
_registerProvider(provider) {
|
||||
provider.searchInProgress = false;
|
||||
|
||||
// Filter out unwanted providers.
|
||||
if (provider.appInfo && !this._parentalControlsManager.shouldShowApp(provider.appInfo))
|
||||
return;
|
||||
|
||||
this._providers.push(provider);
|
||||
this._ensureProviderDisplay(provider);
|
||||
}
|
||||
|
@ -295,8 +295,8 @@ var ShellMountPasswordDialog = GObject.registerClass({
|
||||
this._keyfilesLabel = new St.Label({ visible: false });
|
||||
this._keyfilesLabel.clutter_text.set_markup(
|
||||
/* Translators: %s is the Disks application */
|
||||
_('To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead.')
|
||||
.format(disksApp.get_name()));
|
||||
_("To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead.").format(disksApp.get_name())
|
||||
);
|
||||
this._keyfilesLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._keyfilesLabel.clutter_text.line_wrap = true;
|
||||
content.add_child(this._keyfilesLabel);
|
||||
@ -464,7 +464,8 @@ var ShellMountPasswordDialog = GObject.registerClass({
|
||||
/* Translators: %s is the Disks application */
|
||||
_("Unable to start %s").format(app.get_name()),
|
||||
/* Translators: %s is the Disks application */
|
||||
_('Couldn’t find the %s application').format(app.get_name()));
|
||||
_("Couldn’t find the %s application").format(app.get_name())
|
||||
);
|
||||
}
|
||||
this._onCancelButton();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported Indicator */
|
||||
|
||||
const { Gio, GLib, GnomeBluetooth, GObject } = imports.gi;
|
||||
const { Gio, GnomeBluetooth, GObject } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
@ -35,7 +35,7 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
|
||||
this._sync();
|
||||
});
|
||||
this._proxy.connect('g-properties-changed', this._queueSync.bind(this));
|
||||
this._proxy.connect('g-properties-changed', this._sync.bind(this));
|
||||
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
|
||||
this._item.icon.icon_name = 'bluetooth-active-symbolic';
|
||||
@ -49,27 +49,15 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
this._syncId = 0;
|
||||
this._adapter = null;
|
||||
|
||||
this._client = new GnomeBluetooth.Client();
|
||||
this._model = this._client.get_model();
|
||||
this._model.connect('row-deleted', this._queueSync.bind(this));
|
||||
this._model.connect('row-changed', this._queueSync.bind(this));
|
||||
this._model.connect('row-changed', this._sync.bind(this));
|
||||
this._model.connect('row-deleted', this._sync.bind(this));
|
||||
this._model.connect('row-inserted', this._sync.bind(this));
|
||||
Main.sessionMode.connect('updated', this._sync.bind(this));
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_setHadSetupDevices(value) {
|
||||
if (this._hadSetupDevices === value)
|
||||
return;
|
||||
|
||||
this._hadSetupDevices = value;
|
||||
global.settings.set_boolean(
|
||||
HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
|
||||
}
|
||||
|
||||
_getDefaultAdapter() {
|
||||
let [ret, iter] = this._model.get_iter_first();
|
||||
while (ret) {
|
||||
@ -84,53 +72,46 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
return null;
|
||||
}
|
||||
|
||||
_getDeviceInfos(adapter) {
|
||||
// nDevices is the number of devices setup for the current default
|
||||
// adapter if one exists and is powered. If unpowered or unavailable,
|
||||
// nDevice is "1" if it had setup devices associated to it the last
|
||||
// time it was seen, and "-1" if not.
|
||||
//
|
||||
// nConnectedDevices is the number of devices connected to the default
|
||||
// adapter if one exists and is powered, or -1 if it's not available.
|
||||
_getNDevices() {
|
||||
let adapter = this._getDefaultAdapter();
|
||||
if (!adapter)
|
||||
return [];
|
||||
return [this._hadSetupDevices ? 1 : -1, -1];
|
||||
|
||||
let deviceInfos = [];
|
||||
let nConnectedDevices = 0;
|
||||
let nDevices = 0;
|
||||
let [ret, iter] = this._model.iter_children(adapter);
|
||||
while (ret) {
|
||||
const isPaired = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.PAIRED);
|
||||
const isTrusted = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.TRUSTED);
|
||||
|
||||
if (isPaired || isTrusted) {
|
||||
deviceInfos.push({
|
||||
connected: this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.CONNECTED),
|
||||
name: this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.ALIAS),
|
||||
});
|
||||
}
|
||||
let isConnected = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.CONNECTED);
|
||||
if (isConnected)
|
||||
nConnectedDevices++;
|
||||
|
||||
let isPaired = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.PAIRED);
|
||||
let isTrusted = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.TRUSTED);
|
||||
if (isPaired || isTrusted)
|
||||
nDevices++;
|
||||
ret = this._model.iter_next(iter);
|
||||
}
|
||||
|
||||
return deviceInfos;
|
||||
}
|
||||
if (this._hadSetupDevices != (nDevices > 0)) {
|
||||
this._hadSetupDevices = !this._hadSetupDevices;
|
||||
global.settings.set_boolean(HAD_BLUETOOTH_DEVICES_SETUP, this._hadSetupDevices);
|
||||
}
|
||||
|
||||
_queueSync() {
|
||||
if (this._syncId)
|
||||
return;
|
||||
this._syncId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
|
||||
this._syncId = 0;
|
||||
this._sync();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
return [nDevices, nConnectedDevices];
|
||||
}
|
||||
|
||||
_sync() {
|
||||
let adapter = this._getDefaultAdapter();
|
||||
let devices = this._getDeviceInfos(adapter);
|
||||
const connectedDevices = devices.filter(dev => dev.connected);
|
||||
const nConnectedDevices = connectedDevices.length;
|
||||
|
||||
if (adapter && this._adapter)
|
||||
this._setHadSetupDevices(devices.length > 0);
|
||||
this._adapter = adapter;
|
||||
|
||||
let [nDevices, nConnectedDevices] = this._getNDevices();
|
||||
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
|
||||
|
||||
this.menu.setSensitive(sensitive);
|
||||
@ -138,21 +119,19 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
|
||||
// Remember if there were setup devices and show the menu
|
||||
// if we've seen setup devices and we're not hard blocked
|
||||
if (this._hadSetupDevices)
|
||||
if (nDevices > 0)
|
||||
this._item.visible = !this._proxy.BluetoothHardwareAirplaneMode;
|
||||
else
|
||||
this._item.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode;
|
||||
|
||||
if (nConnectedDevices > 1)
|
||||
if (nConnectedDevices > 0)
|
||||
/* Translators: this is the number of connected bluetooth devices */
|
||||
this._item.label.text = ngettext('%d Connected", "%d Connected', nConnectedDevices).format(nConnectedDevices);
|
||||
else if (nConnectedDevices === 1)
|
||||
this._item.label.text = connectedDevices[0].name;
|
||||
else if (adapter === null)
|
||||
this._item.label.text = _('Bluetooth Off');
|
||||
this._item.label.text = ngettext("%d Connected", "%d Connected", nConnectedDevices).format(nConnectedDevices);
|
||||
else if (nConnectedDevices == -1)
|
||||
this._item.label.text = _("Off");
|
||||
else
|
||||
this._item.label.text = _('Bluetooth On');
|
||||
this._item.label.text = _("On");
|
||||
|
||||
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _('Turn On') : _('Turn Off');
|
||||
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off");
|
||||
}
|
||||
});
|
||||
|
@ -48,9 +48,7 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
this._item.connect('key-press-event', (actor, event) => {
|
||||
return this._slider.emit('key-press-event', event);
|
||||
});
|
||||
this._item.connect('scroll-event', (actor, event) => {
|
||||
return this._slider.emit('scroll-event', event);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
_sliderChanged() {
|
||||
|
@ -199,36 +199,36 @@ var InputSourceSystemSettings = class extends InputSourceSettings {
|
||||
this._reload.bind(this));
|
||||
}
|
||||
|
||||
async _reload() {
|
||||
let props;
|
||||
try {
|
||||
const result = await Gio.DBus.system.call(
|
||||
this._BUS_NAME,
|
||||
this._BUS_PATH,
|
||||
this._BUS_PROPS_IFACE,
|
||||
'GetAll',
|
||||
new GLib.Variant('(s)', [this._BUS_IFACE]),
|
||||
null, Gio.DBusCallFlags.NONE, -1, null);
|
||||
[props] = result.deep_unpack();
|
||||
} catch (e) {
|
||||
log('Could not get properties from %s'.format(this._BUS_NAME));
|
||||
return;
|
||||
}
|
||||
_reload() {
|
||||
Gio.DBus.system.call(this._BUS_NAME,
|
||||
this._BUS_PATH,
|
||||
this._BUS_PROPS_IFACE,
|
||||
'GetAll',
|
||||
new GLib.Variant('(s)', [this._BUS_IFACE]),
|
||||
null, Gio.DBusCallFlags.NONE, -1, null,
|
||||
(conn, result) => {
|
||||
let props;
|
||||
try {
|
||||
props = conn.call_finish(result).deep_unpack()[0];
|
||||
} catch (e) {
|
||||
log('Could not get properties from %s'.format(this._BUS_NAME));
|
||||
return;
|
||||
}
|
||||
let layouts = props['X11Layout'].unpack();
|
||||
let variants = props['X11Variant'].unpack();
|
||||
let options = props['X11Options'].unpack();
|
||||
|
||||
const layouts = props['X11Layout'].unpack();
|
||||
const variants = props['X11Variant'].unpack();
|
||||
const options = props['X11Options'].unpack();
|
||||
|
||||
if (layouts !== this._layouts ||
|
||||
variants !== this._variants) {
|
||||
this._layouts = layouts;
|
||||
this._variants = variants;
|
||||
this._emitInputSourcesChanged();
|
||||
}
|
||||
if (options !== this._options) {
|
||||
this._options = options;
|
||||
this._emitKeyboardOptionsChanged();
|
||||
}
|
||||
if (layouts != this._layouts ||
|
||||
variants != this._variants) {
|
||||
this._layouts = layouts;
|
||||
this._variants = variants;
|
||||
this._emitInputSourcesChanged();
|
||||
}
|
||||
if (options != this._options) {
|
||||
this._options = options;
|
||||
this._emitKeyboardOptionsChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get inputSources() {
|
||||
@ -805,8 +805,8 @@ class InputSourceIndicatorContainer extends St.Widget {
|
||||
}, [0, 0]);
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
// translate box to (0, 0)
|
||||
box.x2 -= box.x1;
|
||||
@ -815,7 +815,7 @@ class InputSourceIndicatorContainer extends St.Widget {
|
||||
box.y1 = 0;
|
||||
|
||||
this.get_children().forEach(c => {
|
||||
c.allocate_align_fill(box, 0.5, 0.5, false, false);
|
||||
c.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -15,10 +15,6 @@ const Util = imports.misc.util;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
Gio._promisify(NM.Client, 'new_async', 'new_finish');
|
||||
Gio._promisify(NM.Client.prototype,
|
||||
'check_connectivity_async', 'check_connectivity_finish');
|
||||
|
||||
const NMConnectionCategory = {
|
||||
INVALID: 'invalid',
|
||||
WIRED: 'wired',
|
||||
@ -716,7 +712,8 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
|
||||
|
||||
let connections = client.get_connections();
|
||||
this._connections = connections.filter(
|
||||
connection => device.connection_valid(connection));
|
||||
connection => device.connection_valid(connection)
|
||||
);
|
||||
|
||||
this._apAddedId = device.connect('access-point-added', this._accessPointAdded.bind(this));
|
||||
this._apRemovedId = device.connect('access-point-removed', this._accessPointRemoved.bind(this));
|
||||
@ -1630,11 +1627,11 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
this._ctypes[NM.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NM.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
|
||||
|
||||
this._getClient();
|
||||
NM.Client.new_async(null, this._clientGot.bind(this));
|
||||
}
|
||||
|
||||
async _getClient() {
|
||||
this._client = await NM.Client.new_async(null);
|
||||
_clientGot(obj, result) {
|
||||
this._client = NM.Client.new_finish(result);
|
||||
|
||||
this._activeConnections = [];
|
||||
this._connections = [];
|
||||
@ -1862,7 +1859,8 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
_syncVpnConnections() {
|
||||
let activeConnections = this._client.get_active_connections() || [];
|
||||
let vpnConnections = activeConnections.filter(
|
||||
a => a instanceof NM.VpnConnection);
|
||||
a => a instanceof NM.VpnConnection
|
||||
);
|
||||
vpnConnections.forEach(a => {
|
||||
ensureActiveConnectionProps(a);
|
||||
});
|
||||
@ -1984,7 +1982,7 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
}
|
||||
}
|
||||
|
||||
async _portalHelperDone(proxy, emitter, parameters) {
|
||||
_portalHelperDone(proxy, emitter, parameters) {
|
||||
let [path, result] = parameters;
|
||||
|
||||
if (result == PortalHelperResult.CANCELLED) {
|
||||
@ -1995,11 +1993,13 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
} else if (result == PortalHelperResult.COMPLETED) {
|
||||
this._closeConnectivityCheck(path);
|
||||
} else if (result == PortalHelperResult.RECHECK) {
|
||||
try {
|
||||
const state = await this._client.check_connectivity_async(null);
|
||||
if (state >= NM.ConnectivityState.FULL)
|
||||
this._closeConnectivityCheck(path);
|
||||
} catch (e) { }
|
||||
this._client.check_connectivity_async(null, (client, res) => {
|
||||
try {
|
||||
let state = client.check_connectivity_finish(res);
|
||||
if (state >= NM.ConnectivityState.FULL)
|
||||
this._closeConnectivityCheck(path);
|
||||
} catch (e) { }
|
||||
});
|
||||
} else {
|
||||
log('Invalid result from portal helper: %s'.format(result));
|
||||
}
|
||||
|
@ -112,12 +112,12 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
|
||||
? '-charging' : '';
|
||||
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
|
||||
const charged =
|
||||
this._proxy.State === UPower.DeviceState.FULLY_CHARGED ||
|
||||
(this._proxy.State === UPower.DeviceState.CHARGING && fillLevel === 100);
|
||||
const icon = charged
|
||||
? 'battery-level-100-charged-symbolic'
|
||||
: 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
|
||||
let icon;
|
||||
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED ||
|
||||
fillLevel === 100)
|
||||
icon = 'battery-level-100-charged-symbolic';
|
||||
else
|
||||
icon = 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
|
||||
|
||||
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
|
||||
// default fallbacks
|
||||
@ -139,7 +139,7 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
label = _("%d\u2009%%").format(100);
|
||||
else
|
||||
label = _("%d\u2009%%").format(this._proxy.Percentage);
|
||||
this._percentageLabel.text = label;
|
||||
this._percentageLabel.clutter_text.set_markup('<span size="smaller">' + label + '</span>');
|
||||
|
||||
// The status label
|
||||
this._item.label.text = this._getStatus();
|
||||
|
@ -11,7 +11,8 @@ class RemoteAccessApplet extends PanelMenu.SystemIndicator {
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
let controller = global.backend.get_remote_access_controller();
|
||||
let backend = Meta.get_backend();
|
||||
let controller = backend.get_remote_access_controller();
|
||||
|
||||
if (!controller)
|
||||
return;
|
||||
|
@ -82,7 +82,8 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
});
|
||||
|
||||
let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
|
||||
'gnome-control-center.desktop');
|
||||
'gnome-control-center.desktop'
|
||||
);
|
||||
if (app) {
|
||||
let [icon, name] = [app.app_info.get_icon().names[0],
|
||||
app.get_name()];
|
||||
|
@ -52,21 +52,22 @@ const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
|
||||
var Client = class {
|
||||
constructor() {
|
||||
this._proxy = null;
|
||||
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
|
||||
Gio.DBusProxy.new(Gio.DBus.system,
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
|
||||
BOLT_DBUS_NAME,
|
||||
BOLT_DBUS_PATH,
|
||||
BOLT_DBUS_CLIENT_IFACE,
|
||||
null,
|
||||
this._onProxyReady.bind(this));
|
||||
|
||||
this.probing = false;
|
||||
this._getProxy();
|
||||
}
|
||||
|
||||
async _getProxy() {
|
||||
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(BoltClientInterface);
|
||||
_onProxyReady(o, res) {
|
||||
try {
|
||||
this._proxy = await Gio.DBusProxy.new(
|
||||
Gio.DBus.system,
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||
nodeInfo.lookup_interface(BOLT_DBUS_CLIENT_IFACE),
|
||||
BOLT_DBUS_NAME,
|
||||
BOLT_DBUS_PATH,
|
||||
BOLT_DBUS_CLIENT_IFACE,
|
||||
null);
|
||||
this._proxy = Gio.DBusProxy.new_finish(res);
|
||||
} catch (e) {
|
||||
log('error creating bolt proxy: %s'.format(e.message));
|
||||
return;
|
||||
@ -242,15 +243,14 @@ class Indicator extends PanelMenu.SystemIndicator {
|
||||
|
||||
this._source = null;
|
||||
this._perm = null;
|
||||
this._createPermission();
|
||||
}
|
||||
|
||||
async _createPermission() {
|
||||
try {
|
||||
this._perm = await Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null);
|
||||
} catch (e) {
|
||||
log('Failed to get PolKit permission: %s'.format(e.toString()));
|
||||
}
|
||||
Polkit.Permission.new('org.freedesktop.bolt.enroll', null, null, (source, res) => {
|
||||
try {
|
||||
this._perm = Polkit.Permission.new_finish(res);
|
||||
} catch (e) {
|
||||
log('Failed to get PolKit permission: %s'.format(e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
|
@ -56,9 +56,6 @@ var StreamSlider = class {
|
||||
this.item.connect('key-press-event', (actor, event) => {
|
||||
return this._slider.emit('key-press-event', event);
|
||||
});
|
||||
this.item.connect('scroll-event', (actor, event) => {
|
||||
return this._slider.emit('scroll-event', event);
|
||||
});
|
||||
|
||||
this._stream = null;
|
||||
this._volumeCancellable = null;
|
||||
|
@ -66,8 +66,8 @@ var SwitcherPopup = GObject.registerClass({
|
||||
this._disableHover();
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
@ -84,7 +84,7 @@ var SwitcherPopup = GObject.registerClass({
|
||||
childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
|
||||
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
|
||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||
this._switcherList.allocate(childBox);
|
||||
this._switcherList.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
_initialSelection(backward, _binding) {
|
||||
@ -317,7 +317,7 @@ var SwitcherPopup = GObject.registerClass({
|
||||
this.ease({
|
||||
opacity: 0,
|
||||
duration: POPUP_FADE_OUT_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
mode: Clutter.Animation.EASE_OUT_QUAD,
|
||||
onComplete: () => this.destroy(),
|
||||
});
|
||||
} else {
|
||||
@ -591,8 +591,8 @@ var SwitcherList = GObject.registerClass({
|
||||
return themeNode.adjust_preferred_height(maxChildMin, maxChildNat);
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
let width = contentBox.x2 - contentBox.x1;
|
||||
@ -606,7 +606,7 @@ var SwitcherList = GObject.registerClass({
|
||||
let childBox = new Clutter.ActorBox();
|
||||
let scrollable = minListWidth > width;
|
||||
|
||||
this._scrollView.allocate(contentBox);
|
||||
this._scrollView.allocate(contentBox, flags);
|
||||
|
||||
let arrowWidth = Math.floor(leftPadding / 3);
|
||||
let arrowHeight = arrowWidth * 2;
|
||||
@ -614,7 +614,7 @@ var SwitcherList = GObject.registerClass({
|
||||
childBox.y1 = this.height / 2 - arrowWidth;
|
||||
childBox.x2 = childBox.x1 + arrowWidth;
|
||||
childBox.y2 = childBox.y1 + arrowHeight;
|
||||
this._leftArrow.allocate(childBox);
|
||||
this._leftArrow.allocate(childBox, flags);
|
||||
this._leftArrow.opacity = this._scrollableLeft && scrollable ? 255 : 0;
|
||||
|
||||
arrowWidth = Math.floor(rightPadding / 3);
|
||||
@ -623,7 +623,7 @@ var SwitcherList = GObject.registerClass({
|
||||
childBox.y1 = this.height / 2 - arrowWidth;
|
||||
childBox.x2 = childBox.x1 + arrowWidth;
|
||||
childBox.y2 = childBox.y1 + arrowHeight;
|
||||
this._rightArrow.allocate(childBox);
|
||||
this._rightArrow.allocate(childBox, flags);
|
||||
this._rightArrow.opacity = this._scrollableRight && scrollable ? 255 : 0;
|
||||
}
|
||||
});
|
||||
|
228
js/ui/tweener.js
Normal file
228
js/ui/tweener.js
Normal file
@ -0,0 +1,228 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported init, addCaller, addTween, getTweenCount, removeTweens,
|
||||
pauseTweens, resumeTweens, registerSpecialProperty,
|
||||
registerSpecialPropertyModifier, registerSpecialPropertySplitter */
|
||||
|
||||
const { Clutter, GLib, Shell } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const Tweener = imports.tweener.tweener;
|
||||
|
||||
const { adjustAnimationTime } = imports.ui.environment;
|
||||
|
||||
// This is a wrapper around imports.tweener.tweener that adds a bit of
|
||||
// Clutter integration. If the tweening target is a Clutter.Actor, then
|
||||
// the tweenings will automatically be removed if the actor is destroyed.
|
||||
|
||||
// ActionScript Tweener methods that imports.tweener.tweener doesn't
|
||||
// currently implement: getTweens, getVersion, registerTransition,
|
||||
// setTimeScale, updateTime.
|
||||
|
||||
// imports.tweener.tweener methods that we don't re-export:
|
||||
// pauseAllTweens, removeAllTweens, resumeAllTweens. (It would be hard
|
||||
// to clean up properly after removeAllTweens, and also, any code that
|
||||
// calls any of these is almost certainly wrong anyway, because they
|
||||
// affect the entire application.)
|
||||
|
||||
// Called from Main.start
|
||||
function init() {
|
||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||
}
|
||||
|
||||
|
||||
function addCaller(target, tweeningParameters) {
|
||||
_wrapTweening(target, tweeningParameters);
|
||||
Tweener.addCaller(target, tweeningParameters);
|
||||
}
|
||||
|
||||
function addTween(target, tweeningParameters) {
|
||||
_wrapTweening(target, tweeningParameters);
|
||||
Tweener.addTween(target, tweeningParameters);
|
||||
}
|
||||
|
||||
function _wrapTweening(target, tweeningParameters) {
|
||||
let state = _getTweenState(target);
|
||||
|
||||
if (!state.destroyedId) {
|
||||
if (target instanceof Clutter.Actor) {
|
||||
state.actor = target;
|
||||
state.destroyedId = target.connect('destroy', _actorDestroyed);
|
||||
} else if (target.actor && target.actor instanceof Clutter.Actor) {
|
||||
state.actor = target.actor;
|
||||
state.destroyedId = target.actor.connect('destroy', () => _actorDestroyed(target));
|
||||
}
|
||||
}
|
||||
|
||||
let { time, delay } = tweeningParameters;
|
||||
if (!isNaN(time))
|
||||
tweeningParameters['time'] = adjustAnimationTime(1000 * time) / 1000;
|
||||
if (!isNaN(delay))
|
||||
tweeningParameters['delay'] = adjustAnimationTime(1000 * delay) / 1000;
|
||||
|
||||
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
|
||||
}
|
||||
|
||||
function _getTweenState(target) {
|
||||
// If we were paranoid, we could keep a plist mapping targets to
|
||||
// states... but we're not that paranoid.
|
||||
if (!target.__ShellTweenerState)
|
||||
target.__ShellTweenerState = {};
|
||||
return target.__ShellTweenerState;
|
||||
}
|
||||
|
||||
function _resetTweenState(target) {
|
||||
let state = target.__ShellTweenerState;
|
||||
|
||||
if (state) {
|
||||
if (state.destroyedId)
|
||||
state.actor.disconnect(state.destroyedId);
|
||||
}
|
||||
|
||||
target.__ShellTweenerState = {};
|
||||
}
|
||||
|
||||
function _addHandler(target, params, name, handler) {
|
||||
if (params[name]) {
|
||||
let oldHandler = params[name];
|
||||
let oldScope = params[`${name}Scope`];
|
||||
let oldParams = params[`${name}Params`];
|
||||
let eventScope = oldScope ? oldScope : target;
|
||||
|
||||
params[name] = () => {
|
||||
oldHandler.apply(eventScope, oldParams);
|
||||
handler(target);
|
||||
};
|
||||
} else {
|
||||
params[name] = () => handler(target);
|
||||
}
|
||||
}
|
||||
|
||||
function _actorDestroyed(target) {
|
||||
_resetTweenState(target);
|
||||
Tweener.removeTweens(target);
|
||||
}
|
||||
|
||||
function _tweenCompleted(target) {
|
||||
if (!isTweening(target))
|
||||
_resetTweenState(target);
|
||||
}
|
||||
|
||||
function getTweenCount(scope) {
|
||||
return Tweener.getTweenCount(scope);
|
||||
}
|
||||
|
||||
// imports.tweener.tweener doesn't provide this method (which exists
|
||||
// in the ActionScript version) but it's easy to implement.
|
||||
function isTweening(scope) {
|
||||
return Tweener.getTweenCount(scope) != 0;
|
||||
}
|
||||
|
||||
function removeTweens(...args) {
|
||||
if (Tweener.removeTweens(args)) {
|
||||
let [scope] = args;
|
||||
// If we just removed the last active tween, clean up
|
||||
if (Tweener.getTweenCount(scope) == 0)
|
||||
_tweenCompleted(scope);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function pauseTweens(...args) {
|
||||
return Tweener.pauseTweens(...args);
|
||||
}
|
||||
|
||||
function resumeTweens(...args) {
|
||||
return Tweener.resumeTweens(...args);
|
||||
}
|
||||
|
||||
|
||||
function registerSpecialProperty(...args) {
|
||||
Tweener.registerSpecialProperty(...args);
|
||||
}
|
||||
|
||||
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
|
||||
Tweener.registerSpecialPropertyModifier(name, modifyFunction, getFunction);
|
||||
}
|
||||
|
||||
function registerSpecialPropertySplitter(name, splitFunction, parameters) {
|
||||
Tweener.registerSpecialPropertySplitter(name, splitFunction, parameters);
|
||||
}
|
||||
|
||||
|
||||
// The 'FrameTicker' object is an object used to feed new frames to
|
||||
// Tweener so it can update values and redraw. The default frame
|
||||
// ticker for Tweener just uses a simple timeout at a fixed frame rate
|
||||
// and has no idea of "catching up" by dropping frames.
|
||||
//
|
||||
// We substitute it with custom frame ticker here that connects
|
||||
// Tweener to a Clutter.TimeLine. Now, Clutter.Timeline itself isn't a
|
||||
// whole lot more sophisticated than a simple timeout at a fixed frame
|
||||
// rate, but at least it knows how to drop frames. (See
|
||||
// HippoAnimationManager for a more sophisticated view of continuous
|
||||
// time updates; even better is to pay attention to the vertical
|
||||
// vblank and sync to that when possible.)
|
||||
//
|
||||
var ClutterFrameTicker = class {
|
||||
constructor() {
|
||||
// We don't have a finite duration; tweener will tell us to stop
|
||||
// when we need to stop, so use 1000 seconds as "infinity", and
|
||||
// set the timeline to loop. Doing this means we have to track
|
||||
// time ourselves, since clutter timeline's time will cycle
|
||||
// instead of strictly increase.
|
||||
this._timeline = new Clutter.Timeline({ duration: 1000 * 1000 });
|
||||
this._timeline.set_loop(true);
|
||||
this._startTime = -1;
|
||||
this._currentTime = -1;
|
||||
|
||||
this._timeline.connect('new-frame', () => {
|
||||
this._onNewFrame();
|
||||
});
|
||||
|
||||
let perfLog = Shell.PerfLog.get_default();
|
||||
perfLog.define_event("tweener.framePrepareStart",
|
||||
"Start of a new animation frame",
|
||||
"");
|
||||
perfLog.define_event("tweener.framePrepareDone",
|
||||
"Finished preparing frame",
|
||||
"");
|
||||
}
|
||||
|
||||
get FRAME_RATE() {
|
||||
return 60;
|
||||
}
|
||||
|
||||
_onNewFrame() {
|
||||
// If there is a lot of setup to start the animation, then
|
||||
// first frame number we get from clutter might be a long ways
|
||||
// into the animation (or the animation might even be done).
|
||||
// That looks bad, so we always start at the first frame of the
|
||||
// animation then only do frame dropping from there.
|
||||
if (this._startTime < 0)
|
||||
this._startTime = GLib.get_monotonic_time() / 1000.0;
|
||||
|
||||
// currentTime is in milliseconds
|
||||
let perfLog = Shell.PerfLog.get_default();
|
||||
this._currentTime = GLib.get_monotonic_time() / 1000.0 - this._startTime;
|
||||
perfLog.event("tweener.framePrepareStart");
|
||||
this.emit('prepare-frame');
|
||||
perfLog.event("tweener.framePrepareDone");
|
||||
}
|
||||
|
||||
getTime() {
|
||||
return this._currentTime;
|
||||
}
|
||||
|
||||
start() {
|
||||
this._timeline.start();
|
||||
global.begin_work();
|
||||
}
|
||||
|
||||
stop() {
|
||||
this._timeline.stop();
|
||||
this._startTime = -1;
|
||||
this._currentTime = -1;
|
||||
global.end_work();
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(ClutterFrameTicker.prototype);
|
@ -405,7 +405,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
|
||||
return this._stack.get_preferred_height(forWidth);
|
||||
}
|
||||
|
||||
vfunc_allocate(container, box) {
|
||||
vfunc_allocate(container, box, flags) {
|
||||
let [width, height] = box.get_size();
|
||||
|
||||
let tenthOfHeight = height / 10.0;
|
||||
@ -432,7 +432,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
|
||||
actorBox.x2 = columnX1 + columnWidth;
|
||||
actorBox.y2 = actorBox.y1 + maxNotificationsHeight;
|
||||
|
||||
this._notifications.allocate(actorBox);
|
||||
this._notifications.allocate(actorBox, flags);
|
||||
|
||||
// Authentication Box
|
||||
let stackY = Math.min(
|
||||
@ -444,7 +444,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
|
||||
actorBox.x2 = columnX1 + columnWidth;
|
||||
actorBox.y2 = stackY + stackHeight;
|
||||
|
||||
this._stack.allocate(actorBox);
|
||||
this._stack.allocate(actorBox, flags);
|
||||
|
||||
// Switch User button
|
||||
if (this._switchUserButton.visible) {
|
||||
@ -461,7 +461,7 @@ class UnlockDialogLayout extends Clutter.LayoutManager {
|
||||
actorBox.x2 = actorBox.x1 + natWidth;
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
this._switchUserButton.allocate(actorBox);
|
||||
this._switchUserButton.allocate(actorBox, flags);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -605,7 +605,7 @@ var UnlockDialog = GObject.registerClass({
|
||||
this._showPrompt();
|
||||
|
||||
if (GLib.unichar_isgraph(unichar))
|
||||
this._authPrompt.addCharacter(unichar);
|
||||
this.addCharacter(unichar);
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
@ -835,6 +835,11 @@ var UnlockDialog = GObject.registerClass({
|
||||
this._authPrompt.cancel();
|
||||
}
|
||||
|
||||
addCharacter(unichar) {
|
||||
this._showPrompt();
|
||||
this._authPrompt.addCharacter(unichar);
|
||||
}
|
||||
|
||||
finish(onComplete) {
|
||||
this._ensureAuthPrompt();
|
||||
this._authPrompt.finish(onComplete);
|
||||
|
@ -144,8 +144,8 @@ class UserWidgetLabel extends St.Widget {
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
@ -164,7 +164,7 @@ class UserWidgetLabel extends St.Widget {
|
||||
childBox.x2 = availWidth;
|
||||
childBox.y2 = availHeight;
|
||||
|
||||
this._currentLabel.allocate(childBox);
|
||||
this._currentLabel.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
vfunc_paint(paintContext) {
|
||||
|
@ -82,10 +82,8 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
|
||||
}
|
||||
|
||||
_formatCountDown() {
|
||||
const fmt = ngettext(
|
||||
'Settings changes will revert in %d second',
|
||||
'Settings changes will revert in %d seconds',
|
||||
this._countDown);
|
||||
let fmt = ngettext("Settings changes will revert in %d second",
|
||||
"Settings changes will revert in %d seconds");
|
||||
return fmt.format(this._countDown);
|
||||
}
|
||||
|
||||
@ -900,47 +898,35 @@ var WindowManager = class {
|
||||
|
||||
global.display.connect('init-xserver', (display, task) => {
|
||||
IBusManager.getIBusManager().restartDaemon(['--xim']);
|
||||
Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail');
|
||||
|
||||
try {
|
||||
if (!Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail'))
|
||||
log('Not starting gsd-xsettings; waiting for gnome-session to do so');
|
||||
|
||||
/* 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);
|
||||
} catch (e) {
|
||||
log('Error starting gsd-xsettings: %s'.format(e.message));
|
||||
/* 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', () => {
|
||||
if (!Meta.is_wayland_compositor())
|
||||
return;
|
||||
try {
|
||||
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
|
||||
} catch (e) {
|
||||
log('Error stopping gsd-xsettings: %s'.format(e.message));
|
||||
}
|
||||
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
|
||||
IBusManager.getIBusManager().restartDaemon();
|
||||
});
|
||||
|
||||
|
@ -51,22 +51,35 @@ class WindowCloneLayout extends Clutter.LayoutManager {
|
||||
this.layout_changed();
|
||||
}
|
||||
|
||||
_makeBoxForWindow(window) {
|
||||
// We need to adjust the position of the actor because of the
|
||||
// consequences of invisible borders -- in reality, the texture
|
||||
// has an extra set of "padding" around it that we need to trim
|
||||
// down.
|
||||
|
||||
// The bounding box is based on the (visible) frame rect, while
|
||||
// the buffer rect contains everything, including the invisible
|
||||
// border padding.
|
||||
let bufferRect = window.get_buffer_rect();
|
||||
|
||||
let box = new Clutter.ActorBox();
|
||||
|
||||
box.set_origin(bufferRect.x - this._boundingBox.x,
|
||||
bufferRect.y - this._boundingBox.y);
|
||||
box.set_size(bufferRect.width, bufferRect.height);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(_container, _forWidth) {
|
||||
return [0, this._boundingBox.height];
|
||||
return [this._boundingBox.height, this._boundingBox.height];
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(_container, _forHeight) {
|
||||
return [0, this._boundingBox.width];
|
||||
return [this._boundingBox.width, this._boundingBox.width];
|
||||
}
|
||||
|
||||
vfunc_allocate(container, box) {
|
||||
// If the scale isn't 1, we weren't allocated our preferred size
|
||||
// and have to scale the children allocations accordingly.
|
||||
const scaleX = box.get_width() / this._boundingBox.width;
|
||||
const scaleY = box.get_height() / this._boundingBox.height;
|
||||
|
||||
const childBox = new Clutter.ActorBox();
|
||||
|
||||
vfunc_allocate(container, box, flags) {
|
||||
container.get_children().forEach(child => {
|
||||
let realWindow;
|
||||
if (child == container._windowClone)
|
||||
@ -74,20 +87,8 @@ class WindowCloneLayout extends Clutter.LayoutManager {
|
||||
else
|
||||
realWindow = child.source;
|
||||
|
||||
const bufferRect = realWindow.meta_window.get_buffer_rect();
|
||||
childBox.set_origin(
|
||||
bufferRect.x - this._boundingBox.x,
|
||||
bufferRect.y - this._boundingBox.y);
|
||||
|
||||
const [, , natWidth, natHeight] = child.get_preferred_size();
|
||||
childBox.set_size(natWidth, natHeight);
|
||||
|
||||
childBox.x1 *= scaleX;
|
||||
childBox.x2 *= scaleX;
|
||||
childBox.y1 *= scaleY;
|
||||
childBox.y2 *= scaleY;
|
||||
|
||||
child.allocate(childBox);
|
||||
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
|
||||
flags);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -154,8 +155,7 @@ var WindowClone = GObject.registerClass({
|
||||
|
||||
this._updateAttachedDialogs();
|
||||
this._computeBoundingBox();
|
||||
this.x = this._boundingBox.x;
|
||||
this.y = this._boundingBox.y;
|
||||
this.set_translation(this._boundingBox.x, this._boundingBox.y, 0);
|
||||
|
||||
this._computeWindowCenter();
|
||||
|
||||
@ -240,9 +240,6 @@ var WindowClone = GObject.registerClass({
|
||||
|
||||
this._onMetaWindowSizeChanged();
|
||||
});
|
||||
|
||||
Shell.util_set_hidden_from_pick(clone, true);
|
||||
|
||||
this.add_child(clone);
|
||||
}
|
||||
|
||||
@ -266,6 +263,18 @@ var WindowClone = GObject.registerClass({
|
||||
return this._boundingBox;
|
||||
}
|
||||
|
||||
get width() {
|
||||
return this._boundingBox.width;
|
||||
}
|
||||
|
||||
get height() {
|
||||
return this._boundingBox.height;
|
||||
}
|
||||
|
||||
getOriginalPosition() {
|
||||
return [this._boundingBox.x, this._boundingBox.y];
|
||||
}
|
||||
|
||||
_computeBoundingBox() {
|
||||
let rect = this.metaWindow.get_frame_rect();
|
||||
|
||||
@ -859,7 +868,7 @@ var LayoutStrategy = class {
|
||||
// thumbnails is much more important to preserve than the width of
|
||||
// them, so two windows with equal height, but maybe differering
|
||||
// widths line up.
|
||||
let ratio = window.boundingBox.height / this._monitor.height;
|
||||
let ratio = window.height / this._monitor.height;
|
||||
|
||||
// The purpose of this manipulation here is to prevent windows
|
||||
// from getting too small. For something like a calculator window,
|
||||
@ -979,12 +988,11 @@ var LayoutStrategy = class {
|
||||
let window = row.windows[j];
|
||||
|
||||
let s = scale * this._computeWindowScale(window) * row.additionalScale;
|
||||
let cellWidth = window.boundingBox.width * s;
|
||||
let cellHeight = window.boundingBox.height * s;
|
||||
let cellWidth = window.width * s;
|
||||
let cellHeight = window.height * s;
|
||||
|
||||
s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
|
||||
let cloneWidth = window.boundingBox.width * s;
|
||||
const cloneHeight = window.boundingBox.height * s;
|
||||
let cloneWidth = window.width * s;
|
||||
|
||||
let cloneX = x + (cellWidth - cloneWidth) / 2;
|
||||
let cloneY = row.y + row.height * row.additionalScale - cellHeight + compensation;
|
||||
@ -993,7 +1001,7 @@ var LayoutStrategy = class {
|
||||
cloneX = Math.floor(cloneX);
|
||||
cloneY = Math.floor(cloneY);
|
||||
|
||||
slots.push([cloneX, cloneY, cloneWidth, cloneHeight, window]);
|
||||
slots.push([cloneX, cloneY, s, window]);
|
||||
x += cellWidth + this._columnSpacing;
|
||||
}
|
||||
}
|
||||
@ -1038,7 +1046,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let window = windows[i];
|
||||
let s = this._computeWindowScale(window);
|
||||
totalWidth += window.boundingBox.width * s;
|
||||
totalWidth += window.width * s;
|
||||
}
|
||||
|
||||
let idealRowWidth = totalWidth / numRows;
|
||||
@ -1056,8 +1064,8 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
||||
for (; windowIdx < sortedWindows.length; windowIdx++) {
|
||||
let window = sortedWindows[windowIdx];
|
||||
let s = this._computeWindowScale(window);
|
||||
let width = window.boundingBox.width * s;
|
||||
let height = window.boundingBox.height * s;
|
||||
let width = window.width * s;
|
||||
let height = window.height * s;
|
||||
row.fullHeight = Math.max(row.fullHeight, height);
|
||||
|
||||
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
|
||||
@ -1332,7 +1340,7 @@ class Workspace extends St.Widget {
|
||||
|
||||
for (let i = 0; i < slots.length; i++) {
|
||||
let slot = slots[i];
|
||||
const [x, y, cellWidth, cellHeight, clone] = slot;
|
||||
let [x, y, scale, clone] = slot;
|
||||
|
||||
clone.slotId = i;
|
||||
|
||||
@ -1341,8 +1349,8 @@ class Workspace extends St.Widget {
|
||||
if (clone.inDrag)
|
||||
continue;
|
||||
|
||||
const cloneWidth = cellWidth;
|
||||
const cloneHeight = cellHeight;
|
||||
let cloneWidth = clone.width * scale;
|
||||
let cloneHeight = clone.height * scale;
|
||||
clone.slot = [x, y, cloneWidth, cloneHeight];
|
||||
|
||||
let cloneCenter = x + cloneWidth / 2;
|
||||
@ -1357,10 +1365,10 @@ class Workspace extends St.Widget {
|
||||
if (!clone.positioned) {
|
||||
// This window appeared after the overview was already up
|
||||
// Grow the clone from the center of the slot
|
||||
clone.x = x + cloneWidth / 2;
|
||||
clone.y = y + cloneHeight / 2;
|
||||
clone.width = 0;
|
||||
clone.height = 0;
|
||||
clone.translation_x = x + cloneWidth / 2;
|
||||
clone.translation_y = y + cloneHeight / 2;
|
||||
clone.scale_x = 0;
|
||||
clone.scale_y = 0;
|
||||
clone.positioned = true;
|
||||
}
|
||||
|
||||
@ -1371,10 +1379,10 @@ class Workspace extends St.Widget {
|
||||
* can be scaled up later */
|
||||
if (initialPositioning) {
|
||||
clone.opacity = 0;
|
||||
clone.x = x;
|
||||
clone.y = y;
|
||||
clone.width = cloneWidth;
|
||||
clone.height = cloneHeight;
|
||||
clone.scale_x = 0;
|
||||
clone.scale_y = 0;
|
||||
clone.translation_x = x;
|
||||
clone.translation_y = y;
|
||||
}
|
||||
|
||||
clone.ease({
|
||||
@ -1384,12 +1392,12 @@ class Workspace extends St.Widget {
|
||||
});
|
||||
}
|
||||
|
||||
this._animateClone(clone, clone.overlay, x, y, cloneWidth, cloneHeight);
|
||||
this._animateClone(clone, clone.overlay, x, y, scale);
|
||||
} else {
|
||||
// cancel any active tweens (otherwise they might override our changes)
|
||||
clone.remove_all_transitions();
|
||||
clone.set_position(x, y);
|
||||
clone.set_size(cloneWidth, cloneHeight);
|
||||
clone.set_translation(x, y, 0);
|
||||
clone.set_scale(scale, scale);
|
||||
clone.set_opacity(255);
|
||||
clone.overlay.relayout(false);
|
||||
this._showWindowOverlay(clone, clone.overlay);
|
||||
@ -1416,10 +1424,12 @@ class Workspace extends St.Widget {
|
||||
}
|
||||
}
|
||||
|
||||
_animateClone(clone, overlay, x, y, width, height) {
|
||||
_animateClone(clone, overlay, x, y, scale) {
|
||||
clone.ease({
|
||||
x, y,
|
||||
width, height,
|
||||
translation_x: x,
|
||||
translation_y: y,
|
||||
scale_x: scale,
|
||||
scale_y: scale,
|
||||
duration: Overview.ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
onComplete: () => {
|
||||
@ -1476,14 +1486,11 @@ class Workspace extends St.Widget {
|
||||
// this point.)
|
||||
if (win) {
|
||||
let [stageX, stageY] = clone.get_transformed_position();
|
||||
const [transformedWidth, transformedHeight] =
|
||||
clone.get_transformed_size();
|
||||
|
||||
let [stageWidth] = clone.get_transformed_size();
|
||||
win._overviewHint = {
|
||||
x: stageX,
|
||||
y: stageY,
|
||||
width: transformedWidth,
|
||||
height: transformedHeight,
|
||||
scale: stageWidth / clone.width,
|
||||
};
|
||||
}
|
||||
clone.destroy();
|
||||
@ -1559,15 +1566,14 @@ class Workspace extends St.Widget {
|
||||
if (win._overviewHint) {
|
||||
let x = win._overviewHint.x - this.x;
|
||||
let y = win._overviewHint.y - this.y;
|
||||
const width = win._overviewHint.width;
|
||||
const height = win._overviewHint.height;
|
||||
let scale = win._overviewHint.scale;
|
||||
delete win._overviewHint;
|
||||
|
||||
clone.slot = [x, y, width, height];
|
||||
clone.slot = [x, y, clone.width * scale, clone.height * scale];
|
||||
clone.positioned = true;
|
||||
|
||||
clone.set_position(x, y);
|
||||
clone.set_size(width, height);
|
||||
clone.set_translation(x, y, 0);
|
||||
clone.set_scale(scale, scale);
|
||||
clone.overlay.relayout(false);
|
||||
}
|
||||
|
||||
@ -1718,10 +1724,11 @@ class Workspace extends St.Widget {
|
||||
overlay.hide();
|
||||
|
||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||
clone.x = clone.boundingBox.x;
|
||||
clone.y = clone.boundingBox.y;
|
||||
clone.width = clone.boundingBox.width;
|
||||
clone.height = clone.boundingBox.height;
|
||||
let [origX, origY] = clone.getOriginalPosition();
|
||||
clone.scale_x = 1;
|
||||
clone.scale_y = 1;
|
||||
clone.translation_x = origX;
|
||||
clone.translation_y = origY;
|
||||
clone.ease({
|
||||
opacity,
|
||||
duration,
|
||||
@ -1769,11 +1776,12 @@ class Workspace extends St.Widget {
|
||||
overlay.hide();
|
||||
|
||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||
let [origX, origY] = clone.getOriginalPosition();
|
||||
clone.ease({
|
||||
x: clone.boundingBox.x,
|
||||
y: clone.boundingBox.y,
|
||||
width: clone.boundingBox.width,
|
||||
height: clone.boundingBox.height,
|
||||
translation_x: origX,
|
||||
translation_y: origY,
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
opacity: 255,
|
||||
duration: Overview.ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
@ -1781,8 +1789,8 @@ class Workspace extends St.Widget {
|
||||
} else {
|
||||
// The window is hidden, make it shrink and fade it out
|
||||
clone.ease({
|
||||
width: 0,
|
||||
height: 0,
|
||||
scale_x: 0,
|
||||
scale_y: 0,
|
||||
opacity: 0,
|
||||
duration: Overview.ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
@ -2027,8 +2035,7 @@ class Workspace extends St.Widget {
|
||||
win._overviewHint = {
|
||||
x: actor.x,
|
||||
y: actor.y,
|
||||
width: actor.width,
|
||||
heigth: actor.height,
|
||||
scale: actor.scale_x,
|
||||
};
|
||||
|
||||
let metaWindow = win.get_meta_window();
|
||||
|
@ -86,8 +86,8 @@ class WorkspaceSwitcherPopupList extends St.Widget {
|
||||
return this._getSizeForOppositeOrientation();
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
box = themeNode.get_content_box(box);
|
||||
@ -111,7 +111,7 @@ class WorkspaceSwitcherPopupList extends St.Widget {
|
||||
} else {
|
||||
y += this._childHeight + this._itemSpacing;
|
||||
}
|
||||
child.allocate(childBox);
|
||||
child.allocate(childBox, flags);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1204,8 +1204,8 @@ var ThumbnailsBox = GObject.registerClass({
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
vfunc_allocate(box) {
|
||||
this.set_allocation(box);
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
|
||||
|
||||
@ -1299,7 +1299,7 @@ var ThumbnailsBox = GObject.registerClass({
|
||||
childBox.x2 = x2;
|
||||
childBox.y1 = Math.round(y);
|
||||
childBox.y2 = Math.round(y + placeholderHeight);
|
||||
this._dropPlaceholder.allocate(childBox);
|
||||
this._dropPlaceholder.allocate(childBox, flags);
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.show();
|
||||
});
|
||||
@ -1331,7 +1331,7 @@ var ThumbnailsBox = GObject.registerClass({
|
||||
childBox.y2 = y1 + portholeHeight;
|
||||
|
||||
thumbnail.set_scale(roundedHScale, roundedVScale);
|
||||
thumbnail.allocate(childBox);
|
||||
thumbnail.allocate(childBox, flags);
|
||||
|
||||
// We round the collapsing portion so that we don't get thumbnails resizing
|
||||
// during an animation due to differences in rounded, but leave the uncollapsed
|
||||
@ -1355,6 +1355,6 @@ var ThumbnailsBox = GObject.registerClass({
|
||||
childBox.x2 += indicatorRightFullBorder;
|
||||
childBox.y1 = indicatorY1 - indicatorTopFullBorder;
|
||||
childBox.y2 = indicatorY2 + indicatorBottomFullBorder;
|
||||
this._indicator.allocate(childBox);
|
||||
this._indicator.allocate(childBox, flags);
|
||||
}
|
||||
});
|
||||
|
@ -8,7 +8,6 @@ const SwipeTracker = imports.ui.swipeTracker;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
var WORKSPACE_SWITCH_TIME = 250;
|
||||
var SCROLL_TIMEOUT_TIME = 150;
|
||||
|
||||
var AnimationType = {
|
||||
ZOOM: 0,
|
||||
@ -816,11 +815,12 @@ class WorkspacesDisplay extends St.Widget {
|
||||
|
||||
this._canScroll = false;
|
||||
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
|
||||
SCROLL_TIMEOUT_TIME, () => {
|
||||
WORKSPACE_SWITCH_TIME, () => {
|
||||
this._canScroll = true;
|
||||
this._scrollTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Clutter } = imports.gi;
|
||||
const { Clutter, Meta } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
@ -17,7 +17,7 @@ var XdndHandler = class {
|
||||
Main.uiGroup.add_actor(this._dummy);
|
||||
this._dummy.hide();
|
||||
|
||||
var dnd = global.backend.get_dnd();
|
||||
var dnd = Meta.get_backend().get_dnd();
|
||||
dnd.connect('dnd-enter', this._onEnter.bind(this));
|
||||
dnd.connect('dnd-position-change', this._onPositionChanged.bind(this));
|
||||
dnd.connect('dnd-leave', this._onLeave.bind(this));
|
||||
|
@ -218,12 +218,12 @@ globals:
|
||||
ARGV: readonly
|
||||
Debugger: readonly
|
||||
GIRepositoryGType: readonly
|
||||
globalThis: readonly
|
||||
imports: readonly
|
||||
Intl: readonly
|
||||
log: readonly
|
||||
logError: readonly
|
||||
print: readonly
|
||||
printerr: readonly
|
||||
window: readonly
|
||||
parserOptions:
|
||||
ecmaVersion: 2019
|
||||
|
32
meson.build
32
meson.build
@ -1,6 +1,6 @@
|
||||
project('gnome-shell', 'c',
|
||||
version: '3.37.2',
|
||||
meson_version: '>= 0.53.0',
|
||||
version: '3.36.1',
|
||||
meson_version: '>= 0.47.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
||||
@ -19,13 +19,13 @@ cogl_pango_pc = 'mutter-cogl-pango-' + mutter_api_version
|
||||
libmutter_pc = 'libmutter-' + mutter_api_version
|
||||
|
||||
ecal_req = '>= 3.33.1'
|
||||
eds_req = '>= 3.33.1'
|
||||
eds_req = '>= 3.17.2'
|
||||
gcr_req = '>= 3.7.5'
|
||||
gio_req = '>= 2.56.0'
|
||||
gi_req = '>= 1.49.1'
|
||||
gjs_req = '>= 1.65.1'
|
||||
gjs_req = '>= 1.63.2'
|
||||
gtk_req = '>= 3.15.0'
|
||||
mutter_req = '>= 3.37.2'
|
||||
mutter_req = '>= 3.36.0'
|
||||
polkit_req = '>= 0.100'
|
||||
schemas_req = '>= 3.33.1'
|
||||
startup_req = '>= 0.11'
|
||||
@ -63,9 +63,16 @@ portaldir = join_paths(datadir, 'xdg-desktop-portal', 'portals')
|
||||
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
|
||||
servicedir = join_paths(datadir, 'dbus-1', 'services')
|
||||
|
||||
# XXX: Once https://github.com/systemd/systemd/issues/9595 is fixed and we can
|
||||
# depend on this version, replace with something like:
|
||||
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
|
||||
# define_variable: ['prefix', prefix])
|
||||
# and uncomment systemd_dep below
|
||||
systemduserunitdir = join_paths(prefix, 'lib', 'systemd', 'user')
|
||||
|
||||
keybindings_dep = dependency('gnome-keybindings', required: false)
|
||||
if keybindings_dep.found()
|
||||
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir', define_variable: ['datadir', datadir])
|
||||
keysdir = keybindings_dep.get_pkgconfig_variable('keysdir')
|
||||
else
|
||||
keysdir = join_paths(datadir, 'gnome-control-center', 'keybindings')
|
||||
endif
|
||||
@ -115,9 +122,8 @@ endif
|
||||
|
||||
if get_option('systemd')
|
||||
libsystemd_dep = dependency('libsystemd')
|
||||
systemd_dep = dependency('systemd')
|
||||
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
|
||||
define_variable: ['prefix', prefix])
|
||||
# XXX: see systemduserunitdir
|
||||
# systemd_dep = dependency('systemd')
|
||||
have_systemd = true
|
||||
else
|
||||
libsystemd_dep = []
|
||||
@ -315,6 +321,8 @@ if get_option('man')
|
||||
summary_dirs += { 'mandir': get_option('mandir') }
|
||||
endif
|
||||
|
||||
summary(summary_dirs, section: 'Directories')
|
||||
summary(summary_build, section: 'Build Configuration')
|
||||
summary(summary_options, section: 'Build Options')
|
||||
if meson.version().version_compare('>= 0.53.0')
|
||||
summary(summary_dirs, section: 'Directories')
|
||||
summary(summary_build, section: 'Build Configuration')
|
||||
summary(summary_options, section: 'Build Options')
|
||||
endif
|
||||
|
@ -56,7 +56,6 @@ nl
|
||||
nn
|
||||
oc
|
||||
or
|
||||
os
|
||||
pa
|
||||
pl
|
||||
pt
|
||||
|
@ -94,7 +94,5 @@ subprojects/extensions-tool/src/command-prefs.c
|
||||
subprojects/extensions-tool/src/command-reset.c
|
||||
subprojects/extensions-tool/src/command-uninstall.c
|
||||
subprojects/extensions-tool/src/main.c
|
||||
subprojects/extensions-tool/src/templates/00-plain.desktop.in
|
||||
subprojects/extensions-tool/src/templates/indicator.desktop.in
|
||||
# Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it.
|
||||
subprojects/gvc/gvc-mixer-control.c
|
||||
|
@ -1 +0,0 @@
|
||||
subprojects/extensions-tool/src/templates/indicator/extension.js
|
439
po/de.po
439
po/de.po
@ -22,9 +22,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
|
||||
"POT-Creation-Date: 2020-05-15 03:04+0000\n"
|
||||
"PO-Revision-Date: 2020-05-24 00:19+0200\n"
|
||||
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
|
||||
"POT-Creation-Date: 2020-03-19 14:34+0000\n"
|
||||
"PO-Revision-Date: 2020-03-20 06:42+0100\n"
|
||||
"Last-Translator: Wolfgang Stoeggl <c72578@yahoo.de>\n"
|
||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -409,12 +409,68 @@ msgstr ""
|
||||
msgid "Network Login"
|
||||
msgstr "Netzwerkanmeldung"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:224
|
||||
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
|
||||
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:4
|
||||
#: js/extensionPrefs/js/main.js:242
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:61
|
||||
msgid "Extensions"
|
||||
msgstr "Erweiterungen"
|
||||
|
||||
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
|
||||
#: js/extensionPrefs/js/main.js:243
|
||||
msgid "Manage your GNOME Extensions"
|
||||
msgstr "Ihre GNOME-Erweiterungen verwalten"
|
||||
|
||||
#: js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
|
||||
msgid ""
|
||||
"GNOME Extensions handles updating extensions, configuring extension "
|
||||
"preferences and removing or disabling unwanted extensions."
|
||||
msgstr ""
|
||||
"GNOME-Erweiterungen dient der Aktualisierung von Erweiterungen, dem "
|
||||
"Konfigurieren der Voreinstellungen von Erweiterungen und dem Entfernen oder "
|
||||
"Deaktivieren nicht gewünschter Erweiterungen."
|
||||
|
||||
#: js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in:7
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "GNOME-Shell-Erweiterungen einrichten"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:164
|
||||
#, javascript-format
|
||||
msgid "Remove “%s”?"
|
||||
msgstr "»%s« entfernen?"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:165
|
||||
msgid ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
msgstr ""
|
||||
"Wenn Sie die Erweiterung entfernen, müssen Sie sie erneut herunterladen, um "
|
||||
"sie wieder zu aktivieren"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:168 js/gdm/authPrompt.js:135
|
||||
#: js/ui/audioDeviceSelection.js:57 js/ui/components/networkAgent.js:109
|
||||
#: js/ui/components/polkitAgent.js:139 js/ui/endSessionDialog.js:374
|
||||
#: js/ui/extensionDownloader.js:177 js/ui/shellMountOperation.js:376
|
||||
#: js/ui/shellMountOperation.js:386 js/ui/status/network.js:913
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:169
|
||||
msgid "Remove"
|
||||
msgstr "Entfernen"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:241
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
"Tim Sabsch <tim@sabsch.com>\n"
|
||||
"Christian Kirbach <christian.kirbach@gmail.com>, 2020"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:285
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:223
|
||||
msgid "Something’s gone wrong"
|
||||
msgstr "Etwas ist schiefgelaufen"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
|
||||
#: js/extensionPrefs/js/main.js:292
|
||||
msgid ""
|
||||
"We’re very sorry, but there’s been a problem: the settings for this "
|
||||
"extension can’t be displayed. We recommend that you report the issue to the "
|
||||
@ -424,25 +480,106 @@ msgstr ""
|
||||
"Erweiterung können nicht angezeigt werden. Wir empfehlen, dass Sie diesen "
|
||||
"Fehler den Autoren der Erweiterung melden."
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
|
||||
#: js/extensionPrefs/js/main.js:299
|
||||
msgid "Technical Details"
|
||||
msgstr "Technische Details"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
|
||||
#: js/extensionPrefs/js/main.js:334
|
||||
msgid "Copy Error"
|
||||
msgstr "Kopierfehler"
|
||||
|
||||
#: js/extensionPrefs/js/main.js:361
|
||||
msgid "Homepage"
|
||||
msgstr "Homepage"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
|
||||
#: js/extensionPrefs/js/main.js:362
|
||||
msgid "Visit extension homepage"
|
||||
msgstr "Internetseite der Erweiterung besuchen"
|
||||
|
||||
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
|
||||
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
|
||||
#: js/ui/endSessionDialog.js:372 js/ui/extensionDownloader.js:181
|
||||
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
|
||||
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
#: js/extensionPrefs/js/main.js:479
|
||||
#, javascript-format
|
||||
msgid "%d extension will be updated on next login."
|
||||
msgid_plural "%d extensions will be updated on next login."
|
||||
msgstr[0] "%d Erweiterung wird bei der nächsten Anmeldung aktualisiert."
|
||||
msgstr[1] "%d Erweiterungen werden bei der nächsten Anmeldung aktualisiert."
|
||||
|
||||
#: js/extensionPrefs/data/ui/extension-row.ui:100
|
||||
#: subprojects/extensions-tool/src/command-create.c:211
|
||||
#: subprojects/extensions-tool/src/main.c:173
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extension-row.ui:123
|
||||
#: subprojects/extensions-tool/src/main.c:185
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extension-row.ui:151
|
||||
msgid "Author"
|
||||
msgstr "Autor"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extension-row.ui:175
|
||||
msgid "Website"
|
||||
msgstr "Webseite"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extension-row.ui:192
|
||||
msgid "Remove…"
|
||||
msgstr "Entfernen …"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:8
|
||||
msgid "Help"
|
||||
msgstr "Hilfe"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:12
|
||||
msgid "About Extensions"
|
||||
msgstr "Info zu Erweiterungen"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:27
|
||||
msgid ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
msgstr ""
|
||||
"Besuchen Sie <a href=\"https://extensions.gnome.org\">extensions.gnome.org</"
|
||||
"a>, um Erweiterungen zu finden und hinzuzufügen."
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:35
|
||||
msgid "Warning"
|
||||
msgstr "Warnung"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:46
|
||||
msgid ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
msgstr ""
|
||||
"Erweiterungen können Probleme am System verursachen, darunter auch "
|
||||
"Leistungsprobleme. Sollten Sie auf Probleme mit Ihrem System stoßen, wird "
|
||||
"die Deaktivierung aller Erweiterungen empfohlen."
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:134
|
||||
msgid "Manually Installed"
|
||||
msgstr "Manuell installiert"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:158
|
||||
msgid "Built-In"
|
||||
msgstr "Mitgeliefert"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:199
|
||||
msgid "No Installed Extensions"
|
||||
msgstr "Keine installierten Erweiterungen"
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:235
|
||||
msgid ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
msgstr ""
|
||||
"Tut uns sehr leid, wir konnten keine Liste der installierten Erweiterungen "
|
||||
"aufstellen. Stellen Sie sicher, dass Sie in GNOME angemeldet sind und "
|
||||
"versuchen Sie es dann erneut."
|
||||
|
||||
#: js/extensionPrefs/data/ui/extensions-window.ui:288
|
||||
msgid "Log Out…"
|
||||
msgstr "Abmelden …"
|
||||
|
||||
#. Cisco LEAP
|
||||
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
|
||||
@ -494,71 +631,71 @@ msgid "(or swipe finger)"
|
||||
msgstr "(oder wischen Sie mit einem Finger)"
|
||||
|
||||
#. Translators: The name of the power-off action in search
|
||||
#: js/misc/systemActions.js:93
|
||||
#: js/misc/systemActions.js:89
|
||||
msgctxt "search-result"
|
||||
msgid "Power Off"
|
||||
msgstr "Ausschalten"
|
||||
|
||||
#. Translators: A list of keywords that match the power-off action, separated by semicolons
|
||||
#: js/misc/systemActions.js:96
|
||||
#: js/misc/systemActions.js:92
|
||||
msgid "power off;shutdown;reboot;restart;halt;stop"
|
||||
msgstr "ausschalten;herunterfahren;neustarten;halten;stoppen"
|
||||
|
||||
#. Translators: The name of the lock screen action in search
|
||||
#: js/misc/systemActions.js:101
|
||||
#: js/misc/systemActions.js:97
|
||||
msgctxt "search-result"
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bildschirm sperren"
|
||||
|
||||
#. Translators: A list of keywords that match the lock screen action, separated by semicolons
|
||||
#: js/misc/systemActions.js:104
|
||||
#: js/misc/systemActions.js:100
|
||||
msgid "lock screen"
|
||||
msgstr "Bildschirm sperren"
|
||||
|
||||
#. Translators: The name of the logout action in search
|
||||
#: js/misc/systemActions.js:109
|
||||
#: js/misc/systemActions.js:105
|
||||
msgctxt "search-result"
|
||||
msgid "Log Out"
|
||||
msgstr "Abmelden"
|
||||
|
||||
#. Translators: A list of keywords that match the logout action, separated by semicolons
|
||||
#: js/misc/systemActions.js:112
|
||||
#: js/misc/systemActions.js:108
|
||||
msgid "logout;log out;sign off"
|
||||
msgstr "abmelden;verlassen"
|
||||
|
||||
#. Translators: The name of the suspend action in search
|
||||
#: js/misc/systemActions.js:117
|
||||
#: js/misc/systemActions.js:113
|
||||
msgctxt "search-result"
|
||||
msgid "Suspend"
|
||||
msgstr "Bereitschaft"
|
||||
|
||||
#. Translators: A list of keywords that match the suspend action, separated by semicolons
|
||||
#: js/misc/systemActions.js:120
|
||||
#: js/misc/systemActions.js:116
|
||||
msgid "suspend;sleep"
|
||||
msgstr "Bereitschaft;Schlafen"
|
||||
|
||||
#. Translators: The name of the switch user action in search
|
||||
#: js/misc/systemActions.js:125
|
||||
#: js/misc/systemActions.js:121
|
||||
msgctxt "search-result"
|
||||
msgid "Switch User"
|
||||
msgstr "Benutzer wechseln"
|
||||
|
||||
#. Translators: A list of keywords that match the switch user action, separated by semicolons
|
||||
#: js/misc/systemActions.js:128
|
||||
#: js/misc/systemActions.js:124
|
||||
msgid "switch user"
|
||||
msgstr "Benutzer wechseln"
|
||||
|
||||
#. Translators: A list of keywords that match the lock orientation action, separated by semicolons
|
||||
#: js/misc/systemActions.js:135
|
||||
#: js/misc/systemActions.js:131
|
||||
msgid "lock orientation;unlock orientation;screen;rotation"
|
||||
msgstr "Hochformat;Querformat;sperren;entsperren;Bildschirm;Drehung;drehen"
|
||||
|
||||
#: js/misc/systemActions.js:255
|
||||
#: js/misc/systemActions.js:251
|
||||
msgctxt "search-result"
|
||||
msgid "Unlock Screen Rotation"
|
||||
msgstr "Bildschirmdrehung entsperren"
|
||||
|
||||
#: js/misc/systemActions.js:256
|
||||
#: js/misc/systemActions.js:252
|
||||
msgctxt "search-result"
|
||||
msgid "Lock Screen Rotation"
|
||||
msgstr "Bildschirmdrehung sperren"
|
||||
@ -724,54 +861,54 @@ msgstr "Zugriff verhindern"
|
||||
msgid "Grant Access"
|
||||
msgstr "Zugriff gewähren"
|
||||
|
||||
#: js/ui/appDisplay.js:939
|
||||
#: js/ui/appDisplay.js:898
|
||||
msgid "Unnamed Folder"
|
||||
msgstr "Unbenannter Ordner"
|
||||
|
||||
#: js/ui/appDisplay.js:962
|
||||
#: js/ui/appDisplay.js:921
|
||||
msgid "Frequently used applications will appear here"
|
||||
msgstr "Häufig genutzte Anwendungen erscheinen hier"
|
||||
|
||||
#: js/ui/appDisplay.js:1097
|
||||
#: js/ui/appDisplay.js:1056
|
||||
msgid "Frequent"
|
||||
msgstr "Häufig"
|
||||
|
||||
#: js/ui/appDisplay.js:1104
|
||||
#: js/ui/appDisplay.js:1063
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
# Fensterüberschrift
|
||||
#. Translators: This is the heading of a list of open windows
|
||||
#: js/ui/appDisplay.js:2480 js/ui/panel.js:75
|
||||
#: js/ui/appDisplay.js:2446 js/ui/panel.js:75
|
||||
msgid "Open Windows"
|
||||
msgstr "Offene Fenster"
|
||||
|
||||
#: js/ui/appDisplay.js:2500 js/ui/panel.js:82
|
||||
#: js/ui/appDisplay.js:2466 js/ui/panel.js:82
|
||||
msgid "New Window"
|
||||
msgstr "Neues Fenster"
|
||||
|
||||
#: js/ui/appDisplay.js:2511
|
||||
#: js/ui/appDisplay.js:2477
|
||||
msgid "Launch using Dedicated Graphics Card"
|
||||
msgstr "Mit dedizierter Grafikkarte starten"
|
||||
|
||||
#: js/ui/appDisplay.js:2539 js/ui/dash.js:239
|
||||
#: js/ui/appDisplay.js:2505 js/ui/dash.js:239
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Aus Favoriten entfernen"
|
||||
|
||||
#: js/ui/appDisplay.js:2545
|
||||
#: js/ui/appDisplay.js:2511
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Zu Favoriten hinzufügen"
|
||||
|
||||
#: js/ui/appDisplay.js:2555 js/ui/panel.js:93
|
||||
#: js/ui/appDisplay.js:2521 js/ui/panel.js:93
|
||||
msgid "Show Details"
|
||||
msgstr "Details anzeigen"
|
||||
|
||||
#: js/ui/appFavorites.js:153
|
||||
#: js/ui/appFavorites.js:152
|
||||
#, javascript-format
|
||||
msgid "%s has been added to your favorites."
|
||||
msgstr "%s wurde zu Ihren Favoriten hinzugefügt."
|
||||
|
||||
#: js/ui/appFavorites.js:186
|
||||
#: js/ui/appFavorites.js:185
|
||||
#, javascript-format
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s wurde aus Ihren Favoriten entfernt."
|
||||
@ -792,7 +929,7 @@ msgstr "Kopfhörer"
|
||||
msgid "Headset"
|
||||
msgstr "Headset"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
|
||||
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
|
||||
msgid "Microphone"
|
||||
msgstr "Mikrofon"
|
||||
|
||||
@ -933,7 +1070,7 @@ msgstr "Keine Termine"
|
||||
msgid "Do Not Disturb"
|
||||
msgstr "Nicht stören"
|
||||
|
||||
#: js/ui/calendar.js:1176
|
||||
#: js/ui/calendar.js:1171
|
||||
msgid "Clear"
|
||||
msgstr "Leeren"
|
||||
|
||||
@ -1086,7 +1223,7 @@ msgstr ""
|
||||
|
||||
#. Translators: this is the other person changing their old IM name to their new
|
||||
#. IM name.
|
||||
#: js/ui/components/telepathyClient.js:823
|
||||
#: js/ui/components/telepathyClient.js:787
|
||||
#, javascript-format
|
||||
msgid "%s is now known as %s"
|
||||
msgstr "%s heißt jetzt %s"
|
||||
@ -1131,23 +1268,23 @@ msgstr "Weltuhren hinzufügen …"
|
||||
msgid "World Clocks"
|
||||
msgstr "Weltuhren"
|
||||
|
||||
#: js/ui/dateMenu.js:289
|
||||
#: js/ui/dateMenu.js:279
|
||||
msgid "Weather"
|
||||
msgstr "Wetter"
|
||||
|
||||
#: js/ui/dateMenu.js:418
|
||||
#: js/ui/dateMenu.js:394
|
||||
msgid "Select a location…"
|
||||
msgstr "Ort auswählen …"
|
||||
|
||||
#: js/ui/dateMenu.js:426
|
||||
#: js/ui/dateMenu.js:407
|
||||
msgid "Loading…"
|
||||
msgstr "Wird geladen …"
|
||||
|
||||
#: js/ui/dateMenu.js:436
|
||||
#: js/ui/dateMenu.js:417
|
||||
msgid "Go online for weather information"
|
||||
msgstr "Gehen Sie Online, um Wetterinformationen beziehen zu können"
|
||||
|
||||
#: js/ui/dateMenu.js:438
|
||||
#: js/ui/dateMenu.js:419
|
||||
msgid "Weather information is currently unavailable"
|
||||
msgstr "Wetterinformationen sind momentan nicht verfügbar"
|
||||
|
||||
@ -1288,35 +1425,35 @@ msgid "Other users are logged in"
|
||||
msgstr "Andere Benutzer sind angemeldet"
|
||||
|
||||
#. Translators: Remote here refers to a remote session, like a ssh login
|
||||
#: js/ui/endSessionDialog.js:586
|
||||
#: js/ui/endSessionDialog.js:588
|
||||
#, javascript-format
|
||||
msgid "%s (remote)"
|
||||
msgstr "%s (Entfernt)"
|
||||
|
||||
#. Translators: Console here refers to a tty like a VT console
|
||||
#: js/ui/endSessionDialog.js:589
|
||||
#: js/ui/endSessionDialog.js:591
|
||||
#, javascript-format
|
||||
msgid "%s (console)"
|
||||
msgstr "%s (Konsole)"
|
||||
|
||||
#: js/ui/extensionDownloader.js:185
|
||||
#: js/ui/extensionDownloader.js:181
|
||||
msgid "Install"
|
||||
msgstr "Installieren"
|
||||
|
||||
#: js/ui/extensionDownloader.js:191
|
||||
#: js/ui/extensionDownloader.js:187
|
||||
msgid "Install Extension"
|
||||
msgstr "Erweiterung installieren"
|
||||
|
||||
#: js/ui/extensionDownloader.js:192
|
||||
#: js/ui/extensionDownloader.js:188
|
||||
#, javascript-format
|
||||
msgid "Download and install “%s” from extensions.gnome.org?"
|
||||
msgstr "»%s« von extensions.gnome.org herunterladen und installieren?"
|
||||
|
||||
#: js/ui/extensionSystem.js:252
|
||||
#: js/ui/extensionSystem.js:228
|
||||
msgid "Extension Updates Available"
|
||||
msgstr "Aktualisierungen für Erweiterungen verfügbar"
|
||||
|
||||
#: js/ui/extensionSystem.js:253
|
||||
#: js/ui/extensionSystem.js:229
|
||||
msgid "Extension updates are ready to be installed."
|
||||
msgstr "Aktualisierungen für Erweiterungen stehen bereit zur Installation."
|
||||
|
||||
@ -1465,11 +1602,11 @@ msgstr "Quelle zeigen"
|
||||
msgid "Web Page"
|
||||
msgstr "Webseite"
|
||||
|
||||
#: js/ui/main.js:279
|
||||
#: js/ui/main.js:274
|
||||
msgid "Logged in as a privileged user"
|
||||
msgstr "Als privilegierter Benutzer angemeldet"
|
||||
|
||||
#: js/ui/main.js:280
|
||||
#: js/ui/main.js:275
|
||||
msgid ""
|
||||
"Running a session as a privileged user should be avoided for security "
|
||||
"reasons. If possible, you should log in as a normal user."
|
||||
@ -1478,23 +1615,23 @@ msgstr ""
|
||||
"Sicherheitsgründen unterlassen werden. Falls möglich, melden Sie sich bitte "
|
||||
"als normaler Benutzer an."
|
||||
|
||||
#: js/ui/main.js:319
|
||||
#: js/ui/main.js:281
|
||||
msgid "Screen Lock disabled"
|
||||
msgstr "Bildschirmsperre deaktiviert"
|
||||
|
||||
#: js/ui/main.js:320
|
||||
#: js/ui/main.js:282
|
||||
msgid "Screen Locking requires the GNOME display manager."
|
||||
msgstr "Die Sperrung des Bildschirms erfordert den GNOME Display-Manager."
|
||||
|
||||
#: js/ui/messageTray.js:1548
|
||||
#: js/ui/messageTray.js:1554
|
||||
msgid "System Information"
|
||||
msgstr "Systeminformationen"
|
||||
|
||||
#: js/ui/mpris.js:204
|
||||
#: js/ui/mpris.js:199
|
||||
msgid "Unknown artist"
|
||||
msgstr "Unbekannter Künstler"
|
||||
|
||||
#: js/ui/mpris.js:214
|
||||
#: js/ui/mpris.js:209
|
||||
msgid "Unknown title"
|
||||
msgstr "Unbekannter Titel"
|
||||
|
||||
@ -1566,16 +1703,16 @@ msgstr "Beenden"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: js/ui/panel.js:437
|
||||
#: js/ui/panel.js:434
|
||||
msgid "Activities"
|
||||
msgstr "Aktivitäten"
|
||||
|
||||
#: js/ui/panel.js:716
|
||||
#: js/ui/panel.js:713
|
||||
msgctxt "System menu in the top bar"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: js/ui/panel.js:829
|
||||
#: js/ui/panel.js:826
|
||||
msgid "Top Bar"
|
||||
msgstr "Oberes Panel"
|
||||
|
||||
@ -1606,11 +1743,11 @@ msgstr "GNOME muss den Bildschirm sperren"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: js/ui/screenShield.js:244 js/ui/screenShield.js:601
|
||||
#: js/ui/screenShield.js:244 js/ui/screenShield.js:598
|
||||
msgid "Unable to lock"
|
||||
msgstr "Sperrung fehlgeschlagen"
|
||||
|
||||
#: js/ui/screenShield.js:245 js/ui/screenShield.js:602
|
||||
#: js/ui/screenShield.js:245 js/ui/screenShield.js:599
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "Sperrung wurde von einer Anwendung blockiert"
|
||||
|
||||
@ -1693,13 +1830,13 @@ msgid "The PIM must be a number or empty."
|
||||
msgstr "Die PIM muss eine Nummer oder leer sein."
|
||||
|
||||
#. Translators: %s is the Disks application
|
||||
#: js/ui/shellMountOperation.js:465
|
||||
#: js/ui/shellMountOperation.js:469
|
||||
#, javascript-format
|
||||
msgid "Unable to start %s"
|
||||
msgstr "%s konnte nicht gestartet werden"
|
||||
|
||||
#. Translators: %s is the Disks application
|
||||
#: js/ui/shellMountOperation.js:467
|
||||
#: js/ui/shellMountOperation.js:471
|
||||
#, javascript-format
|
||||
msgid "Couldn’t find the %s application"
|
||||
msgstr "Die Anwendung %s konnte nicht gefunden werden"
|
||||
@ -2183,11 +2320,11 @@ msgstr "Thunderbolt-Legitimierungsfehler"
|
||||
msgid "Could not authorize the Thunderbolt device: %s"
|
||||
msgstr "Das Thunderbolt-Gerät %s konnte nicht legitimiert werden"
|
||||
|
||||
#: js/ui/status/volume.js:151
|
||||
#: js/ui/status/volume.js:150
|
||||
msgid "Volume changed"
|
||||
msgstr "Lautstärke geändert"
|
||||
|
||||
#: js/ui/status/volume.js:222
|
||||
#: js/ui/status/volume.js:221
|
||||
msgid "Volume"
|
||||
msgstr "Lautstärke"
|
||||
|
||||
@ -2221,23 +2358,23 @@ msgstr "Nur eingebaut"
|
||||
|
||||
#. Translators: This is a time format for a date in
|
||||
#. long format
|
||||
#: js/ui/unlockDialog.js:371
|
||||
#: js/ui/unlockDialog.js:370
|
||||
msgid "%A %B %-d"
|
||||
msgstr "%A, %d. %B"
|
||||
|
||||
#: js/ui/unlockDialog.js:377
|
||||
#: js/ui/unlockDialog.js:376
|
||||
msgid "Swipe up to unlock"
|
||||
msgstr "Nach oben wischen zum Entsperren"
|
||||
|
||||
#: js/ui/unlockDialog.js:378
|
||||
#: js/ui/unlockDialog.js:377
|
||||
msgid "Click or press a key to unlock"
|
||||
msgstr "Durch Mausklick oder Tastendruck entsperren"
|
||||
|
||||
#: js/ui/unlockDialog.js:550
|
||||
#: js/ui/unlockDialog.js:549
|
||||
msgid "Unlock Window"
|
||||
msgstr "Fenster entsperren"
|
||||
|
||||
#: js/ui/unlockDialog.js:559
|
||||
#: js/ui/unlockDialog.js:558
|
||||
msgid "Log in as another user"
|
||||
msgstr "Als anderer Benutzer anmelden"
|
||||
|
||||
@ -2270,7 +2407,7 @@ msgstr "Zurücksetzen"
|
||||
msgid "Keep Changes"
|
||||
msgstr "Beibehalten"
|
||||
|
||||
#: js/ui/windowManager.js:86
|
||||
#: js/ui/windowManager.js:85
|
||||
#, javascript-format
|
||||
msgid "Settings changes will revert in %d second"
|
||||
msgid_plural "Settings changes will revert in %d seconds"
|
||||
@ -2280,7 +2417,7 @@ msgstr[1] ""
|
||||
|
||||
#. Translators: This represents the size of a window. The first number is
|
||||
#. * the width of the window and the second is the height.
|
||||
#: js/ui/windowManager.js:546
|
||||
#: js/ui/windowManager.js:544
|
||||
#, javascript-format
|
||||
msgid "%d × %d"
|
||||
msgstr "%d × %d"
|
||||
@ -2375,12 +2512,12 @@ msgstr ""
|
||||
msgid "List possible modes"
|
||||
msgstr "Die möglichen Modi auflisten"
|
||||
|
||||
#: src/shell-app.c:286
|
||||
#: src/shell-app.c:279
|
||||
msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "Unbekannt"
|
||||
|
||||
#: src/shell-app.c:537
|
||||
#: src/shell-app.c:530
|
||||
#, c-format
|
||||
msgid "Failed to launch “%s”"
|
||||
msgstr "»%s« konnte nicht gestartet werden"
|
||||
@ -2397,143 +2534,6 @@ msgstr "Es muss ein Passwort angegeben werden"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Der Dialog zur Anmeldung wurde vom Benutzer geschlossen"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
|
||||
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
|
||||
#: subprojects/extensions-app/js/main.js:182
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
|
||||
msgid "Extensions"
|
||||
msgstr "Erweiterungen"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
|
||||
#: subprojects/extensions-app/js/main.js:183
|
||||
msgid "Manage your GNOME Extensions"
|
||||
msgstr "Ihre GNOME-Erweiterungen verwalten"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
|
||||
msgid ""
|
||||
"GNOME Extensions handles updating extensions, configuring extension "
|
||||
"preferences and removing or disabling unwanted extensions."
|
||||
msgstr ""
|
||||
"GNOME-Erweiterungen dient der Aktualisierung von Erweiterungen, dem "
|
||||
"Konfigurieren der Voreinstellungen von Erweiterungen und dem Entfernen oder "
|
||||
"Deaktivieren nicht gewünschter Erweiterungen."
|
||||
|
||||
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "GNOME-Shell-Erweiterungen einrichten"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:144
|
||||
#, javascript-format
|
||||
msgid "Remove “%s”?"
|
||||
msgstr "»%s« entfernen?"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:145
|
||||
msgid ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
msgstr ""
|
||||
"Wenn Sie die Erweiterung entfernen, müssen Sie sie erneut herunterladen, um "
|
||||
"sie wieder zu aktivieren"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:149
|
||||
msgid "Remove"
|
||||
msgstr "Entfernen"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:181
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
"Tim Sabsch <tim@sabsch.com>\n"
|
||||
"Christian Kirbach <christian.kirbach@gmail.com>, 2020"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:316
|
||||
#, javascript-format
|
||||
msgid "%d extension will be updated on next login."
|
||||
msgid_plural "%d extensions will be updated on next login."
|
||||
msgstr[0] "%d Erweiterung wird bei der nächsten Anmeldung aktualisiert."
|
||||
msgstr[1] "%d Erweiterungen werden bei der nächsten Anmeldung aktualisiert."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:100
|
||||
#: subprojects/extensions-tool/src/command-create.c:211
|
||||
#: subprojects/extensions-tool/src/main.c:173
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:123
|
||||
#: subprojects/extensions-tool/src/main.c:185
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:151
|
||||
msgid "Author"
|
||||
msgstr "Autor"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:175
|
||||
msgid "Website"
|
||||
msgstr "Webseite"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:192
|
||||
msgid "Remove…"
|
||||
msgstr "Entfernen …"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
|
||||
msgid "Help"
|
||||
msgstr "Hilfe"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
|
||||
msgid "About Extensions"
|
||||
msgstr "Info zu Erweiterungen"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
|
||||
msgid ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
msgstr ""
|
||||
"Besuchen Sie <a href=\"https://extensions.gnome.org\">extensions.gnome.org</"
|
||||
"a>, um Erweiterungen zu finden und hinzuzufügen."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
|
||||
msgid "Warning"
|
||||
msgstr "Warnung"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
|
||||
msgid ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
msgstr ""
|
||||
"Erweiterungen können Probleme am System verursachen, darunter auch "
|
||||
"Leistungsprobleme. Sollten Sie auf Probleme mit Ihrem System stoßen, wird "
|
||||
"die Deaktivierung aller Erweiterungen empfohlen."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:135
|
||||
msgid "Manually Installed"
|
||||
msgstr "Manuell installiert"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:159
|
||||
msgid "Built-In"
|
||||
msgstr "Mitgeliefert"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:200
|
||||
msgid "No Installed Extensions"
|
||||
msgstr "Keine installierten Erweiterungen"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:236
|
||||
msgid ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
msgstr ""
|
||||
"Tut uns sehr leid, wir konnten keine Liste der installierten Erweiterungen "
|
||||
"aufstellen. Stellen Sie sicher, dass Sie in GNOME angemeldet sind und "
|
||||
"versuchen Sie es dann erneut."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:273
|
||||
msgid "Extension Updates Ready"
|
||||
msgstr "Aktualisierungen für Erweiterungen stehen bereit"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:289
|
||||
msgid "Log Out…"
|
||||
msgstr "Abmelden …"
|
||||
|
||||
#. Translators: a file path to an extension directory
|
||||
#: subprojects/extensions-tool/src/command-create.c:125
|
||||
#, c-format
|
||||
@ -2872,9 +2872,6 @@ msgstr[1] "%u Eingänge"
|
||||
msgid "System Sounds"
|
||||
msgstr "Systemklänge"
|
||||
|
||||
#~ msgid "Copy Error"
|
||||
#~ msgstr "Kopierfehler"
|
||||
|
||||
#~ msgid "Username…"
|
||||
#~ msgstr "Benutzername …"
|
||||
|
||||
|
521
po/en_GB.po
521
po/en_GB.po
@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
|
||||
"POT-Creation-Date: 2020-03-31 07:15+0000\n"
|
||||
"PO-Revision-Date: 2020-05-06 19:54+0100\n"
|
||||
"POT-Creation-Date: 2020-02-21 09:52+0000\n"
|
||||
"PO-Revision-Date: 2020-02-23 12:49+0000\n"
|
||||
"Last-Translator: Bruce Cowan <bruce@bcowan.me.uk>\n"
|
||||
"Language-Team: English - United Kingdom <en@li.org>\n"
|
||||
"Language: en_GB\n"
|
||||
@ -19,7 +19,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Gtranslator 3.36.0\n"
|
||||
"X-Generator: Gtranslator 3.34.0\n"
|
||||
"X-Project-Style: gnome\n"
|
||||
|
||||
#: data/50-gnome-shell-system.xml:6
|
||||
@ -46,6 +46,15 @@ msgstr "Show all applications"
|
||||
msgid "Open the application menu"
|
||||
msgstr "Open the application menu"
|
||||
|
||||
#: 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 "Configure GNOME Shell Extensions"
|
||||
|
||||
#: data/org.gnome.Shell.desktop.in.in:4
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
@ -386,12 +395,49 @@ msgstr "Delay focus changes in mouse mode until the pointer stops moving"
|
||||
msgid "Network Login"
|
||||
msgstr "Network Login"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:36
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:223
|
||||
#: js/extensionPrefs/main.js:140
|
||||
#, javascript-format
|
||||
msgid "Remove “%s”?"
|
||||
msgstr "Remove “%s”?"
|
||||
|
||||
#: js/extensionPrefs/main.js:141
|
||||
msgid ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
msgstr ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
|
||||
#: js/extensionPrefs/main.js:144 js/ui/audioDeviceSelection.js:57
|
||||
#: js/ui/components/networkAgent.js:107 js/ui/components/polkitAgent.js:139
|
||||
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:165
|
||||
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
|
||||
#: js/ui/status/network.js:913
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: js/extensionPrefs/main.js:145
|
||||
msgid "Remove"
|
||||
msgstr "Remove"
|
||||
|
||||
#: js/extensionPrefs/main.js:217
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
"Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||
"Bruce Cowan <bruce@bcowan.me.uk>\n"
|
||||
"Chris Leonard <cjl@laptop.org>\n"
|
||||
"David King <amigadave@amigadave.com>\n"
|
||||
"Zander Brown <zbrown@gnome.org>"
|
||||
|
||||
#: js/extensionPrefs/main.js:219
|
||||
msgid "Manage your GNOME Extensions"
|
||||
msgstr "Manage your GNOME Extensions"
|
||||
|
||||
#: js/extensionPrefs/main.js:261 js/extensionPrefs/ui/extensions-window.ui:222
|
||||
msgid "Something’s gone wrong"
|
||||
msgstr "Something’s gone wrong"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:48
|
||||
#: js/extensionPrefs/main.js:268
|
||||
msgid ""
|
||||
"We’re very sorry, but there’s been a problem: the settings for this "
|
||||
"extension can’t be displayed. We recommend that you report the issue to the "
|
||||
@ -401,32 +447,113 @@ msgstr ""
|
||||
"extension can’t be displayed. We recommend that you report the issue to the "
|
||||
"extension authors."
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:82
|
||||
#: js/extensionPrefs/main.js:275
|
||||
msgid "Technical Details"
|
||||
msgstr "Technical Details"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:165
|
||||
#: js/extensionPrefs/main.js:310
|
||||
msgid "Copy Error"
|
||||
msgstr "Copy Error"
|
||||
|
||||
#: js/extensionPrefs/main.js:337
|
||||
msgid "Homepage"
|
||||
msgstr "Homepage"
|
||||
|
||||
#: js/dbusServices/extensions/ui/extension-prefs-dialog.ui:166
|
||||
#: js/extensionPrefs/main.js:338
|
||||
msgid "Visit extension homepage"
|
||||
msgstr "Visit extension homepage"
|
||||
|
||||
#: js/gdm/authPrompt.js:135 js/ui/audioDeviceSelection.js:57
|
||||
#: js/ui/components/networkAgent.js:109 js/ui/components/polkitAgent.js:139
|
||||
#: js/ui/endSessionDialog.js:374 js/ui/extensionDownloader.js:181
|
||||
#: js/ui/shellMountOperation.js:376 js/ui/shellMountOperation.js:386
|
||||
#: js/ui/status/network.js:913 subprojects/extensions-app/js/main.js:148
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
#: js/extensionPrefs/main.js:449
|
||||
#, javascript-format
|
||||
msgid "%d extension will be updated on next login."
|
||||
msgid_plural "%d extensions will be updated on next login."
|
||||
msgstr[0] "%d extension will be updated on next login."
|
||||
msgstr[1] "%d extensions will be updated on next login."
|
||||
|
||||
#: js/extensionPrefs/ui/extension-row.ui:100
|
||||
#: subprojects/extensions-tool/src/command-create.c:211
|
||||
#: subprojects/extensions-tool/src/main.c:173
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: js/extensionPrefs/ui/extension-row.ui:123
|
||||
#: subprojects/extensions-tool/src/main.c:185
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: js/extensionPrefs/ui/extension-row.ui:151
|
||||
msgid "Author"
|
||||
msgstr "Author"
|
||||
|
||||
#: js/extensionPrefs/ui/extension-row.ui:175
|
||||
msgid "Website"
|
||||
msgstr "Website"
|
||||
|
||||
#: js/extensionPrefs/ui/extension-row.ui:192
|
||||
msgid "Remove…"
|
||||
msgstr "Remove…"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:8
|
||||
msgid "Help"
|
||||
msgstr "Help"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:12
|
||||
msgid "About Extensions"
|
||||
msgstr "About Extensions"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:27
|
||||
msgid ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
msgstr ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:35
|
||||
msgid "Warning"
|
||||
msgstr "Warning"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:46
|
||||
msgid ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
msgstr ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:133
|
||||
msgid "Manually Installed"
|
||||
msgstr "Manually Installed"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:157
|
||||
msgid "Built-In"
|
||||
msgstr "Built-In"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:198
|
||||
msgid "No Installed Extensions"
|
||||
msgstr "No Installed Extensions"
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:234
|
||||
msgid ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
msgstr ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
|
||||
#: js/extensionPrefs/ui/extensions-window.ui:287
|
||||
msgid "Log Out…"
|
||||
msgstr "Log Out…"
|
||||
|
||||
#. Cisco LEAP
|
||||
#: js/gdm/authPrompt.js:237 js/ui/components/networkAgent.js:204
|
||||
#: js/ui/components/networkAgent.js:220 js/ui/components/networkAgent.js:244
|
||||
#: js/ui/components/networkAgent.js:265 js/ui/components/networkAgent.js:285
|
||||
#: js/ui/components/networkAgent.js:295 js/ui/components/polkitAgent.js:277
|
||||
#: js/gdm/authPrompt.js:236 js/ui/components/networkAgent.js:202
|
||||
#: js/ui/components/networkAgent.js:218 js/ui/components/networkAgent.js:242
|
||||
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:283
|
||||
#: js/ui/components/networkAgent.js:293 js/ui/components/polkitAgent.js:277
|
||||
#: js/ui/shellMountOperation.js:326
|
||||
#| msgid "Password:"
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
@ -448,8 +575,9 @@ msgstr "(e.g., user or %s)"
|
||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||
#. is not visible here since we only care about phase2 authentication
|
||||
#. (and don't even care of which one)
|
||||
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:240
|
||||
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281
|
||||
#: js/gdm/loginDialog.js:917 js/ui/components/networkAgent.js:238
|
||||
#: js/ui/components/networkAgent.js:261 js/ui/components/networkAgent.js:279
|
||||
#| msgid "Username: "
|
||||
msgid "Username"
|
||||
msgstr "Username"
|
||||
|
||||
@ -630,7 +758,7 @@ msgstr "%A, %H∶%M"
|
||||
#: js/misc/util.js:255
|
||||
#, no-c-format
|
||||
msgid "%B %-d, %H∶%M"
|
||||
msgstr "%-d %B, %H∶%M"
|
||||
msgstr "%d %B, %H∶%M"
|
||||
|
||||
#. Translators: this is the month name, day number, year
|
||||
#. number followed by a time string in 24h format.
|
||||
@ -638,7 +766,7 @@ msgstr "%-d %B, %H∶%M"
|
||||
#: js/misc/util.js:261
|
||||
#, no-c-format
|
||||
msgid "%B %-d %Y, %H∶%M"
|
||||
msgstr "%-d %B %Y, %H∶%M"
|
||||
msgstr "%d %B %Y, %H∶%M"
|
||||
|
||||
#. Show only the time if date is on today
|
||||
#. eslint-disable-line no-lonely-if
|
||||
@ -667,7 +795,7 @@ msgstr "%A, %l:%M %p"
|
||||
#: js/misc/util.js:284
|
||||
#, no-c-format
|
||||
msgid "%B %-d, %l∶%M %p"
|
||||
msgstr "%-d %B, %l∶%M %p"
|
||||
msgstr "%d %B, %l∶%M %p"
|
||||
|
||||
#. Translators: this is the month name, day number, year
|
||||
#. number followed by a time string in 12h format.
|
||||
@ -675,7 +803,7 @@ msgstr "%-d %B, %l∶%M %p"
|
||||
#: js/misc/util.js:290
|
||||
#, no-c-format
|
||||
msgid "%B %-d %Y, %l∶%M %p"
|
||||
msgstr "%-d %B %Y, %l∶%M %p"
|
||||
msgstr "%d %B %Y, %l∶%M %p"
|
||||
|
||||
#. TRANSLATORS: this is the title of the wifi captive portal login window
|
||||
#: js/portalHelper/main.js:41
|
||||
@ -700,44 +828,44 @@ msgstr "Deny Access"
|
||||
msgid "Grant Access"
|
||||
msgstr "Grant Access"
|
||||
|
||||
#: js/ui/appDisplay.js:932
|
||||
#: js/ui/appDisplay.js:906
|
||||
msgid "Unnamed Folder"
|
||||
msgstr "Unnamed Folder"
|
||||
|
||||
#: js/ui/appDisplay.js:955
|
||||
#: js/ui/appDisplay.js:929
|
||||
msgid "Frequently used applications will appear here"
|
||||
msgstr "Frequently used applications will appear here"
|
||||
|
||||
#: js/ui/appDisplay.js:1090
|
||||
#: js/ui/appDisplay.js:1064
|
||||
msgid "Frequent"
|
||||
msgstr "Frequent"
|
||||
|
||||
#: js/ui/appDisplay.js:1097
|
||||
#: js/ui/appDisplay.js:1071
|
||||
msgid "All"
|
||||
msgstr "All"
|
||||
|
||||
#. Translators: This is the heading of a list of open windows
|
||||
#: js/ui/appDisplay.js:2473 js/ui/panel.js:75
|
||||
#: js/ui/appDisplay.js:2450 js/ui/panel.js:75
|
||||
msgid "Open Windows"
|
||||
msgstr "Open Windows"
|
||||
|
||||
#: js/ui/appDisplay.js:2493 js/ui/panel.js:82
|
||||
#: js/ui/appDisplay.js:2470 js/ui/panel.js:82
|
||||
msgid "New Window"
|
||||
msgstr "New Window"
|
||||
|
||||
#: js/ui/appDisplay.js:2504
|
||||
#: js/ui/appDisplay.js:2481
|
||||
msgid "Launch using Dedicated Graphics Card"
|
||||
msgstr "Launch using Dedicated Graphics Card"
|
||||
|
||||
#: js/ui/appDisplay.js:2532 js/ui/dash.js:239
|
||||
#: js/ui/appDisplay.js:2509 js/ui/dash.js:239
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Remove from Favourites"
|
||||
|
||||
#: js/ui/appDisplay.js:2538
|
||||
#: js/ui/appDisplay.js:2515
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Add to Favourites"
|
||||
|
||||
#: js/ui/appDisplay.js:2548 js/ui/panel.js:93
|
||||
#: js/ui/appDisplay.js:2525 js/ui/panel.js:93
|
||||
msgid "Show Details"
|
||||
msgstr "Show Details"
|
||||
|
||||
@ -767,7 +895,7 @@ msgstr "Headphones"
|
||||
msgid "Headset"
|
||||
msgstr "Headset"
|
||||
|
||||
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:270
|
||||
#: js/ui/audioDeviceSelection.js:68 js/ui/status/volume.js:269
|
||||
msgid "Microphone"
|
||||
msgstr "Microphone"
|
||||
|
||||
@ -885,30 +1013,30 @@ msgid "All Day"
|
||||
msgstr "All Day"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on current year
|
||||
#: js/ui/calendar.js:868
|
||||
#: js/ui/calendar.js:867
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %-d"
|
||||
msgstr "%A, %-d %B"
|
||||
msgstr "%A, %d %B"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on different year
|
||||
#: js/ui/calendar.js:871
|
||||
#: js/ui/calendar.js:870
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %-d, %Y"
|
||||
msgstr "%A, %-d %B, %Y"
|
||||
msgstr "%A, %d %B, %Y"
|
||||
|
||||
#: js/ui/calendar.js:1100
|
||||
#: js/ui/calendar.js:1096
|
||||
msgid "No Notifications"
|
||||
msgstr "No Notifications"
|
||||
|
||||
#: js/ui/calendar.js:1103
|
||||
#: js/ui/calendar.js:1099
|
||||
msgid "No Events"
|
||||
msgstr "No Events"
|
||||
|
||||
#: js/ui/calendar.js:1157
|
||||
#: js/ui/calendar.js:1153
|
||||
msgid "Do Not Disturb"
|
||||
msgstr "Do Not Disturb"
|
||||
|
||||
#: js/ui/calendar.js:1176
|
||||
#: js/ui/calendar.js:1167
|
||||
msgid "Clear"
|
||||
msgstr "Clear"
|
||||
|
||||
@ -955,39 +1083,43 @@ msgstr "The installed udisks version does not support the PIM setting"
|
||||
msgid "Open with %s"
|
||||
msgstr "Open with %s"
|
||||
|
||||
#: js/ui/components/networkAgent.js:91
|
||||
#: js/ui/components/networkAgent.js:89
|
||||
msgid ""
|
||||
"Alternatively you can connect by pushing the “WPS” button on your router."
|
||||
msgstr ""
|
||||
"Alternatively you can connect by pushing the “WPS” button on your router."
|
||||
|
||||
#: js/ui/components/networkAgent.js:103 js/ui/status/network.js:223
|
||||
#: js/ui/components/networkAgent.js:101 js/ui/status/network.js:223
|
||||
#: js/ui/status/network.js:314 js/ui/status/network.js:916
|
||||
msgid "Connect"
|
||||
msgstr "Connect"
|
||||
|
||||
#: js/ui/components/networkAgent.js:210
|
||||
#: js/ui/components/networkAgent.js:208
|
||||
#| msgid "Key: "
|
||||
msgid "Key"
|
||||
msgstr "Key"
|
||||
|
||||
#: 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 "Private key password"
|
||||
|
||||
#: js/ui/components/networkAgent.js:269
|
||||
#: js/ui/components/networkAgent.js:267
|
||||
#| msgid "Identity: "
|
||||
msgid "Identity"
|
||||
msgstr "Identity"
|
||||
|
||||
#: js/ui/components/networkAgent.js:283
|
||||
#: js/ui/components/networkAgent.js:281
|
||||
#| msgid "Service: "
|
||||
msgid "Service"
|
||||
msgstr "Service"
|
||||
|
||||
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:340
|
||||
#: js/ui/components/networkAgent.js:679 js/ui/components/networkAgent.js:700
|
||||
#: js/ui/components/networkAgent.js:310 js/ui/components/networkAgent.js:338
|
||||
#: js/ui/components/networkAgent.js:685 js/ui/components/networkAgent.js:706
|
||||
msgid "Authentication required"
|
||||
msgstr "Authentication required"
|
||||
|
||||
#: js/ui/components/networkAgent.js:313 js/ui/components/networkAgent.js:680
|
||||
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:686
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
@ -996,42 +1128,44 @@ msgstr ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"“%s”."
|
||||
|
||||
#: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:684
|
||||
#: js/ui/components/networkAgent.js:315 js/ui/components/networkAgent.js:690
|
||||
msgid "Wired 802.1X authentication"
|
||||
msgstr "Wired 802.1X authentication"
|
||||
|
||||
#: js/ui/components/networkAgent.js:319
|
||||
#: js/ui/components/networkAgent.js:317
|
||||
#| msgid "Network name: "
|
||||
msgid "Network name"
|
||||
msgstr "Network name"
|
||||
|
||||
#: js/ui/components/networkAgent.js:324 js/ui/components/networkAgent.js:688
|
||||
#: js/ui/components/networkAgent.js:322 js/ui/components/networkAgent.js:694
|
||||
msgid "DSL authentication"
|
||||
msgstr "DSL authentication"
|
||||
|
||||
#: js/ui/components/networkAgent.js:331 js/ui/components/networkAgent.js:693
|
||||
#: js/ui/components/networkAgent.js:329 js/ui/components/networkAgent.js:699
|
||||
msgid "PIN code required"
|
||||
msgstr "PIN code required"
|
||||
|
||||
#: js/ui/components/networkAgent.js:332 js/ui/components/networkAgent.js:694
|
||||
#: js/ui/components/networkAgent.js:330 js/ui/components/networkAgent.js:700
|
||||
msgid "PIN code is needed for the mobile broadband device"
|
||||
msgstr "PIN code is needed for the mobile broadband device"
|
||||
|
||||
#: js/ui/components/networkAgent.js:333
|
||||
#: js/ui/components/networkAgent.js:331
|
||||
#| msgid "PIN: "
|
||||
msgid "PIN"
|
||||
msgstr "PIN"
|
||||
|
||||
#: js/ui/components/networkAgent.js:341 js/ui/components/networkAgent.js:685
|
||||
#: js/ui/components/networkAgent.js:689 js/ui/components/networkAgent.js:701
|
||||
#: js/ui/components/networkAgent.js:705
|
||||
#: js/ui/components/networkAgent.js:339 js/ui/components/networkAgent.js:691
|
||||
#: js/ui/components/networkAgent.js:695 js/ui/components/networkAgent.js:707
|
||||
#: js/ui/components/networkAgent.js:711
|
||||
#, javascript-format
|
||||
msgid "A password is required to connect to “%s”."
|
||||
msgstr "A password is required to connect to “%s”."
|
||||
|
||||
#: js/ui/components/networkAgent.js:668 js/ui/status/network.js:1691
|
||||
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1691
|
||||
msgid "Network Manager"
|
||||
msgstr "Network Manager"
|
||||
|
||||
#: js/ui/components/networkAgent.js:704
|
||||
#: js/ui/components/networkAgent.js:710
|
||||
msgid "VPN password"
|
||||
msgstr "VPN password"
|
||||
|
||||
@ -1057,7 +1191,7 @@ msgstr "Sorry, that didn’t work. Please try again."
|
||||
|
||||
#. Translators: this is the other person changing their old IM name to their new
|
||||
#. IM name.
|
||||
#: js/ui/components/telepathyClient.js:823
|
||||
#: js/ui/components/telepathyClient.js:787
|
||||
#, javascript-format
|
||||
msgid "%s is now known as %s"
|
||||
msgstr "%s is now known as %s"
|
||||
@ -1083,7 +1217,7 @@ msgstr "Dash"
|
||||
#.
|
||||
#: js/ui/dateMenu.js:75
|
||||
msgid "%B %-d %Y"
|
||||
msgstr "%-d %B %Y"
|
||||
msgstr "%e %B %Y"
|
||||
|
||||
#. Translators: This is the accessible name of the date button shown
|
||||
#. * below the time in the shell; it should combine the weekday and the
|
||||
@ -1101,106 +1235,106 @@ msgstr "Add world clocks…"
|
||||
msgid "World Clocks"
|
||||
msgstr "World Clocks"
|
||||
|
||||
#: js/ui/dateMenu.js:289
|
||||
#: js/ui/dateMenu.js:276
|
||||
msgid "Weather"
|
||||
msgstr "Weather"
|
||||
|
||||
#: js/ui/dateMenu.js:418
|
||||
#: js/ui/dateMenu.js:391
|
||||
msgid "Select a location…"
|
||||
msgstr "Select a location…"
|
||||
|
||||
#: js/ui/dateMenu.js:426
|
||||
#: js/ui/dateMenu.js:404
|
||||
msgid "Loading…"
|
||||
msgstr "Loading…"
|
||||
|
||||
#: js/ui/dateMenu.js:436
|
||||
#: js/ui/dateMenu.js:414
|
||||
msgid "Go online for weather information"
|
||||
msgstr "Go online for weather information"
|
||||
|
||||
#: js/ui/dateMenu.js:438
|
||||
#: js/ui/dateMenu.js:416
|
||||
msgid "Weather information is currently unavailable"
|
||||
msgstr "Weather information is currently unavailable"
|
||||
|
||||
#: js/ui/endSessionDialog.js:39
|
||||
#: js/ui/endSessionDialog.js:37
|
||||
#, javascript-format
|
||||
msgctxt "title"
|
||||
msgid "Log Out %s"
|
||||
msgstr "Log Out %s"
|
||||
|
||||
#: js/ui/endSessionDialog.js:40
|
||||
#: js/ui/endSessionDialog.js:38
|
||||
msgctxt "title"
|
||||
msgid "Log Out"
|
||||
msgstr "Log Out"
|
||||
|
||||
#: js/ui/endSessionDialog.js:42
|
||||
#: js/ui/endSessionDialog.js:40
|
||||
#, javascript-format
|
||||
msgid "%s will be logged out automatically in %d second."
|
||||
msgid_plural "%s will be logged out automatically in %d seconds."
|
||||
msgstr[0] "%s will be logged out automatically in %d second."
|
||||
msgstr[1] "%s will be logged out automatically in %d seconds."
|
||||
|
||||
#: js/ui/endSessionDialog.js:47
|
||||
#: js/ui/endSessionDialog.js:45
|
||||
#, javascript-format
|
||||
msgid "You will be logged out automatically in %d second."
|
||||
msgid_plural "You will be logged out automatically in %d seconds."
|
||||
msgstr[0] "You will be logged out automatically in %d second."
|
||||
msgstr[1] "You will be logged out automatically in %d seconds."
|
||||
|
||||
#: js/ui/endSessionDialog.js:53
|
||||
#: js/ui/endSessionDialog.js:51
|
||||
msgctxt "button"
|
||||
msgid "Log Out"
|
||||
msgstr "Log Out"
|
||||
|
||||
#: js/ui/endSessionDialog.js:58
|
||||
#: js/ui/endSessionDialog.js:56
|
||||
msgctxt "title"
|
||||
msgid "Power Off"
|
||||
msgstr "Power Off"
|
||||
|
||||
#: js/ui/endSessionDialog.js:59
|
||||
#: js/ui/endSessionDialog.js:57
|
||||
msgctxt "title"
|
||||
msgid "Install Updates & Power Off"
|
||||
msgstr "Install Updates & Power Off"
|
||||
|
||||
#: js/ui/endSessionDialog.js:61
|
||||
#: js/ui/endSessionDialog.js:59
|
||||
#, javascript-format
|
||||
msgid "The system will power off automatically in %d second."
|
||||
msgid_plural "The system will power off automatically in %d seconds."
|
||||
msgstr[0] "The system will power off automatically in %d second."
|
||||
msgstr[1] "The system will power off automatically in %d seconds."
|
||||
|
||||
#: js/ui/endSessionDialog.js:65
|
||||
#: js/ui/endSessionDialog.js:63
|
||||
msgctxt "checkbox"
|
||||
msgid "Install pending software updates"
|
||||
msgstr "Install pending software updates"
|
||||
|
||||
#: js/ui/endSessionDialog.js:68 js/ui/endSessionDialog.js:84
|
||||
#: js/ui/endSessionDialog.js:66 js/ui/endSessionDialog.js:82
|
||||
msgctxt "button"
|
||||
msgid "Restart"
|
||||
msgstr "Restart"
|
||||
|
||||
#: js/ui/endSessionDialog.js:70
|
||||
#: js/ui/endSessionDialog.js:68
|
||||
msgctxt "button"
|
||||
msgid "Power Off"
|
||||
msgstr "Power Off"
|
||||
|
||||
#: js/ui/endSessionDialog.js:76
|
||||
#: js/ui/endSessionDialog.js:74
|
||||
msgctxt "title"
|
||||
msgid "Restart"
|
||||
msgstr "Restart"
|
||||
|
||||
#: js/ui/endSessionDialog.js:78
|
||||
#: js/ui/endSessionDialog.js:76
|
||||
#, javascript-format
|
||||
msgid "The system will restart automatically in %d second."
|
||||
msgid_plural "The system will restart automatically in %d seconds."
|
||||
msgstr[0] "The system will restart automatically in %d second."
|
||||
msgstr[1] "The system will restart automatically in %d seconds."
|
||||
|
||||
#: js/ui/endSessionDialog.js:91
|
||||
#: js/ui/endSessionDialog.js:89
|
||||
msgctxt "title"
|
||||
msgid "Restart & Install Updates"
|
||||
msgstr "Restart & Install Updates"
|
||||
|
||||
#: js/ui/endSessionDialog.js:93
|
||||
#: js/ui/endSessionDialog.js:91
|
||||
#, javascript-format
|
||||
msgid "The system will automatically restart and install updates in %d second."
|
||||
msgid_plural ""
|
||||
@ -1210,22 +1344,22 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"The system will automatically restart and install updates in %d seconds."
|
||||
|
||||
#: js/ui/endSessionDialog.js:99 js/ui/endSessionDialog.js:118
|
||||
#: js/ui/endSessionDialog.js:97 js/ui/endSessionDialog.js:116
|
||||
msgctxt "button"
|
||||
msgid "Restart & Install"
|
||||
msgstr "Restart & Install"
|
||||
|
||||
#: js/ui/endSessionDialog.js:100
|
||||
#: js/ui/endSessionDialog.js:98
|
||||
msgctxt "button"
|
||||
msgid "Install & Power Off"
|
||||
msgstr "Install & Power Off"
|
||||
|
||||
#: js/ui/endSessionDialog.js:101
|
||||
#: js/ui/endSessionDialog.js:99
|
||||
msgctxt "checkbox"
|
||||
msgid "Power off after updates are installed"
|
||||
msgstr "Power off after updates are installed"
|
||||
|
||||
#: js/ui/endSessionDialog.js:108
|
||||
#: js/ui/endSessionDialog.js:106
|
||||
msgctxt "title"
|
||||
msgid "Restart & Install Upgrade"
|
||||
msgstr "Restart & Install Upgrade"
|
||||
@ -1233,7 +1367,7 @@ msgstr "Restart & Install Upgrade"
|
||||
#. Translators: This is the text displayed for system upgrades in the
|
||||
#. shut down dialog. First %s gets replaced with the distro name and
|
||||
#. second %s with the distro version to upgrade to
|
||||
#: js/ui/endSessionDialog.js:113
|
||||
#: js/ui/endSessionDialog.js:111
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"%s %s will be installed after restart. Upgrade installation can take a long "
|
||||
@ -1242,15 +1376,15 @@ msgstr ""
|
||||
"%s %s will be installed after restart. Upgrade installation can take a long "
|
||||
"time: ensure that you have backed up and that the computer is plugged in."
|
||||
|
||||
#: js/ui/endSessionDialog.js:261
|
||||
#: js/ui/endSessionDialog.js:259
|
||||
msgid "Running on battery power: Please plug in before installing updates."
|
||||
msgstr "Running on battery power: Please plug in before installing updates."
|
||||
|
||||
#: js/ui/endSessionDialog.js:270
|
||||
#: js/ui/endSessionDialog.js:268
|
||||
msgid "Some applications are busy or have unsaved work"
|
||||
msgstr "Some applications are busy or have unsaved work"
|
||||
|
||||
#: js/ui/endSessionDialog.js:275
|
||||
#: js/ui/endSessionDialog.js:273
|
||||
msgid "Other users are logged in"
|
||||
msgstr "Other users are logged in"
|
||||
|
||||
@ -1266,24 +1400,24 @@ msgstr "%s (remote)"
|
||||
msgid "%s (console)"
|
||||
msgstr "%s (console)"
|
||||
|
||||
#: js/ui/extensionDownloader.js:185
|
||||
#: js/ui/extensionDownloader.js:169
|
||||
msgid "Install"
|
||||
msgstr "Install"
|
||||
|
||||
#: js/ui/extensionDownloader.js:191
|
||||
#: js/ui/extensionDownloader.js:175
|
||||
msgid "Install Extension"
|
||||
msgstr "Install Extension"
|
||||
|
||||
#: js/ui/extensionDownloader.js:192
|
||||
#: js/ui/extensionDownloader.js:176
|
||||
#, javascript-format
|
||||
msgid "Download and install “%s” from extensions.gnome.org?"
|
||||
msgstr "Download and install “%s” from extensions.gnome.org?"
|
||||
|
||||
#: js/ui/extensionSystem.js:233
|
||||
#: js/ui/extensionSystem.js:228
|
||||
msgid "Extension Updates Available"
|
||||
msgstr "Extension Updates Available"
|
||||
|
||||
#: js/ui/extensionSystem.js:234
|
||||
#: js/ui/extensionSystem.js:229
|
||||
msgid "Extension updates are ready to be installed."
|
||||
msgstr "Extension updates are ready to be installed."
|
||||
|
||||
@ -1430,11 +1564,11 @@ msgstr "View Source"
|
||||
msgid "Web Page"
|
||||
msgstr "Web Page"
|
||||
|
||||
#: js/ui/main.js:277
|
||||
#: js/ui/main.js:269
|
||||
msgid "Logged in as a privileged user"
|
||||
msgstr "Logged in as a privileged user"
|
||||
|
||||
#: js/ui/main.js:278
|
||||
#: js/ui/main.js:270
|
||||
msgid ""
|
||||
"Running a session as a privileged user should be avoided for security "
|
||||
"reasons. If possible, you should log in as a normal user."
|
||||
@ -1442,15 +1576,15 @@ msgstr ""
|
||||
"Running a session as a privileged user should be avoided for security "
|
||||
"reasons. If possible, you should log in as a normal user."
|
||||
|
||||
#: js/ui/main.js:317
|
||||
#: js/ui/main.js:276
|
||||
msgid "Screen Lock disabled"
|
||||
msgstr "Screen Lock disabled"
|
||||
|
||||
#: js/ui/main.js:318
|
||||
#: js/ui/main.js:277
|
||||
msgid "Screen Locking requires the GNOME display manager."
|
||||
msgstr "Screen Locking requires the GNOME display manager."
|
||||
|
||||
#: js/ui/messageTray.js:1551
|
||||
#: js/ui/messageTray.js:1554
|
||||
msgid "System Information"
|
||||
msgstr "System Information"
|
||||
|
||||
@ -1477,6 +1611,7 @@ msgstr "Overview"
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: js/ui/overview.js:107
|
||||
#| msgid "Type to search…"
|
||||
msgid "Type to search"
|
||||
msgstr "Type to search"
|
||||
|
||||
@ -1534,12 +1669,12 @@ msgstr "Quit"
|
||||
msgid "Activities"
|
||||
msgstr "Activities"
|
||||
|
||||
#: js/ui/panel.js:713
|
||||
#: js/ui/panel.js:707
|
||||
msgctxt "System menu in the top bar"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: js/ui/panel.js:826
|
||||
#: js/ui/panel.js:820
|
||||
msgid "Top Bar"
|
||||
msgstr "Top Bar"
|
||||
|
||||
@ -1634,6 +1769,7 @@ msgstr ""
|
||||
"To unlock a volume that uses keyfiles, use the <i>%s</i> utility instead."
|
||||
|
||||
#: js/ui/shellMountOperation.js:306
|
||||
#| msgid "Enter PIM Number…"
|
||||
msgid "PIM Number"
|
||||
msgstr "PIM Number"
|
||||
|
||||
@ -1656,13 +1792,13 @@ msgid "The PIM must be a number or empty."
|
||||
msgstr "The PIM must be a number or empty."
|
||||
|
||||
#. Translators: %s is the Disks application
|
||||
#: js/ui/shellMountOperation.js:465
|
||||
#: js/ui/shellMountOperation.js:469
|
||||
#, javascript-format
|
||||
msgid "Unable to start %s"
|
||||
msgstr "Unable to start %s"
|
||||
|
||||
#. Translators: %s is the Disks application
|
||||
#: js/ui/shellMountOperation.js:467
|
||||
#: js/ui/shellMountOperation.js:471
|
||||
#, javascript-format
|
||||
msgid "Couldn’t find the %s application"
|
||||
msgstr "Couldn’t find the %s application"
|
||||
@ -2135,11 +2271,11 @@ msgstr "Thunderbolt authorisation error"
|
||||
msgid "Could not authorize the Thunderbolt device: %s"
|
||||
msgstr "Could not authorise the Thunderbolt device: %s"
|
||||
|
||||
#: js/ui/status/volume.js:151
|
||||
#: js/ui/status/volume.js:150
|
||||
msgid "Volume changed"
|
||||
msgstr "Volume changed"
|
||||
|
||||
#: js/ui/status/volume.js:222
|
||||
#: js/ui/status/volume.js:221
|
||||
msgid "Volume"
|
||||
msgstr "Volume"
|
||||
|
||||
@ -2173,26 +2309,24 @@ msgstr "Built-in Only"
|
||||
|
||||
#. Translators: This is a time format for a date in
|
||||
#. long format
|
||||
#: js/ui/unlockDialog.js:371
|
||||
#: js/ui/unlockDialog.js:372
|
||||
#| msgctxt "calendar heading"
|
||||
#| msgid "%A, %B %-d"
|
||||
msgid "%A %B %-d"
|
||||
msgstr "%A %-d %B"
|
||||
|
||||
#: js/ui/unlockDialog.js:377
|
||||
#: js/ui/unlockDialog.js:378
|
||||
msgid "Swipe up to unlock"
|
||||
msgstr "Swipe up to unlock"
|
||||
|
||||
#: js/ui/unlockDialog.js:378
|
||||
#: js/ui/unlockDialog.js:379
|
||||
msgid "Click or press a key to unlock"
|
||||
msgstr "Click or press a key to unlock"
|
||||
|
||||
#: js/ui/unlockDialog.js:550
|
||||
#: js/ui/unlockDialog.js:552
|
||||
msgid "Unlock Window"
|
||||
msgstr "Unlock Window"
|
||||
|
||||
#: js/ui/unlockDialog.js:559
|
||||
msgid "Log in as another user"
|
||||
msgstr "Log in as another user"
|
||||
|
||||
#: js/ui/viewSelector.js:181
|
||||
msgid "Applications"
|
||||
msgstr "Applications"
|
||||
@ -2308,19 +2442,19 @@ msgstr "Close"
|
||||
msgid "Evolution Calendar"
|
||||
msgstr "Evolution Calendar"
|
||||
|
||||
#: src/main.c:458 subprojects/extensions-tool/src/main.c:249
|
||||
#: src/main.c:460 subprojects/extensions-tool/src/main.c:249
|
||||
msgid "Print version"
|
||||
msgstr "Print version"
|
||||
|
||||
#: src/main.c:464
|
||||
#: src/main.c:466
|
||||
msgid "Mode used by GDM for login screen"
|
||||
msgstr "Mode used by GDM for login screen"
|
||||
|
||||
#: src/main.c:470
|
||||
#: src/main.c:472
|
||||
msgid "Use a specific mode, e.g. “gdm” for login screen"
|
||||
msgstr "Use a specific mode, e.g. “gdm” for login screen"
|
||||
|
||||
#: src/main.c:476
|
||||
#: src/main.c:478
|
||||
msgid "List possible modes"
|
||||
msgstr "List possible modes"
|
||||
|
||||
@ -2346,140 +2480,6 @@ msgstr "Password cannot be blank"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Authentication dialogue was dismissed by the user"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:5
|
||||
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:4
|
||||
#: subprojects/extensions-app/js/main.js:182
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:61
|
||||
msgid "Extensions"
|
||||
msgstr "Extensions"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:6
|
||||
#: subprojects/extensions-app/js/main.js:183
|
||||
msgid "Manage your GNOME Extensions"
|
||||
msgstr "Manage your GNOME Extensions"
|
||||
|
||||
#: subprojects/extensions-app/data/metainfo/org.gnome.Extensions.metainfo.xml.in:35
|
||||
msgid ""
|
||||
"GNOME Extensions handles updating extensions, configuring extension "
|
||||
"preferences and removing or disabling unwanted extensions."
|
||||
msgstr ""
|
||||
"GNOME Extensions handles updating extensions, configuring extension "
|
||||
"preferences and removing or disabling unwanted extensions."
|
||||
|
||||
#: subprojects/extensions-app/data/org.gnome.Extensions.desktop.in.in:7
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "Configure GNOME Shell Extensions"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:144
|
||||
#, javascript-format
|
||||
msgid "Remove “%s”?"
|
||||
msgstr "Remove “%s”?"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:145
|
||||
msgid ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
msgstr ""
|
||||
"If you remove the extension, you need to return to download it if you want "
|
||||
"to enable it again"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:149
|
||||
msgid "Remove"
|
||||
msgstr "Remove"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:181
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
"Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||
"Bruce Cowan <bruce@bcowan.me.uk>\n"
|
||||
"Chris Leonard <cjl@laptop.org>\n"
|
||||
"David King <amigadave@amigadave.com>\n"
|
||||
"Zander Brown <zbrown@gnome.org>"
|
||||
|
||||
#: subprojects/extensions-app/js/main.js:316
|
||||
#, javascript-format
|
||||
msgid "%d extension will be updated on next login."
|
||||
msgid_plural "%d extensions will be updated on next login."
|
||||
msgstr[0] "%d extension will be updated on next login."
|
||||
msgstr[1] "%d extensions will be updated on next login."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:100
|
||||
#: subprojects/extensions-tool/src/command-create.c:211
|
||||
#: subprojects/extensions-tool/src/main.c:173
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:123
|
||||
#: subprojects/extensions-tool/src/main.c:185
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:151
|
||||
msgid "Author"
|
||||
msgstr "Author"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:175
|
||||
msgid "Website"
|
||||
msgstr "Website"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extension-row.ui:192
|
||||
msgid "Remove…"
|
||||
msgstr "Remove…"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:8
|
||||
msgid "Help"
|
||||
msgstr "Help"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:12
|
||||
msgid "About Extensions"
|
||||
msgstr "About Extensions"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:27
|
||||
msgid ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
msgstr ""
|
||||
"To find and add extensions, visit <a href=\"https://extensions.gnome.org"
|
||||
"\">extensions.gnome.org</a>."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:35
|
||||
msgid "Warning"
|
||||
msgstr "Warning"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:46
|
||||
msgid ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
msgstr ""
|
||||
"Extensions can cause system issues, including performance problems. If you "
|
||||
"encounter problems with your system, it is recommended to disable all "
|
||||
"extensions."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:134
|
||||
msgid "Manually Installed"
|
||||
msgstr "Manually Installed"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:158
|
||||
msgid "Built-In"
|
||||
msgstr "Built-In"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:199
|
||||
msgid "No Installed Extensions"
|
||||
msgstr "No Installed Extensions"
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:235
|
||||
msgid ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
msgstr ""
|
||||
"We’re very sorry, but it was not possible to get the list of installed "
|
||||
"extensions. Make sure you are logged into GNOME and try again."
|
||||
|
||||
#: subprojects/extensions-app/data/ui/extensions-window.ui:288
|
||||
msgid "Log Out…"
|
||||
msgstr "Log Out…"
|
||||
|
||||
#. Translators: a file path to an extension directory
|
||||
#: subprojects/extensions-tool/src/command-create.c:125
|
||||
#, c-format
|
||||
@ -2627,6 +2627,7 @@ msgid "Show extensions with preferences"
|
||||
msgstr "Show extensions with preferences"
|
||||
|
||||
#: subprojects/extensions-tool/src/command-list.c:140
|
||||
#| msgid "Show extensions with preferences"
|
||||
msgid "Show extensions with updates"
|
||||
msgstr "Show extensions with updates"
|
||||
|
||||
@ -2817,9 +2818,6 @@ msgstr[1] "%u Inputs"
|
||||
msgid "System Sounds"
|
||||
msgstr "System Sounds"
|
||||
|
||||
#~ msgid "Copy Error"
|
||||
#~ msgstr "Copy Error"
|
||||
|
||||
#~ msgid "Next"
|
||||
#~ msgstr "Next"
|
||||
|
||||
@ -2846,6 +2844,9 @@ msgstr "System Sounds"
|
||||
#~ msgstr[0] "%d new notification"
|
||||
#~ msgstr[1] "%d new notifications"
|
||||
|
||||
#~ msgid "Log in as another user"
|
||||
#~ msgstr "Log in as another user"
|
||||
|
||||
#~| msgid "Shell Extensions"
|
||||
#~ msgid "org.gnome.Extensions"
|
||||
#~ msgstr "org.gnome.Extensions"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user