Compare commits
604 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb6d9734e4 | |||
53be76c9e2 | |||
be40de5a9b | |||
7359e431d3 | |||
8a5de327bb | |||
1778adae0d | |||
0d035a4e53 | |||
46874eed05 | |||
e95f3febd6 | |||
0bdd1b6fc4 | |||
8a22092632 | |||
915415d919 | |||
14d7897a93 | |||
1398aa6562 | |||
8fcd6c7153 | |||
6ed5bc2f6c | |||
5ec4c2e43e | |||
6f8dd065a4 | |||
02db21fc55 | |||
8c28f9a77d | |||
95b80eec01 | |||
02c76695e5 | |||
d5a1a888d9 | |||
6c33aff6d1 | |||
61f86cbc54 | |||
4c5206954a | |||
8fda3116f0 | |||
7ac35c644e | |||
29b04fcbf2 | |||
55235c2552 | |||
f250643385 | |||
d008c6c5c5 | |||
e2e02c9a2f | |||
e56d7f5021 | |||
e7d44bb349 | |||
321730fcb9 | |||
fe83cd91bb | |||
0b08ee54bb | |||
f6b4b96737 | |||
b87455c089 | |||
2c1a81f448 | |||
b3736f45e6 | |||
3c382c4bbe | |||
5f3bad9c94 | |||
6970f43e66 | |||
9476aa598a | |||
69725e5d41 | |||
42dabef8c7 | |||
e10a768ddb | |||
a8f0787c91 | |||
074129682b | |||
c67460a1e3 | |||
eab320dab5 | |||
04c7cb6fbe | |||
d4582491f5 | |||
0641b1e279 | |||
ae0450b68e | |||
cb0a5de83b | |||
2f5086efaf | |||
68e580e394 | |||
b143869d5d | |||
6a477be874 | |||
03bb8cdcbd | |||
8864816b94 | |||
751cd2f1c1 | |||
6f6b6fb9d6 | |||
fe346b89f0 | |||
0744c6af2e | |||
2e070ab834 | |||
00f9b7bf69 | |||
94ba52af0c | |||
44e1a6ce06 | |||
ccf646f54a | |||
4e84b46c9b | |||
b4797956c7 | |||
c1c45f95af | |||
ac09e0110a | |||
0e37cd2ec9 | |||
76dc77f617 | |||
cb4c0d32c0 | |||
3d4ba028c4 | |||
5481c1899f | |||
2fd120162f | |||
523ba5a719 | |||
07d25cd69d | |||
520cea9394 | |||
58c4212cfa | |||
7059e31f6a | |||
a9234f7631 | |||
1e5a8b0cd7 | |||
5ef343f245 | |||
22e33b4c47 | |||
5ace4682bf | |||
14d9839ed3 | |||
3b6fae582b | |||
3cbdf4f9a5 | |||
d8825e0d12 | |||
3c5fea59df | |||
443c8347ea | |||
ee3f52c097 | |||
4b01bb6f99 | |||
27ef8154dc | |||
0a7e717e0e | |||
2d2824b947 | |||
40c2a403ac | |||
238b87d386 | |||
8c01d341c7 | |||
866629b3d3 | |||
2b3ab3ecec | |||
759120b95f | |||
de0e21612c | |||
83e83444db | |||
5060aee7b2 | |||
12bace2721 | |||
2c45b5416e | |||
96c2473317 | |||
6359d6ef30 | |||
2f6323afc2 | |||
d25bcbc3a7 | |||
dd5d7d3b70 | |||
771b1a0788 | |||
5a9d094f3e | |||
9ca8433170 | |||
0ada312748 | |||
88697add1b | |||
4730b7a094 | |||
aa3e64aec3 | |||
af26e2b212 | |||
8167f20972 | |||
bd4aac8f49 | |||
785dd5c5f7 | |||
71e469a59c | |||
6d4b9d29b8 | |||
33f5bb39cd | |||
a1c3900630 | |||
cdaf164c01 | |||
2bd80579ed | |||
54039c3552 | |||
b197a1affb | |||
51655be6a3 | |||
9697c209c0 | |||
6ecb0a4546 | |||
30861d4800 | |||
a23391ea28 | |||
58e0b80cac | |||
41dd744b74 | |||
bdf66d7b62 | |||
4258ae3ec2 | |||
9b379c49ba | |||
7e70dd8453 | |||
2e209a82f9 | |||
ab0ecc469f | |||
7d75ddf635 | |||
271e43a1ed | |||
2702a82896 | |||
8ad33d8752 | |||
d84bbb8770 | |||
c0c2edf2e1 | |||
de0c3251dd | |||
0afd600ea4 | |||
598407b14a | |||
d9bfa16f05 | |||
03117d65b2 | |||
5520bb3890 | |||
4e6b2eb72a | |||
2e5295b3a9 | |||
3121c9aa29 | |||
1ebbd7c768 | |||
8572bb97c7 | |||
d5ebd8c816 | |||
ed999ce926 | |||
50b7739076 | |||
94995e9c1e | |||
fb04dafb0b | |||
d57234bec9 | |||
38da54fb02 | |||
bbd3275dad | |||
3a3f9aa008 | |||
3c54e863e6 | |||
a63ba61194 | |||
ab9710ee7b | |||
43cef45229 | |||
8db4f3c67f | |||
594a070029 | |||
c2e04e3cfa | |||
293f50e8e5 | |||
df7fea3407 | |||
563412698a | |||
2b30146c6c | |||
0f531d8c44 | |||
218c87994b | |||
f74c07b9ac | |||
59edea4bb4 | |||
4d4d5a0b16 | |||
03c4930883 | |||
9593e20425 | |||
2b1d6e607f | |||
1dff32e48a | |||
1e3a174de9 | |||
7bb84dae80 | |||
44fcb9e9af | |||
2d30e310bc | |||
be2d630348 | |||
bea6045aae | |||
ad491e7922 | |||
fedb8e706a | |||
1be933bc49 | |||
526bb72f3d | |||
49c95cff6c | |||
56a361650c | |||
d4763b157d | |||
d2dc072ba9 | |||
ffaca00594 | |||
9090b7dc3d | |||
a540fe4130 | |||
5be61bbb68 | |||
8e51fee5c1 | |||
9d6fcfdc85 | |||
5f5a3b78a5 | |||
4e5ca6d376 | |||
2fab75f448 | |||
22883f2fa2 | |||
5d9f80bc73 | |||
f7d117488b | |||
244a329ee7 | |||
044572cb60 | |||
746875258d | |||
4892a87dfe | |||
8b9c8ddb1e | |||
eb9000576c | |||
862aaf341e | |||
a5c75ff58b | |||
4541fb9819 | |||
9f8edd980c | |||
e5b9043435 | |||
c0012c2ea4 | |||
b77e4975f0 | |||
e83f2344f6 | |||
de6512be1a | |||
0b72ff1896 | |||
fea0192772 | |||
f81ac498fb | |||
5357e0a18c | |||
d7632bbd3d | |||
1b5e91e4b3 | |||
727195c767 | |||
9158f55360 | |||
8146e9d527 | |||
4247251020 | |||
7eee0e0ed6 | |||
4f0851ca77 | |||
911ae49767 | |||
5af81d4057 | |||
c435889baa | |||
49f79d9d5d | |||
1767cd0f6c | |||
3e0915521a | |||
a298943fac | |||
df9ddf96a5 | |||
4fa5d701d5 | |||
b05683d586 | |||
2f3f3fbcdb | |||
611605a67f | |||
0427a782be | |||
32baff5906 | |||
0089143d06 | |||
05e55cee23 | |||
31e7f0340f | |||
6e317a54fd | |||
9c1f62c38c | |||
1341d5557f | |||
b7d79a5f06 | |||
62233a4db4 | |||
4a7e2ddff5 | |||
fb737ebde0 | |||
bf77cb44e7 | |||
c72e2bb4a9 | |||
68c182b1df | |||
348d303794 | |||
ede0fd8660 | |||
187c2193e8 | |||
706bdd8059 | |||
436861edc8 | |||
9729a2e772 | |||
6b924c00c5 | |||
b90f4d29a4 | |||
47915f8c11 | |||
5dfdeaa4ea | |||
98a2a81f2a | |||
c4850027bc | |||
d4202e7f38 | |||
4f65283f31 | |||
d86d3bbe54 | |||
6f794738e8 | |||
ef7a93bb07 | |||
5197a992a6 | |||
49d8540f6d | |||
6e1a1f1a57 | |||
c73428247c | |||
fc2caf5794 | |||
b117826ada | |||
26b44b48ab | |||
6349f0feb1 | |||
2ae17cfb50 | |||
4785093a5c | |||
859aef78c4 | |||
20730a5465 | |||
fc5f687afc | |||
53e56f2395 | |||
da314aff79 | |||
fe89f7c5ac | |||
8b3be5e063 | |||
58dc538510 | |||
6cbef9355d | |||
22eac5c508 | |||
a2860e9c73 | |||
1c5258ab68 | |||
8641eaa538 | |||
88436383c0 | |||
affdcdcb0e | |||
06174be777 | |||
fde8401124 | |||
70ac33d58c | |||
5a897407d9 | |||
1b3c26364b | |||
ae07aa7864 | |||
fb80831269 | |||
561cecf383 | |||
60ccdc2deb | |||
d7d996b1d3 | |||
32b8bc39ac | |||
9dc99ad611 | |||
628cb4d553 | |||
ad80bce78d | |||
1c9d821aa2 | |||
510b060947 | |||
26e33ff093 | |||
5f2bd70690 | |||
6dfa550663 | |||
252e2420ad | |||
572d54981e | |||
61471f9fb4 | |||
4d0a742d64 | |||
5f4e0e5ff8 | |||
a4c159ecad | |||
b1f893e998 | |||
789dc165af | |||
115eda9650 | |||
d027e35cef | |||
b3e178af9d | |||
559ec8750a | |||
02c3980b83 | |||
6f027ee7dc | |||
6d6c2e5b99 | |||
4a4f752459 | |||
8f1fff1374 | |||
deead2af97 | |||
9e881ab637 | |||
b6ec02cef2 | |||
26e3ccda49 | |||
2bda79cb3a | |||
19c60ff5c5 | |||
e3c5c9a2e7 | |||
2c17c186b8 | |||
ef1697d00d | |||
40e7638a4b | |||
aaf69b2898 | |||
0464361ca5 | |||
420697693b | |||
37f53a42da | |||
5617ffc79c | |||
ca4d86e9e5 | |||
0141fef561 | |||
5d4a804c90 | |||
6bc3300e5a | |||
15f69bdc3b | |||
0bcf76970a | |||
03c4628cad | |||
9f4ae9618a | |||
3590af15bb | |||
c5de7fd20e | |||
7127fb1fa1 | |||
7cf11abefc | |||
d78b416e1a | |||
f5144ec899 | |||
08d1ebe7ee | |||
a665801e9f | |||
112e3b110b | |||
94a674c008 | |||
72be8eeb31 | |||
ad8690bb2e | |||
76cb08a72a | |||
2d4989e937 | |||
f248b91f82 | |||
d671eb1969 | |||
70f4906ca5 | |||
ffb9aa1ace | |||
823fd855cf | |||
f5ee225362 | |||
ff1ea4b1c9 | |||
779b5afa51 | |||
6d870f6ae4 | |||
d3926cbca9 | |||
a308804679 | |||
a4e4da705a | |||
7a494ec027 | |||
d53ebb101a | |||
f3168d22a6 | |||
be06101e9a | |||
6e4178981a | |||
b85ea59cda | |||
bbd68626cc | |||
8490173879 | |||
baed9518c2 | |||
27d0d9f2b3 | |||
382282b931 | |||
23d233857e | |||
9620bd0f22 | |||
ecfe56ca63 | |||
eabb02d3da | |||
da3953a388 | |||
2d26dbc96f | |||
7073471302 | |||
81f0e7de9e | |||
33e05f5912 | |||
c1d3e304cb | |||
1b169655ac | |||
67393e09c3 | |||
1ec8d2c531 | |||
a111bfb90a | |||
7dd326f090 | |||
24a26e025b | |||
1eb7ba0506 | |||
d17d99bd6d | |||
fd50b9a45e | |||
a1534dab02 | |||
7484458b7c | |||
5ca039c1db | |||
2294ae0c46 | |||
4d2b2a12ea | |||
c6d57059ff | |||
5f13cf767e | |||
93425b0500 | |||
a87ab6d0fc | |||
1c117c469a | |||
8003f8b803 | |||
7df93458d7 | |||
753618a19f | |||
e355756758 | |||
62a3b9e6a3 | |||
dc79393b27 | |||
c334aa2a4c | |||
9f61a4f5fd | |||
15d0050994 | |||
1846f337d8 | |||
a9e63039ce | |||
7edd5f27d1 | |||
9b47195974 | |||
4ef8041be0 | |||
f0a7395b30 | |||
c1a6effea0 | |||
f78efc46e7 | |||
42ae052da7 | |||
fab390826e | |||
2a9923628b | |||
291aa0b053 | |||
83eb75ad7a | |||
bb215966e5 | |||
545d49c70d | |||
ace44af815 | |||
699e97559d | |||
4aecf4c973 | |||
b092c5f37d | |||
aca8aec94b | |||
9cfb51c106 | |||
e2352f5126 | |||
40e624444c | |||
3cf67b1236 | |||
5dedb97fcc | |||
4590094605 | |||
15e7625c80 | |||
cdd2803498 | |||
43fb2b38b1 | |||
95224bd006 | |||
446183adee | |||
345a8fe748 | |||
d8593c5b4a | |||
f89d721c12 | |||
af34b7c25e | |||
b108aa1ace | |||
5dbf09c008 | |||
680dc18c6b | |||
73413ac6c0 | |||
f61c8e5e1d | |||
36713db990 | |||
6bb7d4002f | |||
aa28d487d3 | |||
a7d974481c | |||
3730314dd5 | |||
6b0c8c9fe0 | |||
28a56d24ad | |||
5e6629e1a7 | |||
a00b967df0 | |||
193e4ae31e | |||
409a27c3b8 | |||
ba97e8da7a | |||
c47e672eea | |||
43a19739ab | |||
36f9147b21 | |||
8647922df9 | |||
df3068d9ca | |||
036e67049b | |||
f02033acb7 | |||
91d73d65c3 | |||
81c4c23016 | |||
fef2bac8ab | |||
c59c5eb893 | |||
a977c1388a | |||
0f799ae313 | |||
23c3f3fdea | |||
82c7090e9e | |||
0fdfebdb67 | |||
208c551787 | |||
b10606e884 | |||
f4a64f77f2 | |||
e92477a752 | |||
37e0a73c8f | |||
4f76e05058 | |||
3134222d27 | |||
a9ed128dce | |||
c264cc4131 | |||
a7943ff934 | |||
c353914dd0 | |||
91319e3963 | |||
dc4ff941bd | |||
b597d5faf0 | |||
f6da36ad3a | |||
5f4e2749a2 | |||
69b1fb699f | |||
259f90bbf6 | |||
8665045326 | |||
a7bb8ee639 | |||
8f732e4f45 | |||
95a31b0c31 | |||
36b9f45368 | |||
46575804cc | |||
86a00b6872 | |||
23d6d13d80 | |||
09addfc87c | |||
a2f27a9409 | |||
412003efbf | |||
582b3aacf4 | |||
1af0b54c1e | |||
74ba2e6634 | |||
78608a5080 | |||
7a86637f8d | |||
c2961f2152 | |||
6845c6f958 | |||
794a056819 | |||
69ad75cf48 | |||
3db52155dd | |||
38805ae662 | |||
dfa0750ffd | |||
d80e7e0118 | |||
b7e2718bdc | |||
e68dfed1f7 | |||
bacfdbbb03 | |||
99ce3deeb0 | |||
d75a3484d6 | |||
3dcb593a71 | |||
1847a4f4cc | |||
deec0bf255 | |||
8bb9eb0fc9 | |||
21de3c327b | |||
081d94e0f6 | |||
ddd1825162 | |||
5f223e0bd8 | |||
809d92129b | |||
8840608a25 | |||
edbb204332 | |||
9dc3b73ef9 | |||
a7d618915c | |||
3e3da8e2f8 | |||
a6763e7731 | |||
8f15193b40 | |||
467b7c1bca | |||
97963a1ca8 | |||
2fc1f1adbe | |||
200f4908d5 | |||
1f864c905d | |||
df77fb6793 | |||
3fa3889fa5 | |||
4b28b90e0f | |||
e0a992af73 | |||
7c4e43c84f | |||
b57832716a | |||
945a019974 | |||
22e21ad7d1 | |||
ae48f8bda9 | |||
62abf3edc7 | |||
f8ce47c24d | |||
ddb3a5c625 | |||
c6d2bc4c57 | |||
e3a0b6d4ee |
1
.gitignore
vendored
@ -80,3 +80,4 @@ tests/run-test.sh
|
||||
*~
|
||||
*.patch
|
||||
*.sw?
|
||||
.vscode
|
||||
|
88
.gitlab-ci.yml
Normal file
@ -0,0 +1,88 @@
|
||||
stages:
|
||||
- review
|
||||
- source_check
|
||||
- build
|
||||
- test
|
||||
|
||||
variables:
|
||||
JS_LOG: "js-report.txt"
|
||||
POT_LOG: "pot-update.txt"
|
||||
|
||||
.only_default: &only_default
|
||||
only:
|
||||
- branches
|
||||
- tags
|
||||
- merge_requests
|
||||
|
||||
check_commit_log:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
script:
|
||||
- ./.gitlab-ci/check-commit-log.sh
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
js_check:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
|
||||
stage: source_check
|
||||
script:
|
||||
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
|
||||
- (! grep -q . $JS_LOG)
|
||||
<<: *only_default
|
||||
only:
|
||||
changes:
|
||||
- js/**/*
|
||||
artifacts:
|
||||
paths:
|
||||
- ${JS_LOG}
|
||||
when: on_failure
|
||||
|
||||
build:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
|
||||
stage: build
|
||||
before_script:
|
||||
- .gitlab-ci/checkout-mutter.sh
|
||||
- meson mutter mutter/build --prefix=/usr -Dtests=false
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
- meson . build -Dbuiltype=debugoptimized
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
<<: *only_default
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- mutter
|
||||
- build
|
||||
|
||||
test:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
|
||||
stage: test
|
||||
before_script:
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
- xvfb-run meson test -C build --no-rebuild
|
||||
<<: *only_default
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- build/meson-logs/testlog.txt
|
||||
when: on_failure
|
||||
|
||||
test-pot:
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
|
||||
stage: test
|
||||
before_script:
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
# Check that pot files are generated correctly:
|
||||
# https://savannah.gnu.org/bugs/?50920#comment5
|
||||
- ninja -C build gnome-shell-pot 2>&1 | awk '
|
||||
BEGIN { start=0; }
|
||||
start==1 { print $0; }
|
||||
/gnome-shell-pot/ { start=1; }
|
||||
' | tee $POT_LOG
|
||||
- (! grep -q . $POT_LOG)
|
||||
<<: *only_default
|
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)' && \
|
||||
|
||||
# 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
|
31
.gitlab-ci/check-commit-log.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
echo Cannot review non-merge request
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
|
||||
branch_point=$(git merge-base HEAD FETCH_HEAD)
|
||||
|
||||
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
|
||||
|
||||
if [ -z "$commits" ]; then
|
||||
echo Commit range empty
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function commit_message_has_url() {
|
||||
commit=$1
|
||||
commit_message=$(git show -s --format='format:%b' $commit)
|
||||
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
|
||||
return $?
|
||||
}
|
||||
|
||||
for commit in $commits; do
|
||||
if ! commit_message_has_url $commit; then
|
||||
echo "Missing merge request or issue URL on commit $(echo $commit | cut -c -8)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
35
.gitlab-ci/checkout-mutter.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
shell_branch=$(git describe --contains --all HEAD)
|
||||
mutter_target=
|
||||
|
||||
git clone https://gitlab.gnome.org/GNOME/mutter.git
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo Checkout failed
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd mutter
|
||||
|
||||
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//gnome-shell/mutter}
|
||||
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
|
||||
echo Looking for $merge_request_branch on remote ...
|
||||
if git fetch -q $merge_request_remote $merge_request_branch 2>/dev/null; then
|
||||
mutter_target=FETCH_HEAD
|
||||
else
|
||||
mutter_target=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
echo Using $mutter_target instead
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$mutter_target" ]; then
|
||||
mutter_target=$(git branch -r -l origin/$shell_branch)
|
||||
mutter_target=${mutter_target:-$(git branch -r -l ${shell_branch#remotes/})}
|
||||
mutter_target=${mutter_target:-origin/master}
|
||||
echo Using $mutter_target instead
|
||||
fi
|
||||
|
||||
git checkout -q $mutter_target
|
31
.project
@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>gnome-shell</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.linuxtools.cdt.autotools.genmakebuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
<nature>org.eclipse.linuxtools.cdt.autotools.autotoolsNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,148 +0,0 @@
|
||||
#Fri Nov 28 14:33:30 EST 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
|
||||
org.eclipse.cdt.core.formatter.alignment_for_compact_if=0
|
||||
org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
|
||||
org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
|
||||
org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
|
||||
org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=next_line_shifted
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_block=next_line_shifted
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=next_line_shifted
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_switch=next_line_shifted
|
||||
org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line
|
||||
org.eclipse.cdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.cdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
|
||||
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
|
||||
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=true
|
||||
org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=true
|
||||
org.eclipse.cdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.cdt.core.formatter.indentation.size=8
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
|
||||
org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.cdt.core.formatter.lineSplit=80
|
||||
org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.cdt.core.formatter.tabulation.char=space
|
||||
org.eclipse.cdt.core.formatter.tabulation.size=2
|
||||
org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
@ -1,4 +0,0 @@
|
||||
#Fri Nov 28 14:33:30 EST 2008
|
||||
eclipse.preferences.version=1
|
||||
formatter_profile=org.eclipse.cdt.ui.default.gnu_profile
|
||||
formatter_settings_version=1
|
@ -1,315 +0,0 @@
|
||||
#Fri Nov 28 14:43:43 EST 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.wst.jsdt.core.codeComplete.argumentPrefixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.argumentSuffixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.fieldPrefixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.fieldSuffixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.localPrefixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.localSuffixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.staticFieldPrefixes=
|
||||
org.eclipse.wst.jsdt.core.codeComplete.staticFieldSuffixes=
|
||||
org.eclipse.wst.jsdt.core.compiler.codegen.inlineJsrBytecode=disabled
|
||||
org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform=1.2
|
||||
org.eclipse.wst.jsdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.wst.jsdt.core.compiler.compliance=1.4
|
||||
org.eclipse.wst.jsdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.wst.jsdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.wst.jsdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.enumIdentifier=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.forbiddenReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.looseVarDecleration=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.nullReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.optionalSemicolon=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.undefinedField=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedFieldReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedMethodReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedTypeReference=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter=ignore
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.wst.jsdt.core.compiler.source=1.3
|
||||
org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns=false
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field=0
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration=0
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package=0
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups=1
|
||||
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations=0
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags=true
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.comment.line_length=80
|
||||
org.eclipse.wst.jsdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.wst.jsdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer=1
|
||||
org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.wst.jsdt.core.formatter.indentation.size=4
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_and_in_type_parameter=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.wst.jsdt.core.formatter.lineSplit=80
|
||||
org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column=false
|
||||
org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.wst.jsdt.core.formatter.tabulation.char=space
|
||||
org.eclipse.wst.jsdt.core.formatter.tabulation.size=4
|
||||
org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true
|
@ -1,10 +0,0 @@
|
||||
#Fri Nov 28 14:39:12 EST 2008
|
||||
eclipse.preferences.version=1
|
||||
formatter_profile=_gjs
|
||||
formatter_settings_version=11
|
||||
org.eclipse.wst.jsdt.ui.exception.name=e
|
||||
org.eclipse.wst.jsdt.ui.gettersetter.use.is=true
|
||||
org.eclipse.wst.jsdt.ui.javadoc=false
|
||||
org.eclipse.wst.jsdt.ui.keywordthis=false
|
||||
org.eclipse.wst.jsdt.ui.overrideannotation=true
|
||||
org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
|
@ -1 +0,0 @@
|
||||
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
@ -1 +0,0 @@
|
||||
Window
|
93
HACKING.md
@ -80,10 +80,7 @@ e.g. `imports.ui.popupMenu`.
|
||||
Each import block should be sorted alphabetically. Don't import modules you
|
||||
don't use.
|
||||
```javascript
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const { GLib, Gio, St } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
@ -121,40 +118,34 @@ See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/N
|
||||
|
||||
## Classes
|
||||
|
||||
There are many approaches to classes in JavaScript. We use our own class framework
|
||||
(sigh), which is built in gjs. The advantage is that it supports inheriting from
|
||||
GObjects, although this feature isn't used very often in the Shell itself.
|
||||
There are many approaches to classes in JavaScript. We use standard ES6 classes
|
||||
whenever possible, that is when not inheriting from GObjects.
|
||||
```javascript
|
||||
var IconLabelMenuItem = new Lang.Class({
|
||||
Name: 'IconLabelMenuItem',
|
||||
Extends: PopupMenu.PopupMenuBaseItem,
|
||||
|
||||
_init(icon, label) {
|
||||
this.parent({ reactive: false });
|
||||
var IconLabelMenuItem = class extends PopupMenu.PopupMenuBaseItem {
|
||||
constructor(icon, label) {
|
||||
super({ reactive: false });
|
||||
this.actor.add_child(icon);
|
||||
this.actor.add_child(label);
|
||||
},
|
||||
}
|
||||
|
||||
open() {
|
||||
log("menu opened!");
|
||||
}
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
|
||||
automatically inherit from Object.
|
||||
For GObject inheritence, we use the GObject.registerClass() function provided
|
||||
by gjs.
|
||||
```javascript
|
||||
var MyActor = GObject.registerClass(
|
||||
class MyActor extends Clutter.Actor {
|
||||
_init(params) {
|
||||
super._init(params);
|
||||
|
||||
* Leave a blank line between the "class header" (Name, Extends, and other
|
||||
things) and the "class body" (methods). Leave a blank line between each
|
||||
method.
|
||||
|
||||
* No space before the colon, one space after.
|
||||
|
||||
* No trailing comma after the last item.
|
||||
|
||||
* Make sure to use a semicolon after the closing paren to the class. It's
|
||||
still a giant function call, even though it may resemble a more
|
||||
conventional syntax.
|
||||
this.name = 'MyCustomActor';
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## GObject Introspection
|
||||
|
||||
@ -162,19 +153,18 @@ GObject Introspection is a powerful feature that allows us to have native
|
||||
bindings for almost any library built around GObject. If a library requires
|
||||
you to inherit from a type to use it, you can do so:
|
||||
```javascript
|
||||
var MyClutterActor = new Lang.Class({
|
||||
Name: 'MyClutterActor',
|
||||
Extends: Clutter.Actor,
|
||||
var MyClutterActor = GObject.registerClass(
|
||||
class MyClutterActor extends Clutter.Actor {
|
||||
|
||||
vfunc_get_preferred_width(actor, forHeight) {
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
return [100, 100];
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(actor, forWidth) {
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
return [100, 100];
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_paint(actor) {
|
||||
vfunc_paint() {
|
||||
let alloc = this.get_allocation_box();
|
||||
Cogl.set_source_color4ub(255, 0, 0, 255);
|
||||
Cogl.rectangle(alloc.x1, alloc.y1,
|
||||
@ -207,20 +197,18 @@ that has a property called `actor`. We call this wrapper class the "delegate".
|
||||
We sometimes use expando properties to set a property called `_delegate` on
|
||||
the actor itself:
|
||||
```javascript
|
||||
var MyClass = new Lang.Class({
|
||||
Name: 'MyClass',
|
||||
|
||||
_init() {
|
||||
var MyClass = class {
|
||||
constructor() {
|
||||
this.actor = new St.Button({ text: "This is a button" });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.actor.connect('clicked', this._onClicked.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onClicked(actor) {
|
||||
actor.set_label("You clicked the button!");
|
||||
}
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
The 'delegate' property is important for anything which trying to get the
|
||||
@ -246,8 +234,6 @@ variable that can be captured in closures.
|
||||
All closures should be wrapped with Function.prototype.bind or use arrow
|
||||
notation.
|
||||
```javascript
|
||||
const Lang = imports.lang;
|
||||
|
||||
let closure1 = () => { this._fnorbate(); };
|
||||
let closure2 = this._fnorbate.bind(this);
|
||||
```
|
||||
@ -255,19 +241,18 @@ notation.
|
||||
A more realistic example would be connecting to a signal on a method of a
|
||||
prototype:
|
||||
```javascript
|
||||
const Lang = imports.lang;
|
||||
const FnorbLib = imports.fborbLib;
|
||||
|
||||
var MyClass = new Lang.Class({
|
||||
var MyClass = class {
|
||||
_init() {
|
||||
let fnorb = new FnorbLib.Fnorb();
|
||||
fnorb.connect('frobate', this._onFnorbFrobate.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onFnorbFrobate(fnorb) {
|
||||
this._updateFnorb();
|
||||
}
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
## Object literal syntax
|
||||
@ -301,23 +286,21 @@ property.
|
||||
```javascript
|
||||
var ANIMATION_TIME = 2000;
|
||||
|
||||
var MyClass = new Lang.Class({
|
||||
Name: 'MyClass',
|
||||
|
||||
_init() {
|
||||
var MyClass = class {
|
||||
constructor() {
|
||||
this.actor = new St.BoxLayout();
|
||||
this._position = 0;
|
||||
},
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position;
|
||||
},
|
||||
}
|
||||
|
||||
set position(value) {
|
||||
this._position = value;
|
||||
this.actor.set_position(value, value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let myThing = new MyClass();
|
||||
Tweener.addTween(myThing,
|
||||
|
199
NEWS
@ -1,3 +1,202 @@
|
||||
3.33.3
|
||||
======
|
||||
* Prepare for optional X11 [Carlos; !378]
|
||||
* Fix opening window menu [Marco; !557]
|
||||
* Reload search providers when installed applications change [Cosimo; !562]
|
||||
* Implement locate-pointer accessibility feature [Olivier; #981]
|
||||
* Allow to disable window menus via session mode [Cosimo; !569]
|
||||
* Implement mouse accessibility [Olivier; !474]
|
||||
* Call GDM's RegisterSession() after startup [Iain; !570]
|
||||
* Fix extended keys popups being hidden by on-screen keyboard [Marco; !583]
|
||||
* Fix top bar being hidden by lock screen [Jonas; !571]
|
||||
* Update theme to better match GTK's Adwaita [Frederik; #841]
|
||||
* Set up GJS profiler when GJS_TRACE_FD is set [Christian; !573]
|
||||
* Misc. bug fixes and cleanups [Jonas, Cosimo, Robert, Florian, Marco, Simon,
|
||||
Laurent, Niels, Will; !551, !555, !464, #1333, !565, !572, !568, !558, #1205,
|
||||
#1336, !579, !576, #1392, !582, !586, #1406, #1351]
|
||||
|
||||
Contributors:
|
||||
Laurent Bigonville, Cosimo Cecchi, Piotr Drąg, Jonas Dreßler,
|
||||
Frederik Feichtmeier, Olivier Fourdan, Carlos Garnacho, Niels De Graef,
|
||||
Christian Hergert, Iain Lane, Robert Mader, Florian Müllner, Simon Schampijer,
|
||||
Jakub Steiner, Will Thompson, Marco Trevisan (Treviño)
|
||||
|
||||
Translators:
|
||||
Kukuh Syafaat [id], Balázs Meskó [hu], Daniel Mustieles [es],
|
||||
Fabio Tomat [fur], Nathan Follens [nl], Goran Vidović [hr], Jordi Mas [ca]
|
||||
|
||||
3.33.2
|
||||
======
|
||||
* Fix keeping actors visible in scrollviews [Marco; #1061]
|
||||
* Move some chrome above popup windows [Jonas D.; !358]
|
||||
* Include 'sandboxed-app-id' in winodw introspection info [Florian; #1289]
|
||||
* Port to libecal-2.0 [Milan; !501]
|
||||
* Support TCRYPT in mount password dialog [segfault; !126]
|
||||
* Misc. bug fixes and cleanups [Florian, Marco, Veerasamy; !517, #745, !499,
|
||||
!510, !515, !546, !549]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Milan Crha, Jonas Dreßler, Florian Müllner, segfault,
|
||||
Veerasamy Sevagen, Marco Trevisan (Treviño)
|
||||
|
||||
Translators:
|
||||
Daniel Mustieles [es]
|
||||
|
||||
3.33.1
|
||||
======
|
||||
* Refine the app menu [Florian; #968]
|
||||
* Refine window preview style [Feichtmeier; !461]
|
||||
* Only emit ::style-changed on actual changes [Carlos; #1153]
|
||||
* Disable emoji on-screen keyboard support on X11 [Florian; #1172]
|
||||
* Fix tablet button mapping overlay [Carlos; #1220]
|
||||
* Don't crash for world clock locations with no timezone [Florian; #1062]
|
||||
* Don't leak old on-screen keyboard layout groups [Carlos; mutter#556]
|
||||
* Fix ellipsization in dialog subtitles/bodies [Marco; !531]
|
||||
* Fix glitch of fullscreen window in workspace switch animation [Jonas D.; !322]
|
||||
* Fix distortion of some image contents [Florian; !525]
|
||||
* Allow dragging unfocused tiled/maximized windows from top bar [Dylan; #679290]
|
||||
* Handle network interface name changes [Fabrice; !534]
|
||||
* Avoid unnecessary style changes when computing :first/:last-child
|
||||
[Florian; !529]
|
||||
* Misc. bug fixes and cleanups [Florian, Marco, Robert, Georges, Carlos, Simon,
|
||||
Jonas D.; !487, !441, !502, !503, !504, !506, #822, !551, !512, !509, !511,
|
||||
#1054, !524, #1065, !331, !540]
|
||||
|
||||
Contributors:
|
||||
Fabrice Bellet, Jonas Dreßler, Feichtmeier, Carlos Garnacho, Robert Mader,
|
||||
Dylan McCall, Simon McVittie, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Marco Trevisan (Treviño)
|
||||
|
||||
Translators:
|
||||
Daniel Mustieles [es], Kukuh Syafaat [id], Fabio Tomat [fur],
|
||||
Carmen Bianca BAKKER [eo], Dingzhong Chen [zh_CN], Tim Sabsch [de]
|
||||
|
||||
3.32.1
|
||||
======
|
||||
* Fix avatar scaling on login screen [Florian; #1024]
|
||||
* Fix distortion of desktop zoom [Florian; #646]
|
||||
* Fix mouse cursor visibility when using desktop zoom [Florian, Marco; #1020]
|
||||
* Fix screen dimming after wake-up on lock screen [Xiaoguang; #900]
|
||||
* Fix Alt+Esc switcher [Florian; #1064]
|
||||
* Respect struts for popover placement [Andrea; #1102]
|
||||
* Fix app icons updates after theme changes [Florian; #1117]
|
||||
* Fix desktop zoom after resolution changes [Marco; #1120]
|
||||
* Implement stick-to-finger workspace switch overview gestures [Florian; #516]
|
||||
* Make World Clocks offsets relative to local time [Florian; #1157]
|
||||
* Fix top app icon disappearing from dash [Florian; #1053]
|
||||
* Update switch style to match new Adwaita [Jakub; !496]
|
||||
* Ensure CSS units are pixel-aligned when scaling is used [Carlos; #91]
|
||||
* Misc. bug fixes and cleanups [Florian, Jakub, Robert, Alex, Carlos, Phil,
|
||||
Marco, Benjamin, AsciiWolf, Ray, verdre; !444, #1016, #1018, !449, #1036,
|
||||
!455, #1094, !440, #1023, #624, #1017, !476, !473, !480, #1130, !485, !481,
|
||||
!490, !489, #1151, !435, #1160, !482, #1150, #1166, !384]
|
||||
|
||||
Contributors:
|
||||
AsciiWolf, Andrea Azzarone, Benjamin Berg, Carlos Garnacho, Victor Ibragimov,
|
||||
Robert Mader, Alex Monday, Florian Müllner, Jakub Steiner, Ray Strode,
|
||||
Marco Trevisan (Treviño), verdre, Xiaoguang Wang, Phil Wyett
|
||||
|
||||
Translators:
|
||||
Victor Ibragimov [tg, af, et, ja], Bruce Cowan [en_GB], Piotr Drąg [tg],
|
||||
Charles Monzat [fr], Khaled Hosny [ar], Goran Vidović [hr],
|
||||
Cheng-Chia Tseng [zh_TW], Carmen Bianca BAKKER [eo], Daniel Mustieles [es],
|
||||
Dušan Kazik [sk]
|
||||
|
||||
3.32.0
|
||||
======
|
||||
* Fix sizing issues in on-screen-keyboard emoji panel [Carlos; !439]
|
||||
* Fix test linker failure on Debian/Ubuntu [Iain; !442]
|
||||
* Avoid assertion when sizing fallback app icons from CSS [Florian; #1027]
|
||||
* Fix mis-sized menu arrows after texture cache changes [Florian; !452]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Iain Lane, Florian Müllner
|
||||
|
||||
Translators:
|
||||
Gábor Kelemen [hu], Victor Ibragimov [tg], Ryuta Fujii [ja], Piotr Drąg [af,
|
||||
tg], Mart Raudsepp [et]
|
||||
|
||||
3.31.92
|
||||
=======
|
||||
* Fix visual glitch in submenus [Alex; #987]
|
||||
* Support fractional scaling [Jonas, Marco; #765011, !5]
|
||||
* Only consider visible children for :first-child/:last-child [Florian; !312]
|
||||
* Hide trailing separator in search results [verdre; !311]
|
||||
* Remember choice in inhibit-shortcuts dialogue [Olivier; !382]
|
||||
* Don't toggle on-screen keyboard on every focus change [Carlos; !397]
|
||||
* Fix legacy tray icons not responding to events on wayland [Florian; #191]
|
||||
* Fix generating French OSK layout [Florian; #997]
|
||||
* Use borderless round user images [Florian; #811]
|
||||
* Misc. bug fixes and cleanups [Andrea, Robert, Florian, Marco, Niels,
|
||||
Benjamin; !414, !417, !420, #996, !408, !422, !425, #1006, !427, !315,
|
||||
#989, !430, !431, !432, #1015, !429, !423, !419, !434]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Alan, Andrea Azzarone, Benjamin Berg, Olivier Fourdan,
|
||||
Carlos Garnacho, Niels De Graef, Robert Mader, Alex Monday, Florian Müllner,
|
||||
Marco Trevisan (Treviño), verdre
|
||||
|
||||
Translators:
|
||||
Carmen Bianca BAKKER [eo], Asier Sarasua Garmendia [eu], Stas Solovey [ru],
|
||||
Changwoo Ryu [ko], Julien Humbert [fr], Milo Casagrande [it],
|
||||
Марко Костић [sr], Ask Hjorth Larsen [da], Kukuh Syafaat [id],
|
||||
Daniel Șerbănescu [ro], Bernd Homuth [de], Trần Ngọc Quân [vi],
|
||||
Nathan Follens [nl], Rūdolfs Mazurs [lv], Aurimas Černius [lt]
|
||||
|
||||
3.31.91
|
||||
=======
|
||||
* Don't close on-screen-keyboard's language menu on hover [Florian; #171]
|
||||
* Don't let unfullscreen gesture interfere with top bar taps [Jonas D.; #552]
|
||||
* Always use symbolic user icon in system menu [Florian; #957]
|
||||
* Add flags parameter in GrabAccelerators API [Andrea; #68]
|
||||
* Misc. bug fixes and cleanups [Florian, Jonas A.; !399, !398, !400, !402,
|
||||
!407, !410, !411]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Andrea Azzarone, Arnaud Bonatti, Jonas Dreßler, Florian Müllner
|
||||
|
||||
Translators:
|
||||
Jordi Mas [ca], Ryuta Fujii [ja], Marek Cernocky [cs], Fran Dieguez [gl],
|
||||
Jiri Grönroos [fi], Serdar Sağlam [tr], Anders Jonsson [sv],
|
||||
Matej Urbančič [sl], Gun Chleoc [gd], Kukuh Syafaat [id],
|
||||
Baurzhan Muftakhidinov [kk], Alan Mortensen [da], Rafael Fontenelle [pt_BR],
|
||||
Sveinn í Felli [is]
|
||||
|
||||
3.31.90
|
||||
=======
|
||||
* Fix input methods after ibus restarts [Takao; #295]
|
||||
* Refresh world clocks and weather sections [Florian; #262]
|
||||
* Port to ES6 classes (update your extensions!) [Florian; !361]
|
||||
* networkAgent: Advise users when WPS support is available [Lubomir; !329]
|
||||
* Performance improvements [Carlos; #832, #815]
|
||||
* Fix drag-and-drop with wacom pens [Carlos; #540]
|
||||
* Fix CAPS LOCK indication on wayland [Carlos; #762881]
|
||||
* Show details of non-sensitive notifications on lock screen [Philip; #726]
|
||||
* Refine extension-prefs' error UI [Florian; !193]
|
||||
* Add switch-to-application-n keybindings [Florian; #648000]
|
||||
* Remove top bar translucency [Florian; #408]
|
||||
* Support emojis and keypads in on-screen keyboard [Carlos; #675]
|
||||
* Don't allow popups to re-enable keyboard shortcuts on lock screen
|
||||
(CVE-2019-3820) [Florian, Ray; #851]
|
||||
* Replace app menu [Florian; #624]
|
||||
* Include commonly copied+pasted extension helpers [Florian; !150]
|
||||
* Misc. bug fixes and cleanups [Florian, Daniel, Philip, Sergio, Pascal,
|
||||
Georges, verdre, Carlos, Christopher; #780, #909, !316, !308, !309, #915,
|
||||
!350, !362, !357, !365, !366, !283, !367, #942, !371, !373, !374, !343,
|
||||
!375, !292, !317, !377, !379, !346, !383, #953, !388]
|
||||
|
||||
Contributors:
|
||||
Sergio Costas, Christopher Davis, Bilal Elmoussaoui, Takao Fujiwara,
|
||||
Carlos Garnacho, Niels De Graef, Christian Kellner, Ignat Loskutov,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack, Lubomir Rintel,
|
||||
Jakub Steiner, Ray Strode, verdre, Daniel van Vugt, Philip Withnall
|
||||
|
||||
Translators:
|
||||
Daniel Mustieles [es], Carmen Bianca BAKKER [eo], Charles Monzat [fr],
|
||||
Pieter Schalk Schoeman [af], Jordi Mas [ca], Matej Urbančič [sl],
|
||||
Fran Dieguez [gl], Balázs Úr [hu], A S Alam [pa], Fabio Tomat [fur],
|
||||
Aurimas Černius [lt], Piotr Drąg [pl], Marek Cernocky [cs], Ryuta Fujii [ja]
|
||||
|
||||
3.31.4
|
||||
======
|
||||
* Improve icon grid performance [Daniel; #174]
|
||||
|
@ -11,6 +11,14 @@ see the [project wiki][project-wiki].
|
||||
|
||||
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
|
||||
|
||||
## Contributing
|
||||
|
||||
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/gnome-shell.
|
||||
|
||||
Commit messages should follow the [GNOME commit message
|
||||
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
|
||||
to either an issue or a merge request in each commit.
|
||||
|
||||
## License
|
||||
GNOME Shell is distributed under the terms of the GNU General Public License,
|
||||
version 2 or later. See the [COPYING][license] file for details.
|
||||
|
40
README.mdwn
Normal file
@ -0,0 +1,40 @@
|
||||
cldr2json
|
||||
=========
|
||||
|
||||
This script converts Unicode CLDR android keyboard layouts to JSON usable by
|
||||
GNOME Shell.
|
||||
|
||||
CLDR keyboard layouts can be found at
|
||||
<http://www.unicode.org/Public/cldr/latest/keyboards.zip>
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
./cldr2json <input file or directory> <output directory>
|
||||
|
||||
example:
|
||||
|
||||
./cldr2json cldr/keyboards/android/ json_layouts/
|
||||
|
||||
|
||||
Keyboard layout mapping
|
||||
=======================
|
||||
|
||||
Unicode CLDR layout identifiers are language codes, while XKB layout
|
||||
identifiers are... something else. The mapping between the two currently uses
|
||||
heuristic based on the layout descriptions, in this order:
|
||||
|
||||
- if the CLDR layout description matches an XKB layout description, chose its
|
||||
XKB identifier
|
||||
- if one word of the CLDR layout description matches an XKB layout
|
||||
description, chose its XKB identifier
|
||||
- if the CLDR layout description matches one word of an XKB layout description,
|
||||
chose its XKB identifier
|
||||
|
||||
That doesn't always work. For instance it fails for "en" language, that should
|
||||
match "us" XKB identifier. For such cases, there is a mapping in
|
||||
LOCALE_TO_XKB_OVERRIDES at the top of the script. If you discover a weird
|
||||
mapping of if you get a "failed to find XKB mapping for <locale>" warning then
|
||||
please consider adding an override there.
|
||||
|
208
cldr2json.py
Executable file
@ -0,0 +1,208 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright 2015 Daiki Ueno <dueno@src.gnome.org>
|
||||
# 2016 Parag Nemade <pnemade@redhat.com>
|
||||
# 2017 Alan <alan@boum.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
import glob
|
||||
import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree
|
||||
|
||||
import gi
|
||||
gi.require_version('GnomeDesktop', '3.0') # NOQA: E402
|
||||
from gi.repository import GnomeDesktop
|
||||
|
||||
ESCAPE_PATTERN = re.compile(r'\\u\{([0-9A-Fa-f]+?)\}')
|
||||
ISO_PATTERN = re.compile(r'[A-E]([0-9]+)')
|
||||
|
||||
LOCALE_TO_XKB_OVERRIDES = {
|
||||
'af': 'za',
|
||||
'en': 'us',
|
||||
'en-GB': 'uk',
|
||||
'es-US': 'latam',
|
||||
'fr-CA': 'ca',
|
||||
'hi': 'in+bolnagri',
|
||||
'ky': 'kg',
|
||||
'nl-BE': 'be',
|
||||
'zu': None
|
||||
}
|
||||
|
||||
|
||||
def parse_single_key(value):
|
||||
def unescape(m):
|
||||
return chr(int(m.group(1), 16))
|
||||
value = ESCAPE_PATTERN.sub(unescape, value)
|
||||
return value
|
||||
|
||||
|
||||
def parse_rows(keymap):
|
||||
unsorted_rows = {}
|
||||
for _map in keymap.iter('map'):
|
||||
value = _map.get('to')
|
||||
key = [parse_single_key(value)]
|
||||
iso = _map.get('iso')
|
||||
if not ISO_PATTERN.match(iso):
|
||||
sys.stderr.write('invalid ISO key name: %s\n' % iso)
|
||||
continue
|
||||
if not iso[0] in unsorted_rows:
|
||||
unsorted_rows[iso[0]] = []
|
||||
unsorted_rows[iso[0]].append((int(iso[1:]), key))
|
||||
# add subkeys
|
||||
longPress = _map.get('longPress')
|
||||
if longPress:
|
||||
for value in longPress.split(' '):
|
||||
subkey = parse_single_key(value)
|
||||
key.append(subkey)
|
||||
|
||||
rows = []
|
||||
for k, v in sorted(list(unsorted_rows.items()),
|
||||
key=lambda x: x[0],
|
||||
reverse=True):
|
||||
row = []
|
||||
for key in sorted(v, key=lambda x: x):
|
||||
row.append(key[1])
|
||||
rows.append(row)
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
def convert_xml(tree):
|
||||
root = {}
|
||||
for xml_keyboard in tree.iter("keyboard"):
|
||||
locale_full = xml_keyboard.get("locale")
|
||||
locale, sep, end = locale_full.partition("-t-")
|
||||
root["locale"] = locale
|
||||
for xml_name in tree.iter("name"):
|
||||
name = xml_name.get("value")
|
||||
root["name"] = name
|
||||
root["levels"] = []
|
||||
# parse levels
|
||||
for index, keymap in enumerate(tree.iter('keyMap')):
|
||||
# FIXME: heuristics here
|
||||
modifiers = keymap.get('modifiers')
|
||||
if not modifiers:
|
||||
mode = 'default'
|
||||
modifiers = ''
|
||||
elif 'shift' in modifiers.split(' '):
|
||||
mode = 'latched'
|
||||
modifiers = 'shift'
|
||||
else:
|
||||
mode = 'locked'
|
||||
level = {}
|
||||
level["level"] = modifiers
|
||||
level["mode"] = mode
|
||||
level["rows"] = parse_rows(keymap)
|
||||
root["levels"].append(level)
|
||||
return root
|
||||
|
||||
|
||||
def locale_to_xkb(locale, name):
|
||||
if locale in sorted(LOCALE_TO_XKB_OVERRIDES.keys()):
|
||||
xkb = LOCALE_TO_XKB_OVERRIDES[locale]
|
||||
logging.debug("override for %s → %s",
|
||||
locale, xkb)
|
||||
if xkb:
|
||||
return xkb
|
||||
else:
|
||||
raise KeyError("layout %s explicitely disabled in overrides"
|
||||
% locale)
|
||||
xkb_names = sorted(name_to_xkb.keys())
|
||||
if name in xkb_names:
|
||||
return name_to_xkb[name]
|
||||
else:
|
||||
logging.debug("name %s failed" % name)
|
||||
for sub_name in name.split(' '):
|
||||
if sub_name in xkb_names:
|
||||
xkb = name_to_xkb[sub_name]
|
||||
logging.debug("dumb mapping failed but match with locale word: "
|
||||
"%s (%s) → %s (%s)",
|
||||
locale, name, xkb, sub_name)
|
||||
return xkb
|
||||
else:
|
||||
logging.debug("sub_name failed")
|
||||
for xkb_name in xkb_names:
|
||||
for xkb_sub_name in xkb_name.split(' '):
|
||||
if xkb_sub_name.strip('()') == name:
|
||||
xkb = name_to_xkb[xkb_name]
|
||||
logging.debug("dumb mapping failed but match with xkb word: "
|
||||
"%s (%s) → %s (%s)",
|
||||
locale, name, xkb, xkb_name)
|
||||
return xkb
|
||||
raise KeyError("failed to find XKB mapping for %s" % locale)
|
||||
|
||||
|
||||
def convert_file(source_file, destination_path):
|
||||
logging.info("Parsing %s", source_file)
|
||||
|
||||
itree = xml.etree.ElementTree.ElementTree()
|
||||
itree.parse(source_file)
|
||||
|
||||
root = convert_xml(itree)
|
||||
|
||||
try:
|
||||
xkb_name = locale_to_xkb(root["locale"], root["name"])
|
||||
except KeyError as e:
|
||||
logging.warn(e)
|
||||
return False
|
||||
destination_file = os.path.join(destination_path, xkb_name + ".json")
|
||||
|
||||
with open(destination_file, 'w', encoding="utf-8") as dest_fd:
|
||||
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
|
||||
|
||||
logging.debug("written %s", destination_file)
|
||||
|
||||
|
||||
def load_xkb_mappings():
|
||||
xkb = GnomeDesktop.XkbInfo()
|
||||
layouts = xkb.get_all_layouts()
|
||||
name_to_xkb = {}
|
||||
|
||||
for layout in layouts:
|
||||
name = xkb.get_layout_info(layout).display_name
|
||||
name_to_xkb[name] = layout
|
||||
|
||||
return name_to_xkb
|
||||
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "C")
|
||||
name_to_xkb = load_xkb_mappings()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "DEBUG" in os.environ:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("supply a CLDR keyboard file")
|
||||
sys.exit(1)
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("supply an output directory")
|
||||
sys.exit(1)
|
||||
|
||||
source = sys.argv[1]
|
||||
destination = sys.argv[2]
|
||||
if os.path.isfile(source):
|
||||
convert_file(source, destination)
|
||||
elif os.path.isdir(source):
|
||||
for path in glob.glob(source + "/*-t-k0-android.xml"):
|
||||
convert_file(path, destination)
|
12
data/dbus-interfaces/org.gnome.Shell.CalendarServer.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<node>
|
||||
<interface name="org.gnome.Shell.CalendarServer">
|
||||
<method name="GetEvents">
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="a(sssbxxa{sv})" direction="out" />
|
||||
</method>
|
||||
<property name="HasCalendars" type="b" access="read" />
|
||||
<signal name="Changed" />
|
||||
</interface>
|
||||
</node>
|
@ -9,9 +9,6 @@
|
||||
<method name="ShowOSD">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
<method name="ShowMonitorLabels">
|
||||
<arg type="a{uv}" direction="in" name="params"/>
|
||||
</method>
|
||||
<method name="ShowMonitorLabels2">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
@ -22,17 +19,22 @@
|
||||
<method name="ShowApplications"/>
|
||||
<method name="GrabAccelerator">
|
||||
<arg type="s" direction="in" name="accelerator"/>
|
||||
<arg type="u" direction="in" name="flags"/>
|
||||
<arg type="u" direction="in" name="modeFlags"/>
|
||||
<arg type="u" direction="in" name="grabFlags"/>
|
||||
<arg type="u" direction="out" name="action"/>
|
||||
</method>
|
||||
<method name="GrabAccelerators">
|
||||
<arg type="a(su)" direction="in" name="accelerators"/>
|
||||
<arg type="a(suu)" direction="in" name="accelerators"/>
|
||||
<arg type="au" direction="out" name="actions"/>
|
||||
</method>
|
||||
<method name="UngrabAccelerator">
|
||||
<arg type="u" direction="in" name="action"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<method name="UngrabAccelerators">
|
||||
<arg type="au" direction="in" name="action"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<signal name="AcceleratorActivated">
|
||||
<arg name="action" type="u"/>
|
||||
<arg name="parameters" type="a{sv}"/>
|
||||
|
15740
data/emoji.json
Normal file
@ -39,6 +39,7 @@
|
||||
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Rfkill.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<file>be.json</file>
|
||||
<file>bg.json</file>
|
||||
<file>by.json</file>
|
||||
<file>ca.json</file>
|
||||
<file>cz.json</file>
|
||||
<file>de.json</file>
|
||||
<file>dk.json</file>
|
||||
@ -54,5 +55,6 @@
|
||||
<file>us.json</file>
|
||||
<file>vn.json</file>
|
||||
<file>za.json</file>
|
||||
<file>emoji.json</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@ -20,12 +20,16 @@
|
||||
<file>no-notifications.svg</file>
|
||||
<file>noise-texture.png</file>
|
||||
<file>pad-osd.css</file>
|
||||
<file alias="icons/pointer-double-click-symbolic.svg">pointer-double-click-symbolic.svg</file>
|
||||
<file alias="icons/pointer-drag-symbolic.svg">pointer-drag-symbolic.svg</file>
|
||||
<file alias="icons/pointer-primary-click-symbolic.svg">pointer-primary-click-symbolic.svg</file>
|
||||
<file alias="icons/pointer-secondary-click-symbolic.svg">pointer-secondary-click-symbolic.svg</file>
|
||||
<file>process-working.svg</file>
|
||||
<file>toggle-off-us.svg</file>
|
||||
<file>toggle-off-intl.svg</file>
|
||||
<file>toggle-off.svg</file>
|
||||
<file>toggle-off-dark.svg</file>
|
||||
<file>toggle-off-hc.svg</file>
|
||||
<file>toggle-on-us.svg</file>
|
||||
<file>toggle-on-intl.svg</file>
|
||||
<file>toggle-on.svg</file>
|
||||
<file>toggle-on-dark.svg</file>
|
||||
<file>toggle-on-hc.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@ -99,7 +99,6 @@
|
||||
</description>
|
||||
</key>
|
||||
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
|
||||
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
|
||||
@ -145,16 +144,41 @@
|
||||
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
|
||||
<description></description>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="keyboard-type" type="s">
|
||||
<default>'touch'</default>
|
||||
<summary>Which keyboard to use</summary>
|
||||
<description>
|
||||
The type of keyboard to use.
|
||||
</description>
|
||||
<key name="switch-to-application-1" type="as">
|
||||
<default>["<Super>1"]</default>
|
||||
<summary>Switch to application 1</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-2" type="as">
|
||||
<default>["<Super>2"]</default>
|
||||
<summary>Switch to application 2</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-3" type="as">
|
||||
<default>["<Super>3"]</default>
|
||||
<summary>Switch to application 3</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-4" type="as">
|
||||
<default>["<Super>4"]</default>
|
||||
<summary>Switch to application 4</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-5" type="as">
|
||||
<default>["<Super>5"]</default>
|
||||
<summary>Switch to application 5</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-6" type="as">
|
||||
<default>["<Super>6"]</default>
|
||||
<summary>Switch to application 6</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-7" type="as">
|
||||
<default>["<Super>7"]</default>
|
||||
<summary>Switch to application 7</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-8" type="as">
|
||||
<default>["<Super>8"]</default>
|
||||
<summary>Switch to application 8</summary>
|
||||
</key>
|
||||
<key name="switch-to-application-9" type="as">
|
||||
<default>["<Super>9"]</default>
|
||||
<summary>Switch to application 9</summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
|
599
data/osk-layouts/ca.json
Normal file
@ -0,0 +1,599 @@
|
||||
{
|
||||
"levels": [
|
||||
{
|
||||
"level": "",
|
||||
"mode": "default",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"q"
|
||||
],
|
||||
[
|
||||
"w"
|
||||
],
|
||||
[
|
||||
"e",
|
||||
"é",
|
||||
"è",
|
||||
"ê",
|
||||
"ë",
|
||||
"%",
|
||||
"ę",
|
||||
"ė",
|
||||
"ē"
|
||||
],
|
||||
[
|
||||
"r"
|
||||
],
|
||||
[
|
||||
"t"
|
||||
],
|
||||
[
|
||||
"y",
|
||||
"%",
|
||||
"ÿ"
|
||||
],
|
||||
[
|
||||
"u",
|
||||
"ù",
|
||||
"û",
|
||||
"%",
|
||||
"ü",
|
||||
"ú",
|
||||
"ū"
|
||||
],
|
||||
[
|
||||
"i",
|
||||
"î",
|
||||
"%",
|
||||
"ï",
|
||||
"ì",
|
||||
"í",
|
||||
"į",
|
||||
"ī"
|
||||
],
|
||||
[
|
||||
"o",
|
||||
"ô",
|
||||
"œ",
|
||||
"%",
|
||||
"ö",
|
||||
"ò",
|
||||
"ó",
|
||||
"õ",
|
||||
"ø",
|
||||
"ō",
|
||||
"º"
|
||||
],
|
||||
[
|
||||
"p"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"s"
|
||||
],
|
||||
[
|
||||
"d"
|
||||
],
|
||||
[
|
||||
"f"
|
||||
],
|
||||
[
|
||||
"g"
|
||||
],
|
||||
[
|
||||
"h"
|
||||
],
|
||||
[
|
||||
"j"
|
||||
],
|
||||
[
|
||||
"k"
|
||||
],
|
||||
[
|
||||
"l"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"z"
|
||||
],
|
||||
[
|
||||
"x"
|
||||
],
|
||||
[
|
||||
"c",
|
||||
"ç",
|
||||
"ć",
|
||||
"č"
|
||||
],
|
||||
[
|
||||
"v"
|
||||
],
|
||||
[
|
||||
"b"
|
||||
],
|
||||
[
|
||||
"n"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
".",
|
||||
"#",
|
||||
"!",
|
||||
",",
|
||||
"?",
|
||||
"-",
|
||||
":",
|
||||
"'",
|
||||
"@"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "shift",
|
||||
"mode": "latched",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"Q"
|
||||
],
|
||||
[
|
||||
"W"
|
||||
],
|
||||
[
|
||||
"E",
|
||||
"É",
|
||||
"È",
|
||||
"Ê",
|
||||
"Ë",
|
||||
"%",
|
||||
"Ę",
|
||||
"Ė",
|
||||
"Ē"
|
||||
],
|
||||
[
|
||||
"R"
|
||||
],
|
||||
[
|
||||
"T"
|
||||
],
|
||||
[
|
||||
"Y",
|
||||
"%",
|
||||
"Ÿ"
|
||||
],
|
||||
[
|
||||
"U",
|
||||
"Ù",
|
||||
"Û",
|
||||
"%",
|
||||
"Ü",
|
||||
"Ú",
|
||||
"Ū"
|
||||
],
|
||||
[
|
||||
"I",
|
||||
"Î",
|
||||
"%",
|
||||
"Ï",
|
||||
"Ì",
|
||||
"Í",
|
||||
"Į",
|
||||
"Ī"
|
||||
],
|
||||
[
|
||||
"O",
|
||||
"Ô",
|
||||
"Œ",
|
||||
"%",
|
||||
"Ö",
|
||||
"Ò",
|
||||
"Ó",
|
||||
"Õ",
|
||||
"Ø",
|
||||
"Ō",
|
||||
"º"
|
||||
],
|
||||
[
|
||||
"P"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"S"
|
||||
],
|
||||
[
|
||||
"D"
|
||||
],
|
||||
[
|
||||
"F"
|
||||
],
|
||||
[
|
||||
"G"
|
||||
],
|
||||
[
|
||||
"H"
|
||||
],
|
||||
[
|
||||
"J"
|
||||
],
|
||||
[
|
||||
"K"
|
||||
],
|
||||
[
|
||||
"L"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"Z"
|
||||
],
|
||||
[
|
||||
"X"
|
||||
],
|
||||
[
|
||||
"C",
|
||||
"Ç",
|
||||
"Ć",
|
||||
"Č"
|
||||
],
|
||||
[
|
||||
"V"
|
||||
],
|
||||
[
|
||||
"B"
|
||||
],
|
||||
[
|
||||
"N"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
".",
|
||||
"#",
|
||||
"!",
|
||||
",",
|
||||
"?",
|
||||
"-",
|
||||
":",
|
||||
"'",
|
||||
"@"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "opt",
|
||||
"mode": "locked",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"1",
|
||||
"¹",
|
||||
"½",
|
||||
"⅓",
|
||||
"¼",
|
||||
"⅛"
|
||||
],
|
||||
[
|
||||
"2",
|
||||
"²",
|
||||
"⅔"
|
||||
],
|
||||
[
|
||||
"3",
|
||||
"³",
|
||||
"¾",
|
||||
"⅜"
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"⁴"
|
||||
],
|
||||
[
|
||||
"5",
|
||||
"⅝"
|
||||
],
|
||||
[
|
||||
"6"
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"⅞"
|
||||
],
|
||||
[
|
||||
"8"
|
||||
],
|
||||
[
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"0",
|
||||
"ⁿ",
|
||||
"∅"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"@"
|
||||
],
|
||||
[
|
||||
"#"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"¢",
|
||||
"£",
|
||||
"€",
|
||||
"¥",
|
||||
"₱"
|
||||
],
|
||||
[
|
||||
"%",
|
||||
"‰"
|
||||
],
|
||||
[
|
||||
"&"
|
||||
],
|
||||
[
|
||||
"-",
|
||||
"_",
|
||||
"–",
|
||||
"—",
|
||||
"·"
|
||||
],
|
||||
[
|
||||
"+",
|
||||
"±"
|
||||
],
|
||||
[
|
||||
"(",
|
||||
"<",
|
||||
"{",
|
||||
"["
|
||||
],
|
||||
[
|
||||
")",
|
||||
">",
|
||||
"}",
|
||||
"]"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"*",
|
||||
"†",
|
||||
"‡",
|
||||
"★"
|
||||
],
|
||||
[
|
||||
"\"",
|
||||
"“",
|
||||
"”",
|
||||
"«",
|
||||
"»"
|
||||
],
|
||||
[
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
],
|
||||
[
|
||||
":"
|
||||
],
|
||||
[
|
||||
";"
|
||||
],
|
||||
[
|
||||
"!",
|
||||
"¡"
|
||||
],
|
||||
[
|
||||
"?",
|
||||
"¿"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"_"
|
||||
],
|
||||
[
|
||||
"/"
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
".",
|
||||
"…"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "opt+shift",
|
||||
"mode": "locked",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"~"
|
||||
],
|
||||
[
|
||||
"`"
|
||||
],
|
||||
[
|
||||
"|"
|
||||
],
|
||||
[
|
||||
"•",
|
||||
"♪",
|
||||
"♥",
|
||||
"♠",
|
||||
"♦",
|
||||
"♣"
|
||||
],
|
||||
[
|
||||
"√"
|
||||
],
|
||||
[
|
||||
"Π",
|
||||
"π"
|
||||
],
|
||||
[
|
||||
"÷"
|
||||
],
|
||||
[
|
||||
"×"
|
||||
],
|
||||
[
|
||||
"¶",
|
||||
"§"
|
||||
],
|
||||
[
|
||||
"∆"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"£"
|
||||
],
|
||||
[
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"€"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
],
|
||||
[
|
||||
"^",
|
||||
"↑",
|
||||
"↓",
|
||||
"←",
|
||||
"→"
|
||||
],
|
||||
[
|
||||
"°",
|
||||
"′",
|
||||
"″"
|
||||
],
|
||||
[
|
||||
"=",
|
||||
"≠",
|
||||
"≈",
|
||||
"∞"
|
||||
],
|
||||
[
|
||||
"{"
|
||||
],
|
||||
[
|
||||
"}"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"\\"
|
||||
],
|
||||
[
|
||||
"©"
|
||||
],
|
||||
[
|
||||
"®"
|
||||
],
|
||||
[
|
||||
"™"
|
||||
],
|
||||
[
|
||||
"℅"
|
||||
],
|
||||
[
|
||||
"["
|
||||
],
|
||||
[
|
||||
"]"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"<",
|
||||
"‹",
|
||||
"≤",
|
||||
"«"
|
||||
],
|
||||
[
|
||||
">",
|
||||
"›",
|
||||
"≥",
|
||||
"»"
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
".",
|
||||
"…"
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"locale": "fr-CA",
|
||||
"name": "French Canada"
|
||||
}
|
@ -6,10 +6,20 @@
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"q"
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"w"
|
||||
"z"
|
||||
],
|
||||
[
|
||||
"e",
|
||||
@ -71,17 +81,7 @@
|
||||
],
|
||||
[
|
||||
[
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
"q"
|
||||
],
|
||||
[
|
||||
"s"
|
||||
@ -106,11 +106,14 @@
|
||||
],
|
||||
[
|
||||
"l"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"z"
|
||||
"w"
|
||||
],
|
||||
[
|
||||
"x"
|
||||
@ -131,7 +134,11 @@
|
||||
"n"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
]
|
||||
],
|
||||
[
|
||||
@ -161,10 +168,20 @@
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"Q"
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"W"
|
||||
"Z"
|
||||
],
|
||||
[
|
||||
"E",
|
||||
@ -226,17 +243,7 @@
|
||||
],
|
||||
[
|
||||
[
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
"Q"
|
||||
],
|
||||
[
|
||||
"S"
|
||||
@ -261,11 +268,14 @@
|
||||
],
|
||||
[
|
||||
"L"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"Z"
|
||||
"W"
|
||||
],
|
||||
[
|
||||
"X"
|
||||
@ -286,7 +296,11 @@
|
||||
"N"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
]
|
||||
],
|
||||
[
|
||||
@ -369,10 +383,10 @@
|
||||
"#"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"€",
|
||||
"¢",
|
||||
"£",
|
||||
"€",
|
||||
"$",
|
||||
"¥",
|
||||
"₱"
|
||||
],
|
||||
@ -511,13 +525,14 @@
|
||||
"£"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"€"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"^",
|
||||
@ -594,6 +609,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"locale": "fr-CA",
|
||||
"name": "French Canada"
|
||||
"locale": "fr",
|
||||
"name": "French"
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
$variant: 'light';
|
||||
|
||||
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
|
||||
@import "gnome-shell-sass/_drawing";
|
||||
@import "gnome-shell-sass/_common";
|
||||
|
@ -2,33 +2,34 @@
|
||||
// it gets @if ed depending on $variant
|
||||
|
||||
|
||||
$base_color: if($variant =='light', #ffffff, #292929);
|
||||
$bg_color: if($variant =='light', #ededed, #393f3f);
|
||||
$fg_color: if($variant =='light', #2e3436, #eeeeec);
|
||||
$base_color: if($variant == 'light', #ffffff, lighten(desaturate(#241f31, 20%), 2%));
|
||||
$bg_color: if($variant == 'light', #f6f5f4, darken(desaturate(#3d3846, 100%), 4%));
|
||||
$fg_color: if($variant == 'light', #2e3436, #eeeeec);
|
||||
|
||||
$selected_fg_color: #ffffff;
|
||||
$selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
|
||||
$selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
|
||||
darken($selected_bg_color, 20%));
|
||||
$borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
|
||||
$borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
|
||||
$link_color: if($variant == 'light', darken($selected_bg_color,10%),
|
||||
lighten($selected_bg_color,20%));
|
||||
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
|
||||
lighten($selected_bg_color,10%));
|
||||
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 10%));
|
||||
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
|
||||
$borders_color: if($variant == 'light', darken($bg_color, 18%), darken($bg_color, 10%));
|
||||
$borders_edge: if($variant == 'light', transparentize(white, 0.2), transparentize($fg_color, 0.93));
|
||||
$link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
|
||||
$link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%));
|
||||
$top_hilight: $borders_edge;
|
||||
|
||||
$warning_color: #f57900;
|
||||
$error_color: #cc0000;
|
||||
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
|
||||
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
|
||||
$error_color: #ff8080;
|
||||
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
|
||||
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
|
||||
|
||||
$osd_fg_color: #eeeeec;
|
||||
$osd_bg_color: #2e3436;
|
||||
$osd_text_color: white;
|
||||
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 12%),0.04);
|
||||
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
|
||||
$osd_insensitive_fg_color: mix($osd_fg_color, opacify($osd_bg_color, 1), 50%);
|
||||
$osd_borders_color: transparentize(black, 0.3);
|
||||
$osd_outer_borders_color: transparentize(white, 0.9);
|
||||
$osd_outer_borders_color: transparentize(white, 0.84);
|
||||
|
||||
$tooltip_borders_color: $osd_outer_borders_color;
|
||||
$shadow_color: transparentize(black, 0.9);
|
||||
|
||||
//insensitive state derived colors
|
||||
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
|
||||
|
@ -37,16 +37,13 @@
|
||||
// possible $t values:
|
||||
// normal, focus, insensitive
|
||||
//
|
||||
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
|
||||
|
||||
@if $t==normal {
|
||||
background-color: $base_color;
|
||||
border-color: $borders_color;
|
||||
@include _shadows($_inner_shadows);
|
||||
|
||||
}
|
||||
@if $t==focus {
|
||||
@include _shadows($_inner_shadows);
|
||||
border-color: if($fc==$selected_bg_color,
|
||||
$selected_borders_color,
|
||||
darken($fc,35%));
|
||||
@ -111,7 +108,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
|
||||
@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: $borders_edge) {
|
||||
//
|
||||
// Button drawing function
|
||||
//
|
||||
@ -130,19 +127,17 @@
|
||||
$_hilight_color: _button_hilight_color($c);
|
||||
$_button_edge: if($edge == none, none, _widget_edge($edge));
|
||||
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
|
||||
|
||||
$_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03);
|
||||
|
||||
@if $t==normal {
|
||||
//
|
||||
// normal button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
|
||||
$osd_bg_color);
|
||||
|
||||
color: $osd_fg_color;
|
||||
background-color: $_bg;
|
||||
border-color: $osd_borders_color;
|
||||
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
|
||||
color: $tc;
|
||||
background-color: $c;
|
||||
border-color: $borders_color;
|
||||
box-shadow: $_button_shadow;
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
}
|
||||
@ -150,26 +145,21 @@
|
||||
//
|
||||
// focused button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
|
||||
lighten($osd_bg_color,3%));
|
||||
|
||||
color: $osd_fg_color;
|
||||
color: $tc;
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
|
||||
box-shadow: inset 0px 0px 0px 2px $selected_bg_color;
|
||||
//border-color: $selected_bg_color;
|
||||
}
|
||||
|
||||
@else if $t==hover {
|
||||
//
|
||||
// active osd button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
|
||||
lighten($osd_bg_color,3%));
|
||||
|
||||
color: white;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: $_bg;
|
||||
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
|
||||
color: $tc;
|
||||
border-color: $borders_color;
|
||||
background-color: $c;
|
||||
box-shadow: $_button_shadow;
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
|
||||
@ -178,27 +168,18 @@
|
||||
//
|
||||
// active osd button
|
||||
//
|
||||
$_bg: if($c!=$bg_color, $c, $osd_borders_color);
|
||||
|
||||
color: white;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: $selected_bg_color;
|
||||
// This should be none, but it's creating some issues with borders, so to
|
||||
// workaround it for now, use inset wich goes through a different code path.
|
||||
// see https://bugzilla.gnome.org/show_bug.cgi?id=752934
|
||||
box-shadow: inset 0 0 black;
|
||||
color: $tc;
|
||||
border-color: $borders_color;
|
||||
background-color: $c;
|
||||
text-shadow: none;
|
||||
icon-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
@else if $t==insensitive {
|
||||
//
|
||||
// insensitive osd button
|
||||
//
|
||||
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
|
||||
|
||||
color: $insensitive_fg_color;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: $_bg;
|
||||
border-color: $insensitive_borders_color;
|
||||
background-color: $insensitive_bg_color;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
icon-shadow: none;
|
||||
|
@ -26,6 +26,7 @@ $osd_borders_color: transparentize(black, 0.3);
|
||||
$osd_outer_borders_color: transparentize(white, 0.9);
|
||||
|
||||
$tooltip_borders_color: $osd_outer_borders_color;
|
||||
$shadow_color: transparentize(black, 0.9);
|
||||
|
||||
//insensitive state derived colors
|
||||
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
|
||||
|
28
data/theme/pointer-double-click-symbolic.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="20"
|
||||
height="20"
|
||||
id="svg2">
|
||||
<g
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="id1"
|
||||
transform="translate(-19,-0.75)">
|
||||
<path
|
||||
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 19.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.38151 2.829427,-2.763021 4.24414,-4.144531 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 0.01057,-0.470226 -0.405577,-0.908445 -0.434651,-1.313638 0.259401,-0.25321 0.518802,-0.50642 0.778203,-0.75963 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 -0.192325,-0.904303 -0.717854,-1.698026 -1.068629,-2.548967 -0.238908,-0.512658 -0.477817,-1.025315 -0.716725,-1.537973 1.755859,0 3.511719,0 5.267578,0 C 34.777352,9.738932 30.31641,5.0970051 25.855469,0.45507812 c 0,2.08138018 0,4.16276048 0,6.24414068 -2,-2.0813802 -4,-4.1627605 -6,-6.24414068 z m 1.5,3.72656248 c 2,2.0813801 4,4.1627603 6,6.2441404 0,-2.0813801 0,-4.1627603 0,-6.2441404 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.366537,0 -2.733073,0 -4.09961,0 0.883468,1.903435 1.781983,3.800273 2.656081,5.707817 0.0065,0.622781 -1.227555,0.980575 -1.325116,0.207118 -0.80433,-1.640251 -1.608661,-3.280501 -2.412991,-4.920752 -1.020182,0.995443 -2.040365,1.990885 -3.060547,2.986328 0.263642,0.608048 0.596803,1.192457 0.814693,1.816134 -0.182662,0.601037 -1.26833,0.8373 -1.365856,0.06795 -0.796094,-1.623456 -1.592189,-3.246912 -2.388284,-4.870368 -1.059245,1.033854 -2.118489,2.067708 -3.177734,3.101562 -4e-6,-4.265002 -7e-6,-8.5300036 -1.1e-5,-12.7950054 z"
|
||||
id="path5565" />
|
||||
</g>
|
||||
<g
|
||||
id="id2"
|
||||
transform="translate(-25,-0.75)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
20
data/theme/pointer-drag-symbolic.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="20"
|
||||
height="20"
|
||||
id="svg2">
|
||||
<g
|
||||
id="g835">
|
||||
<path
|
||||
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 10.705078 1.671875 C 9.8685536 1.7465699 8.886927 1.5353073 8.2578125 2.2480469 C 8.0785627 2.7511513 7.8667422 2.9777446 7.3125 2.8652344 C 6.5186841 2.8141575 5.6105879 2.9190179 5.125 3.6386719 C 4.5700923 4.4696324 4.8113194 5.4949043 4.7578125 6.4316406 L 4.7578125 7.9335938 C 4.2480917 7.6156216 3.6258927 7.8015358 3.0585938 7.7519531 C 2.6157606 7.7312277 2.1774807 7.7771069 1.7402344 7.84375 C 1.7971654 10.529678 1.813967 13.217089 1.8613281 15.902344 C 1.9550191 17.204635 3.0933719 18.307155 4.40625 18.326172 C 5.0391993 18.341272 5.8885801 18.332951 6.6308594 18.337891 C 9.8526764 18.325821 13.076973 18.38774 16.296875 18.28125 C 17.459088 18.161027 18.510143 17.092798 18.367188 15.884766 L 18.367188 6.4042969 C 17.660379 5.4636119 16.551912 4.623434 15.308594 4.8339844 C 15.009045 4.3804158 14.822476 3.3608651 14.082031 3.0351562 C 13.727176 2.744118 13.242443 2.9253873 12.822266 2.8730469 C 12.524824 2.8003648 11.966366 3.0655864 11.953125 2.6210938 C 11.795774 2.0995736 11.23789 1.7125276 10.705078 1.671875 z M 10.599609 3.1757812 C 10.764131 3.4472414 10.782382 3.9294982 10.818359 4.3007812 C 10.824915 4.3076775 10.838155 4.3066925 10.845703 4.3125 C 10.836598 4.3123268 10.827465 4.3126732 10.818359 4.3125 L 11.3125 10.212891 L 11.976562 4.3710938 L 13.322266 4.375 C 13.858345 4.7645492 13.735252 5.5154752 13.876953 6.0976562 C 13.865826 6.1651282 13.88335 6.1937019 13.892578 6.234375 C 13.891928 6.2343667 13.891276 6.2343833 13.890625 6.234375 L 13.902344 6.3203125 L 14.384766 10.185547 L 15.048828 6.265625 C 15.622863 6.228498 16.206517 6.3041365 16.607422 6.7675781 C 17.017062 6.9844433 16.823063 7.4565491 16.867188 7.8261719 L 16.867188 16.167969 C 16.530129 17.131654 15.267211 16.71624 14.492188 16.828125 C 11.121671 16.841205 7.7500508 16.861953 4.3808594 16.814453 C 3.4051926 16.786173 3.2389196 15.744474 3.3398438 14.972656 C 3.3282027 13.065594 3.2950998 11.158732 3.2617188 9.2519531 C 3.5880829 9.2584131 3.9376766 9.2391948 4.25 9.2617188 C 4.7438842 10.17694 4.7346154 11.262903 4.7578125 12.277344 C 5.2504494 12.270544 5.8011939 12.317174 6.2578125 12.277344 C 6.2669593 9.7577406 6.2393741 7.2373172 6.2714844 4.71875 C 6.3763823 4.198849 7.0022289 4.409587 7.3828125 4.3652344 L 8.0585938 4.3652344 L 8.546875 10.212891 L 9.2167969 4.3359375 L 9.2128906 4.3359375 C 9.2438386 3.9531035 9.0622615 3.4401006 9.4609375 3.2167969 L 10.599609 3.1757812 z "
|
||||
id="path5630" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
26
data/theme/pointer-primary-click-symbolic.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="20"
|
||||
height="20"
|
||||
id="svg2"
|
||||
version="1.1">
|
||||
<g
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="id1"
|
||||
transform="translate(-22.25,-0.75)">
|
||||
<path
|
||||
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
|
||||
id="path5565" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
26
data/theme/pointer-secondary-click-symbolic.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="20"
|
||||
height="20"
|
||||
id="svg2">
|
||||
<g
|
||||
id="layer1"
|
||||
style="display:inline;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,42,-0.75)"
|
||||
id="g5847"
|
||||
style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
|
||||
<path
|
||||
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
|
||||
id="path5851" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
1
data/theme/toggle-off-dark.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-42.76)"/></defs><g transform="translate(0 -291.18)" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#323233" stroke="#272728"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none" fill="url(#b)" stroke="#151515"/></g></svg>
|
After Width: | Height: | Size: 725 B |
@ -1,209 +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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="65"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="toggle-off-us.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4"
|
||||
id="linearGradient38024"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
|
||||
x1="6"
|
||||
y1="102.95528"
|
||||
x2="6"
|
||||
y2="84.505203" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient76469-7-7-4">
|
||||
<stop
|
||||
style="stop-color:#2e3232;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop76471-7-1-5" />
|
||||
<stop
|
||||
style="stop-color:#3e4545;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76473-9-0-0" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4-0"
|
||||
is_visible="true" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient37802-8"
|
||||
id="linearGradient12311-3-1-0-5-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
|
||||
x1="610.13782"
|
||||
y1="501.43866"
|
||||
x2="610.13782"
|
||||
y2="492.52756" />
|
||||
<linearGradient
|
||||
id="linearGradient37802-8"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop37804-1"
|
||||
offset="0"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop37806-8"
|
||||
offset="1"
|
||||
style="stop-color:#16191a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="492.52756"
|
||||
x2="610.13782"
|
||||
y1="501.43866"
|
||||
x1="610.13782"
|
||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient13602"
|
||||
xlink:href="#linearGradient37802-8"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-5.0602834"
|
||||
inkscape:cy="16.473273"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1375"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<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(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
id="g37996"
|
||||
transform="translate(-115,1277)">
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
|
||||
id="rect13475"
|
||||
width="98"
|
||||
height="25"
|
||||
x="644.5"
|
||||
y="484.61118"
|
||||
rx="4.7429576"
|
||||
ry="3.8424656" />
|
||||
<rect
|
||||
ry="3.8424656"
|
||||
rx="4.7429576"
|
||||
y="483.5"
|
||||
x="644.5"
|
||||
height="25"
|
||||
width="98"
|
||||
id="rect38000"
|
||||
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-49.946213,-1.890275)"
|
||||
id="g38002">
|
||||
<g
|
||||
transform="translate(-115,1247)"
|
||||
style="display:inline"
|
||||
id="g38004">
|
||||
<rect
|
||||
ry="3.7972314"
|
||||
rx="4.6871223"
|
||||
y="515.5"
|
||||
x="694.53046"
|
||||
height="25"
|
||||
width="45.969578"
|
||||
id="rect38006"
|
||||
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 699.09675,516.7365 36.86904,0"
|
||||
id="path38016"
|
||||
inkscape:path-effect="#path-effect77541-4"
|
||||
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:2.15627193;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
||||
id="path13479"
|
||||
sodipodi:cx="16.4375"
|
||||
sodipodi:cy="10.8125"
|
||||
sodipodi:rx="4.3125"
|
||||
sodipodi:ry="4.3125"
|
||||
d="m 20.75,10.8125 a 4.3125,4.3125 0 1 1 -8.625,0 4.3125,4.3125 0 1 1 8.625,0 z"
|
||||
transform="matrix(1.4212691,0,0,1.1514287,577.38488,1761.1138)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 7.5 KiB |
@ -1,255 +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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="65"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="toggle-on-intl.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4"
|
||||
id="linearGradient38024"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
|
||||
x1="6"
|
||||
y1="102.95528"
|
||||
x2="6"
|
||||
y2="84.505203" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient76469-7-7-4">
|
||||
<stop
|
||||
style="stop-color:#2e3232;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop76471-7-1-5" />
|
||||
<stop
|
||||
style="stop-color:#3e4545;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76473-9-0-0" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient37802"
|
||||
id="linearGradient12311-3-1-0-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
|
||||
x1="610.13782"
|
||||
y1="501.43866"
|
||||
x2="610.13782"
|
||||
y2="492.52756" />
|
||||
<linearGradient
|
||||
id="linearGradient37802"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop37804"
|
||||
offset="0"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop37806"
|
||||
offset="1"
|
||||
style="stop-color:#16191a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4-3"
|
||||
id="linearGradient77680"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,1.0322581,717.71949,428.68472)"
|
||||
x1="6"
|
||||
y1="102.95528"
|
||||
x2="6"
|
||||
y2="84.505203" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient76469-7-7-4-3">
|
||||
<stop
|
||||
style="stop-color:#2e3232;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop76471-7-1-5-7" />
|
||||
<stop
|
||||
style="stop-color:#3e4545;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76473-9-0-0-9" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4-0"
|
||||
is_visible="true" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient37802-8"
|
||||
id="linearGradient12311-3-1-0-5-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
|
||||
x1="610.13782"
|
||||
y1="501.43866"
|
||||
x2="610.13782"
|
||||
y2="492.52756" />
|
||||
<linearGradient
|
||||
id="linearGradient37802-8"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop37804-1"
|
||||
offset="0"
|
||||
style="stop-color:#2c2c2c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop37806-8"
|
||||
offset="1"
|
||||
style="stop-color:#16191a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="492.52756"
|
||||
x2="610.13782"
|
||||
y1="501.43866"
|
||||
x1="610.13782"
|
||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient13602"
|
||||
xlink:href="#linearGradient37802-8"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="16.760995"
|
||||
inkscape:cy="21.955673"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1375"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<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(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
id="g37996"
|
||||
transform="translate(-115,1277)">
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
|
||||
id="rect13475"
|
||||
width="98"
|
||||
height="25"
|
||||
x="644.5"
|
||||
y="484.61118"
|
||||
rx="4.7429576"
|
||||
ry="3.8424656" />
|
||||
<rect
|
||||
ry="3.8424656"
|
||||
rx="4.7429576"
|
||||
y="483.5"
|
||||
x="644.5"
|
||||
height="25"
|
||||
width="98"
|
||||
id="rect38000"
|
||||
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-49.946213,-1.890275)"
|
||||
id="g38002">
|
||||
<g
|
||||
transform="translate(-115,1247)"
|
||||
style="display:inline"
|
||||
id="g38004">
|
||||
<rect
|
||||
ry="3.7972314"
|
||||
rx="4.6871223"
|
||||
y="515.5"
|
||||
x="694.53046"
|
||||
height="25"
|
||||
width="45.969578"
|
||||
id="rect38006"
|
||||
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 699.09675,516.7365 36.86904,0"
|
||||
id="path38016"
|
||||
inkscape:path-effect="#path-effect77541-4"
|
||||
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:13.79166794px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
|
||||
x="520.29974"
|
||||
y="1997.0011"
|
||||
id="text75614"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="scale(1.1236771,0.88993537)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan75616"
|
||||
x="520.29974"
|
||||
y="1997.0011">OFF</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 8.8 KiB |
1
data/theme/toggle-off.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#e1dedb" stroke="#cdc7c2" stroke-linecap="round" stroke-linejoin="round"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke="#aa9f98" stroke-linecap="round" stroke-linejoin="round"/><g transform="matrix(.97148 0 0 1 1658.914 -2552.91)" stroke-width="1.015" stroke-linecap="round" stroke-linejoin="round"><rect ry="13.17" rx="13.556" y="1234.681" x="-1242.732" height="26" width="49.409" style="marker:none" fill="#e1dedb" stroke="#cdc7c2"/><rect style="marker:none" width="26.763" height="26" x="-1242.732" y="1234.769" rx="13.511" ry="13.126" fill="#f8f7f7" stroke="#aa9f98"/></g><g transform="matrix(.97148 0 0 1 1658.914 -2512.91)" stroke-width="1.015" stroke="#2b73cc"><rect style="marker:none" width="49.409" height="26" x="-1242.732" y="1234.681" rx="13.556" ry="13.17" fill="#3081e3"/><rect ry="13.126" rx="13.511" y="1234.769" x="-1220.086" height="26" width="26.763" style="marker:none" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
data/theme/toggle-on-dark.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-19)"/></defs><g transform="translate(0 -291.18)" stroke="#030e1b" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#15539e"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none" fill="url(#b)"/></g></svg>
|
After Width: | Height: | Size: 707 B |
@ -1,192 +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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="65"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-on-intl.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461"
|
||||
id="linearGradient77551"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
|
||||
x1="1164.7644"
|
||||
y1="962.93695"
|
||||
x2="1164.7644"
|
||||
y2="970.51404" />
|
||||
<linearGradient
|
||||
id="linearGradient77461"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop77463"
|
||||
offset="0"
|
||||
style="stop-color:#182f4c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop77465"
|
||||
offset="1"
|
||||
style="stop-color:#205b9a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4"
|
||||
id="linearGradient38024"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
|
||||
x1="6"
|
||||
y1="102.95528"
|
||||
x2="6"
|
||||
y2="84.505203" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient76469-7-7-4">
|
||||
<stop
|
||||
style="stop-color:#2e3232;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop76471-7-1-5" />
|
||||
<stop
|
||||
style="stop-color:#3e4545;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76473-9-0-0" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="37.410841"
|
||||
inkscape:cy="16.009314"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
id="g37996"
|
||||
transform="translate(-115,1277)">
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
|
||||
id="rect13475"
|
||||
width="98"
|
||||
height="25"
|
||||
x="644.5"
|
||||
y="484.61118"
|
||||
rx="4.7429576"
|
||||
ry="3.8424656" />
|
||||
<rect
|
||||
ry="3.8424656"
|
||||
rx="4.7429576"
|
||||
y="483.5"
|
||||
x="644.5"
|
||||
height="25"
|
||||
width="98"
|
||||
id="rect38000"
|
||||
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(2.0625,-2)"
|
||||
id="g38002">
|
||||
<g
|
||||
transform="translate(-115,1247)"
|
||||
style="display:inline"
|
||||
id="g38004">
|
||||
<rect
|
||||
ry="3.7972314"
|
||||
rx="4.6871223"
|
||||
y="515.5"
|
||||
x="694.53046"
|
||||
height="25"
|
||||
width="45.969578"
|
||||
id="rect38006"
|
||||
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 699.09675,516.7365 36.86904,0"
|
||||
id="path38016"
|
||||
inkscape:path-effect="#path-effect77541-4"
|
||||
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
||||
id="rect13678"
|
||||
width="3.0646207"
|
||||
height="12.414008"
|
||||
x="554.77728"
|
||||
y="1767.3566" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 6.8 KiB |
@ -1,207 +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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="65"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-on-us.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4"
|
||||
id="linearGradient38024"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
|
||||
x1="6"
|
||||
y1="102.95528"
|
||||
x2="6"
|
||||
y2="84.505203" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient76469-7-7-4">
|
||||
<stop
|
||||
style="stop-color:#2e3232;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop76471-7-1-5" />
|
||||
<stop
|
||||
style="stop-color:#3e4545;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop76473-9-0-0" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
<linearGradient
|
||||
id="linearGradient77461-1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop77463-1"
|
||||
offset="0"
|
||||
style="stop-color:#182f4c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop77465-4"
|
||||
offset="1"
|
||||
style="stop-color:#205b9a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461-1"
|
||||
id="linearGradient77551-6-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8527367,0,0,0.80554422,-969.41608,-778.00299)"
|
||||
x1="1164.7644"
|
||||
y1="962.93695"
|
||||
x2="1164.7644"
|
||||
y2="970.51404" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461-1"
|
||||
id="linearGradient11198"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.3066667,0,0,1,-1066.3709,794.25325)"
|
||||
x1="1322.5831"
|
||||
y1="-312.51855"
|
||||
x2="1322.5831"
|
||||
y2="-306.53461" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-26.798898"
|
||||
inkscape:cy="5.3753009"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
id="g37996"
|
||||
transform="translate(-115,1277)">
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
|
||||
id="rect13475"
|
||||
width="98"
|
||||
height="25"
|
||||
x="644.5"
|
||||
y="484.61118"
|
||||
rx="4.7429576"
|
||||
ry="3.8424656" />
|
||||
<rect
|
||||
ry="3.8424656"
|
||||
rx="4.7429576"
|
||||
y="483.5"
|
||||
x="644.5"
|
||||
height="25"
|
||||
width="98"
|
||||
id="rect38000"
|
||||
style="color:#000000;fill:url(#linearGradient11198);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;clip-rule:nonzero;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(2.0625,-2)"
|
||||
id="g38002">
|
||||
<g
|
||||
transform="translate(-115,1247)"
|
||||
style="display:inline"
|
||||
id="g38004">
|
||||
<rect
|
||||
ry="3.7972314"
|
||||
rx="4.6871223"
|
||||
y="515.5"
|
||||
x="694.53046"
|
||||
height="25"
|
||||
width="45.969578"
|
||||
id="rect38006"
|
||||
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 699.09675,516.7365 36.86904,0"
|
||||
id="path38016"
|
||||
inkscape:path-effect="#path-effect77541-4"
|
||||
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
transform="scale(1.1000946,0.90901274)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text38018"
|
||||
y="1955.5205"
|
||||
x="495.94223"
|
||||
style="font-size:13.29953671px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="1955.5205"
|
||||
x="495.94223"
|
||||
id="tspan38020"
|
||||
sodipodi:role="line">ON</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 7.7 KiB |
1
data/theme/toggle-on.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)" stroke="#2b73cc"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#3081e3"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></svg>
|
After Width: | Height: | Size: 473 B |
@ -40,6 +40,7 @@ do
|
||||
done
|
||||
|
||||
cat >>$TMP_GRESOURCE_FILE <<EOF
|
||||
<file>emoji.json</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
EOF
|
||||
|
@ -1,12 +1,5 @@
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Gettext = imports.gettext;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Pango = imports.gi.Pango;
|
||||
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
|
||||
const Format = imports.format;
|
||||
|
||||
const _ = Gettext.gettext;
|
||||
@ -24,9 +17,8 @@ function stripPrefix(string, prefix) {
|
||||
return string;
|
||||
}
|
||||
|
||||
var Application = new Lang.Class({
|
||||
Name: 'Application',
|
||||
_init() {
|
||||
var Application = class {
|
||||
constructor() {
|
||||
GLib.set_prgname('gnome-shell-extension-prefs');
|
||||
this.application = new Gtk.Application({
|
||||
application_id: 'org.gnome.shell.ExtensionPrefs',
|
||||
@ -42,7 +34,7 @@ var Application = new Lang.Class({
|
||||
this._startupUuid = null;
|
||||
this._loaded = false;
|
||||
this._skipMainWindow = false;
|
||||
},
|
||||
}
|
||||
|
||||
_extensionAvailable(uuid) {
|
||||
let extension = ExtensionUtils.extensions[uuid];
|
||||
@ -54,7 +46,7 @@ var Application = new Lang.Class({
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_getExtensionPrefsModule(extension) {
|
||||
let uuid = extension.metadata.uuid;
|
||||
@ -69,7 +61,7 @@ var Application = new Lang.Class({
|
||||
|
||||
this._extensionPrefsModules[uuid] = prefsModule;
|
||||
return prefsModule;
|
||||
},
|
||||
}
|
||||
|
||||
_selectExtension(uuid) {
|
||||
if (!this._extensionAvailable(uuid))
|
||||
@ -104,33 +96,122 @@ var Application = new Lang.Class({
|
||||
dialog.set_default_size(600, 400);
|
||||
dialog.add(widget);
|
||||
dialog.show();
|
||||
},
|
||||
}
|
||||
|
||||
_buildErrorUI(extension, exc) {
|
||||
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
||||
let scroll = new Gtk.ScrolledWindow({
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
propagate_natural_height: true
|
||||
});
|
||||
|
||||
let box = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 12,
|
||||
margin: 100,
|
||||
margin_bottom: 60
|
||||
});
|
||||
scroll.add(box);
|
||||
|
||||
let label = new Gtk.Label({
|
||||
label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
|
||||
label: '<span size="x-large">%s</span>'.format(_("Something’s gone wrong")),
|
||||
use_markup: true
|
||||
});
|
||||
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
|
||||
box.add(label);
|
||||
|
||||
label = new Gtk.Label({
|
||||
label: _("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 extension authors."),
|
||||
justify: Gtk.Justification.CENTER,
|
||||
wrap: true
|
||||
});
|
||||
box.add(label);
|
||||
|
||||
let errortext = '';
|
||||
errortext += exc;
|
||||
errortext += '\n\n';
|
||||
errortext += 'Stack trace:\n';
|
||||
let expander = new Expander({
|
||||
label: _("Technical Details"),
|
||||
margin_top: 12
|
||||
});
|
||||
box.add(expander);
|
||||
|
||||
// Indent stack trace.
|
||||
errortext += exc.stack.split('\n').map(line => ' ' + line).join('\n');
|
||||
let errortext = `${exc}\n\nStack trace:\n${
|
||||
// Indent stack trace.
|
||||
exc.stack.split('\n').map(line => ` ${line}`).join('\n')
|
||||
}`;
|
||||
|
||||
let scroll = new Gtk.ScrolledWindow({ vexpand: true });
|
||||
let buffer = new Gtk.TextBuffer({ text: errortext });
|
||||
let textview = new Gtk.TextView({ buffer: buffer });
|
||||
textview.override_font(Pango.font_description_from_string('monospace'));
|
||||
scroll.add(textview);
|
||||
box.add(scroll);
|
||||
let textview = new Gtk.TextView({
|
||||
buffer: buffer,
|
||||
wrap_mode: Gtk.WrapMode.WORD,
|
||||
monospace: true,
|
||||
editable: false,
|
||||
top_margin: 12,
|
||||
bottom_margin: 12,
|
||||
left_margin: 12,
|
||||
right_margin: 12
|
||||
});
|
||||
|
||||
box.show_all();
|
||||
return box;
|
||||
},
|
||||
let toolbar = new Gtk.Toolbar();
|
||||
let provider = new Gtk.CssProvider();
|
||||
provider.load_from_data(`* {
|
||||
border: 0 solid @borders;
|
||||
border-top-width: 1px;
|
||||
}`);
|
||||
toolbar.get_style_context().add_provider(
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
);
|
||||
|
||||
let copyButton = new Gtk.ToolButton({
|
||||
icon_name: 'edit-copy-symbolic',
|
||||
tooltip_text: _("Copy Error")
|
||||
});
|
||||
toolbar.add(copyButton);
|
||||
|
||||
copyButton.connect('clicked', w => {
|
||||
let clipboard = Gtk.Clipboard.get_default(w.get_display());
|
||||
// markdown for pasting in gitlab issues
|
||||
let lines = [
|
||||
`The settings of extension ${extension.uuid} had an error:`,
|
||||
'```',
|
||||
`${exc}`,
|
||||
'```',
|
||||
'',
|
||||
'Stack trace:',
|
||||
'```',
|
||||
exc.stack.replace(/\n$/, ''), // stack without trailing newline
|
||||
'```',
|
||||
''
|
||||
];
|
||||
clipboard.set_text(lines.join('\n'), -1);
|
||||
});
|
||||
|
||||
let spacing = new Gtk.SeparatorToolItem({ draw: false });
|
||||
toolbar.add(spacing);
|
||||
toolbar.child_set_property(spacing, "expand", true);
|
||||
|
||||
let urlButton = new Gtk.ToolButton({
|
||||
label: _("Homepage"),
|
||||
tooltip_text: _("Visit extension homepage"),
|
||||
no_show_all: true,
|
||||
visible: extension.metadata.url != null
|
||||
});
|
||||
toolbar.add(urlButton);
|
||||
|
||||
urlButton.connect('clicked', w => {
|
||||
let context = w.get_display().get_app_launch_context();
|
||||
Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context);
|
||||
});
|
||||
|
||||
let expandedBox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL
|
||||
});
|
||||
expandedBox.add(textview);
|
||||
expandedBox.add(toolbar);
|
||||
|
||||
expander.add(expandedBox);
|
||||
|
||||
scroll.show_all();
|
||||
return scroll;
|
||||
}
|
||||
|
||||
_buildUI(app) {
|
||||
this._window = new Gtk.ApplicationWindow({ application: app,
|
||||
@ -150,8 +231,12 @@ var Application = new Lang.Class({
|
||||
Gio.SettingsBindFlags.DEFAULT |
|
||||
Gio.SettingsBindFlags.INVERT_BOOLEAN);
|
||||
|
||||
this._mainStack = new Gtk.Stack({
|
||||
transition_type: Gtk.StackTransitionType.CROSSFADE
|
||||
});
|
||||
this._window.add(this._mainStack);
|
||||
|
||||
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
this._window.add(scroll);
|
||||
|
||||
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE });
|
||||
this._extensionSelector.set_sort_func(this._sortList.bind(this));
|
||||
@ -159,6 +244,8 @@ var Application = new Lang.Class({
|
||||
|
||||
scroll.add(this._extensionSelector);
|
||||
|
||||
this._mainStack.add_named(scroll, 'listing');
|
||||
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
|
||||
|
||||
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
|
||||
this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
|
||||
@ -167,13 +254,13 @@ var Application = new Lang.Class({
|
||||
});
|
||||
|
||||
this._window.show_all();
|
||||
},
|
||||
}
|
||||
|
||||
_sortList(row1, row2) {
|
||||
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
|
||||
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
|
||||
return name1.localeCompare(name2);
|
||||
},
|
||||
}
|
||||
|
||||
_updateHeader(row, before) {
|
||||
if (!before || row.get_header())
|
||||
@ -181,14 +268,14 @@ var Application = new Lang.Class({
|
||||
|
||||
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
|
||||
row.set_header(sep);
|
||||
},
|
||||
}
|
||||
|
||||
_scanExtensions() {
|
||||
let finder = new ExtensionUtils.ExtensionFinder();
|
||||
finder.connect('extension-found', this._extensionFound.bind(this));
|
||||
finder.scanExtensions();
|
||||
this._extensionsLoaded();
|
||||
},
|
||||
}
|
||||
|
||||
_extensionFound(finder, extension) {
|
||||
let row = new ExtensionRow(extension.uuid);
|
||||
@ -200,24 +287,29 @@ var Application = new Lang.Class({
|
||||
|
||||
row.show_all();
|
||||
this._extensionSelector.add(row);
|
||||
},
|
||||
}
|
||||
|
||||
_extensionsLoaded() {
|
||||
if (this._extensionSelector.get_children().length > 0)
|
||||
this._mainStack.visible_child_name = 'listing';
|
||||
else
|
||||
this._mainStack.visible_child_name = 'placeholder';
|
||||
|
||||
if (this._startupUuid && this._extensionAvailable(this._startupUuid))
|
||||
this._selectExtension(this._startupUuid);
|
||||
this._startupUuid = null;
|
||||
this._skipMainWindow = false;
|
||||
this._loaded = true;
|
||||
},
|
||||
}
|
||||
|
||||
_onActivate() {
|
||||
this._window.present();
|
||||
},
|
||||
}
|
||||
|
||||
_onStartup(app) {
|
||||
this._buildUI(app);
|
||||
this._scanExtensions();
|
||||
},
|
||||
}
|
||||
|
||||
_onCommandLine(app, commandLine) {
|
||||
app.activate();
|
||||
@ -240,26 +332,187 @@ var Application = new Lang.Class({
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var DescriptionLabel = new Lang.Class({
|
||||
Name: 'DescriptionLabel',
|
||||
Extends: Gtk.Label,
|
||||
var Expander = GObject.registerClass({
|
||||
Properties: {
|
||||
'label': GObject.ParamSpec.string(
|
||||
'label', 'label', 'label',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
null
|
||||
)
|
||||
}
|
||||
}, class Expander extends Gtk.Box {
|
||||
_init(params = {}) {
|
||||
this._labelText = null;
|
||||
|
||||
vfunc_get_preferred_height_for_width(width) {
|
||||
// Hack: Request the maximum height allowed by the line limit
|
||||
if (this.lines > 0)
|
||||
return this.parent(0);
|
||||
return this.parent(width);
|
||||
super._init(Object.assign(params, {
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 0
|
||||
}));
|
||||
|
||||
this._frame = new Gtk.Frame({
|
||||
shadow_type: Gtk.ShadowType.IN,
|
||||
hexpand: true
|
||||
});
|
||||
|
||||
let eventBox = new Gtk.EventBox();
|
||||
this._frame.add(eventBox);
|
||||
|
||||
let hbox = new Gtk.Box({
|
||||
spacing: 6,
|
||||
margin: 12
|
||||
});
|
||||
eventBox.add(hbox);
|
||||
|
||||
this._arrow = new Gtk.Image({
|
||||
icon_name: 'pan-end-symbolic'
|
||||
});
|
||||
hbox.add(this._arrow);
|
||||
|
||||
this._label = new Gtk.Label({ label: this._labelText });
|
||||
hbox.add(this._label);
|
||||
|
||||
this._revealer = new Gtk.Revealer();
|
||||
|
||||
this._childBin = new Gtk.Frame({
|
||||
shadow_type: Gtk.ShadowType.IN
|
||||
});
|
||||
this._revealer.add(this._childBin);
|
||||
|
||||
// Directly chain up to parent for internal children
|
||||
super.add(this._frame);
|
||||
super.add(this._revealer);
|
||||
|
||||
let provider = new Gtk.CssProvider();
|
||||
provider.load_from_data('* { border-top-width: 0; }');
|
||||
this._childBin.get_style_context().add_provider(
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
);
|
||||
|
||||
this._gesture = new Gtk.GestureMultiPress({
|
||||
widget: this._frame,
|
||||
button: 0,
|
||||
exclusive: true
|
||||
});
|
||||
this._gesture.connect('released', (gesture, nPress) => {
|
||||
if (nPress == 1)
|
||||
this._revealer.reveal_child = !this._revealer.reveal_child;
|
||||
});
|
||||
this._revealer.connect('notify::reveal-child', () => {
|
||||
if (this._revealer.reveal_child)
|
||||
this._arrow.icon_name = 'pan-down-symbolic';
|
||||
else
|
||||
this._arrow.icon_name = 'pan-end-symbolic';
|
||||
});
|
||||
}
|
||||
|
||||
get label() {
|
||||
return this._labelText;
|
||||
}
|
||||
|
||||
set label(text) {
|
||||
if (this._labelText == text)
|
||||
return;
|
||||
|
||||
if (this._label)
|
||||
this._label.label = text;
|
||||
this._labelText = text;
|
||||
this.notify('label');
|
||||
}
|
||||
|
||||
add(child) {
|
||||
// set expanded child
|
||||
this._childBin.get_children().forEach(c => {
|
||||
this._childBin.remove(c);
|
||||
});
|
||||
|
||||
if (child)
|
||||
this._childBin.add(child);
|
||||
}
|
||||
});
|
||||
|
||||
var ExtensionRow = new Lang.Class({
|
||||
Name: 'ExtensionRow',
|
||||
Extends: Gtk.ListBoxRow,
|
||||
var EmptyPlaceholder = GObject.registerClass(
|
||||
class EmptyPlaceholder extends Gtk.Box {
|
||||
_init() {
|
||||
super._init({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 6,
|
||||
margin: 32
|
||||
});
|
||||
|
||||
let image = new Gtk.Image({
|
||||
icon_name: 'application-x-addon-symbolic',
|
||||
pixel_size: 96,
|
||||
visible: true,
|
||||
vexpand: true,
|
||||
valign: Gtk.Align.END
|
||||
});
|
||||
image.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
|
||||
this.add(image);
|
||||
|
||||
let label = new Gtk.Label({
|
||||
label: `<b><span size="x-large">${_("No Extensions Installed" )}</span></b>`,
|
||||
use_markup: true,
|
||||
visible: true
|
||||
});
|
||||
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
|
||||
this.add(label);
|
||||
|
||||
let appInfo = Gio.DesktopAppInfo.new('org.gnome.Software.desktop');
|
||||
|
||||
let desc = new Gtk.Label({
|
||||
label: _("Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>."),
|
||||
use_markup: true,
|
||||
wrap: true,
|
||||
justify: Gtk.Justification.CENTER,
|
||||
visible: true,
|
||||
max_width_chars: 50,
|
||||
hexpand: true,
|
||||
vexpand: (appInfo == null),
|
||||
halign: Gtk.Align.CENTER,
|
||||
valign: Gtk.Align.START
|
||||
});
|
||||
this.add(desc);
|
||||
|
||||
if (appInfo) {
|
||||
let button = new Gtk.Button({
|
||||
label: _("Browse in Software"),
|
||||
image: new Gtk.Image({
|
||||
icon_name: "org.gnome.Software-symbolic"
|
||||
}),
|
||||
always_show_image: true,
|
||||
margin_top: 12,
|
||||
visible: true,
|
||||
halign: Gtk.Align.CENTER,
|
||||
valign: Gtk.Align.START,
|
||||
vexpand: true
|
||||
});
|
||||
this.add(button);
|
||||
|
||||
button.connect('clicked', w => {
|
||||
let context = w.get_display().get_app_launch_context();
|
||||
appInfo.launch([], context);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var DescriptionLabel = GObject.registerClass(
|
||||
class DescriptionLabel extends Gtk.Label {
|
||||
vfunc_get_preferred_height_for_width(width) {
|
||||
// Hack: Request the maximum height allowed by the line limit
|
||||
if (this.lines > 0)
|
||||
return super.vfunc_get_preferred_height_for_width(0);
|
||||
return super.vfunc_get_preferred_height_for_width(width);
|
||||
}
|
||||
});
|
||||
|
||||
var ExtensionRow = GObject.registerClass(
|
||||
class ExtensionRow extends Gtk.ListBoxRow {
|
||||
_init(uuid) {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this.uuid = uuid;
|
||||
|
||||
@ -277,7 +530,7 @@ var ExtensionRow = new Lang.Class({
|
||||
});
|
||||
|
||||
this._buildUI();
|
||||
},
|
||||
}
|
||||
|
||||
_buildUI() {
|
||||
let extension = ExtensionUtils.extensions[this.uuid];
|
||||
@ -305,9 +558,9 @@ var ExtensionRow = new Lang.Class({
|
||||
|
||||
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
|
||||
no_show_all: true });
|
||||
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
|
||||
icon_size: Gtk.IconSize.BUTTON,
|
||||
visible: true }));
|
||||
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
|
||||
icon_size: Gtk.IconSize.BUTTON,
|
||||
visible: true }));
|
||||
button.get_style_context().add_class('circular');
|
||||
hbox.add(button);
|
||||
|
||||
@ -324,7 +577,7 @@ var ExtensionRow = new Lang.Class({
|
||||
});
|
||||
this._switch.connect('state-set', () => true);
|
||||
hbox.add(this._switch);
|
||||
},
|
||||
}
|
||||
|
||||
_canEnable() {
|
||||
let extension = ExtensionUtils.extensions[this.uuid];
|
||||
@ -332,21 +585,21 @@ var ExtensionRow = new Lang.Class({
|
||||
|
||||
return !this._settings.get_boolean('disable-user-extensions') &&
|
||||
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
|
||||
},
|
||||
}
|
||||
|
||||
_isEnabled() {
|
||||
let extensions = this._settings.get_strv('enabled-extensions');
|
||||
return extensions.indexOf(this.uuid) != -1;
|
||||
},
|
||||
return extensions.includes(this.uuid);
|
||||
}
|
||||
|
||||
_enable() {
|
||||
let extensions = this._settings.get_strv('enabled-extensions');
|
||||
if (extensions.indexOf(this.uuid) != -1)
|
||||
if (extensions.includes(this.uuid))
|
||||
return;
|
||||
|
||||
extensions.push(this.uuid);
|
||||
this._settings.set_strv('enabled-extensions', extensions);
|
||||
},
|
||||
}
|
||||
|
||||
_disable() {
|
||||
let extensions = this._settings.get_strv('enabled-extensions');
|
||||
@ -365,12 +618,12 @@ function initEnvironment() {
|
||||
// Monkey-patch in a "global" object that fakes some Shell utilities
|
||||
// that ExtensionUtils depends on.
|
||||
window.global = {
|
||||
log() {
|
||||
print([].join.call(arguments, ', '));
|
||||
log(...args) {
|
||||
print(args.join(', '));
|
||||
},
|
||||
|
||||
logError(s) {
|
||||
log('ERROR: ' + s);
|
||||
log(`ERROR: ${s}`);
|
||||
},
|
||||
|
||||
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
|
||||
|
@ -1,11 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Pango = imports.gi.Pango;
|
||||
const { Clutter, Pango, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Batch = imports.gdm.batch;
|
||||
@ -38,10 +34,8 @@ var BeginRequestType = {
|
||||
DONT_PROVIDE_USERNAME: 1
|
||||
};
|
||||
|
||||
var AuthPrompt = new Lang.Class({
|
||||
Name: 'AuthPrompt',
|
||||
|
||||
_init(gdmClient, mode) {
|
||||
var AuthPrompt = class {
|
||||
constructor(gdmClient, mode) {
|
||||
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
|
||||
|
||||
this._gdmClient = gdmClient;
|
||||
@ -65,23 +59,23 @@ var AuthPrompt = new Lang.Class({
|
||||
this.smartcardDetected = this._userVerifier.smartcardDetected;
|
||||
|
||||
this.connect('next', () => {
|
||||
this.updateSensitivity(false);
|
||||
this.startSpinning();
|
||||
if (this._queryingService) {
|
||||
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
|
||||
} else {
|
||||
this._preemptiveAnswer = this._entry.text;
|
||||
}
|
||||
});
|
||||
this.updateSensitivity(false);
|
||||
this.startSpinning();
|
||||
if (this._queryingService) {
|
||||
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
|
||||
} else {
|
||||
this._preemptiveAnswer = this._entry.text;
|
||||
}
|
||||
});
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
|
||||
vertical: true });
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.actor.connect('key-press-event', (actor, event) => {
|
||||
if (event.get_key_symbol() == Clutter.KEY_Escape)
|
||||
this.cancel();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
if (event.get_key_symbol() == Clutter.KEY_Escape)
|
||||
this.cancel();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
|
||||
this._userWell = new St.Bin({ x_fill: true,
|
||||
x_align: St.Align.START });
|
||||
@ -99,7 +93,7 @@ var AuthPrompt = new Lang.Class({
|
||||
x_align: St.Align.START });
|
||||
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
|
||||
can_focus: true });
|
||||
ShellEntry.addContextMenu(this._entry, { isPassword: true });
|
||||
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
|
||||
|
||||
this.actor.add(this._entry,
|
||||
{ expand: true,
|
||||
@ -118,7 +112,7 @@ var AuthPrompt = new Lang.Class({
|
||||
this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
|
||||
vertical: false });
|
||||
this.actor.add(this._buttonBox,
|
||||
{ expand: true,
|
||||
{ expand: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.END });
|
||||
|
||||
@ -127,17 +121,16 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
this._initButtons();
|
||||
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
|
||||
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
|
||||
this._spinner.actor.opacity = 0;
|
||||
this._spinner.actor.show();
|
||||
this._defaultButtonWell.add_child(this._spinner.actor);
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._userVerifier.destroy();
|
||||
this._userVerifier = null;
|
||||
},
|
||||
}
|
||||
|
||||
_initButtons() {
|
||||
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
|
||||
@ -145,7 +138,7 @@ var AuthPrompt = new Lang.Class({
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
label: _("Cancel") });
|
||||
this.cancelButton.connect('clicked', () => { this.cancel(); });
|
||||
this.cancelButton.connect('clicked', () => this.cancel());
|
||||
this._buttonBox.add(this.cancelButton,
|
||||
{ expand: false,
|
||||
x_fill: false,
|
||||
@ -164,7 +157,7 @@ var AuthPrompt = new Lang.Class({
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
label: _("Next") });
|
||||
this.nextButton.connect('clicked', () => { this.emit('next'); });
|
||||
this.nextButton.connect('clicked', () => this.emit('next'));
|
||||
this.nextButton.add_style_pseudo_class('default');
|
||||
this._buttonBox.add(this.nextButton,
|
||||
{ expand: false,
|
||||
@ -185,7 +178,7 @@ var AuthPrompt = new Lang.Class({
|
||||
if (this.nextButton.reactive)
|
||||
this.emit('next');
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_onAskQuestion(verifier, serviceName, question, passwordChar) {
|
||||
if (this._queryingService)
|
||||
@ -211,12 +204,12 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
this.updateSensitivity(true);
|
||||
this.emit('prompted');
|
||||
},
|
||||
}
|
||||
|
||||
_onOVirtUserAuthenticated() {
|
||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||
this.reset();
|
||||
},
|
||||
}
|
||||
|
||||
_onSmartcardStatusChanged() {
|
||||
this.smartcardDetected = this._userVerifier.smartcardDetected;
|
||||
@ -235,12 +228,12 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||
this.reset();
|
||||
},
|
||||
}
|
||||
|
||||
_onShowMessage(userVerifier, message, type) {
|
||||
this.setMessage(message, type);
|
||||
this.emit('prompted');
|
||||
},
|
||||
}
|
||||
|
||||
_onVerificationFailed(userVerifier, canRetry) {
|
||||
this._queryingService = null;
|
||||
@ -249,22 +242,22 @@ var AuthPrompt = new Lang.Class({
|
||||
this.updateSensitivity(canRetry);
|
||||
this.setActorInDefaultButtonWell(null);
|
||||
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
|
||||
},
|
||||
}
|
||||
|
||||
_onVerificationComplete() {
|
||||
this.setActorInDefaultButtonWell(null);
|
||||
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
|
||||
this.cancelButton.reactive = false;
|
||||
},
|
||||
}
|
||||
|
||||
_onReset() {
|
||||
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
|
||||
this.reset();
|
||||
},
|
||||
}
|
||||
|
||||
addActorToDefaultButtonWell(actor) {
|
||||
this._defaultButtonWell.add_child(actor);
|
||||
},
|
||||
}
|
||||
|
||||
setActorInDefaultButtonWell(actor, animate) {
|
||||
if (!this._defaultButtonWellActor &&
|
||||
@ -302,12 +295,11 @@ var AuthPrompt = new Lang.Class({
|
||||
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
|
||||
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete() {
|
||||
if (wasSpinner) {
|
||||
if (this._spinner)
|
||||
this._spinner.stop();
|
||||
}
|
||||
onComplete: () => {
|
||||
if (wasSpinner) {
|
||||
if (this._spinner)
|
||||
this._spinner.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -328,25 +320,25 @@ var AuthPrompt = new Lang.Class({
|
||||
}
|
||||
|
||||
this._defaultButtonWellActor = actor;
|
||||
},
|
||||
}
|
||||
|
||||
startSpinning() {
|
||||
this.setActorInDefaultButtonWell(this._spinner.actor, true);
|
||||
},
|
||||
}
|
||||
|
||||
stopSpinning() {
|
||||
this.setActorInDefaultButtonWell(null, false);
|
||||
},
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._entry.text = '';
|
||||
this.stopSpinning();
|
||||
},
|
||||
}
|
||||
|
||||
setPasswordChar(passwordChar) {
|
||||
this._entry.clutter_text.set_password_char(passwordChar);
|
||||
this._entry.menu.isPassword = passwordChar != '';
|
||||
},
|
||||
}
|
||||
|
||||
setQuestion(question) {
|
||||
this._label.set_text(question);
|
||||
@ -355,7 +347,7 @@ var AuthPrompt = new Lang.Class({
|
||||
this._entry.show();
|
||||
|
||||
this._entry.grab_key_focus();
|
||||
},
|
||||
}
|
||||
|
||||
getAnswer() {
|
||||
let text;
|
||||
@ -368,7 +360,7 @@ var AuthPrompt = new Lang.Class({
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
}
|
||||
|
||||
_fadeOutMessage() {
|
||||
if (this._message.opacity == 0)
|
||||
@ -379,7 +371,7 @@ var AuthPrompt = new Lang.Class({
|
||||
time: MESSAGE_FADE_OUT_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setMessage(message, type) {
|
||||
if (type == GdmUtil.MessageType.ERROR)
|
||||
@ -399,18 +391,18 @@ var AuthPrompt = new Lang.Class({
|
||||
} else {
|
||||
this._message.opacity = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateNextButtonSensitivity(sensitive) {
|
||||
this.nextButton.reactive = sensitive;
|
||||
this.nextButton.can_focus = sensitive;
|
||||
},
|
||||
}
|
||||
|
||||
updateSensitivity(sensitive) {
|
||||
this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
|
||||
this._entry.reactive = sensitive;
|
||||
this._entry.clutter_text.editable = sensitive;
|
||||
},
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.setActorInDefaultButtonWell(null, true);
|
||||
@ -421,7 +413,7 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
this.updateSensitivity(true);
|
||||
this._entry.set_text('');
|
||||
},
|
||||
}
|
||||
|
||||
setUser(user) {
|
||||
let oldChild = this._userWell.get_child();
|
||||
@ -432,7 +424,7 @@ var AuthPrompt = new Lang.Class({
|
||||
let userWidget = new UserWidget.UserWidget(user);
|
||||
this._userWell.set_child(userWidget.actor);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
reset() {
|
||||
let oldStatus = this.verificationStatus;
|
||||
@ -470,7 +462,7 @@ var AuthPrompt = new Lang.Class({
|
||||
}
|
||||
|
||||
this.emit('reset', beginRequestType);
|
||||
},
|
||||
}
|
||||
|
||||
addCharacter(unichar) {
|
||||
if (!this._entry.visible)
|
||||
@ -478,7 +470,7 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
this._entry.grab_key_focus();
|
||||
this._entry.clutter_text.insert_unichar(unichar);
|
||||
},
|
||||
}
|
||||
|
||||
begin(params) {
|
||||
params = Params.parse(params, { userName: null,
|
||||
@ -492,7 +484,7 @@ var AuthPrompt = new Lang.Class({
|
||||
|
||||
this._userVerifier.begin(params.userName, hold);
|
||||
this.verificationStatus = AuthPromptStatus.VERIFYING;
|
||||
},
|
||||
}
|
||||
|
||||
finish(onComplete) {
|
||||
if (!this._userVerifier.hasPendingMessages) {
|
||||
@ -506,7 +498,7 @@ var AuthPrompt = new Lang.Class({
|
||||
this._userVerifier.clear();
|
||||
onComplete();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
|
||||
@ -515,5 +507,5 @@ var AuthPrompt = new Lang.Class({
|
||||
this.reset();
|
||||
this.emit('cancelled');
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(AuthPrompt.prototype);
|
||||
|
116
js/gdm/batch.js
@ -44,45 +44,40 @@
|
||||
* replaced by something else.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
const { GObject } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
var Task = new Lang.Class({
|
||||
Name: 'Task',
|
||||
|
||||
_init(scope, handler) {
|
||||
var Task = class {
|
||||
constructor(scope, handler) {
|
||||
if (scope)
|
||||
this.scope = scope;
|
||||
else
|
||||
this.scope = this;
|
||||
|
||||
this.handler = handler;
|
||||
},
|
||||
}
|
||||
|
||||
run() {
|
||||
if (this.handler)
|
||||
return this.handler.call(this.scope);
|
||||
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Task.prototype);
|
||||
|
||||
var Hold = new Lang.Class({
|
||||
Name: 'Hold',
|
||||
Extends: Task,
|
||||
|
||||
_init() {
|
||||
this.parent(this, () => this);
|
||||
var Hold = class extends Task {
|
||||
constructor() {
|
||||
super(null, () => this);
|
||||
|
||||
this._acquisitions = 1;
|
||||
},
|
||||
}
|
||||
|
||||
acquire() {
|
||||
if (this._acquisitions <= 0)
|
||||
throw new Error("Cannot acquire hold after it's been released");
|
||||
this._acquisitions++;
|
||||
},
|
||||
}
|
||||
|
||||
acquireUntilAfter(hold) {
|
||||
if (!hold.isAcquired())
|
||||
@ -93,27 +88,24 @@ var Hold = new Lang.Class({
|
||||
hold.disconnect(signalId);
|
||||
this.release();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
release() {
|
||||
this._acquisitions--;
|
||||
|
||||
if (this._acquisitions == 0)
|
||||
this.emit('release');
|
||||
},
|
||||
}
|
||||
|
||||
isAcquired() {
|
||||
return this._acquisitions > 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(Hold.prototype);
|
||||
|
||||
var Batch = new Lang.Class({
|
||||
Name: 'Batch',
|
||||
Extends: Task,
|
||||
|
||||
_init(scope, tasks) {
|
||||
this.parent();
|
||||
var Batch = class extends Task {
|
||||
constructor(scope, tasks) {
|
||||
super();
|
||||
|
||||
this.tasks = [];
|
||||
|
||||
@ -130,11 +122,11 @@ var Batch = new Lang.Class({
|
||||
|
||||
this.tasks.push(task);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
process() {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
throw new GObject.NotImplementedError(`process in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
runTask() {
|
||||
if (!(this._currentTaskIndex in this.tasks)) {
|
||||
@ -142,11 +134,11 @@ var Batch = new Lang.Class({
|
||||
}
|
||||
|
||||
return this.tasks[this._currentTaskIndex].run();
|
||||
},
|
||||
}
|
||||
|
||||
_finish() {
|
||||
this.hold.release();
|
||||
},
|
||||
}
|
||||
|
||||
nextTask() {
|
||||
this._currentTaskIndex++;
|
||||
@ -159,7 +151,7 @@ var Batch = new Lang.Class({
|
||||
}
|
||||
|
||||
this.process();
|
||||
},
|
||||
}
|
||||
|
||||
_start() {
|
||||
// acquire a hold to get released when the entire
|
||||
@ -167,7 +159,7 @@ var Batch = new Lang.Class({
|
||||
this.hold = new Hold();
|
||||
this._currentTaskIndex = 0;
|
||||
this.process();
|
||||
},
|
||||
}
|
||||
|
||||
run() {
|
||||
this._start();
|
||||
@ -175,52 +167,46 @@ var Batch = new Lang.Class({
|
||||
// hold may be destroyed at this point
|
||||
// if we're already done running
|
||||
return this.hold;
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(Batch.prototype);
|
||||
|
||||
var ConcurrentBatch = new Lang.Class({
|
||||
Name: 'ConcurrentBatch',
|
||||
Extends: Batch,
|
||||
|
||||
var ConcurrentBatch = class extends Batch {
|
||||
process() {
|
||||
let hold = this.runTask();
|
||||
let hold = this.runTask();
|
||||
|
||||
if (hold) {
|
||||
this.hold.acquireUntilAfter(hold);
|
||||
}
|
||||
if (hold) {
|
||||
this.hold.acquireUntilAfter(hold);
|
||||
}
|
||||
|
||||
// Regardless of the state of the just run task,
|
||||
// fire off the next one, so all the tasks can run
|
||||
// concurrently.
|
||||
this.nextTask();
|
||||
// Regardless of the state of the just run task,
|
||||
// fire off the next one, so all the tasks can run
|
||||
// concurrently.
|
||||
this.nextTask();
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ConcurrentBatch.prototype);
|
||||
|
||||
var ConsecutiveBatch = new Lang.Class({
|
||||
Name: 'ConsecutiveBatch',
|
||||
Extends: Batch,
|
||||
|
||||
var ConsecutiveBatch = class extends Batch {
|
||||
process() {
|
||||
let hold = this.runTask();
|
||||
let hold = this.runTask();
|
||||
|
||||
if (hold && hold.isAcquired()) {
|
||||
// This task is inhibiting the batch. Wait on it
|
||||
// before processing the next one.
|
||||
let signalId = hold.connect('release', () => {
|
||||
hold.disconnect(signalId);
|
||||
this.nextTask();
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// This task finished, process the next one
|
||||
this.nextTask();
|
||||
}
|
||||
if (hold && hold.isAcquired()) {
|
||||
// This task is inhibiting the batch. Wait on it
|
||||
// before processing the next one.
|
||||
let signalId = hold.connect('release', () => {
|
||||
hold.disconnect(signalId);
|
||||
this.nextTask();
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// This task finished, process the next one
|
||||
this.nextTask();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ConsecutiveBatch.prototype);
|
||||
|
@ -1,9 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const FprintManagerIface = `
|
||||
<node>
|
||||
@ -26,8 +23,8 @@ function FprintManager() {
|
||||
|
||||
try {
|
||||
self.init(null);
|
||||
} catch(e) {
|
||||
log('Failed to connect to Fprint service: ' + e.message);
|
||||
} catch (e) {
|
||||
log(`Failed to connect to Fprint service: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -16,20 +16,9 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const Atk = imports.gi.Atk;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { AccountsService, Atk, Clutter, Gdm, Gio,
|
||||
GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const AuthPrompt = imports.gdm.authPrompt;
|
||||
const Batch = imports.gdm.batch;
|
||||
@ -50,13 +39,11 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
||||
const _LOGO_ICON_HEIGHT = 48;
|
||||
const _MAX_BOTTOM_MENU_ITEMS = 5;
|
||||
|
||||
var UserListItem = new Lang.Class({
|
||||
Name: 'UserListItem',
|
||||
|
||||
_init(user) {
|
||||
var UserListItem = class {
|
||||
constructor(user) {
|
||||
this.user = user;
|
||||
this._userChangedId = this.user.connect('changed',
|
||||
this._onUserChanged.bind(this));
|
||||
this._onUserChanged.bind(this));
|
||||
|
||||
let layout = new St.BoxLayout({ vertical: true });
|
||||
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
|
||||
@ -91,26 +78,26 @@ var UserListItem = new Lang.Class({
|
||||
|
||||
this.actor.connect('clicked', this._onClicked.bind(this));
|
||||
this._onUserChanged();
|
||||
},
|
||||
}
|
||||
|
||||
_onUserChanged() {
|
||||
this._updateLoggedIn();
|
||||
},
|
||||
}
|
||||
|
||||
_updateLoggedIn() {
|
||||
if (this.user.is_logged_in())
|
||||
this.actor.add_style_pseudo_class('logged-in');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('logged-in');
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.user.disconnect(this._userChangedId);
|
||||
},
|
||||
}
|
||||
|
||||
_onClicked() {
|
||||
this.emit('activate');
|
||||
},
|
||||
}
|
||||
|
||||
_setSelected(selected) {
|
||||
if (selected) {
|
||||
@ -119,7 +106,7 @@ var UserListItem = new Lang.Class({
|
||||
} else {
|
||||
this.actor.remove_style_pseudo_class('selected');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showTimedLoginIndicator(time) {
|
||||
let hold = new Batch.Hold();
|
||||
@ -147,7 +134,7 @@ var UserListItem = new Lang.Class({
|
||||
GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId');
|
||||
|
||||
return hold;
|
||||
},
|
||||
}
|
||||
|
||||
hideTimedLoginIndicator() {
|
||||
if (this._timedLoginTimeoutId) {
|
||||
@ -158,16 +145,14 @@ var UserListItem = new Lang.Class({
|
||||
this._timedLoginIndicator.visible = false;
|
||||
this._timedLoginIndicator.scale_x = 0.;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(UserListItem.prototype);
|
||||
|
||||
var UserList = new Lang.Class({
|
||||
Name: 'UserList',
|
||||
|
||||
_init() {
|
||||
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
var UserList = class {
|
||||
constructor() {
|
||||
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
|
||||
this.actor.set_policy(St.PolicyType.NEVER,
|
||||
St.PolicyType.AUTOMATIC);
|
||||
|
||||
this._box = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'login-dialog-user-list',
|
||||
@ -177,7 +162,7 @@ var UserList = new Lang.Class({
|
||||
this._items = {};
|
||||
|
||||
this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_moveFocusToItems() {
|
||||
let hasItems = Object.keys(this._items).length > 0;
|
||||
@ -188,22 +173,20 @@ var UserList = new Lang.Class({
|
||||
if (global.stage.get_key_focus() != this.actor)
|
||||
return;
|
||||
|
||||
let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
if (!focusSet) {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._moveFocusToItems();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onItemActivated(activatedItem) {
|
||||
this.emit('activate', activatedItem);
|
||||
},
|
||||
}
|
||||
|
||||
updateStyle(isExpanded) {
|
||||
let tasks = [];
|
||||
|
||||
if (isExpanded)
|
||||
this._box.add_style_pseudo_class('expanded');
|
||||
else
|
||||
@ -213,7 +196,7 @@ var UserList = new Lang.Class({
|
||||
let item = this._items[userName];
|
||||
item.actor.sync_hover();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
scrollToItem(item) {
|
||||
let box = item.actor.get_allocation_box();
|
||||
@ -226,7 +209,7 @@ var UserList = new Lang.Class({
|
||||
{ value: value,
|
||||
time: _SCROLL_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
}
|
||||
|
||||
jumpToItem(item) {
|
||||
let box = item.actor.get_allocation_box();
|
||||
@ -236,7 +219,7 @@ var UserList = new Lang.Class({
|
||||
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
|
||||
|
||||
adjustment.set_value(value);
|
||||
},
|
||||
}
|
||||
|
||||
getItemFromUserName(userName) {
|
||||
let item = this._items[userName];
|
||||
@ -245,11 +228,11 @@ var UserList = new Lang.Class({
|
||||
return null;
|
||||
|
||||
return item;
|
||||
},
|
||||
}
|
||||
|
||||
containsUser(user) {
|
||||
return this._items[user.get_user_name()] != null;
|
||||
},
|
||||
}
|
||||
|
||||
addUser(user) {
|
||||
if (!user.is_loaded)
|
||||
@ -259,7 +242,7 @@ var UserList = new Lang.Class({
|
||||
return;
|
||||
|
||||
if (user.locked)
|
||||
return;
|
||||
return;
|
||||
|
||||
let userName = user.get_user_name();
|
||||
|
||||
@ -276,12 +259,12 @@ var UserList = new Lang.Class({
|
||||
item.connect('activate', this._onItemActivated.bind(this));
|
||||
|
||||
// Try to keep the focused item front-and-center
|
||||
item.actor.connect('key-focus-in', () => { this.scrollToItem(item); });
|
||||
item.actor.connect('key-focus-in', () => this.scrollToItem(item));
|
||||
|
||||
this._moveFocusToItems();
|
||||
|
||||
this.emit('item-added', item);
|
||||
},
|
||||
}
|
||||
|
||||
removeUser(user) {
|
||||
if (!user.is_loaded)
|
||||
@ -299,18 +282,16 @@ var UserList = new Lang.Class({
|
||||
|
||||
item.actor.destroy();
|
||||
delete this._items[userName];
|
||||
},
|
||||
}
|
||||
|
||||
numItems() {
|
||||
return Object.keys(this._items).length;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(UserList.prototype);
|
||||
|
||||
var SessionMenuButton = new Lang.Class({
|
||||
Name: 'SessionMenuButton',
|
||||
|
||||
_init() {
|
||||
var SessionMenuButton = class {
|
||||
constructor() {
|
||||
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
|
||||
this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
|
||||
reactive: true,
|
||||
@ -336,27 +317,28 @@ var SessionMenuButton = new Lang.Class({
|
||||
this._menu.actor.hide();
|
||||
|
||||
this._menu.connect('open-state-changed', (menu, isOpen) => {
|
||||
if (isOpen)
|
||||
this._button.add_style_pseudo_class('active');
|
||||
else
|
||||
this._button.remove_style_pseudo_class('active');
|
||||
if (isOpen)
|
||||
this._button.add_style_pseudo_class('active');
|
||||
else
|
||||
this._button.remove_style_pseudo_class('active');
|
||||
});
|
||||
|
||||
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
|
||||
this._manager = new PopupMenu.PopupMenuManager(this._button,
|
||||
{ actionMode: Shell.ActionMode.NONE });
|
||||
this._manager.addMenu(this._menu);
|
||||
|
||||
this._button.connect('clicked', () => { this._menu.toggle(); });
|
||||
this._button.connect('clicked', () => this._menu.toggle());
|
||||
|
||||
this._items = {};
|
||||
this._activeSessionId = null;
|
||||
this._populate();
|
||||
},
|
||||
}
|
||||
|
||||
updateSensitivity(sensitive) {
|
||||
this._button.reactive = sensitive;
|
||||
this._button.can_focus = sensitive;
|
||||
this._menu.close(BoxPointer.PopupAnimation.NONE);
|
||||
},
|
||||
}
|
||||
|
||||
_updateOrnament() {
|
||||
let itemIds = Object.keys(this._items);
|
||||
@ -366,19 +348,19 @@ var SessionMenuButton = new Lang.Class({
|
||||
else
|
||||
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
setActiveSession(sessionId) {
|
||||
if (sessionId == this._activeSessionId)
|
||||
return;
|
||||
if (sessionId == this._activeSessionId)
|
||||
return;
|
||||
|
||||
this._activeSessionId = sessionId;
|
||||
this._updateOrnament();
|
||||
},
|
||||
this._activeSessionId = sessionId;
|
||||
this._updateOrnament();
|
||||
}
|
||||
|
||||
close() {
|
||||
this._menu.close();
|
||||
},
|
||||
}
|
||||
|
||||
_populate() {
|
||||
let ids = Gdm.get_session_ids();
|
||||
@ -403,16 +385,14 @@ var SessionMenuButton = new Lang.Class({
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(SessionMenuButton.prototype);
|
||||
|
||||
var LoginDialog = new Lang.Class({
|
||||
Name: 'LoginDialog',
|
||||
Extends: St.Widget,
|
||||
var LoginDialog = GObject.registerClass({
|
||||
Signals: { 'failed': {} },
|
||||
|
||||
}, class LoginDialog extends St.Widget {
|
||||
_init(parentActor) {
|
||||
this.parent({ style_class: 'login-dialog',
|
||||
super._init({ style_class: 'login-dialog',
|
||||
visible: false });
|
||||
|
||||
this.get_accessible().set_role(Atk.Role.WINDOW);
|
||||
@ -421,18 +401,18 @@ var LoginDialog = new Lang.Class({
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
parentActor.add_child(this);
|
||||
|
||||
this._userManager = AccountsService.UserManager.get_default()
|
||||
this._userManager = AccountsService.UserManager.get_default();
|
||||
this._gdmClient = new Gdm.Client();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
||||
|
||||
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
|
||||
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`,
|
||||
this._updateBanner.bind(this));
|
||||
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
|
||||
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`,
|
||||
this._updateBanner.bind(this));
|
||||
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
|
||||
this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`,
|
||||
this._updateDisableUserList.bind(this));
|
||||
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
|
||||
this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`,
|
||||
this._updateLogo.bind(this));
|
||||
|
||||
this._textureCache = St.TextureCache.get_default();
|
||||
@ -482,8 +462,8 @@ var LoginDialog = new Lang.Class({
|
||||
|
||||
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
|
||||
opacity: 0,
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
vscrollbar_policy: St.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: St.PolicyType.NEVER });
|
||||
this.add_child(this._bannerView);
|
||||
|
||||
let bannerBox = new St.BoxLayout({ vertical: true });
|
||||
@ -499,6 +479,9 @@ var LoginDialog = new Lang.Class({
|
||||
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END });
|
||||
this._logoBin.connect('resource-scale-changed', () => {
|
||||
this._updateLogoTexture(this._textureCache, this._logoFile);
|
||||
});
|
||||
this.add_child(this._logoBin);
|
||||
this._updateLogo();
|
||||
|
||||
@ -530,7 +513,7 @@ var LoginDialog = new Lang.Class({
|
||||
// focus later
|
||||
this._startupCompleteId = Main.layoutManager.connect('startup-complete',
|
||||
this._updateDisableUserList.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_getBannerAllocation(dialogBox) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
@ -544,7 +527,7 @@ var LoginDialog = new Lang.Class({
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
}
|
||||
|
||||
_getLogoBinAllocation(dialogBox) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
@ -558,7 +541,7 @@ var LoginDialog = new Lang.Class({
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
}
|
||||
|
||||
_getCenterActorAllocation(dialogBox, actor) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
@ -576,7 +559,7 @@ var LoginDialog = new Lang.Class({
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(dialogBox, flags) {
|
||||
this.set_allocation(dialogBox, flags);
|
||||
@ -590,19 +573,15 @@ var LoginDialog = new Lang.Class({
|
||||
// First find out what space the children require
|
||||
let bannerAllocation = null;
|
||||
let bannerHeight = 0;
|
||||
let bannerWidth = 0;
|
||||
if (this._bannerView.visible) {
|
||||
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
|
||||
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
|
||||
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
|
||||
}
|
||||
|
||||
let authPromptAllocation = null;
|
||||
let authPromptHeight = 0;
|
||||
let authPromptWidth = 0;
|
||||
if (this._authPrompt.actor.visible) {
|
||||
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
|
||||
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
|
||||
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
|
||||
}
|
||||
|
||||
@ -634,64 +613,64 @@ var LoginDialog = new Lang.Class({
|
||||
let leftOverYSpace = bannerSpace - bannerHeight;
|
||||
|
||||
if (leftOverYSpace > 0) {
|
||||
// First figure out how much left over space is up top
|
||||
let leftOverTopSpace = leftOverYSpace / 2;
|
||||
// First figure out how much left over space is up top
|
||||
let leftOverTopSpace = leftOverYSpace / 2;
|
||||
|
||||
// Then, shift the banner into the middle of that extra space
|
||||
let yShift = Math.floor(leftOverTopSpace / 2);
|
||||
// Then, shift the banner into the middle of that extra space
|
||||
let yShift = Math.floor(leftOverTopSpace / 2);
|
||||
|
||||
bannerAllocation.y1 += yShift;
|
||||
bannerAllocation.y2 += yShift;
|
||||
bannerAllocation.y1 += yShift;
|
||||
bannerAllocation.y2 += yShift;
|
||||
} else {
|
||||
// Then figure out how much space there would be if we switched to a
|
||||
// wide layout with banner on one side and authprompt on the other.
|
||||
let leftOverXSpace = dialogWidth - authPromptWidth;
|
||||
// Then figure out how much space there would be if we switched to a
|
||||
// wide layout with banner on one side and authprompt on the other.
|
||||
let leftOverXSpace = dialogWidth - authPromptWidth;
|
||||
|
||||
// In a wide view, half of the available space goes to the banner,
|
||||
// and the other half goes to the margins.
|
||||
let wideBannerWidth = leftOverXSpace / 2;
|
||||
let wideSpacing = leftOverXSpace - wideBannerWidth;
|
||||
// In a wide view, half of the available space goes to the banner,
|
||||
// and the other half goes to the margins.
|
||||
let wideBannerWidth = leftOverXSpace / 2;
|
||||
let wideSpacing = leftOverXSpace - wideBannerWidth;
|
||||
|
||||
// If we do go with a wide layout, we need there to be at least enough
|
||||
// space for the banner and the auth prompt to be the same width,
|
||||
// so it doesn't look unbalanced.
|
||||
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
|
||||
let centerX = dialogBox.x1 + dialogWidth / 2;
|
||||
let centerY = dialogBox.y1 + dialogHeight / 2;
|
||||
// If we do go with a wide layout, we need there to be at least enough
|
||||
// space for the banner and the auth prompt to be the same width,
|
||||
// so it doesn't look unbalanced.
|
||||
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
|
||||
let centerX = dialogBox.x1 + dialogWidth / 2;
|
||||
let centerY = dialogBox.y1 + dialogHeight / 2;
|
||||
|
||||
// A small portion of the spacing goes down the center of the
|
||||
// screen to help delimit the two columns of the wide view
|
||||
let centerGap = wideSpacing / 8;
|
||||
// A small portion of the spacing goes down the center of the
|
||||
// screen to help delimit the two columns of the wide view
|
||||
let centerGap = wideSpacing / 8;
|
||||
|
||||
// place the banner along the left edge of the center margin
|
||||
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
|
||||
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
|
||||
// place the banner along the left edge of the center margin
|
||||
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
|
||||
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
|
||||
|
||||
// figure out how tall it would like to be and try to accomodate
|
||||
// but don't let it get too close to the logo
|
||||
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
|
||||
// figure out how tall it would like to be and try to accommodate
|
||||
// but don't let it get too close to the logo
|
||||
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
|
||||
|
||||
let maxWideHeight = dialogHeight - 3 * logoHeight;
|
||||
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
|
||||
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
|
||||
let maxWideHeight = dialogHeight - 3 * logoHeight;
|
||||
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
|
||||
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
|
||||
|
||||
// place the auth prompt along the right edge of the center margin
|
||||
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
|
||||
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
|
||||
} else {
|
||||
// If we aren't going to do a wide view, then we need to limit
|
||||
// the height of the banner so it will present scrollbars
|
||||
// place the auth prompt along the right edge of the center margin
|
||||
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
|
||||
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
|
||||
} else {
|
||||
// If we aren't going to do a wide view, then we need to limit
|
||||
// the height of the banner so it will present scrollbars
|
||||
|
||||
// First figure out how much space there is without the banner
|
||||
leftOverYSpace += bannerHeight;
|
||||
// First figure out how much space there is without the banner
|
||||
leftOverYSpace += bannerHeight;
|
||||
|
||||
// Then figure out how much of that space is up top
|
||||
let availableTopSpace = Math.floor(leftOverYSpace / 2);
|
||||
// Then figure out how much of that space is up top
|
||||
let availableTopSpace = Math.floor(leftOverYSpace / 2);
|
||||
|
||||
// Then give all of that space to the banner
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
|
||||
}
|
||||
// Then give all of that space to the banner
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
|
||||
}
|
||||
}
|
||||
} else if (userSelectionAllocation) {
|
||||
// Grow the user list to fill the space
|
||||
@ -719,7 +698,7 @@ var LoginDialog = new Lang.Class({
|
||||
|
||||
if (logoAllocation)
|
||||
this._logoBin.allocate(logoAllocation, flags);
|
||||
},
|
||||
}
|
||||
|
||||
_ensureUserListLoaded() {
|
||||
if (!this._userManager.is_loaded) {
|
||||
@ -735,7 +714,7 @@ var LoginDialog = new Lang.Class({
|
||||
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this));
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateDisableUserList() {
|
||||
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
|
||||
@ -750,7 +729,7 @@ var LoginDialog = new Lang.Class({
|
||||
if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||
this._authPrompt.reset();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateCancelButton() {
|
||||
let cancelVisible;
|
||||
@ -763,7 +742,7 @@ var LoginDialog = new Lang.Class({
|
||||
cancelVisible = true;
|
||||
|
||||
this._authPrompt.cancelButton.visible = cancelVisible;
|
||||
},
|
||||
}
|
||||
|
||||
_updateBanner() {
|
||||
let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
|
||||
@ -775,7 +754,7 @@ var LoginDialog = new Lang.Class({
|
||||
} else {
|
||||
this._bannerLabel.hide();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_fadeInBannerView() {
|
||||
this._bannerView.show();
|
||||
@ -783,33 +762,34 @@ var LoginDialog = new Lang.Class({
|
||||
{ opacity: 255,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
}
|
||||
|
||||
_hideBannerView() {
|
||||
Tweener.removeTweens(this._bannerView);
|
||||
this._bannerView.opacity = 0;
|
||||
this._bannerView.hide();
|
||||
},
|
||||
}
|
||||
|
||||
_updateLogoTexture(cache, file) {
|
||||
if (this._logoFile && !this._logoFile.equal(file))
|
||||
return;
|
||||
|
||||
this._logoBin.destroy_all_children();
|
||||
if (this._logoFile) {
|
||||
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, _LOGO_ICON_HEIGHT,
|
||||
scaleFactor));
|
||||
scaleFactor,
|
||||
this._logoBin.resource_scale));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateLogo() {
|
||||
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
|
||||
|
||||
this._logoFile = path ? Gio.file_new_for_path(path) : null;
|
||||
this._updateLogoTexture(this._textureCache, this._logoFile);
|
||||
},
|
||||
}
|
||||
|
||||
_onPrompted() {
|
||||
if (this._shouldShowSessionMenuButton()) {
|
||||
@ -819,7 +799,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._sessionMenuButton.updateSensitivity(false);
|
||||
}
|
||||
this._showPrompt();
|
||||
},
|
||||
}
|
||||
|
||||
_resetGreeterProxy() {
|
||||
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
|
||||
@ -835,7 +815,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
|
||||
this._onTimedLoginRequested.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onReset(authPrompt, beginRequest) {
|
||||
this._resetGreeterProxy();
|
||||
@ -856,22 +836,22 @@ var LoginDialog = new Lang.Class({
|
||||
} else {
|
||||
this._hideUserListAndBeginVerification();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onDefaultSessionChanged(client, sessionId) {
|
||||
this._sessionMenuButton.setActiveSession(sessionId);
|
||||
},
|
||||
}
|
||||
|
||||
_shouldShowSessionMenuButton() {
|
||||
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
|
||||
this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
if (this._user && this._user.is_loaded && this._user.is_logged_in())
|
||||
return false;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_showPrompt() {
|
||||
if (this._authPrompt.actor.visible)
|
||||
@ -883,7 +863,7 @@ var LoginDialog = new Lang.Class({
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
this._fadeInBannerView();
|
||||
},
|
||||
}
|
||||
|
||||
_showRealmLoginHint(realmManager, hint) {
|
||||
if (!hint)
|
||||
@ -896,7 +876,7 @@ var LoginDialog = new Lang.Class({
|
||||
// Translators: this message is shown below the username entry field
|
||||
// to clue the user in on how to login to the local network realm
|
||||
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
|
||||
},
|
||||
}
|
||||
|
||||
_askForUsernameAndBeginVerification() {
|
||||
this._authPrompt.setPasswordChar('');
|
||||
@ -923,7 +903,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._sessionMenuButton.updateSensitivity(false);
|
||||
this._authPrompt.updateSensitivity(true);
|
||||
this._showPrompt();
|
||||
},
|
||||
}
|
||||
|
||||
_loginScreenSessionActivated() {
|
||||
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||
@ -933,7 +913,7 @@ var LoginDialog = new Lang.Class({
|
||||
{ opacity: 255,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onUpdate() {
|
||||
onUpdate: () => {
|
||||
let children = Main.layoutManager.uiGroup.get_children();
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
@ -941,13 +921,11 @@ var LoginDialog = new Lang.Class({
|
||||
children[i].opacity = this.opacity;
|
||||
}
|
||||
},
|
||||
onUpdateScope: this,
|
||||
onComplete() {
|
||||
onComplete: () => {
|
||||
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||
this._authPrompt.reset();
|
||||
},
|
||||
onCompleteScope: this });
|
||||
},
|
||||
} });
|
||||
}
|
||||
|
||||
_gotGreeterSessionProxy(proxy) {
|
||||
this._greeterSessionProxy = proxy;
|
||||
@ -956,14 +934,14 @@ var LoginDialog = new Lang.Class({
|
||||
if (proxy.Active)
|
||||
this._loginScreenSessionActivated();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_startSession(serviceName) {
|
||||
Tweener.addTween(this,
|
||||
{ opacity: 0,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onUpdate() {
|
||||
onUpdate: () => {
|
||||
let children = Main.layoutManager.uiGroup.get_children();
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
@ -971,22 +949,20 @@ var LoginDialog = new Lang.Class({
|
||||
children[i].opacity = this.opacity;
|
||||
}
|
||||
},
|
||||
onUpdateScope: this,
|
||||
onComplete() {
|
||||
onComplete: () => {
|
||||
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
|
||||
},
|
||||
onCompleteScope: this });
|
||||
},
|
||||
} });
|
||||
}
|
||||
|
||||
_onSessionOpened(client, serviceName) {
|
||||
this._authPrompt.finish(() => { this._startSession(serviceName); });
|
||||
},
|
||||
this._authPrompt.finish(() => this._startSession(serviceName));
|
||||
}
|
||||
|
||||
_waitForItemForUser(userName) {
|
||||
let item = this._userList.getItemFromUserName(userName);
|
||||
|
||||
if (item)
|
||||
return null;
|
||||
return null;
|
||||
|
||||
let hold = new Batch.Hold();
|
||||
let signalId = this._userList.connect('item-added',
|
||||
@ -997,10 +973,10 @@ var LoginDialog = new Lang.Class({
|
||||
hold.release();
|
||||
});
|
||||
|
||||
hold.connect('release', () => { this._userList.disconnect(signalId); });
|
||||
hold.connect('release', () => this._userList.disconnect(signalId));
|
||||
|
||||
return hold;
|
||||
},
|
||||
}
|
||||
|
||||
_blockTimedLoginUntilIdle() {
|
||||
let hold = new Batch.Hold();
|
||||
@ -1013,7 +989,7 @@ var LoginDialog = new Lang.Class({
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId');
|
||||
return hold;
|
||||
},
|
||||
}
|
||||
|
||||
_startTimedLogin(userName, delay) {
|
||||
let firstRun = true;
|
||||
@ -1061,6 +1037,7 @@ var LoginDialog = new Lang.Class({
|
||||
return this._blockTimedLoginUntilIdle();
|
||||
} else {
|
||||
animationTime = delay;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1086,7 +1063,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
|
||||
|
||||
return this._timedLoginBatch.run();
|
||||
},
|
||||
}
|
||||
|
||||
_onTimedLoginRequested(client, userName, seconds) {
|
||||
if (this._timedLoginBatch)
|
||||
@ -1096,35 +1073,35 @@ var LoginDialog = new Lang.Class({
|
||||
|
||||
// Restart timed login on user interaction
|
||||
global.stage.connect('captured-event', (actor, event) => {
|
||||
if (event.type() == Clutter.EventType.KEY_PRESS ||
|
||||
if (event.type() == Clutter.EventType.KEY_PRESS ||
|
||||
event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
this._startTimedLogin(userName, seconds);
|
||||
}
|
||||
this._startTimedLogin(userName, seconds);
|
||||
}
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_setUserListExpanded(expanded) {
|
||||
this._userList.updateStyle(expanded);
|
||||
this._userSelectionBox.visible = expanded;
|
||||
},
|
||||
}
|
||||
|
||||
_hideUserList() {
|
||||
this._setUserListExpanded(false);
|
||||
if (this._userSelectionBox.visible)
|
||||
GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
|
||||
},
|
||||
}
|
||||
|
||||
_hideUserListAskForUsernameAndBeginVerification() {
|
||||
this._hideUserList();
|
||||
this._askForUsernameAndBeginVerification();
|
||||
},
|
||||
}
|
||||
|
||||
_hideUserListAndBeginVerification() {
|
||||
this._hideUserList();
|
||||
this._authPrompt.begin();
|
||||
},
|
||||
}
|
||||
|
||||
_showUserList() {
|
||||
this._ensureUserListLoaded();
|
||||
@ -1134,7 +1111,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._setUserListExpanded(true);
|
||||
this._notListedButton.show();
|
||||
this._userList.actor.grab_key_focus();
|
||||
},
|
||||
}
|
||||
|
||||
_beginVerificationForItem(item) {
|
||||
this._authPrompt.setUser(item.user);
|
||||
@ -1145,7 +1122,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._authPrompt.begin({ userName: userName,
|
||||
hold: hold });
|
||||
return hold;
|
||||
},
|
||||
}
|
||||
|
||||
_onUserListActivated(activatedItem) {
|
||||
this._user = activatedItem.user;
|
||||
@ -1155,7 +1132,7 @@ var LoginDialog = new Lang.Class({
|
||||
let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
|
||||
this._beginVerificationForItem(activatedItem)]);
|
||||
batch.run();
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._userManagerLoadedId) {
|
||||
@ -1196,7 +1173,7 @@ var LoginDialog = new Lang.Class({
|
||||
this._realmManager.release();
|
||||
this._realmManager = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_loadUserList() {
|
||||
if (this._userListLoaded)
|
||||
@ -1234,7 +1211,7 @@ var LoginDialog = new Lang.Class({
|
||||
});
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
open() {
|
||||
Main.ctrlAltTabManager.addGroup(this,
|
||||
@ -1253,22 +1230,22 @@ var LoginDialog = new Lang.Class({
|
||||
transition: 'easeInQuad' });
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
close() {
|
||||
Main.popModal(this);
|
||||
Main.ctrlAltTabManager.removeGroup(this);
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._authPrompt.cancel();
|
||||
},
|
||||
}
|
||||
|
||||
addCharacter(unichar) {
|
||||
// Don't allow type ahead at the login screen
|
||||
},
|
||||
}
|
||||
|
||||
finish(onComplete) {
|
||||
this._authPrompt.finish(onComplete);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const OVirtCredentialsIface = `
|
||||
@ -28,33 +27,32 @@ function OVirtCredentials() {
|
||||
return self;
|
||||
}
|
||||
|
||||
var OVirtCredentialsManager = new Lang.Class({
|
||||
Name: 'OVirtCredentialsManager',
|
||||
_init() {
|
||||
var OVirtCredentialsManager = class {
|
||||
constructor() {
|
||||
this._token = null;
|
||||
|
||||
this._credentials = new OVirtCredentials();
|
||||
this._credentials.connectSignal('UserAuthenticated',
|
||||
this._onUserAuthenticated.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onUserAuthenticated(proxy, sender, [token]) {
|
||||
this._token = token;
|
||||
this.emit('user-authenticated', token);
|
||||
},
|
||||
}
|
||||
|
||||
hasToken() {
|
||||
return this._token != null;
|
||||
},
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this._token;
|
||||
},
|
||||
}
|
||||
|
||||
resetToken() {
|
||||
this._token = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(OVirtCredentialsManager.prototype);
|
||||
|
||||
function getOVirtCredentialsManager() {
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
@ -16,14 +14,12 @@ const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
|
||||
const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
|
||||
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
|
||||
|
||||
var Manager = new Lang.Class({
|
||||
Name: 'Manager',
|
||||
|
||||
_init(parentActor) {
|
||||
var Manager = class {
|
||||
constructor(parentActor) {
|
||||
this._aggregateProvider = Provider(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
'/org/freedesktop/realmd',
|
||||
this._reloadRealms.bind(this))
|
||||
this._reloadRealms.bind(this));
|
||||
this._realms = {};
|
||||
|
||||
this._signalId = this._aggregateProvider.connect('g-properties-changed',
|
||||
@ -31,7 +27,7 @@ var Manager = new Lang.Class({
|
||||
if ('Realms' in properties.deep_unpack())
|
||||
this._reloadRealms();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_reloadRealms() {
|
||||
let realmPaths = this._aggregateProvider.Realms;
|
||||
@ -40,12 +36,12 @@ var Manager = new Lang.Class({
|
||||
return;
|
||||
|
||||
for (let i = 0; i < realmPaths.length; i++) {
|
||||
let realm = Realm(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
realmPaths[i],
|
||||
this._onRealmLoaded.bind(this));
|
||||
Realm(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
realmPaths[i],
|
||||
this._onRealmLoaded.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_reloadRealm(realm) {
|
||||
if (!realm.Configured) {
|
||||
@ -58,7 +54,7 @@ var Manager = new Lang.Class({
|
||||
this._realms[realm.get_object_path()] = realm;
|
||||
|
||||
this._updateLoginFormat();
|
||||
},
|
||||
}
|
||||
|
||||
_onRealmLoaded(realm, error) {
|
||||
if (error)
|
||||
@ -70,7 +66,7 @@ var Manager = new Lang.Class({
|
||||
if ('Configured' in properties.deep_unpack())
|
||||
this._reloadRealm(realm);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateLoginFormat() {
|
||||
let newLoginFormat;
|
||||
@ -87,7 +83,7 @@ var Manager = new Lang.Class({
|
||||
this._loginFormat = newLoginFormat;
|
||||
this.emit('login-format-changed', newLoginFormat);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
get loginFormat() {
|
||||
if (this._loginFormat !== undefined)
|
||||
@ -96,16 +92,16 @@ var Manager = new Lang.Class({
|
||||
this._updateLoginFormat();
|
||||
|
||||
return this._loginFormat;
|
||||
},
|
||||
}
|
||||
|
||||
release() {
|
||||
Service(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
'/org/freedesktop/realmd',
|
||||
service => { service.ReleaseRemote(); });
|
||||
service => service.ReleaseRemote());
|
||||
this._aggregateProvider.disconnect(this._signalId);
|
||||
this._realms = { };
|
||||
this._updateLoginFormat();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(Manager.prototype)
|
||||
};
|
||||
Signals.addSignalMethods(Manager.prototype);
|
||||
|
141
js/gdm/util.js
@ -1,19 +1,13 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const { Clutter, Gio, GLib } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Batch = imports.gdm.batch;
|
||||
const Fprint = imports.gdm.fingerprint;
|
||||
const OVirt = imports.gdm.oVirt;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const SmartcardManager = imports.misc.smartcardManager;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
@ -36,7 +30,7 @@ var LOGO_KEY = 'logo';
|
||||
var DISABLE_USER_LIST_KEY = 'disable-user-list';
|
||||
|
||||
// Give user 48ms to read each character of a PAM message
|
||||
var USER_READ_TIME = 48
|
||||
var USER_READ_TIME = 48;
|
||||
|
||||
var MessageType = {
|
||||
NONE: 0,
|
||||
@ -119,10 +113,8 @@ function cloneAndFadeOutActor(actor) {
|
||||
return hold;
|
||||
}
|
||||
|
||||
var ShellUserVerifier = new Lang.Class({
|
||||
Name: 'ShellUserVerifier',
|
||||
|
||||
_init(client, params) {
|
||||
var ShellUserVerifier = class {
|
||||
constructor(client, params) {
|
||||
params = Params.parse(params, { reauthenticationOnly: false });
|
||||
this._reauthOnly = params.reauthenticationOnly;
|
||||
|
||||
@ -165,7 +157,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
|
||||
this._oVirtUserAuthenticated.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
begin(userName, hold) {
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
@ -183,7 +175,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
} else {
|
||||
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
if (this._cancellable)
|
||||
@ -193,14 +185,14 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._userVerifier.call_cancel_sync(null);
|
||||
this.clear();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_clearUserVerifier() {
|
||||
if (this._userVerifier) {
|
||||
this._userVerifier.run_dispose();
|
||||
this._userVerifier = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
clear() {
|
||||
if (this._cancellable) {
|
||||
@ -210,7 +202,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this._clearUserVerifier();
|
||||
this._clearMessageQueue();
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clear();
|
||||
@ -224,7 +216,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
|
||||
this._oVirtCredentialsManager = null;
|
||||
},
|
||||
}
|
||||
|
||||
answerQuery(serviceName, answer) {
|
||||
if (!this.hasPendingMessages) {
|
||||
@ -235,12 +227,12 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getIntervalForMessage(message) {
|
||||
// We probably could be smarter here
|
||||
return message.length * USER_READ_TIME;
|
||||
},
|
||||
}
|
||||
|
||||
finishMessageQueue() {
|
||||
if (!this.hasPendingMessages)
|
||||
@ -250,7 +242,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this.hasPendingMessages = false;
|
||||
this.emit('no-more-messages');
|
||||
},
|
||||
}
|
||||
|
||||
_queueMessageTimeout() {
|
||||
if (this._messageQueue.length == 0) {
|
||||
@ -273,7 +265,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
|
||||
},
|
||||
}
|
||||
|
||||
_queueMessage(message, messageType) {
|
||||
let interval = this._getIntervalForMessage(message);
|
||||
@ -281,7 +273,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this.hasPendingMessages = true;
|
||||
this._messageQueue.push({ text: message, type: messageType, interval: interval });
|
||||
this._queueMessageTimeout();
|
||||
},
|
||||
}
|
||||
|
||||
_clearMessageQueue() {
|
||||
this.finishMessageQueue();
|
||||
@ -291,7 +283,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._messageQueueTimeoutId = 0;
|
||||
}
|
||||
this.emit('show-message', null, MessageType.NONE);
|
||||
},
|
||||
}
|
||||
|
||||
_checkForFingerprintReader() {
|
||||
this._haveFingerprintReader = false;
|
||||
@ -309,12 +301,12 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._updateDefaultService();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_oVirtUserAuthenticated(token) {
|
||||
this._preemptingService = OVIRT_SERVICE_NAME;
|
||||
this.emit('ovirt-user-authenticated');
|
||||
},
|
||||
}
|
||||
|
||||
_checkForSmartcard() {
|
||||
let smartcardDetected;
|
||||
@ -336,7 +328,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this.emit('smartcard-status-changed');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_reportInitError(where, error) {
|
||||
logError(error, where);
|
||||
@ -344,13 +336,13 @@ var ShellUserVerifier = new Lang.Class({
|
||||
|
||||
this._queueMessage(_("Authentication error"), MessageType.ERROR);
|
||||
this._verificationFailed(false);
|
||||
},
|
||||
}
|
||||
|
||||
_reauthenticationChannelOpened(client, result) {
|
||||
try {
|
||||
this._clearUserVerifier();
|
||||
this._userVerifier = client.open_reauthentication_channel_finish(result);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
|
||||
@ -371,13 +363,13 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._connectSignals();
|
||||
this._beginVerification();
|
||||
this._hold.release();
|
||||
},
|
||||
}
|
||||
|
||||
_userVerifierGot(client, result) {
|
||||
try {
|
||||
this._clearUserVerifier();
|
||||
this._userVerifier = client.get_user_verifier_finish(result);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
this._reportInitError('Failed to obtain user verifier', e);
|
||||
@ -387,7 +379,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._connectSignals();
|
||||
this._beginVerification();
|
||||
this._hold.release();
|
||||
},
|
||||
}
|
||||
|
||||
_connectSignals() {
|
||||
this._userVerifier.connect('info', this._onInfo.bind(this));
|
||||
@ -397,22 +389,22 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this));
|
||||
this._userVerifier.connect('reset', this._onReset.bind(this));
|
||||
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_getForegroundService() {
|
||||
if (this._preemptingService)
|
||||
return this._preemptingService;
|
||||
|
||||
return this._defaultService;
|
||||
},
|
||||
}
|
||||
|
||||
serviceIsForeground(serviceName) {
|
||||
return serviceName == this._getForegroundService();
|
||||
},
|
||||
}
|
||||
|
||||
serviceIsDefault(serviceName) {
|
||||
return serviceName == this._defaultService;
|
||||
},
|
||||
}
|
||||
|
||||
_updateDefaultService() {
|
||||
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
|
||||
@ -426,50 +418,45 @@ var ShellUserVerifier = new Lang.Class({
|
||||
log("no authentication service is enabled, using password authentication");
|
||||
this._defaultService = PASSWORD_SERVICE_NAME;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_startService(serviceName) {
|
||||
this._hold.acquire();
|
||||
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._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();
|
||||
});
|
||||
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._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() {
|
||||
this._startService(this._getForegroundService());
|
||||
|
||||
if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME))
|
||||
this._startService(FINGERPRINT_SERVICE_NAME);
|
||||
},
|
||||
}
|
||||
|
||||
_onInfo(client, serviceName, info) {
|
||||
if (this.serviceIsForeground(serviceName)) {
|
||||
@ -484,21 +471,21 @@ var ShellUserVerifier = new Lang.Class({
|
||||
// to indicate the user can swipe their finger instead
|
||||
this._queueMessage(_("(or swipe finger)"), MessageType.HINT);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onProblem(client, serviceName, problem) {
|
||||
if (!this.serviceIsForeground(serviceName))
|
||||
return;
|
||||
|
||||
this._queueMessage(problem, MessageType.ERROR);
|
||||
},
|
||||
}
|
||||
|
||||
_onInfoQuery(client, serviceName, question) {
|
||||
if (!this.serviceIsForeground(serviceName))
|
||||
return;
|
||||
|
||||
this.emit('ask-question', serviceName, question, '');
|
||||
},
|
||||
}
|
||||
|
||||
_onSecretInfoQuery(client, serviceName, secretQuestion) {
|
||||
if (!this.serviceIsForeground(serviceName))
|
||||
@ -511,7 +498,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
}
|
||||
|
||||
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
|
||||
},
|
||||
}
|
||||
|
||||
_onReset() {
|
||||
// Clear previous attempts to authenticate
|
||||
@ -519,20 +506,20 @@ var ShellUserVerifier = new Lang.Class({
|
||||
this._updateDefaultService();
|
||||
|
||||
this.emit('reset');
|
||||
},
|
||||
}
|
||||
|
||||
_onVerificationComplete() {
|
||||
this.emit('verification-complete');
|
||||
},
|
||||
}
|
||||
|
||||
_cancelAndReset() {
|
||||
this.cancel();
|
||||
this._onReset();
|
||||
},
|
||||
}
|
||||
|
||||
_retry() {
|
||||
this.begin(this._userName, new Batch.Hold());
|
||||
},
|
||||
}
|
||||
|
||||
_verificationFailed(retry) {
|
||||
// For Not Listed / enterprise logins, immediately reset
|
||||
@ -567,7 +554,7 @@ var ShellUserVerifier = new Lang.Class({
|
||||
}
|
||||
|
||||
this.emit('verification-failed', canRetry);
|
||||
},
|
||||
}
|
||||
|
||||
_onConversationStopped(client, serviceName) {
|
||||
// If the login failed with the preauthenticated oVirt credentials
|
||||
@ -586,6 +573,6 @@ var ShellUserVerifier = new Lang.Class({
|
||||
if (this.serviceIsForeground(serviceName)) {
|
||||
this._verificationFailed(true);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(ShellUserVerifier.prototype);
|
||||
|
@ -64,6 +64,7 @@
|
||||
<file>ui/keyboard.js</file>
|
||||
<file>ui/layout.js</file>
|
||||
<file>ui/lightbox.js</file>
|
||||
<file>ui/locatePointer.js</file>
|
||||
<file>ui/lookingGlass.js</file>
|
||||
<file>ui/magnifier.js</file>
|
||||
<file>ui/magnifierDBus.js</file>
|
||||
@ -78,12 +79,14 @@
|
||||
<file>ui/overview.js</file>
|
||||
<file>ui/overviewControls.js</file>
|
||||
<file>ui/padOsd.js</file>
|
||||
<file>ui/pageIndicators.js</file>
|
||||
<file>ui/panel.js</file>
|
||||
<file>ui/panelMenu.js</file>
|
||||
<file>ui/pointerA11yTimeout.js</file>
|
||||
<file>ui/pointerWatcher.js</file>
|
||||
<file>ui/popupMenu.js</file>
|
||||
<file>ui/remoteMenu.js</file>
|
||||
<file>ui/remoteSearch.js</file>
|
||||
<file>ui/ripples.js</file>
|
||||
<file>ui/runDialog.js</file>
|
||||
<file>ui/screenShield.js</file>
|
||||
<file>ui/screencast.js</file>
|
||||
@ -120,6 +123,7 @@
|
||||
|
||||
<file>ui/status/accessibility.js</file>
|
||||
<file>ui/status/brightness.js</file>
|
||||
<file>ui/status/dwellClick.js</file>
|
||||
<file>ui/status/location.js</file>
|
||||
<file>ui/status/keyboard.js</file>
|
||||
<file>ui/status/nightLight.js</file>
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Common utils for the extension system and the extension
|
||||
// preferences tool
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Gettext = imports.gettext;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
@ -31,7 +31,7 @@ function getCurrentExtension() {
|
||||
// Search for an occurrence of an extension stack frame
|
||||
// Start at 1 because 0 is the stack frame of this function
|
||||
for (let i = 1; i < stack.length; i++) {
|
||||
if (stack[i].indexOf('/gnome-shell/extensions/') > -1) {
|
||||
if (stack[i].includes('/gnome-shell/extensions/')) {
|
||||
extensionStackLine = stack[i];
|
||||
break;
|
||||
}
|
||||
@ -64,6 +64,66 @@ function getCurrentExtension() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* initTranslations:
|
||||
* @domain: (optional): the gettext domain to use
|
||||
*
|
||||
* Initialize Gettext to load translations from extensionsdir/locale.
|
||||
* If @domain is not provided, it will be taken from metadata['gettext-domain']
|
||||
*/
|
||||
function initTranslations(domain) {
|
||||
let extension = getCurrentExtension();
|
||||
|
||||
if (!extension)
|
||||
throw new Error('initTranslations() can only be called from extensions');
|
||||
|
||||
domain = domain || extension.metadata['gettext-domain'];
|
||||
|
||||
// Expect USER extensions to have a locale/ subfolder, otherwise assume a
|
||||
// SYSTEM extension that has been installed in the same prefix as the shell
|
||||
let localeDir = extension.dir.get_child('locale');
|
||||
if (localeDir.query_exists(null))
|
||||
Gettext.bindtextdomain(domain, localeDir.get_path());
|
||||
else
|
||||
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* getSettings:
|
||||
* @schema: (optional): the GSettings schema id
|
||||
*
|
||||
* Builds and returns a GSettings schema for @schema, using schema files
|
||||
* in extensionsdir/schemas. If @schema is omitted, it is taken from
|
||||
* metadata['settings-schema'].
|
||||
*/
|
||||
function getSettings(schema) {
|
||||
let extension = getCurrentExtension();
|
||||
|
||||
if (!extension)
|
||||
throw new Error('getSettings() can only be called from extensions');
|
||||
|
||||
schema = schema || extension.metadata['settings-schema'];
|
||||
|
||||
const GioSSS = Gio.SettingsSchemaSource;
|
||||
|
||||
// Expect USER extensions to have a schemas/ subfolder, otherwise assume a
|
||||
// SYSTEM extension that has been installed in the same prefix as the shell
|
||||
let schemaDir = extension.dir.get_child('schemas');
|
||||
let schemaSource;
|
||||
if (schemaDir.query_exists(null))
|
||||
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
|
||||
GioSSS.get_default(),
|
||||
false);
|
||||
else
|
||||
schemaSource = GioSSS.get_default();
|
||||
|
||||
let schemaObj = schemaSource.lookup(schema, true);
|
||||
if (!schemaObj)
|
||||
throw new Error(`Schema ${schema} could not be found for extension ${extension.metadata.uuid}. Please check your installation`);
|
||||
|
||||
return new Gio.Settings({ settings_schema: schemaObj });
|
||||
}
|
||||
|
||||
/**
|
||||
* versionCheck:
|
||||
* @required: an array of versions we're compatible with
|
||||
@ -102,8 +162,6 @@ function isOutOfDate(extension) {
|
||||
}
|
||||
|
||||
function createExtensionObject(uuid, dir, type) {
|
||||
let info;
|
||||
|
||||
let metadataFile = dir.get_child('metadata.json');
|
||||
if (!metadataFile.query_exists(null)) {
|
||||
throw new Error('Missing metadata.json');
|
||||
@ -115,25 +173,25 @@ function createExtensionObject(uuid, dir, type) {
|
||||
if (metadataContents instanceof Uint8Array)
|
||||
metadataContents = imports.byteArray.toString(metadataContents);
|
||||
} catch (e) {
|
||||
throw new Error('Failed to load metadata.json: ' + e);
|
||||
throw new Error(`Failed to load metadata.json: ${e}`);
|
||||
}
|
||||
let meta;
|
||||
try {
|
||||
meta = JSON.parse(metadataContents);
|
||||
} catch (e) {
|
||||
throw new Error('Failed to parse metadata.json: ' + e);
|
||||
throw new Error(`Failed to parse metadata.json: ${e}`);
|
||||
}
|
||||
|
||||
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
|
||||
for (let i = 0; i < requiredProperties.length; i++) {
|
||||
let prop = requiredProperties[i];
|
||||
if (!meta[prop]) {
|
||||
throw new Error('missing "' + prop + '" property in metadata.json');
|
||||
throw new Error(`missing "${prop}" property in metadata.json`);
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid != meta.uuid) {
|
||||
throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
|
||||
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
|
||||
}
|
||||
|
||||
let extension = {};
|
||||
@ -160,9 +218,7 @@ function installImporter(extension) {
|
||||
imports.searchPath = oldSearchPath;
|
||||
}
|
||||
|
||||
var ExtensionFinder = new Lang.Class({
|
||||
Name: 'ExtensionFinder',
|
||||
|
||||
var ExtensionFinder = class {
|
||||
_loadExtension(extensionDir, info, perUserDir) {
|
||||
let fileType = info.get_file_type();
|
||||
if (fileType != Gio.FileType.DIRECTORY)
|
||||
@ -179,12 +235,12 @@ var ExtensionFinder = new Lang.Class({
|
||||
: ExtensionType.SYSTEM;
|
||||
try {
|
||||
extension = createExtensionObject(uuid, extensionDir, type);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
logError(e, 'Could not load extension %s'.format(uuid));
|
||||
return;
|
||||
}
|
||||
this.emit('extension-found', extension);
|
||||
},
|
||||
}
|
||||
|
||||
scanExtensions() {
|
||||
let perUserDir = Gio.File.new_for_path(global.userdatadir);
|
||||
@ -192,5 +248,5 @@ var ExtensionFinder = new Lang.Class({
|
||||
this._loadExtension(dir, info, perUserDir);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ExtensionFinder.prototype);
|
||||
|
@ -1,10 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const { Gio, GLib } = imports.gi;
|
||||
const Config = imports.misc.config;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
function collectFromDatadirs(subdir, includeUserDir, processFile) {
|
||||
let dataDirs = GLib.get_system_data_dirs();
|
||||
@ -39,7 +36,7 @@ function recursivelyDeleteDir(dir, deleteParent) {
|
||||
let children = dir.enumerate_children('standard::name,standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE, null);
|
||||
|
||||
let info, child;
|
||||
let info;
|
||||
while ((info = children.next_file(null)) != null) {
|
||||
let type = info.get_file_type();
|
||||
let child = dir.get_child(info.get_name());
|
||||
@ -60,7 +57,7 @@ function recursivelyMoveDir(srcDir, destDir) {
|
||||
if (!destDir.query_exists(null))
|
||||
destDir.make_directory_with_parents(null);
|
||||
|
||||
let info, child;
|
||||
let info;
|
||||
while ((info = children.next_file(null)) != null) {
|
||||
let type = info.get_file_type();
|
||||
let srcChild = srcDir.get_child(info.get_name());
|
||||
@ -89,11 +86,11 @@ function loadInterfaceXML(iface) {
|
||||
try {
|
||||
let [ok, bytes] = f.load_contents(null);
|
||||
if (bytes instanceof Uint8Array)
|
||||
xml = imports.byteArray.toString(bytes)
|
||||
xml = imports.byteArray.toString(bytes);
|
||||
else
|
||||
xml = bytes.toString();
|
||||
} catch (e) {
|
||||
log('Failed to load D-Bus interface ' + iface);
|
||||
log(`Failed to load D-Bus interface ${iface}`);
|
||||
}
|
||||
|
||||
return xml;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
|
@ -1,16 +1,13 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
var DEFAULT_LIMIT = 512;
|
||||
|
||||
var HistoryManager = new Lang.Class({
|
||||
Name: 'HistoryManager',
|
||||
|
||||
_init(params) {
|
||||
var HistoryManager = class {
|
||||
constructor(params) {
|
||||
params = Params.parse(params, { gsettingsKey: null,
|
||||
limit: DEFAULT_LIMIT,
|
||||
entry: null });
|
||||
@ -21,7 +18,7 @@ var HistoryManager = new Lang.Class({
|
||||
this._historyIndex = 0;
|
||||
if (this._key) {
|
||||
this._history = global.settings.get_strv(this._key);
|
||||
global.settings.connect('changed::' + this._key,
|
||||
global.settings.connect(`changed::${this._key}`,
|
||||
this._historyChanged.bind(this));
|
||||
|
||||
} else {
|
||||
@ -34,12 +31,12 @@ var HistoryManager = new Lang.Class({
|
||||
this._entry.connect('key-press-event',
|
||||
this._onEntryKeyPress.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_historyChanged() {
|
||||
this._history = global.settings.get_strv(this._key);
|
||||
this._historyIndex = this._history.length;
|
||||
},
|
||||
}
|
||||
|
||||
_setPrevItem(text) {
|
||||
if (this._historyIndex <= 0)
|
||||
@ -50,7 +47,7 @@ var HistoryManager = new Lang.Class({
|
||||
this._historyIndex--;
|
||||
this._indexChanged();
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_setNextItem(text) {
|
||||
if (this._historyIndex >= this._history.length)
|
||||
@ -61,7 +58,7 @@ var HistoryManager = new Lang.Class({
|
||||
this._historyIndex++;
|
||||
this._indexChanged();
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
lastItem() {
|
||||
if (this._historyIndex != this._history.length) {
|
||||
@ -69,8 +66,8 @@ var HistoryManager = new Lang.Class({
|
||||
this._indexChanged();
|
||||
}
|
||||
|
||||
return this._historyIndex ? this._history[this._historyIndex -1] : null;
|
||||
},
|
||||
return this._historyIndex ? this._history[this._historyIndex - 1] : null;
|
||||
}
|
||||
|
||||
addItem(input) {
|
||||
if (this._history.length == 0 ||
|
||||
@ -81,7 +78,7 @@ var HistoryManager = new Lang.Class({
|
||||
this._save();
|
||||
}
|
||||
this._historyIndex = this._history.length;
|
||||
},
|
||||
}
|
||||
|
||||
_onEntryKeyPress(entry, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
@ -91,7 +88,7 @@ var HistoryManager = new Lang.Class({
|
||||
return this._setNextItem(entry.get_text());
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
_indexChanged() {
|
||||
let current = this._history[this._historyIndex] || '';
|
||||
@ -99,7 +96,7 @@ var HistoryManager = new Lang.Class({
|
||||
|
||||
if (this._entry)
|
||||
this._entry.set_text(current);
|
||||
},
|
||||
}
|
||||
|
||||
_save() {
|
||||
if (this._history.length > this._limit)
|
||||
@ -108,5 +105,5 @@ var HistoryManager = new Lang.Class({
|
||||
if (this._key)
|
||||
global.settings.set_strv(this._key, this._history);
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(HistoryManager.prototype);
|
||||
|
@ -1,12 +1,9 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const { Gio, GLib, IBus } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const IBus = imports.gi.IBus;
|
||||
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
||||
|
||||
// Ensure runtime version matches
|
||||
@ -32,21 +29,20 @@ function getIBusManager() {
|
||||
return _ibusManager;
|
||||
}
|
||||
|
||||
var IBusManager = new Lang.Class({
|
||||
Name: 'IBusManager',
|
||||
|
||||
// This is the longest we'll keep the keyboard frozen until an input
|
||||
// source is active.
|
||||
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
|
||||
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
|
||||
|
||||
_init() {
|
||||
var IBusManager = class {
|
||||
constructor() {
|
||||
IBus.init();
|
||||
|
||||
// This is the longest we'll keep the keyboard frozen until an input
|
||||
// source is active.
|
||||
this._MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
|
||||
this._PRELOAD_ENGINES_DELAY_TIME = 30; // sec
|
||||
|
||||
|
||||
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
|
||||
|
||||
this._panelService = null;
|
||||
this._engines = {};
|
||||
this._engines = new Map();
|
||||
this._ready = false;
|
||||
this._registerPropertiesId = 0;
|
||||
this._currentEngineName = null;
|
||||
@ -60,16 +56,16 @@ var IBusManager = new Lang.Class({
|
||||
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
|
||||
|
||||
this._spawn();
|
||||
},
|
||||
}
|
||||
|
||||
_spawn() {
|
||||
try {
|
||||
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
|
||||
Gio.SubprocessFlags.NONE);
|
||||
} catch(e) {
|
||||
log('Failed to launch ibus-daemon: ' + e.message);
|
||||
} catch (e) {
|
||||
log(`Failed to launch ibus-daemon: ${e.message}`);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_clear() {
|
||||
if (this._panelService)
|
||||
@ -77,7 +73,7 @@ var IBusManager = new Lang.Class({
|
||||
|
||||
this._panelService = null;
|
||||
this._candidatePopup.setPanelService(null);
|
||||
this._engines = {};
|
||||
this._engines.clear();
|
||||
this._ready = false;
|
||||
this._registerPropertiesId = 0;
|
||||
this._currentEngineName = null;
|
||||
@ -85,7 +81,7 @@ var IBusManager = new Lang.Class({
|
||||
this.emit('ready', false);
|
||||
|
||||
this._spawn();
|
||||
},
|
||||
}
|
||||
|
||||
_onConnected() {
|
||||
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
|
||||
@ -93,20 +89,20 @@ var IBusManager = new Lang.Class({
|
||||
IBus.BusNameFlag.REPLACE_EXISTING,
|
||||
-1, null,
|
||||
this._initPanelService.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_initEngines(ibus, result) {
|
||||
let enginesList = this._ibus.list_engines_async_finish(result);
|
||||
if (enginesList) {
|
||||
for (let i = 0; i < enginesList.length; ++i) {
|
||||
let name = enginesList[i].get_name();
|
||||
this._engines[name] = enginesList[i];
|
||||
this._engines.set(name, enginesList[i]);
|
||||
}
|
||||
this._updateReadiness();
|
||||
} else {
|
||||
this._clear();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_initPanelService(ibus, result) {
|
||||
let success = this._ibus.request_name_async_finish(result);
|
||||
@ -123,7 +119,7 @@ var IBusManager = new Lang.Class({
|
||||
if (!GLib.str_has_suffix(path, '/InputContext_1'))
|
||||
this.emit ('focus-in');
|
||||
});
|
||||
this._panelService.connect('focus-out', () => { this.emit('focus-out'); });
|
||||
this._panelService.connect('focus-out', () => this.emit('focus-out'));
|
||||
|
||||
try {
|
||||
// IBus versions older than 1.5.10 have a bug which
|
||||
@ -142,7 +138,7 @@ var IBusManager = new Lang.Class({
|
||||
engine = this._ibus.get_global_engine_async_finish(result);
|
||||
if (!engine)
|
||||
return;
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
this._engineChanged(this._ibus, engine.get_name());
|
||||
@ -151,13 +147,12 @@ var IBusManager = new Lang.Class({
|
||||
} else {
|
||||
this._clear();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateReadiness() {
|
||||
this._ready = (Object.keys(this._engines).length > 0 &&
|
||||
this._panelService != null);
|
||||
this._ready = this._engines.size > 0 && this._panelService != null;
|
||||
this.emit('ready', this._ready);
|
||||
},
|
||||
}
|
||||
|
||||
_engineChanged(bus, engineName) {
|
||||
if (!this._ready)
|
||||
@ -178,26 +173,26 @@ var IBusManager = new Lang.Class({
|
||||
|
||||
this.emit('properties-registered', this._currentEngineName, props);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateProperty(panel, prop) {
|
||||
this.emit('property-updated', this._currentEngineName, prop);
|
||||
},
|
||||
}
|
||||
|
||||
_setContentType(panel, purpose, hints) {
|
||||
this.emit('set-content-type', purpose, hints);
|
||||
},
|
||||
}
|
||||
|
||||
activateProperty(key, state) {
|
||||
this._panelService.property_activate(key, state);
|
||||
},
|
||||
}
|
||||
|
||||
getEngineDesc(id) {
|
||||
if (!this._ready || !this._engines.hasOwnProperty(id))
|
||||
if (!this._ready || !this._engines.has(id))
|
||||
return null;
|
||||
|
||||
return this._engines[id];
|
||||
},
|
||||
return this._engines.get(id);
|
||||
}
|
||||
|
||||
setEngine(id, callback) {
|
||||
// Send id even if id == this._currentEngineName
|
||||
@ -211,7 +206,7 @@ var IBusManager = new Lang.Class({
|
||||
|
||||
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
|
||||
null, callback || null);
|
||||
},
|
||||
}
|
||||
|
||||
preloadEngines(ids) {
|
||||
if (!this._ibus || ids.length == 0)
|
||||
@ -233,6 +228,6 @@ var IBusManager = new Lang.Class({
|
||||
this._preloadEnginesId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(IBusManager.prototype);
|
||||
|
@ -1,23 +1,21 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const IBus = imports.gi.IBus;
|
||||
const { Clutter, GLib, GObject, IBus } = imports.gi;
|
||||
|
||||
const Keyboard = imports.ui.status.keyboard;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
var InputMethod = new Lang.Class({
|
||||
Name: 'InputMethod',
|
||||
Extends: Clutter.InputMethod,
|
||||
var HIDE_PANEL_TIME = 50;
|
||||
|
||||
var InputMethod = GObject.registerClass(
|
||||
class InputMethod extends Clutter.InputMethod {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
this._hints = 0;
|
||||
this._purpose = 0;
|
||||
this._enabled = true;
|
||||
this._currentFocus = null;
|
||||
this._preeditStr = '';
|
||||
this._preeditPos = 0;
|
||||
this._preeditVisible = false;
|
||||
this._hidePanelId = 0;
|
||||
this._ibus = IBus.Bus.new_async();
|
||||
this._ibus.connect('connected', this._onConnected.bind(this));
|
||||
this._ibus.connect('disconnected', this._clear.bind(this));
|
||||
@ -30,11 +28,11 @@ var InputMethod = new Lang.Class({
|
||||
|
||||
if (this._ibus.is_connected())
|
||||
this._onConnected();
|
||||
},
|
||||
}
|
||||
|
||||
get currentFocus() {
|
||||
return this._currentFocus;
|
||||
},
|
||||
}
|
||||
|
||||
_updateCapabilities() {
|
||||
let caps = 0;
|
||||
@ -49,21 +47,19 @@ var InputMethod = new Lang.Class({
|
||||
|
||||
if (this._context)
|
||||
this._context.set_capabilities(caps);
|
||||
},
|
||||
}
|
||||
|
||||
_onSourceChanged() {
|
||||
this._currentSource = this._inputSourceManager.currentSource;
|
||||
},
|
||||
}
|
||||
|
||||
_onConnected() {
|
||||
this._ibus.create_input_context_async ('gnome-shell', -1, null,
|
||||
this._setContext.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_setContext(bus, res) {
|
||||
this._context = this._ibus.create_input_context_async_finish(res);
|
||||
this._context.connect('enabled', () => { this._enabled = true });
|
||||
this._context.connect('disabled', () => { this._enabled = false });
|
||||
this._context.connect('commit-text', this._onCommitText.bind(this));
|
||||
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
|
||||
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
|
||||
@ -72,30 +68,29 @@ var InputMethod = new Lang.Class({
|
||||
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
|
||||
|
||||
this._updateCapabilities();
|
||||
},
|
||||
}
|
||||
|
||||
_clear() {
|
||||
this._context = null;
|
||||
this._hints = 0;
|
||||
this._purpose = 0;
|
||||
this._enabled = false;
|
||||
this._preeditStr = ''
|
||||
this._preeditStr = '';
|
||||
this._preeditPos = 0;
|
||||
this._preeditVisible = false;
|
||||
},
|
||||
}
|
||||
|
||||
_emitRequestSurrounding() {
|
||||
if (this._context.needs_surrounding_text())
|
||||
this.emit('request-surrounding');
|
||||
},
|
||||
}
|
||||
|
||||
_onCommitText(context, text) {
|
||||
this.commit(text.get_text());
|
||||
},
|
||||
}
|
||||
|
||||
_onDeleteSurroundingText(context) {
|
||||
this.delete_surrounding();
|
||||
},
|
||||
}
|
||||
|
||||
_onUpdatePreeditText(context, text, pos, visible) {
|
||||
if (text == null)
|
||||
@ -111,17 +106,17 @@ var InputMethod = new Lang.Class({
|
||||
this._preeditStr = preedit;
|
||||
this._preeditPos = pos;
|
||||
this._preeditVisible = visible;
|
||||
},
|
||||
}
|
||||
|
||||
_onShowPreeditText(context) {
|
||||
this._preeditVisible = true;
|
||||
this.set_preedit_text(this._preeditStr, this._preeditPos);
|
||||
},
|
||||
}
|
||||
|
||||
_onHidePreeditText(context) {
|
||||
this.set_preedit_text(null, this._preeditPos);
|
||||
this._preeditVisible = false;
|
||||
},
|
||||
}
|
||||
|
||||
_onForwardKeyEvent(context, keyval, keycode, state) {
|
||||
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
|
||||
@ -135,7 +130,7 @@ var InputMethod = new Lang.Class({
|
||||
time = global.display.get_current_time_roundtrip();
|
||||
|
||||
this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_focus_in(focus) {
|
||||
this._currentFocus = focus;
|
||||
@ -144,7 +139,12 @@ var InputMethod = new Lang.Class({
|
||||
this._updateCapabilities();
|
||||
this._emitRequestSurrounding();
|
||||
}
|
||||
},
|
||||
|
||||
if (this._hidePanelId) {
|
||||
GLib.source_remove(this._hidePanelId);
|
||||
this._hidePanelId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_focus_out() {
|
||||
this._currentFocus = null;
|
||||
@ -158,7 +158,13 @@ var InputMethod = new Lang.Class({
|
||||
this.set_preedit_text(null, 0);
|
||||
this._preeditStr = null;
|
||||
}
|
||||
},
|
||||
|
||||
this._hidePanelId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, HIDE_PANEL_TIME, () => {
|
||||
this.set_input_panel_state(Clutter.InputPanelState.OFF);
|
||||
this._hidePanelId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_reset() {
|
||||
if (this._context) {
|
||||
@ -171,7 +177,7 @@ var InputMethod = new Lang.Class({
|
||||
this.set_preedit_text(null, 0);
|
||||
this._preeditStr = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_set_cursor_location(rect) {
|
||||
if (this._context) {
|
||||
@ -179,7 +185,7 @@ var InputMethod = new Lang.Class({
|
||||
rect.get_width(), rect.get_height());
|
||||
this._emitRequestSurrounding();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_set_surrounding(text, cursor, anchor) {
|
||||
if (!this._context || !text)
|
||||
@ -187,7 +193,7 @@ var InputMethod = new Lang.Class({
|
||||
|
||||
let ibusText = IBus.Text.new_from_string(text);
|
||||
this._context.set_surrounding_text(ibusText, cursor, anchor);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_update_content_hints(hints) {
|
||||
let ibusHints = 0;
|
||||
@ -207,7 +213,7 @@ var InputMethod = new Lang.Class({
|
||||
this._hints = ibusHints;
|
||||
if (this._context)
|
||||
this._context.set_content_type(this._purpose, this._hints);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_update_content_purpose(purpose) {
|
||||
let ibusPurpose = 0;
|
||||
@ -233,10 +239,10 @@ var InputMethod = new Lang.Class({
|
||||
this._purpose = ibusPurpose;
|
||||
if (this._context)
|
||||
this._context.set_content_type(this._purpose, this._hints);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_filter_key_event(event) {
|
||||
if (!this._context || !this._enabled)
|
||||
if (!this._context)
|
||||
return false;
|
||||
if (!this._currentSource)
|
||||
return false;
|
||||
@ -256,9 +262,9 @@ var InputMethod = new Lang.Class({
|
||||
let retval = context.process_key_event_async_finish(res);
|
||||
this.notify_key_event(event, retval);
|
||||
} catch (e) {
|
||||
log('Error processing key on IM: ' + e.message);
|
||||
log(`Error processing key on IM: ${e.message}`);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
@ -1,8 +1,4 @@
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { Gio, GLib, Meta, Shell } = imports.gi;
|
||||
|
||||
const INTROSPECT_SCHEMA = 'org.gnome.shell';
|
||||
const INTROSPECT_KEY = 'introspect';
|
||||
@ -12,10 +8,8 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
|
||||
|
||||
var IntrospectService = new Lang.Class({
|
||||
Name: 'IntrospectService',
|
||||
|
||||
_init() {
|
||||
var IntrospectService = class {
|
||||
constructor() {
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(IntrospectDBusIface,
|
||||
this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Introspect');
|
||||
@ -45,21 +39,24 @@ var IntrospectService = new Lang.Class({
|
||||
});
|
||||
|
||||
this._syncRunningApplications();
|
||||
},
|
||||
}
|
||||
|
||||
_isStandaloneApp(app) {
|
||||
let windows = app.get_windows();
|
||||
|
||||
return app.get_windows().some(w => w.transient_for == null);
|
||||
},
|
||||
}
|
||||
|
||||
_isIntrospectEnabled() {
|
||||
return this._settings.get_boolean(INTROSPECT_KEY);
|
||||
},
|
||||
return this._settings.get_boolean(INTROSPECT_KEY);
|
||||
}
|
||||
|
||||
_isSenderWhitelisted(sender) {
|
||||
return APP_WHITELIST.includes(sender);
|
||||
},
|
||||
return APP_WHITELIST.includes(sender);
|
||||
}
|
||||
|
||||
_getSandboxedAppId(app) {
|
||||
let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
|
||||
return ids.find(id => id != null);
|
||||
}
|
||||
|
||||
_syncRunningApplications() {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
@ -82,6 +79,10 @@ var IntrospectService = new Lang.Class({
|
||||
newActiveApplication = app.get_id();
|
||||
}
|
||||
|
||||
let sandboxedAppId = this._getSandboxedAppId(app);
|
||||
if (sandboxedAppId)
|
||||
appInfo['sandboxed-app-id'] = new GLib.Variant('s', sandboxedAppId);
|
||||
|
||||
newRunningApplications[app.get_id()] = appInfo;
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ var IntrospectService = new Lang.Class({
|
||||
}
|
||||
this._runningApplicationsDirty = false;
|
||||
this._activeApplicationDirty = false;
|
||||
},
|
||||
}
|
||||
|
||||
_isEligibleWindow(window) {
|
||||
if (window.is_override_redirect())
|
||||
@ -106,7 +107,7 @@ var IntrospectService = new Lang.Class({
|
||||
type == Meta.WindowType.DIALOG ||
|
||||
type == Meta.WindowType.MODAL_DIALOG ||
|
||||
type == Meta.WindowType.UTILITY);
|
||||
},
|
||||
}
|
||||
|
||||
GetRunningApplicationsAsync(params, invocation) {
|
||||
if (!this._isIntrospectEnabled() &&
|
||||
@ -118,7 +119,7 @@ var IntrospectService = new Lang.Class({
|
||||
}
|
||||
|
||||
invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
|
||||
},
|
||||
}
|
||||
|
||||
GetWindowsAsync(params, invocation) {
|
||||
let focusWindow = global.display.get_focus_window();
|
||||
@ -143,6 +144,7 @@ var IntrospectService = new Lang.Class({
|
||||
let frameRect = window.get_frame_rect();
|
||||
let title = window.get_title();
|
||||
let wmClass = window.get_wm_class();
|
||||
let sandboxedAppId = window.get_sandboxed_app_id();
|
||||
|
||||
windowsList[windowId] = {
|
||||
'app-id': GLib.Variant.new('s', app.get_id()),
|
||||
@ -159,8 +161,12 @@ var IntrospectService = new Lang.Class({
|
||||
|
||||
if (wmClass != null)
|
||||
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
|
||||
|
||||
if (sandboxedAppId != null)
|
||||
windowsList[windowId]['sandboxed-app-id'] =
|
||||
GLib.Variant.new('s', sandboxedAppId);
|
||||
}
|
||||
}
|
||||
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -51,14 +51,14 @@ function getCompletions(text, commandHeader, globalCompletionList) {
|
||||
// if we encounter anything that isn't a letter, '.', ')', or ']',
|
||||
// we should stop parsing.
|
||||
function isStopChar(c) {
|
||||
return !c.match(/[\w\.\)\]]/);
|
||||
return !c.match(/[\w.)\]]/);
|
||||
}
|
||||
|
||||
// Given the ending position of a quoted string, find where it starts
|
||||
function findMatchingQuote(expr, offset) {
|
||||
let quoteChar = expr.charAt(offset);
|
||||
for (let i = offset - 1; i >= 0; --i) {
|
||||
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
|
||||
if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ function findMatchingQuote(expr, offset) {
|
||||
// Given the ending position of a regex, find where it starts
|
||||
function findMatchingSlash(expr, offset) {
|
||||
for (let i = offset - 1; i >= 0; --i) {
|
||||
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
|
||||
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -81,7 +81,7 @@ function findMatchingSlash(expr, offset) {
|
||||
// findMatchingBrace("[(])", 3) returns 1.
|
||||
function findMatchingBrace(expr, offset) {
|
||||
let closeBrace = expr.charAt(offset);
|
||||
let openBrace = ({')': '(', ']': '['})[closeBrace];
|
||||
let openBrace = ({ ')': '(', ']': '[' })[closeBrace];
|
||||
|
||||
function findTheBrace(expr, offset) {
|
||||
if (offset < 0) {
|
||||
@ -117,11 +117,11 @@ function getExpressionOffset(expr, offset) {
|
||||
while (offset >= 0) {
|
||||
let currChar = expr.charAt(offset);
|
||||
|
||||
if (isStopChar(currChar)){
|
||||
if (isStopChar(currChar)) {
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
if (currChar.match(/[\)\]]/)) {
|
||||
if (currChar.match(/[)\]]/)) {
|
||||
offset = findMatchingBrace(expr, offset);
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ function getPropertyNamesFromExpression(expr, commandHeader) {
|
||||
let obj = {};
|
||||
if (!isUnsafeExpression(expr)) {
|
||||
try {
|
||||
obj = eval(commandHeader + expr);
|
||||
obj = eval(commandHeader + expr);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
@ -168,7 +168,7 @@ function getPropertyNamesFromExpression(expr, commandHeader) {
|
||||
}
|
||||
|
||||
let propsUnique = {};
|
||||
if (typeof obj === 'object'){
|
||||
if (typeof obj === 'object') {
|
||||
let allProps = getAllProps(obj);
|
||||
// Get only things we are allowed to complete following a '.'
|
||||
allProps = allProps.filter( isValidPropertyName );
|
||||
|
@ -1,9 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const { GLib, GnomeDesktop, Meta } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
@ -38,22 +35,20 @@ function holdKeyboard() {
|
||||
global.display.freeze_keyboard(global.get_current_time());
|
||||
}
|
||||
|
||||
var KeyboardManager = new Lang.Class({
|
||||
Name: 'KeyboardManager',
|
||||
var KeyboardManager = class {
|
||||
constructor() {
|
||||
// The XKB protocol doesn't allow for more that 4 layouts in a
|
||||
// keymap. Wayland doesn't impose this limit and libxkbcommon can
|
||||
// handle up to 32 layouts but since we need to support X clients
|
||||
// even as a Wayland compositor, we can't bump this.
|
||||
this.MAX_LAYOUTS_PER_GROUP = 4;
|
||||
|
||||
// The XKB protocol doesn't allow for more that 4 layouts in a
|
||||
// keymap. Wayland doesn't impose this limit and libxkbcommon can
|
||||
// handle up to 32 layouts but since we need to support X clients
|
||||
// even as a Wayland compositor, we can't bump this.
|
||||
MAX_LAYOUTS_PER_GROUP: 4,
|
||||
|
||||
_init() {
|
||||
this._xkbInfo = getXkbInfo();
|
||||
this._current = null;
|
||||
this._localeLayoutInfo = this._getLocaleLayout();
|
||||
this._layoutInfos = {};
|
||||
this._currentKeymap = null;
|
||||
},
|
||||
}
|
||||
|
||||
_applyLayoutGroup(group) {
|
||||
let options = this._buildOptionsString();
|
||||
@ -65,13 +60,13 @@ var KeyboardManager = new Lang.Class({
|
||||
this._currentKeymap.options == options)
|
||||
return;
|
||||
|
||||
this._currentKeymap = {layouts, variants, options};
|
||||
this._currentKeymap = { layouts, variants, options };
|
||||
Meta.get_backend().set_keymap(layouts, variants, options);
|
||||
},
|
||||
}
|
||||
|
||||
_applyLayoutGroupIndex(idx) {
|
||||
Meta.get_backend().lock_layout_group(idx);
|
||||
},
|
||||
}
|
||||
|
||||
apply(id) {
|
||||
let info = this._layoutInfos[id];
|
||||
@ -87,7 +82,7 @@ var KeyboardManager = new Lang.Class({
|
||||
}
|
||||
|
||||
this._current = info;
|
||||
},
|
||||
}
|
||||
|
||||
reapply() {
|
||||
if (!this._current)
|
||||
@ -95,7 +90,7 @@ var KeyboardManager = new Lang.Class({
|
||||
|
||||
this._applyLayoutGroup(this._current.group);
|
||||
this._applyLayoutGroupIndex(this._current.groupIndex);
|
||||
},
|
||||
}
|
||||
|
||||
setUserLayouts(ids) {
|
||||
this._current = null;
|
||||
@ -126,11 +121,11 @@ var KeyboardManager = new Lang.Class({
|
||||
|
||||
i += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getLocaleLayout() {
|
||||
let locale = GLib.get_language_names()[0];
|
||||
if (locale.indexOf('_') == -1)
|
||||
if (!locale.includes('_'))
|
||||
locale = DEFAULT_LOCALE;
|
||||
|
||||
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);
|
||||
@ -143,21 +138,21 @@ var KeyboardManager = new Lang.Class({
|
||||
return { layout: _layout, variant: _variant };
|
||||
else
|
||||
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
|
||||
},
|
||||
}
|
||||
|
||||
_buildGroupStrings(_group) {
|
||||
let group = _group.concat(this._localeLayoutInfo);
|
||||
let layouts = group.map(g => g.layout).join(',');
|
||||
let variants = group.map(g => g.variant).join(',');
|
||||
return [layouts, variants];
|
||||
},
|
||||
}
|
||||
|
||||
setKeyboardOptions(options) {
|
||||
this._xkbOptions = options;
|
||||
},
|
||||
}
|
||||
|
||||
_buildOptionsString() {
|
||||
let options = this._xkbOptions.join(',');
|
||||
return options;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,10 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { GLib, Gio } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
@ -47,11 +43,33 @@ function canLock() {
|
||||
|
||||
let version = result.deep_unpack()[0].deep_unpack();
|
||||
return haveSystemd() && versionCompare('3.5.91', version);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function registerSessionWithGDM() {
|
||||
log("Registering session with GDM");
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -70,10 +88,8 @@ function getLoginManager() {
|
||||
return _loginManager;
|
||||
}
|
||||
|
||||
var LoginManagerSystemd = new Lang.Class({
|
||||
Name: 'LoginManagerSystemd',
|
||||
|
||||
_init() {
|
||||
var LoginManagerSystemd = class {
|
||||
constructor() {
|
||||
this._proxy = new SystemdLoginManager(Gio.DBus.system,
|
||||
'org.freedesktop.login1',
|
||||
'/org/freedesktop/login1');
|
||||
@ -82,7 +98,7 @@ var LoginManagerSystemd = new Lang.Class({
|
||||
'/org/freedesktop/login1/user/self');
|
||||
this._proxy.connectSignal('PrepareForSleep',
|
||||
this._prepareForSleep.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
getCurrentSessionProxy(callback) {
|
||||
if (this._currentSession) {
|
||||
@ -129,7 +145,7 @@ var LoginManagerSystemd = new Lang.Class({
|
||||
callback(this._currentSession);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
canSuspend(asyncCallback) {
|
||||
this._proxy.CanSuspendRemote((result, error) => {
|
||||
@ -141,7 +157,7 @@ var LoginManagerSystemd = new Lang.Class({
|
||||
asyncCallback(canSuspend, needsAuth);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
listSessions(asyncCallback) {
|
||||
this._proxy.ListSessionsRemote((result, error) => {
|
||||
@ -150,11 +166,11 @@ var LoginManagerSystemd = new Lang.Class({
|
||||
else
|
||||
asyncCallback(result[0]);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
suspend() {
|
||||
this._proxy.SuspendRemote(true);
|
||||
},
|
||||
}
|
||||
|
||||
inhibit(reason, callback) {
|
||||
let inVariant = GLib.Variant.new('(ssss)',
|
||||
@ -169,43 +185,41 @@ var LoginManagerSystemd = new Lang.Class({
|
||||
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
|
||||
fd = fdList.steal_fds()[0];
|
||||
callback(new Gio.UnixInputStream({ fd: fd }));
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
logError(e, "Error getting systemd inhibitor");
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_prepareForSleep(proxy, sender, [aboutToSuspend]) {
|
||||
this.emit('prepare-for-sleep', aboutToSuspend);
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(LoginManagerSystemd.prototype);
|
||||
|
||||
var LoginManagerDummy = new Lang.Class({
|
||||
Name: 'LoginManagerDummy',
|
||||
|
||||
var LoginManagerDummy = class {
|
||||
getCurrentSessionProxy(callback) {
|
||||
// we could return a DummySession object that fakes whatever callers
|
||||
// expect (at the time of writing: connect() and connectSignal()
|
||||
// methods), but just never calling the callback should be safer
|
||||
},
|
||||
}
|
||||
|
||||
canSuspend(asyncCallback) {
|
||||
asyncCallback(false, false);
|
||||
},
|
||||
}
|
||||
|
||||
listSessions(asyncCallback) {
|
||||
asyncCallback([]);
|
||||
},
|
||||
}
|
||||
|
||||
suspend() {
|
||||
this.emit('prepare-for-sleep', true);
|
||||
this.emit('prepare-for-sleep', false);
|
||||
},
|
||||
}
|
||||
|
||||
inhibit(reason, callback) {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(LoginManagerDummy.prototype);
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const NMA = imports.gi.NMA;
|
||||
const { Gio, NMA } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
@ -28,33 +26,33 @@ function _getMobileProvidersDatabase() {
|
||||
}
|
||||
|
||||
// _findProviderForMccMnc:
|
||||
// @operator_name: operator name
|
||||
// @operator_code: operator code
|
||||
// @operatorName: operator name
|
||||
// @operatorCode: operator code
|
||||
//
|
||||
// Given an operator name string (which may not be a real operator name) and an
|
||||
// operator code string, tries to find a proper operator name to display.
|
||||
//
|
||||
function _findProviderForMccMnc(operator_name, operator_code) {
|
||||
if (operator_name) {
|
||||
if (operator_name.length != 0 &&
|
||||
(operator_name.length > 6 || operator_name.length < 5)) {
|
||||
function _findProviderForMccMnc(operatorName, operatorCode) {
|
||||
if (operatorName) {
|
||||
if (operatorName.length != 0 &&
|
||||
(operatorName.length > 6 || operatorName.length < 5)) {
|
||||
// this looks like a valid name, i.e. not an MCCMNC (that some
|
||||
// devices return when not yet connected
|
||||
return operator_name;
|
||||
return operatorName;
|
||||
}
|
||||
|
||||
if (isNaN(parseInt(operator_name))) {
|
||||
if (isNaN(parseInt(operatorName))) {
|
||||
// name is definitely not a MCCMNC, so it may be a name
|
||||
// after all; return that
|
||||
return operator_name;
|
||||
return operatorName;
|
||||
}
|
||||
}
|
||||
|
||||
let needle;
|
||||
if ((!operator_name || operator_name.length == 0) && operator_code)
|
||||
needle = operator_code;
|
||||
else if (operator_name && (operator_name.length == 6 || operator_name.length == 5))
|
||||
needle = operator_name;
|
||||
if ((!operatorName || operatorName.length == 0) && operatorCode)
|
||||
needle = operatorCode;
|
||||
else if (operatorName && (operatorName.length == 6 || operatorName.length == 5))
|
||||
needle = operatorName;
|
||||
else // nothing to search
|
||||
return null;
|
||||
|
||||
@ -73,7 +71,7 @@ function _findProviderForMccMnc(operator_name, operator_code) {
|
||||
// Tries to find the operator name corresponding to the given SID
|
||||
//
|
||||
function _findProviderForSid(sid) {
|
||||
if (sid == 0)
|
||||
if (!sid)
|
||||
return null;
|
||||
|
||||
let mpd = _getMobileProvidersDatabase();
|
||||
@ -100,10 +98,8 @@ const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInter
|
||||
const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma');
|
||||
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
|
||||
|
||||
var ModemGsm = new Lang.Class({
|
||||
Name: 'ModemGsm',
|
||||
|
||||
_init(path) {
|
||||
var ModemGsm = class {
|
||||
constructor(path) {
|
||||
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
@ -139,13 +135,11 @@ var ModemGsm = new Lang.Class({
|
||||
this.emit('notify::signal-quality');
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ModemGsm.prototype);
|
||||
|
||||
var ModemCdma = new Lang.Class({
|
||||
Name: 'ModemCdma',
|
||||
|
||||
_init(path) {
|
||||
var ModemCdma = class {
|
||||
constructor(path) {
|
||||
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
@ -169,7 +163,7 @@ var ModemCdma = new Lang.Class({
|
||||
}
|
||||
this.emit('notify::signal-quality');
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_refreshServingSystem() {
|
||||
this._proxy.GetServingSystemRemote(([result], err) => {
|
||||
@ -179,12 +173,12 @@ var ModemCdma = new Lang.Class({
|
||||
} else {
|
||||
let [bandClass, band, sid] = result;
|
||||
|
||||
this.operator_name = _findProviderForSid(sid)
|
||||
this.operator_name = _findProviderForSid(sid);
|
||||
}
|
||||
this.emit('notify::operator-name');
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ModemCdma.prototype);
|
||||
|
||||
|
||||
@ -201,10 +195,8 @@ const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gp
|
||||
const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma');
|
||||
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
|
||||
|
||||
var BroadbandModem = new Lang.Class({
|
||||
Name: 'BroadbandModem',
|
||||
|
||||
_init(path, capabilities) {
|
||||
var BroadbandModem = class {
|
||||
constructor(path, capabilities) {
|
||||
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
|
||||
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
|
||||
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
|
||||
@ -229,40 +221,40 @@ var BroadbandModem = new Lang.Class({
|
||||
this._reloadCdmaOperatorName();
|
||||
});
|
||||
this._reloadCdmaOperatorName();
|
||||
},
|
||||
}
|
||||
|
||||
_reloadSignalQuality() {
|
||||
let [quality, recent] = this._proxy.SignalQuality;
|
||||
this.signal_quality = quality;
|
||||
this.emit('notify::signal-quality');
|
||||
},
|
||||
}
|
||||
|
||||
_reloadOperatorName() {
|
||||
let new_name = "";
|
||||
let newName = "";
|
||||
if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0)
|
||||
new_name += this.operator_name_3gpp;
|
||||
newName += this.operator_name_3gpp;
|
||||
|
||||
if (this.operator_name_cdma && this.operator_name_cdma.length > 0) {
|
||||
if (new_name != "")
|
||||
new_name += ", ";
|
||||
new_name += this.operator_name_cdma;
|
||||
if (newName != "")
|
||||
newName += ", ";
|
||||
newName += this.operator_name_cdma;
|
||||
}
|
||||
|
||||
this.operator_name = new_name;
|
||||
this.operator_name = newName;
|
||||
this.emit('notify::operator-name');
|
||||
},
|
||||
}
|
||||
|
||||
_reload3gppOperatorName() {
|
||||
let name = this._proxy_3gpp.OperatorName;
|
||||
let code = this._proxy_3gpp.OperatorCode;
|
||||
this.operator_name_3gpp = _findProviderForMccMnc(name, code);
|
||||
this._reloadOperatorName();
|
||||
},
|
||||
}
|
||||
|
||||
_reloadCdmaOperatorName() {
|
||||
let sid = this._proxy_cdma.Sid;
|
||||
this.operator_name_cdma = _findProviderForSid(sid);
|
||||
this._reloadOperatorName();
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(BroadbandModem.prototype);
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const { Gio, GLib } = imports.gi;
|
||||
const Params = imports.misc.params;
|
||||
const Signals = imports.signals;
|
||||
|
||||
@ -27,9 +25,8 @@ const ObjectManagerIface = `
|
||||
|
||||
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
|
||||
|
||||
var ObjectManager = new Lang.Class({
|
||||
Name: 'ObjectManager',
|
||||
_init(params) {
|
||||
var ObjectManager = class {
|
||||
constructor(params) {
|
||||
params = Params.parse(params, { connection: null,
|
||||
name: null,
|
||||
objectPath: null,
|
||||
@ -63,7 +60,7 @@ var ObjectManager = new Lang.Class({
|
||||
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
|
||||
this._cancellable,
|
||||
this._onManagerProxyLoaded.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_tryToCompleteLoad() {
|
||||
if (this._numLoadInhibitors == 0)
|
||||
@ -74,62 +71,59 @@ var ObjectManager = new Lang.Class({
|
||||
if (this._onLoaded)
|
||||
this._onLoaded();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_addInterface(objectPath, interfaceName, onFinished) {
|
||||
let info = this._interfaceInfos[interfaceName];
|
||||
|
||||
if (!info) {
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
return;
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
|
||||
g_name: this._serviceName,
|
||||
g_object_path: objectPath,
|
||||
g_interface_name: interfaceName,
|
||||
g_interface_info: info,
|
||||
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
|
||||
g_name: this._serviceName,
|
||||
g_object_path: objectPath,
|
||||
g_interface_name: interfaceName,
|
||||
g_interface_info: info,
|
||||
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
|
||||
|
||||
proxy.init_async(GLib.PRIORITY_DEFAULT,
|
||||
this._cancellable,
|
||||
(initable, result) => {
|
||||
let error = null;
|
||||
try {
|
||||
initable.init_finish(result);
|
||||
} 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;
|
||||
}
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
let isNewObject;
|
||||
if (!this._objects[objectPath]) {
|
||||
this._objects[objectPath] = {};
|
||||
isNewObject = true;
|
||||
} else {
|
||||
isNewObject = false;
|
||||
}
|
||||
let isNewObject;
|
||||
if (!this._objects[objectPath]) {
|
||||
this._objects[objectPath] = {};
|
||||
isNewObject = true;
|
||||
} else {
|
||||
isNewObject = false;
|
||||
}
|
||||
|
||||
this._objects[objectPath][interfaceName] = proxy;
|
||||
this._objects[objectPath][interfaceName] = proxy;
|
||||
|
||||
if (!this._interfaces[interfaceName])
|
||||
this._interfaces[interfaceName] = [];
|
||||
if (!this._interfaces[interfaceName])
|
||||
this._interfaces[interfaceName] = [];
|
||||
|
||||
this._interfaces[interfaceName].push(proxy);
|
||||
this._interfaces[interfaceName].push(proxy);
|
||||
|
||||
if (isNewObject)
|
||||
this.emit('object-added', objectPath);
|
||||
if (isNewObject)
|
||||
this.emit('object-added', objectPath);
|
||||
|
||||
this.emit('interface-added', interfaceName, proxy);
|
||||
this.emit('interface-added', interfaceName, proxy);
|
||||
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
if (onFinished)
|
||||
onFinished();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_removeInterface(objectPath, interfaceName) {
|
||||
if (!this._objects[objectPath])
|
||||
@ -155,14 +149,13 @@ var ObjectManager = new Lang.Class({
|
||||
delete this._objects[objectPath];
|
||||
this.emit('object-removed', objectPath);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onManagerProxyLoaded(initable, result) {
|
||||
let error = null;
|
||||
try {
|
||||
initable.init_finish(result);
|
||||
} catch(e) {
|
||||
logError(e, 'could not initialize object manager for object ' + params.name);
|
||||
} catch (e) {
|
||||
logError(e, `could not initialize object manager for object ${this._serviceName}`);
|
||||
|
||||
this._tryToCompleteLoad();
|
||||
return;
|
||||
@ -194,13 +187,13 @@ var ObjectManager = new Lang.Class({
|
||||
|
||||
if (this._managerProxy.g_name_owner)
|
||||
this._onNameAppeared();
|
||||
},
|
||||
}
|
||||
|
||||
_onNameAppeared() {
|
||||
this._managerProxy.GetManagedObjectsRemote((result, error) => {
|
||||
if (!result) {
|
||||
if (error) {
|
||||
logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
|
||||
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
|
||||
}
|
||||
|
||||
this._tryToCompleteLoad();
|
||||
@ -232,7 +225,7 @@ var ObjectManager = new Lang.Class({
|
||||
}
|
||||
this._tryToCompleteLoad();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_onNameVanished() {
|
||||
let objectPaths = Object.keys(this._objects);
|
||||
@ -248,14 +241,14 @@ var ObjectManager = new Lang.Class({
|
||||
this._removeInterface(objectPath, interfaceName);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_registerInterfaces(interfaces) {
|
||||
for (let i = 0; i < interfaces.length; i++) {
|
||||
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
|
||||
this._interfaceInfos[info.name] = info;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getProxy(objectPath, interfaceName) {
|
||||
let object = this._objects[objectPath];
|
||||
@ -264,7 +257,7 @@ var ObjectManager = new Lang.Class({
|
||||
return null;
|
||||
|
||||
return object[interfaceName];
|
||||
},
|
||||
}
|
||||
|
||||
getProxiesForInterface(interfaceName) {
|
||||
let proxyList = this._interfaces[interfaceName];
|
||||
@ -273,7 +266,7 @@ var ObjectManager = new Lang.Class({
|
||||
return [];
|
||||
|
||||
return proxyList;
|
||||
},
|
||||
}
|
||||
|
||||
getAllProxies() {
|
||||
let proxies = [];
|
||||
@ -283,8 +276,8 @@ var ObjectManager = new Lang.Class({
|
||||
let object = this._objects[objectPaths];
|
||||
|
||||
let interfaceNames = Object.keys(object);
|
||||
for (let j = 0; i < interfaceNames.length; i++) {
|
||||
let interfaceName = interfaceNames[i];
|
||||
for (let j = 0; j < interfaceNames.length; j++) {
|
||||
let interfaceName = interfaceNames[j];
|
||||
if (object[interfaceName])
|
||||
proxies.push(object(interfaceName));
|
||||
}
|
||||
@ -292,5 +285,5 @@ var ObjectManager = new Lang.Class({
|
||||
|
||||
return proxies;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(ObjectManager.prototype);
|
||||
|
@ -1,5 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
// parse:
|
||||
// @params: caller-provided parameter object, or %null
|
||||
// @defaults-provided defaults object
|
||||
@ -14,22 +16,14 @@
|
||||
//
|
||||
// Return value: a new object, containing the merged parameters from
|
||||
// @params and @defaults
|
||||
function parse(params, defaults, allowExtras) {
|
||||
let ret = {}, prop;
|
||||
|
||||
if (!params)
|
||||
params = {};
|
||||
|
||||
for (prop in params) {
|
||||
if (!(prop in defaults) && !allowExtras)
|
||||
throw new Error('Unrecognized parameter "' + prop + '"');
|
||||
ret[prop] = params[prop];
|
||||
function parse(params = {}, defaults, allowExtras) {
|
||||
if (!allowExtras) {
|
||||
for (let prop in params)
|
||||
if (!(prop in defaults))
|
||||
throw new Error(`Unrecognized parameter "${prop}"`);
|
||||
}
|
||||
|
||||
for (prop in defaults) {
|
||||
if (!(prop in params))
|
||||
ret[prop] = defaults[prop];
|
||||
}
|
||||
|
||||
return ret;
|
||||
let defaultsCopy = {};
|
||||
Lang.copyProperties(defaults, defaultsCopy);
|
||||
return Object.assign(defaultsCopy, params);
|
||||
}
|
@ -12,4 +12,4 @@ function PermissionStore(initCallback, cancellable) {
|
||||
'org.freedesktop.impl.portal.PermissionStore',
|
||||
'/org/freedesktop/impl/portal/PermissionStore',
|
||||
initCallback, cancellable);
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const ObjectManager = imports.misc.objectManager;
|
||||
@ -26,17 +24,16 @@ function getSmartcardManager() {
|
||||
return _smartcardManager;
|
||||
}
|
||||
|
||||
var SmartcardManager = new Lang.Class({
|
||||
Name: 'SmartcardManager',
|
||||
_init() {
|
||||
var SmartcardManager = class {
|
||||
constructor() {
|
||||
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
|
||||
name: "org.gnome.SettingsDaemon.Smartcard",
|
||||
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
|
||||
knownInterfaces: [ SmartcardTokenIface ],
|
||||
knownInterfaces: [SmartcardTokenIface],
|
||||
onLoaded: this._onLoaded.bind(this) });
|
||||
this._insertedTokens = {};
|
||||
this._loginToken = null;
|
||||
},
|
||||
}
|
||||
|
||||
_onLoaded() {
|
||||
let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token');
|
||||
@ -53,7 +50,7 @@ var SmartcardManager = new Lang.Class({
|
||||
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
|
||||
this._removeToken(proxy);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateToken(token) {
|
||||
let objectPath = token.get_object_path();
|
||||
@ -65,7 +62,7 @@ var SmartcardManager = new Lang.Class({
|
||||
|
||||
if (token.UsedToLogin)
|
||||
this._loginToken = token;
|
||||
},
|
||||
}
|
||||
|
||||
_addToken(token) {
|
||||
this._updateToken(token);
|
||||
@ -85,7 +82,7 @@ var SmartcardManager = new Lang.Class({
|
||||
// Emit a smartcard-inserted at startup if it's already plugged in
|
||||
if (token.IsInserted)
|
||||
this.emit('smartcard-inserted', token);
|
||||
},
|
||||
}
|
||||
|
||||
_removeToken(token) {
|
||||
let objectPath = token.get_object_path();
|
||||
@ -99,11 +96,11 @@ var SmartcardManager = new Lang.Class({
|
||||
this._loginToken = null;
|
||||
|
||||
token.disconnectAll();
|
||||
},
|
||||
}
|
||||
|
||||
hasInsertedTokens() {
|
||||
return Object.keys(this._insertedTokens).length > 0;
|
||||
},
|
||||
}
|
||||
|
||||
hasInsertedLoginToken() {
|
||||
if (!this._loginToken)
|
||||
@ -115,5 +112,5 @@ var SmartcardManager = new Lang.Class({
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(SmartcardManager.prototype);
|
||||
|
@ -1,11 +1,4 @@
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const GObject = imports.gi.GObject;
|
||||
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
@ -44,9 +37,7 @@ function getDefault() {
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
const SystemActions = new Lang.Class({
|
||||
Name: 'SystemActions',
|
||||
Extends: GObject.Object,
|
||||
const SystemActions = GObject.registerClass({
|
||||
Properties: {
|
||||
'can-power-off': GObject.ParamSpec.boolean('can-power-off',
|
||||
'can-power-off',
|
||||
@ -83,57 +74,63 @@ const SystemActions = new Lang.Class({
|
||||
'orientation-lock-icon',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
null)
|
||||
},
|
||||
|
||||
}
|
||||
}, class SystemActions extends GObject.Object {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this._canHavePowerOff = true;
|
||||
this._canHaveSuspend = true;
|
||||
|
||||
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: _("power off;shutdown;reboot;restart").split(';'),
|
||||
available: false });
|
||||
this._actions.set(LOCK_SCREEN_ACTION_ID,
|
||||
{ // Translators: The name of the lock screen action in search
|
||||
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: _("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: 'application-exit-symbolic',
|
||||
// Translators: A list of keywords that match the logout action, separated by semicolons
|
||||
keywords: _("logout;sign off").split(';'),
|
||||
available: false });
|
||||
this._actions.set(SUSPEND_ACTION_ID,
|
||||
{ // Translators: The name of the suspend action in search
|
||||
name: C_("search-result", "Suspend"),
|
||||
iconName: 'media-playback-pause-symbolic',
|
||||
// Translators: A list of keywords that match the suspend action, separated by semicolons
|
||||
keywords: _("suspend;sleep").split(';'),
|
||||
available: false });
|
||||
this._actions.set(SWITCH_USER_ACTION_ID,
|
||||
{ // Translators: The name of the switch user action in search
|
||||
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: _("switch user").split(';'),
|
||||
available: false });
|
||||
this._actions.set(LOCK_ORIENTATION_ACTION_ID,
|
||||
{ // Translators: The name of the lock orientation action in search
|
||||
name: C_("search-result", "Lock Orientation"),
|
||||
iconName: '',
|
||||
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
|
||||
keywords: _("lock orientation;screen;rotation").split(';'),
|
||||
available: false });
|
||||
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: _("power off;shutdown;reboot;restart").split(/[; ]/),
|
||||
available: false
|
||||
});
|
||||
this._actions.set(LOCK_SCREEN_ACTION_ID, {
|
||||
// Translators: The name of the lock screen action in search
|
||||
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: _("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: 'application-exit-symbolic',
|
||||
// Translators: A list of keywords that match the logout action, separated by semicolons
|
||||
keywords: _("logout;log out;sign off").split(/[; ]/),
|
||||
available: false
|
||||
});
|
||||
this._actions.set(SUSPEND_ACTION_ID, {
|
||||
// Translators: The name of the suspend action in search
|
||||
name: C_("search-result", "Suspend"),
|
||||
iconName: 'media-playback-pause-symbolic',
|
||||
// Translators: A list of keywords that match the suspend action, separated by semicolons
|
||||
keywords: _("suspend;sleep").split(/[; ]/),
|
||||
available: false
|
||||
});
|
||||
this._actions.set(SWITCH_USER_ACTION_ID, {
|
||||
// Translators: The name of the switch user action in search
|
||||
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: _("switch user").split(/[; ]/),
|
||||
available: false
|
||||
});
|
||||
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
|
||||
// Translators: The name of the lock orientation action in search
|
||||
name: C_("search-result", "Lock Orientation"),
|
||||
iconName: '',
|
||||
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
|
||||
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
|
||||
available: false
|
||||
});
|
||||
|
||||
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
|
||||
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
|
||||
@ -146,37 +143,39 @@ const SystemActions = new Lang.Class({
|
||||
this._userManager = AccountsService.UserManager.get_default();
|
||||
|
||||
this._userManager.connect('notify::is-loaded',
|
||||
() => { this._updateMultiUser(); });
|
||||
() => this._updateMultiUser());
|
||||
this._userManager.connect('notify::has-multiple-users',
|
||||
() => { this._updateMultiUser(); });
|
||||
() => this._updateMultiUser());
|
||||
this._userManager.connect('user-added',
|
||||
() => { this._updateMultiUser(); });
|
||||
() => this._updateMultiUser());
|
||||
this._userManager.connect('user-removed',
|
||||
() => { this._updateMultiUser(); });
|
||||
() => this._updateMultiUser());
|
||||
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_USER_SWITCH_KEY,
|
||||
() => { this._updateSwitchUser(); });
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
||||
() => { this._updateLogout(); });
|
||||
global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
|
||||
() => { this._updateLogout(); });
|
||||
this._lockdownSettings.connect(`changed::${DISABLE_USER_SWITCH_KEY}`,
|
||||
() => this._updateSwitchUser());
|
||||
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
|
||||
() => this._updateLogout());
|
||||
global.settings.connect(`changed::${ALWAYS_SHOW_LOG_OUT_KEY}`,
|
||||
() => this._updateLogout());
|
||||
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
|
||||
() => { this._updateLockScreen(); });
|
||||
this._lockdownSettings.connect(`changed::${DISABLE_LOCK_SCREEN_KEY}`,
|
||||
() => this._updateLockScreen());
|
||||
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
||||
() => { this._updateHaveShutdown(); });
|
||||
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
|
||||
() => this._updateHaveShutdown());
|
||||
|
||||
this.forceUpdate();
|
||||
|
||||
this._orientationSettings.connect('changed::orientation-lock',
|
||||
() => { this._updateOrientationLock();
|
||||
this._updateOrientationLockIcon(); });
|
||||
() => {
|
||||
this._updateOrientationLock();
|
||||
this._updateOrientationLockIcon();
|
||||
});
|
||||
Main.layoutManager.connect('monitors-changed',
|
||||
() => { this._updateOrientationLock(); });
|
||||
() => this._updateOrientationLock());
|
||||
Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
() => { this._sensorProxyAppeared(); },
|
||||
() => this._sensorProxyAppeared(),
|
||||
() => {
|
||||
this._sensorProxy = null;
|
||||
this._updateOrientationLock();
|
||||
@ -184,37 +183,37 @@ const SystemActions = new Lang.Class({
|
||||
this._updateOrientationLock();
|
||||
this._updateOrientationLockIcon();
|
||||
|
||||
Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
|
||||
Main.sessionMode.connect('updated', () => this._sessionUpdated());
|
||||
this._sessionUpdated();
|
||||
},
|
||||
}
|
||||
|
||||
get can_power_off() {
|
||||
return this._actions.get(POWER_OFF_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get can_suspend() {
|
||||
return this._actions.get(SUSPEND_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get can_lock_screen() {
|
||||
return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get can_switch_user() {
|
||||
return this._actions.get(SWITCH_USER_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get can_logout() {
|
||||
return this._actions.get(LOGOUT_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get can_lock_orientation() {
|
||||
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
|
||||
},
|
||||
}
|
||||
|
||||
get orientation_lock_icon() {
|
||||
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
|
||||
},
|
||||
}
|
||||
|
||||
_sensorProxyAppeared() {
|
||||
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
|
||||
@ -224,10 +223,10 @@ const SystemActions = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
this._sensorProxy.connect('g-properties-changed',
|
||||
() => { this._updateOrientationLock(); });
|
||||
() => this._updateOrientationLock());
|
||||
this._updateOrientationLock();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateOrientationLock() {
|
||||
let available = false;
|
||||
@ -238,7 +237,7 @@ const SystemActions = new Lang.Class({
|
||||
this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
|
||||
|
||||
this.notify('can-lock-orientation');
|
||||
},
|
||||
}
|
||||
|
||||
_updateOrientationLockIcon() {
|
||||
let locked = this._orientationSettings.get_boolean('orientation-lock');
|
||||
@ -247,14 +246,14 @@ const SystemActions = new Lang.Class({
|
||||
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
|
||||
|
||||
this.notify('orientation-lock-icon');
|
||||
},
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
this._updateLockScreen();
|
||||
this._updatePowerOff();
|
||||
this._updateSuspend();
|
||||
this._updateMultiUser();
|
||||
},
|
||||
}
|
||||
|
||||
forceUpdate() {
|
||||
// Whether those actions are available or not depends on both lockdown
|
||||
@ -262,58 +261,58 @@ const SystemActions = new Lang.Class({
|
||||
// latter, so their value may be outdated; force an update now
|
||||
this._updateHaveShutdown();
|
||||
this._updateHaveSuspend();
|
||||
},
|
||||
}
|
||||
|
||||
getMatchingActions(terms) {
|
||||
// terms is a list of strings
|
||||
terms = terms.map((term) => { return term.toLowerCase(); });
|
||||
terms = terms.map((term) => term.toLowerCase());
|
||||
|
||||
let results = [];
|
||||
|
||||
for (let [key, {available, keywords}] of this._actions)
|
||||
if (available && terms.every(t => keywords.some(k => (k.indexOf(t) >= 0))))
|
||||
for (let [key, { available, keywords }] of this._actions)
|
||||
if (available && terms.every(t => keywords.some(k => k.startsWith(t))))
|
||||
results.push(key);
|
||||
|
||||
return results;
|
||||
},
|
||||
}
|
||||
|
||||
getName(id) {
|
||||
return this._actions.get(id).name;
|
||||
},
|
||||
}
|
||||
|
||||
getIconName(id) {
|
||||
return this._actions.get(id).iconName;
|
||||
},
|
||||
}
|
||||
|
||||
activateAction(id) {
|
||||
switch (id) {
|
||||
case POWER_OFF_ACTION_ID:
|
||||
this.activatePowerOff();
|
||||
break;
|
||||
case LOCK_SCREEN_ACTION_ID:
|
||||
this.activateLockScreen();
|
||||
break;
|
||||
case LOGOUT_ACTION_ID:
|
||||
this.activateLogout();
|
||||
break;
|
||||
case SUSPEND_ACTION_ID:
|
||||
this.activateSuspend();
|
||||
break;
|
||||
case SWITCH_USER_ACTION_ID:
|
||||
this.activateSwitchUser();
|
||||
break;
|
||||
case LOCK_ORIENTATION_ACTION_ID:
|
||||
this.activateLockOrientation();
|
||||
break;
|
||||
case POWER_OFF_ACTION_ID:
|
||||
this.activatePowerOff();
|
||||
break;
|
||||
case LOCK_SCREEN_ACTION_ID:
|
||||
this.activateLockScreen();
|
||||
break;
|
||||
case LOGOUT_ACTION_ID:
|
||||
this.activateLogout();
|
||||
break;
|
||||
case SUSPEND_ACTION_ID:
|
||||
this.activateSuspend();
|
||||
break;
|
||||
case SWITCH_USER_ACTION_ID:
|
||||
this.activateSwitchUser();
|
||||
break;
|
||||
case LOCK_ORIENTATION_ACTION_ID:
|
||||
this.activateLockOrientation();
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateLockScreen() {
|
||||
let showLock = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
|
||||
let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
|
||||
this._actions.get(LOCK_SCREEN_ACTION_ID).available = showLock && allowLockScreen && LoginManager.canLock();
|
||||
this.notify('can-lock-screen');
|
||||
},
|
||||
}
|
||||
|
||||
_updateHaveShutdown() {
|
||||
this._session.CanShutdownRemote((result, error) => {
|
||||
@ -323,7 +322,7 @@ const SystemActions = new Lang.Class({
|
||||
this._canHavePowerOff = result[0];
|
||||
this._updatePowerOff();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updatePowerOff() {
|
||||
let disabled = Main.sessionMode.isLocked ||
|
||||
@ -331,7 +330,7 @@ const SystemActions = new Lang.Class({
|
||||
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
|
||||
this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled;
|
||||
this.notify('can-power-off');
|
||||
},
|
||||
}
|
||||
|
||||
_updateHaveSuspend() {
|
||||
this._loginManager.canSuspend(
|
||||
@ -340,7 +339,7 @@ const SystemActions = new Lang.Class({
|
||||
this._suspendNeedsAuth = needsAuth;
|
||||
this._updateSuspend();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateSuspend() {
|
||||
let disabled = (Main.sessionMode.isLocked &&
|
||||
@ -349,12 +348,12 @@ const SystemActions = new Lang.Class({
|
||||
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
|
||||
this._actions.get(SUSPEND_ACTION_ID).available = this._canHaveSuspend && !disabled;
|
||||
this.notify('can-suspend');
|
||||
},
|
||||
}
|
||||
|
||||
_updateMultiUser() {
|
||||
this._updateLogout();
|
||||
this._updateSwitchUser();
|
||||
},
|
||||
}
|
||||
|
||||
_updateSwitchUser() {
|
||||
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
|
||||
@ -366,7 +365,7 @@ const SystemActions = new Lang.Class({
|
||||
this.notify('can-switch-user');
|
||||
|
||||
return visible;
|
||||
},
|
||||
}
|
||||
|
||||
_updateLogout() {
|
||||
let user = this._userManager.get_user(GLib.get_user_name());
|
||||
@ -384,7 +383,7 @@ const SystemActions = new Lang.Class({
|
||||
this.notify('can-logout');
|
||||
|
||||
return visible;
|
||||
},
|
||||
}
|
||||
|
||||
activateLockOrientation() {
|
||||
if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available)
|
||||
@ -392,14 +391,14 @@ const SystemActions = new Lang.Class({
|
||||
|
||||
let locked = this._orientationSettings.get_boolean('orientation-lock');
|
||||
this._orientationSettings.set_boolean('orientation-lock', !locked);
|
||||
},
|
||||
}
|
||||
|
||||
activateLockScreen() {
|
||||
if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available)
|
||||
throw new Error('The lock-screen action is not available!');
|
||||
|
||||
Main.screenShield.lock(true);
|
||||
},
|
||||
}
|
||||
|
||||
activateSwitchUser() {
|
||||
if (!this._actions.get(SWITCH_USER_ACTION_ID).available)
|
||||
@ -412,7 +411,7 @@ const SystemActions = new Lang.Class({
|
||||
Gdm.goto_login_session_sync(null);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
activateLogout() {
|
||||
if (!this._actions.get(LOGOUT_ACTION_ID).available)
|
||||
@ -420,14 +419,14 @@ const SystemActions = new Lang.Class({
|
||||
|
||||
Main.overview.hide();
|
||||
this._session.LogoutRemote(0);
|
||||
},
|
||||
}
|
||||
|
||||
activatePowerOff() {
|
||||
if (!this._actions.get(POWER_OFF_ACTION_ID).available)
|
||||
throw new Error('The power-off action is not available!');
|
||||
|
||||
this._session.ShutdownRemote(0);
|
||||
},
|
||||
}
|
||||
|
||||
activateSuspend() {
|
||||
if (!this._actions.get(SUSPEND_ACTION_ID).available)
|
||||
|
@ -1,14 +1,9 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
|
||||
const Gettext = imports.gettext;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@ -22,7 +17,7 @@ const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
|
||||
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
|
||||
|
||||
const _urlRegexp = new RegExp(
|
||||
'(^|' + _leadingJunk + ')' +
|
||||
`(^|${_leadingJunk})` +
|
||||
'(' +
|
||||
'(?:' +
|
||||
'(?:http|https|ftp)://' + // scheme://
|
||||
@ -34,12 +29,12 @@ const _urlRegexp = new RegExp(
|
||||
'(?:' + // one or more:
|
||||
'[^\\s()<>]+' + // run of non-space non-()
|
||||
'|' + // or
|
||||
_balancedParens + // balanced parens
|
||||
`${_balancedParens}` + // balanced parens
|
||||
')+' +
|
||||
'(?:' + // end with:
|
||||
_balancedParens + // balanced parens
|
||||
`${_balancedParens}` + // balanced parens
|
||||
'|' + // or
|
||||
_notTrailingJunk + // last non-junk char
|
||||
`${_notTrailingJunk}` + // last non-junk char
|
||||
')' +
|
||||
')', 'gi');
|
||||
|
||||
@ -74,16 +69,16 @@ function spawn(argv) {
|
||||
}
|
||||
|
||||
// spawnCommandLine:
|
||||
// @command_line: a command line
|
||||
// @commandLine: a command line
|
||||
//
|
||||
// Runs @command_line in the background, handling any errors that
|
||||
// Runs @commandLine in the background, handling any errors that
|
||||
// occur when trying to parse or start the program.
|
||||
function spawnCommandLine(command_line) {
|
||||
function spawnCommandLine(commandLine) {
|
||||
try {
|
||||
let [success, argv] = GLib.shell_parse_argv(command_line);
|
||||
let [success, argv] = GLib.shell_parse_argv(commandLine);
|
||||
trySpawn(argv);
|
||||
} catch (err) {
|
||||
_handleSpawnError(command_line, err);
|
||||
_handleSpawnError(commandLine, err);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +93,7 @@ function spawnApp(argv) {
|
||||
|
||||
let context = global.create_app_launch_context(0, -1);
|
||||
app.launch([], context);
|
||||
} catch(err) {
|
||||
} catch (err) {
|
||||
_handleSpawnError(argv[0], err);
|
||||
}
|
||||
}
|
||||
@ -108,8 +103,7 @@ function spawnApp(argv) {
|
||||
//
|
||||
// Runs @argv in the background. If launching @argv fails,
|
||||
// this will throw an error.
|
||||
function trySpawn(argv)
|
||||
{
|
||||
function trySpawn(argv) {
|
||||
var success, pid;
|
||||
try {
|
||||
[success, pid] = GLib.spawn_async(null, argv, null,
|
||||
@ -140,19 +134,19 @@ function trySpawn(argv)
|
||||
}
|
||||
|
||||
// trySpawnCommandLine:
|
||||
// @command_line: a command line
|
||||
// @commandLine: a command line
|
||||
//
|
||||
// Runs @command_line in the background. If launching @command_line
|
||||
// Runs @commandLine in the background. If launching @commandLine
|
||||
// fails, this will throw an error.
|
||||
function trySpawnCommandLine(command_line) {
|
||||
function trySpawnCommandLine(commandLine) {
|
||||
let success, argv;
|
||||
|
||||
try {
|
||||
[success, argv] = GLib.shell_parse_argv(command_line);
|
||||
[success, argv] = GLib.shell_parse_argv(commandLine);
|
||||
} catch (err) {
|
||||
// Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
// something nicer
|
||||
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
|
||||
err.message = err.message.replace(/[^:]*: /, `${_("Could not parse command:")}\n`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
@ -227,7 +221,7 @@ function formatTime(time, params) {
|
||||
/* Translators: Time in 24h format */
|
||||
format = N_("%H\u2236%M");
|
||||
// Show the word "Yesterday" and time if date is on yesterday
|
||||
else if (daysAgo <2)
|
||||
else if (daysAgo < 2)
|
||||
/* Translators: this is the word "Yesterday" followed by a
|
||||
time string in 24h format. i.e. "Yesterday, 14:30" */
|
||||
// xgettext:no-c-format
|
||||
@ -256,7 +250,7 @@ function formatTime(time, params) {
|
||||
/* Translators: Time in 12h format */
|
||||
format = N_("%l\u2236%M %p");
|
||||
// Show the word "Yesterday" and time if date is on yesterday
|
||||
else if (daysAgo <2)
|
||||
else if (daysAgo < 2)
|
||||
/* Translators: this is the word "Yesterday" followed by a
|
||||
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
|
||||
// xgettext:no-c-format
|
||||
@ -294,7 +288,7 @@ function createTimeLabel(date, params) {
|
||||
let id = _desktopSettings.connect('changed::clock-format', () => {
|
||||
label.text = formatTime(date, params);
|
||||
});
|
||||
label.connect('destroy', () => { _desktopSettings.disconnect(id); });
|
||||
label.connect('destroy', () => _desktopSettings.disconnect(id));
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -348,12 +342,10 @@ function insertSorted(array, val, cmp) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
var CloseButton = new Lang.Class({
|
||||
Name: 'CloseButton',
|
||||
Extends: St.Button,
|
||||
|
||||
var CloseButton = GObject.registerClass(
|
||||
class CloseButton extends St.Button {
|
||||
_init(boxpointer) {
|
||||
this.parent({ style_class: 'notification-close'});
|
||||
super._init({ style_class: 'notification-close' });
|
||||
|
||||
// This is a bit tricky. St.Bin has its own x-align/y-align properties
|
||||
// that compete with Clutter's properties. This should be fixed for
|
||||
@ -370,10 +362,10 @@ var CloseButton = new Lang.Class({
|
||||
this._boxPointer = boxpointer;
|
||||
if (boxpointer)
|
||||
this._boxPointer.connect('arrow-side-changed', this._sync.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_computeBoxPointerOffset() {
|
||||
if (!this._boxPointer || !this._boxPointer.actor.get_stage())
|
||||
if (!this._boxPointer || !this._boxPointer.get_stage())
|
||||
return 0;
|
||||
|
||||
let side = this._boxPointer.arrowSide;
|
||||
@ -381,20 +373,20 @@ var CloseButton = new Lang.Class({
|
||||
return this._boxPointer.getArrowHeight();
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
}
|
||||
|
||||
_sync() {
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
let offY = this._computeBoxPointerOffset();
|
||||
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
|
||||
this.translation_x = themeNode.get_length('-shell-close-overlap-x');
|
||||
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_style_changed() {
|
||||
this._sync();
|
||||
this.parent();
|
||||
},
|
||||
super.vfunc_style_changed();
|
||||
}
|
||||
});
|
||||
|
||||
function makeCloseButton(boxpointer) {
|
||||
@ -437,10 +429,8 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
|
||||
var AppSettingsMonitor = new Lang.Class({
|
||||
Name: 'AppSettingsMonitor',
|
||||
|
||||
_init(appId, schemaId) {
|
||||
var AppSettingsMonitor = class {
|
||||
constructor(appId, schemaId) {
|
||||
this._appId = appId;
|
||||
this._schemaId = schemaId;
|
||||
|
||||
@ -454,38 +444,38 @@ var AppSettingsMonitor = new Lang.Class({
|
||||
this._appSystem.connect('installed-changed',
|
||||
this._onInstalledChanged.bind(this));
|
||||
this._onInstalledChanged();
|
||||
},
|
||||
}
|
||||
|
||||
get available() {
|
||||
return this._app != null && this._settings != null;
|
||||
},
|
||||
}
|
||||
|
||||
activateApp() {
|
||||
if (this._app)
|
||||
this._app.activate();
|
||||
},
|
||||
}
|
||||
|
||||
watchSetting(key, callback) {
|
||||
let handler = { id: 0, key: key, callback: callback };
|
||||
this._handlers.push(handler);
|
||||
|
||||
this._connectHandler(handler);
|
||||
},
|
||||
}
|
||||
|
||||
_connectHandler(handler) {
|
||||
if (!this._settings || handler.id > 0)
|
||||
return;
|
||||
|
||||
handler.id = this._settings.connect('changed::' + handler.key,
|
||||
handler.id = this._settings.connect(`changed::${handler.key}`,
|
||||
handler.callback);
|
||||
handler.callback(this._settings, handler.key);
|
||||
},
|
||||
}
|
||||
|
||||
_disconnectHandler(handler) {
|
||||
if (this._settings && handler.id > 0)
|
||||
this._settings.disconnect(handler.id);
|
||||
handler.id = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_onInstalledChanged() {
|
||||
let hadApp = (this._app != null);
|
||||
@ -499,20 +489,20 @@ var AppSettingsMonitor = new Lang.Class({
|
||||
this._checkSettings();
|
||||
else
|
||||
this._setSettings(null);
|
||||
},
|
||||
}
|
||||
|
||||
_setSettings(settings) {
|
||||
this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
|
||||
this._handlers.forEach((handler) => this._disconnectHandler(handler));
|
||||
|
||||
let hadSettings = (this._settings != null);
|
||||
this._settings = settings;
|
||||
let haveSettings = (this._settings != null);
|
||||
|
||||
this._handlers.forEach((handler) => { this._connectHandler(handler); });
|
||||
this._handlers.forEach((handler) => this._connectHandler(handler));
|
||||
|
||||
if (hadSettings != haveSettings)
|
||||
this.emit('available-changed');
|
||||
},
|
||||
}
|
||||
|
||||
_checkSettings() {
|
||||
let schema = this._schemaSource.lookup(this._schemaId, true);
|
||||
@ -525,5 +515,5 @@ var AppSettingsMonitor = new Lang.Class({
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(AppSettingsMonitor.prototype);
|
||||
|
@ -1,10 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Geoclue = imports.gi.Geoclue;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GWeather = imports.gi.GWeather;
|
||||
const Lang = imports.lang;
|
||||
const { Geoclue, Gio, GLib, GWeather } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const PermissionStore = imports.misc.permissionStore;
|
||||
@ -13,10 +9,8 @@ const Util = imports.misc.util;
|
||||
// Minimum time between updates to show loading indication
|
||||
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
|
||||
|
||||
var WeatherClient = new Lang.Class({
|
||||
Name: 'WeatherClient',
|
||||
|
||||
_init() {
|
||||
var WeatherClient = class {
|
||||
constructor() {
|
||||
this._loading = false;
|
||||
this._locationValid = false;
|
||||
this._lastUpdate = GLib.DateTime.new_from_unix_local(0);
|
||||
@ -32,13 +26,21 @@ var WeatherClient = new Lang.Class({
|
||||
this._weatherAuthorized = false;
|
||||
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
|
||||
if (error) {
|
||||
log('Failed to connect to permissionStore: ' + error.message);
|
||||
log(`Failed to connect to permissionStore: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._permStore.g_name_owner == null) {
|
||||
// Failed to auto-start, likely because xdg-desktop-portal
|
||||
// isn't installed; don't restrict access to location service
|
||||
this._weatherAuthorized = true;
|
||||
this._updateAutoLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
|
||||
if (error)
|
||||
log('Error looking up permission: ' + error.message);
|
||||
log(`Error looking up permission: ${error.message}`);
|
||||
|
||||
let [perms, data] = error ? [{}, null] : res;
|
||||
let params = ['gnome', 'geolocation', false, data, perms];
|
||||
@ -64,34 +66,34 @@ var WeatherClient = new Lang.Class({
|
||||
this.emit('changed');
|
||||
});
|
||||
|
||||
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
|
||||
'org.gnome.Weather.Application');
|
||||
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
|
||||
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
|
||||
'org.gnome.Weather');
|
||||
this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
|
||||
this._weatherAppMon.watchSetting('automatic-location',
|
||||
this._onAutomaticLocationChanged.bind(this));
|
||||
this._weatherAppMon.watchSetting('locations',
|
||||
this._onLocationsChanged.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
get available() {
|
||||
return this._weatherAppMon.available;
|
||||
},
|
||||
}
|
||||
|
||||
get loading() {
|
||||
return this._loading;
|
||||
},
|
||||
}
|
||||
|
||||
get hasLocation() {
|
||||
return this._locationValid;
|
||||
},
|
||||
}
|
||||
|
||||
get info() {
|
||||
return this._weatherInfo;
|
||||
},
|
||||
}
|
||||
|
||||
activateApp() {
|
||||
this._weatherAppMon.activateApp();
|
||||
},
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this._locationValid)
|
||||
@ -104,13 +106,13 @@ var WeatherClient = new Lang.Class({
|
||||
this._weatherInfo.update();
|
||||
else
|
||||
this._loadInfo();
|
||||
},
|
||||
}
|
||||
|
||||
get _useAutoLocation() {
|
||||
return this._autoLocationRequested &&
|
||||
this._locationSettings.get_boolean('enabled') &&
|
||||
this._weatherAuthorized;
|
||||
},
|
||||
}
|
||||
|
||||
_loadInfo() {
|
||||
let id = this._weatherInfo.connect('updated', () => {
|
||||
@ -122,7 +124,7 @@ var WeatherClient = new Lang.Class({
|
||||
this.emit('changed');
|
||||
|
||||
this._weatherInfo.update();
|
||||
},
|
||||
}
|
||||
|
||||
_locationsEqual(loc1, loc2) {
|
||||
if (loc1 == loc2)
|
||||
@ -132,7 +134,7 @@ var WeatherClient = new Lang.Class({
|
||||
return false;
|
||||
|
||||
return loc1.equal(loc2);
|
||||
},
|
||||
}
|
||||
|
||||
_setLocation(location) {
|
||||
if (this._locationsEqual(this._weatherInfo.location, location))
|
||||
@ -148,7 +150,7 @@ var WeatherClient = new Lang.Class({
|
||||
this._loadInfo();
|
||||
else
|
||||
this.emit('changed');
|
||||
},
|
||||
}
|
||||
|
||||
_updateLocationMonitoring() {
|
||||
if (this._useAutoLocation) {
|
||||
@ -164,7 +166,7 @@ var WeatherClient = new Lang.Class({
|
||||
this._gclueService.disconnect(this._gclueLocationChangedId);
|
||||
this._gclueLocationChangedId = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_startGClueService() {
|
||||
if (this._gclueStarting)
|
||||
@ -176,8 +178,8 @@ var WeatherClient = new Lang.Class({
|
||||
(o, res) => {
|
||||
try {
|
||||
this._gclueService = Geoclue.Simple.new_finish(res);
|
||||
} catch(e) {
|
||||
log('Failed to connect to Geoclue2 service: ' + e.message);
|
||||
} catch (e) {
|
||||
log(`Failed to connect to Geoclue2 service: ${e.message}`);
|
||||
this._setLocation(this._mostRecentLocation);
|
||||
return;
|
||||
}
|
||||
@ -185,7 +187,7 @@ var WeatherClient = new Lang.Class({
|
||||
this._gclueService.get_client().distance_threshold = 100;
|
||||
this._updateLocationMonitoring();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_onGClueLocationChanged() {
|
||||
let geoLocation = this._gclueService.location;
|
||||
@ -194,7 +196,7 @@ var WeatherClient = new Lang.Class({
|
||||
geoLocation.latitude,
|
||||
geoLocation.longitude);
|
||||
this._setLocation(location);
|
||||
},
|
||||
}
|
||||
|
||||
_onAutomaticLocationChanged(settings, key) {
|
||||
let useAutoLocation = settings.get_boolean(key);
|
||||
@ -204,7 +206,7 @@ var WeatherClient = new Lang.Class({
|
||||
this._autoLocationRequested = useAutoLocation;
|
||||
|
||||
this._updateAutoLocation();
|
||||
},
|
||||
}
|
||||
|
||||
_updateAutoLocation() {
|
||||
this._updateLocationMonitoring();
|
||||
@ -213,7 +215,7 @@ var WeatherClient = new Lang.Class({
|
||||
this._startGClueService();
|
||||
else
|
||||
this._setLocation(this._mostRecentLocation);
|
||||
},
|
||||
}
|
||||
|
||||
_onLocationsChanged(settings, key) {
|
||||
let serialized = settings.get_value(key).deep_unpack().shift();
|
||||
@ -229,7 +231,7 @@ var WeatherClient = new Lang.Class({
|
||||
|
||||
if (!this._useAutoLocation || !this._gclueStarted)
|
||||
this._setLocation(this._mostRecentLocation);
|
||||
},
|
||||
}
|
||||
|
||||
_onPermStoreChanged(proxy, sender, params) {
|
||||
let [table, id, deleted, data, perms] = params;
|
||||
@ -237,11 +239,11 @@ var WeatherClient = new Lang.Class({
|
||||
if (table != 'gnome' || id != 'geolocation')
|
||||
return;
|
||||
|
||||
let permission = perms['org.gnome.Weather.Application'] || ['NONE'];
|
||||
let permission = perms['org.gnome.Weather'] || ['NONE'];
|
||||
let [accuracy] = permission;
|
||||
this._weatherAuthorized = accuracy != 'NONE';
|
||||
|
||||
this._updateAutoLocation();
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(WeatherClient.prototype);
|
||||
|
@ -10,7 +10,7 @@ const Scripting = imports.ui.scripting;
|
||||
// someone should be able to get an idea of how well the shell is performing
|
||||
// on a particular system.
|
||||
|
||||
let METRICS = {
|
||||
var METRICS = {
|
||||
overviewLatencyFirst:
|
||||
{ description: "Time to first frame after triggering overview, first time",
|
||||
units: "us" },
|
||||
@ -19,7 +19,7 @@ let METRICS = {
|
||||
units: "frames / s" },
|
||||
overviewLatencySubsequent:
|
||||
{ description: "Time to first frame after triggering overview, second time",
|
||||
units: "us"},
|
||||
units: "us" },
|
||||
overviewFpsSubsequent:
|
||||
{ description: "Frames rate when going to the overview, second time",
|
||||
units: "frames / s" },
|
||||
@ -52,7 +52,7 @@ let METRICS = {
|
||||
units: "us" },
|
||||
applicationsShowTimeSubsequent:
|
||||
{ description: "Time to switch to applications view, second time",
|
||||
units: "us"}
|
||||
units: "us" }
|
||||
};
|
||||
|
||||
let WINDOW_CONFIGS = [
|
||||
@ -65,7 +65,7 @@ let WINDOW_CONFIGS = [
|
||||
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }
|
||||
];
|
||||
|
||||
function run() {
|
||||
function *run() {
|
||||
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
|
||||
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
|
||||
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
|
||||
@ -136,7 +136,6 @@ let overviewFrames;
|
||||
let overviewLatency;
|
||||
let mallocUsedSize = 0;
|
||||
let overviewShowCount = 0;
|
||||
let firstOverviewUsedSize;
|
||||
let haveSwapComplete = false;
|
||||
let applicationsShowStart;
|
||||
let applicationsShowCount = 0;
|
||||
|
@ -1,12 +1,8 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const { Clutter, Gio, Shell } = imports.gi;
|
||||
const Main = imports.ui.main;
|
||||
const Scripting = imports.ui.scripting;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
let METRICS = {
|
||||
var METRICS = {
|
||||
timeToDesktop:
|
||||
{ description: "Time from starting graphical.target to desktop showing",
|
||||
units: "us" },
|
||||
@ -34,7 +30,7 @@ let METRICS = {
|
||||
geditStartTime:
|
||||
{ description: "Time from gedit launch to window drawn",
|
||||
units: "us" },
|
||||
}
|
||||
};
|
||||
|
||||
function waitAndDraw(milliseconds) {
|
||||
let cb;
|
||||
@ -52,7 +48,7 @@ function waitAndDraw(milliseconds) {
|
||||
cb();
|
||||
});
|
||||
|
||||
return callback => { cb = callback; };
|
||||
return callback => cb = callback;
|
||||
}
|
||||
|
||||
function waitSignal(object, signal) {
|
||||
@ -64,7 +60,7 @@ function waitSignal(object, signal) {
|
||||
cb();
|
||||
});
|
||||
|
||||
return callback => { cb = callback; };
|
||||
return callback => cb = callback;
|
||||
}
|
||||
|
||||
function extractBootTimestamp() {
|
||||
@ -89,7 +85,7 @@ function extractBootTimestamp() {
|
||||
return result;
|
||||
}
|
||||
|
||||
function run() {
|
||||
function *run() {
|
||||
Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
|
||||
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
|
||||
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
|
||||
@ -108,7 +104,10 @@ function run() {
|
||||
yield Scripting.waitLeisure();
|
||||
Scripting.scriptEvent('desktopShown');
|
||||
|
||||
Gtk.Settings.get_default().gtk_enable_animations = false;
|
||||
let interfaceSettings = new Gio.Settings({
|
||||
schema_id: 'org.gnome.desktop.interface'
|
||||
});
|
||||
interfaceSettings.set_boolean('enable-animations', false);
|
||||
|
||||
Scripting.scriptEvent('overviewShowStart');
|
||||
Main.overview.show();
|
||||
@ -158,7 +157,7 @@ function run() {
|
||||
Main.overview.hide();
|
||||
|
||||
yield Scripting.createTestWindow({ maximized: true,
|
||||
redraws: true});
|
||||
redraws: true });
|
||||
yield Scripting.waitTestWindows();
|
||||
|
||||
yield Scripting.sleep(1000);
|
||||
@ -204,7 +203,7 @@ function run() {
|
||||
|
||||
yield Scripting.sleep(1000);
|
||||
|
||||
Gtk.Settings.get_default().gtk_enable_animations = true;
|
||||
interfaceSettings.set_boolean('enable-animations', true);
|
||||
}
|
||||
|
||||
let overviewShowStart;
|
||||
@ -270,11 +269,11 @@ function script_collectTimings(time) {
|
||||
if (len == 0)
|
||||
median = -1;
|
||||
else if (len % 2 == 1)
|
||||
median = times[(len - 1)/ 2];
|
||||
median = times[(len - 1) / 2];
|
||||
else
|
||||
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
|
||||
|
||||
METRICS[timing + 'RedrawTime'].value = median;
|
||||
METRICS[`${timing}RedrawTime`].value = median;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,6 @@
|
||||
const Format = imports.format;
|
||||
const Gettext = imports.gettext;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Soup = imports.gi.Soup;
|
||||
const WebKit = imports.gi.WebKit2;
|
||||
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi;
|
||||
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
@ -26,19 +19,16 @@ const PortalHelperSecurityLevel = {
|
||||
INSECURE: 2
|
||||
};
|
||||
|
||||
const INACTIVITY_TIMEOUT = 30000; //ms
|
||||
const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
|
||||
const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
|
||||
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
|
||||
|
||||
const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
|
||||
|
||||
var PortalHeaderBar = new Lang.Class({
|
||||
Name: 'PortalHeaderBar',
|
||||
Extends: Gtk.HeaderBar,
|
||||
|
||||
var PortalHeaderBar = GObject.registerClass(
|
||||
class PortalHeaderBar extends Gtk.HeaderBar {
|
||||
_init() {
|
||||
this.parent({ show_close_button: true });
|
||||
super._init({ show_close_button: true });
|
||||
|
||||
// See ephy-title-box.c in epiphany for the layout
|
||||
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
|
||||
@ -68,16 +58,16 @@ var PortalHeaderBar = new Lang.Class({
|
||||
single_line_mode: true,
|
||||
ellipsize: Pango.EllipsizeMode.END,
|
||||
valign: Gtk.Align.BASELINE,
|
||||
selectable: true});
|
||||
selectable: true });
|
||||
this.subtitleLabel.get_style_context().add_class('subtitle');
|
||||
hbox.add(this.subtitleLabel);
|
||||
|
||||
vbox.show_all();
|
||||
},
|
||||
}
|
||||
|
||||
setSubtitle(label) {
|
||||
this.subtitleLabel.set_text(label);
|
||||
},
|
||||
}
|
||||
|
||||
setSecurityIcon(securityLevel) {
|
||||
switch (securityLevel) {
|
||||
@ -95,15 +85,13 @@ var PortalHeaderBar = new Lang.Class({
|
||||
this._lockImage.set_tooltip_text(_('Your connection to this hotspot login is not secure. Passwords or other information you enter on this page can be viewed by people nearby.'));
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var PortalWindow = new Lang.Class({
|
||||
Name: 'PortalWindow',
|
||||
Extends: Gtk.ApplicationWindow,
|
||||
|
||||
var PortalWindow = GObject.registerClass(
|
||||
class PortalWindow extends Gtk.ApplicationWindow {
|
||||
_init(application, url, timestamp, doneCallback) {
|
||||
this.parent({ application: application });
|
||||
super._init({ application: application });
|
||||
|
||||
this.connect('delete-event', this.destroyWindow.bind(this));
|
||||
this._headerBar = new PortalHeaderBar();
|
||||
@ -144,11 +132,11 @@ var PortalWindow = new Lang.Class({
|
||||
this.present_with_time(timestamp);
|
||||
|
||||
this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']);
|
||||
},
|
||||
}
|
||||
|
||||
destroyWindow() {
|
||||
this.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
_syncUri() {
|
||||
let uri = this._webView.uri;
|
||||
@ -156,12 +144,12 @@ var PortalWindow = new Lang.Class({
|
||||
this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null));
|
||||
else
|
||||
this._headerBar.setSubtitle('');
|
||||
},
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this._everSeenRedirect = false;
|
||||
this._webView.load_uri(this._originalUrl);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_delete_event(event) {
|
||||
if (this._recheckAtExit)
|
||||
@ -169,7 +157,7 @@ var PortalWindow = new Lang.Class({
|
||||
else
|
||||
this._doneCallback(PortalHelperResult.CANCELLED);
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
_onLoadChanged(view, loadEvent) {
|
||||
if (loadEvent == WebKit.LoadEvent.STARTED) {
|
||||
@ -183,11 +171,11 @@ var PortalWindow = new Lang.Class({
|
||||
else
|
||||
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onInsecureContentDetected() {
|
||||
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
|
||||
},
|
||||
}
|
||||
|
||||
_onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
|
||||
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
|
||||
@ -195,7 +183,7 @@ var PortalWindow = new Lang.Class({
|
||||
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
|
||||
this._webView.load_uri(failingURI);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_onDecidePolicy(view, decision, type) {
|
||||
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
|
||||
@ -262,15 +250,13 @@ var PortalWindow = new Lang.Class({
|
||||
|
||||
decision.use();
|
||||
return true;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var WebPortalHelper = new Lang.Class({
|
||||
Name: 'WebPortalHelper',
|
||||
Extends: Gtk.Application,
|
||||
|
||||
var WebPortalHelper = GObject.registerClass(
|
||||
class WebPortalHelper extends Gtk.Application {
|
||||
_init() {
|
||||
this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
|
||||
super._init({ application_id: 'org.gnome.Shell.PortalHelper',
|
||||
flags: Gio.ApplicationFlags.IS_SERVICE,
|
||||
inactivity_timeout: 30000 });
|
||||
|
||||
@ -278,32 +264,32 @@ var WebPortalHelper = new Lang.Class({
|
||||
this._queue = [];
|
||||
|
||||
let action = new Gio.SimpleAction({ name: 'quit' });
|
||||
action.connect('activate', () => { this.active_window.destroyWindow(); });
|
||||
action.connect('activate', () => this.active_window.destroyWindow());
|
||||
this.add_action(action);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_dbus_register(connection, path) {
|
||||
this._dbusImpl.export(connection, path);
|
||||
this.parent(connection, path);
|
||||
super.vfunc_dbus_register(connection, path);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_dbus_unregister(connection, path) {
|
||||
this._dbusImpl.unexport_from_connection(connection);
|
||||
this.parent(connection, path);
|
||||
},
|
||||
super.vfunc_dbus_unregister(connection, path);
|
||||
}
|
||||
|
||||
vfunc_activate() {
|
||||
// If launched manually (for example for testing), force a dummy authentication
|
||||
// session with the default url
|
||||
this.Authenticate('/org/gnome/dummy', '', 0);
|
||||
},
|
||||
}
|
||||
|
||||
Authenticate(connection, url, timestamp) {
|
||||
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
|
||||
|
||||
this._processQueue();
|
||||
},
|
||||
}
|
||||
|
||||
Close(connection) {
|
||||
for (let i = 0; i < this._queue.length; i++) {
|
||||
@ -318,7 +304,7 @@ var WebPortalHelper = new Lang.Class({
|
||||
}
|
||||
|
||||
this._processQueue();
|
||||
},
|
||||
}
|
||||
|
||||
Refresh(connection) {
|
||||
for (let i = 0; i < this._queue.length; i++) {
|
||||
@ -330,7 +316,7 @@ var WebPortalHelper = new Lang.Class({
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_processQueue() {
|
||||
if (this._queue.length == 0)
|
||||
@ -343,7 +329,7 @@ var WebPortalHelper = new Lang.Class({
|
||||
top.window = new PortalWindow(this, top.url, top.timestamp, result => {
|
||||
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
function initEnvironment() {
|
||||
|
@ -1,10 +1,4 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi;
|
||||
|
||||
const CheckBox = imports.ui.checkBox;
|
||||
const Dialog = imports.ui.dialog;
|
||||
@ -21,12 +15,10 @@ var DialogResponse = {
|
||||
CLOSED: 2
|
||||
};
|
||||
|
||||
var AccessDialog = new Lang.Class({
|
||||
Name: 'AccessDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
var AccessDialog = GObject.registerClass(
|
||||
class AccessDialog extends ModalDialog.ModalDialog {
|
||||
_init(invocation, handle, title, subtitle, body, options) {
|
||||
this.parent({ styleClass: 'access-dialog' });
|
||||
super._init({ styleClass: 'access-dialog' });
|
||||
|
||||
this._invocation = invocation;
|
||||
this._handle = handle;
|
||||
@ -38,7 +30,7 @@ var AccessDialog = new Lang.Class({
|
||||
options[option] = options[option].deep_unpack();
|
||||
|
||||
this._buildLayout(title, subtitle, body, options);
|
||||
},
|
||||
}
|
||||
|
||||
_buildLayout(title, subtitle, body, options) {
|
||||
// No support for non-modal system dialogs, so ignore the option
|
||||
@ -77,15 +69,15 @@ var AccessDialog = new Lang.Class({
|
||||
this.addButton({ label: grantLabel,
|
||||
action: () => {
|
||||
this._sendResponse(DialogResponse.OK);
|
||||
}});
|
||||
},
|
||||
} });
|
||||
}
|
||||
|
||||
open() {
|
||||
this.parent();
|
||||
super.open();
|
||||
|
||||
let connection = this._invocation.get_connection();
|
||||
this._requestExported = this._request.export(connection, this._handle);
|
||||
},
|
||||
}
|
||||
|
||||
CloseAsync(invocation, params) {
|
||||
if (this._invocation.get_sender() != invocation.get_sender()) {
|
||||
@ -96,7 +88,7 @@ var AccessDialog = new Lang.Class({
|
||||
}
|
||||
|
||||
this._sendResponse(DialogResponse.CLOSED);
|
||||
},
|
||||
}
|
||||
|
||||
_sendResponse(response) {
|
||||
if (this._requestExported)
|
||||
@ -120,10 +112,8 @@ var AccessDialog = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var AccessDialogDBus = new Lang.Class({
|
||||
Name: 'AccessDialogDBus',
|
||||
|
||||
_init() {
|
||||
var AccessDialogDBus = class {
|
||||
constructor() {
|
||||
this._accessDialog = null;
|
||||
|
||||
this._windowTracker = Shell.WindowTracker.get_default();
|
||||
@ -132,7 +122,7 @@ var AccessDialogDBus = new Lang.Class({
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop');
|
||||
|
||||
Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
},
|
||||
}
|
||||
|
||||
AccessDialogAsync(params, invocation) {
|
||||
if (this._accessDialog) {
|
||||
@ -145,7 +135,7 @@ var AccessDialogDBus = new Lang.Class({
|
||||
let [handle, appId, parentWindow, title, subtitle, body, options] = params;
|
||||
// We probably want to use parentWindow and global.display.focus_window
|
||||
// for this check in the future
|
||||
if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) {
|
||||
if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) {
|
||||
invocation.return_error_literal(Gio.DBusError,
|
||||
Gio.DBusError.ACCESS_DENIED,
|
||||
'Only the focused app is allowed to show a system access dialog');
|
||||
@ -156,8 +146,8 @@ var AccessDialogDBus = new Lang.Class({
|
||||
subtitle, body, options);
|
||||
dialog.open();
|
||||
|
||||
dialog.connect('closed', () => { this._accessDialog = null; });
|
||||
dialog.connect('closed', () => this._accessDialog = null);
|
||||
|
||||
this._accessDialog = dialog;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
303
js/ui/altTab.js
@ -1,15 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const SwitcherPopup = imports.ui.switcherPopup;
|
||||
@ -44,7 +36,7 @@ function _createWindowClone(window, size) {
|
||||
// usual hack for the usual bug in ClutterBinLayout...
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
};
|
||||
}
|
||||
|
||||
function getWindows(workspace) {
|
||||
// We ignore skip-taskbar windows in switchers, but if they are attached
|
||||
@ -59,12 +51,10 @@ function getWindows(workspace) {
|
||||
}).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
|
||||
}
|
||||
|
||||
var AppSwitcherPopup = new Lang.Class({
|
||||
Name: 'AppSwitcherPopup',
|
||||
Extends: SwitcherPopup.SwitcherPopup,
|
||||
|
||||
var AppSwitcherPopup = GObject.registerClass(
|
||||
class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this._thumbnails = null;
|
||||
this._thumbnailTimeoutId = 0;
|
||||
@ -79,10 +69,10 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
|
||||
this._switcherList = new AppSwitcher(apps, this);
|
||||
this._items = this._switcherList.icons;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
this.parent(box, flags);
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
// Allocate the thumbnails
|
||||
// We try to avoid overflowing the screen so we base the resulting size on
|
||||
@ -117,7 +107,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||
this._thumbnails.allocate(childBox, flags);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_initialSelection(backward, binding) {
|
||||
if (binding == 'switch-group') {
|
||||
@ -140,7 +130,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
} else {
|
||||
this._select(1);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_nextWindow() {
|
||||
// We actually want the second window if we're in the unset state
|
||||
@ -148,14 +138,15 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
this._currentWindow = 0;
|
||||
return SwitcherPopup.mod(this._currentWindow + 1,
|
||||
this._items[this._selectedIndex].cachedWindows.length);
|
||||
},
|
||||
}
|
||||
|
||||
_previousWindow() {
|
||||
// Also assume second window here
|
||||
if (this._currentWindow == -1)
|
||||
this._currentWindow = 1;
|
||||
return SwitcherPopup.mod(this._currentWindow - 1,
|
||||
this._items[this._selectedIndex].cachedWindows.length);
|
||||
},
|
||||
}
|
||||
|
||||
_closeAppWindow(appIndex, windowIndex) {
|
||||
let appIcon = this._items[appIndex];
|
||||
@ -167,7 +158,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
return;
|
||||
|
||||
window.delete(global.get_current_time());
|
||||
},
|
||||
}
|
||||
|
||||
_quitApplication(appIndex) {
|
||||
let appIcon = this._items[appIndex];
|
||||
@ -175,7 +166,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
return;
|
||||
|
||||
appIcon.app.request_quit();
|
||||
},
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
|
||||
@ -214,7 +205,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
}
|
||||
|
||||
_scrollHandler(direction) {
|
||||
if (direction == Clutter.ScrollDirection.UP) {
|
||||
@ -244,7 +235,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
this._select(this._next());
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_itemActivatedHandler(n) {
|
||||
// If the user clicks on the selected app, activate the
|
||||
@ -254,24 +245,24 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
this._select(n, this._currentWindow);
|
||||
else
|
||||
this._select(n);
|
||||
},
|
||||
}
|
||||
|
||||
_itemEnteredHandler(n) {
|
||||
this._select(n);
|
||||
},
|
||||
}
|
||||
|
||||
_windowActivated(thumbnailList, n) {
|
||||
let appIcon = this._items[this._selectedIndex];
|
||||
Main.activateWindow(appIcon.cachedWindows[n]);
|
||||
this.fadeAndDestroy();
|
||||
},
|
||||
}
|
||||
|
||||
_windowEntered(thumbnailList, n) {
|
||||
if (!this.mouseActive)
|
||||
return;
|
||||
|
||||
this._select(this._selectedIndex, n);
|
||||
},
|
||||
}
|
||||
|
||||
_windowRemoved(thumbnailList, n) {
|
||||
let appIcon = this._items[this._selectedIndex];
|
||||
@ -282,7 +273,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
let newIndex = Math.min(n, appIcon.cachedWindows.length - 1);
|
||||
this._select(this._selectedIndex, newIndex);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_finish(timestamp) {
|
||||
let appIcon = this._items[this._selectedIndex];
|
||||
@ -291,17 +282,17 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
else if (appIcon.cachedWindows[this._currentWindow])
|
||||
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
|
||||
|
||||
this.parent();
|
||||
},
|
||||
super._finish(timestamp);
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.parent();
|
||||
super._onDestroy();
|
||||
|
||||
if (this._thumbnails)
|
||||
this._destroyThumbnails();
|
||||
if (this._thumbnailTimeoutId != 0)
|
||||
Mainloop.source_remove(this._thumbnailTimeoutId);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* _select:
|
||||
@ -357,7 +348,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
this._timeoutPopupThumbnails.bind(this));
|
||||
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_timeoutPopupThumbnails() {
|
||||
if (!this._thumbnails)
|
||||
@ -365,7 +356,7 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
this._thumbnailTimeoutId = 0;
|
||||
this._thumbnailsFocused = false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
_destroyThumbnails() {
|
||||
let thumbnailsActor = this._thumbnails;
|
||||
@ -379,9 +370,9 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
}
|
||||
});
|
||||
this._thumbnails = null;
|
||||
if (this._switcherList._items[this._selectedIndex])
|
||||
if (this._switcherList._items[this._selectedIndex])
|
||||
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
|
||||
},
|
||||
}
|
||||
|
||||
_createThumbnails() {
|
||||
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
|
||||
@ -404,17 +395,15 @@ var AppSwitcherPopup = new Lang.Class({
|
||||
{ opacity: 255,
|
||||
time: THUMBNAIL_FADE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: () => { this.thumbnailsVisible = true; }
|
||||
onComplete: () => this.thumbnailsVisible = true
|
||||
});
|
||||
|
||||
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
|
||||
}
|
||||
});
|
||||
|
||||
var CyclerHighlight = new Lang.Class({
|
||||
Name: 'CyclerHighlight',
|
||||
|
||||
_init() {
|
||||
class CyclerHighlight {
|
||||
constructor() {
|
||||
this._window = null;
|
||||
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
@ -434,7 +423,7 @@ var CyclerHighlight = new Lang.Class({
|
||||
this.actor.connect('notify::allocation',
|
||||
this._onAllocationChanged.bind(this));
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
set window(w) {
|
||||
if (this._window == w)
|
||||
@ -452,7 +441,7 @@ var CyclerHighlight = new Lang.Class({
|
||||
windowActor.hide();
|
||||
|
||||
this._clone.source = windowActor;
|
||||
},
|
||||
}
|
||||
|
||||
_onAllocationChanged() {
|
||||
if (!this._window) {
|
||||
@ -465,35 +454,31 @@ var CyclerHighlight = new Lang.Class({
|
||||
this._highlight.set_position(rect.x - x, rect.y - y);
|
||||
this._highlight.show();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.window = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We don't show an actual popup, so just provide what SwitcherPopup
|
||||
// expects instead of inheriting from SwitcherList
|
||||
var CyclerList = new Lang.Class({
|
||||
Name: 'CyclerList',
|
||||
Extends: St.Widget,
|
||||
var CyclerList = GObject.registerClass({
|
||||
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
|
||||
'item-entered': { param_types: [GObject.TYPE_INT] },
|
||||
'item-removed': { param_types: [GObject.TYPE_INT] },
|
||||
'item-highlighted': { param_types: [GObject.TYPE_INT] } },
|
||||
|
||||
}, class CyclerList extends St.Widget {
|
||||
highlight(index, justOutline) {
|
||||
this.emit('item-highlighted', index);
|
||||
}
|
||||
});
|
||||
|
||||
var CyclerPopup = new Lang.Class({
|
||||
Name: 'CyclerPopup',
|
||||
Extends: SwitcherPopup.SwitcherPopup,
|
||||
Abstract: true,
|
||||
|
||||
var CyclerPopup = GObject.registerClass({
|
||||
GTypeFlags: GObject.TypeFlags.ABSTRACT
|
||||
}, class CyclerPopup extends SwitcherPopup.SwitcherPopup {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this._items = this._getWindows();
|
||||
|
||||
@ -507,12 +492,12 @@ var CyclerPopup = new Lang.Class({
|
||||
this._switcherList.connect('item-highlighted', (list, index) => {
|
||||
this._highlightItem(index);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_highlightItem(index, justOutline) {
|
||||
this._highlight.window = this._items[index];
|
||||
global.window_group.set_child_above_sibling(this._highlight.actor, null);
|
||||
},
|
||||
}
|
||||
|
||||
_finish() {
|
||||
let window = this._items[this._selectedIndex];
|
||||
@ -537,25 +522,23 @@ var CyclerPopup = new Lang.Class({
|
||||
Main.wm.actionMoveWindow(window, ws);
|
||||
}
|
||||
|
||||
this.parent();
|
||||
},
|
||||
super._finish();
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._highlight.actor.destroy();
|
||||
|
||||
this.parent();
|
||||
super._onDestroy();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var GroupCyclerPopup = new Lang.Class({
|
||||
Name: 'GroupCyclerPopup',
|
||||
Extends: CyclerPopup,
|
||||
|
||||
var GroupCyclerPopup = GObject.registerClass(
|
||||
class GroupCyclerPopup extends CyclerPopup {
|
||||
_getWindows() {
|
||||
let app = Shell.WindowTracker.get_default().focus_app;
|
||||
return app ? app.get_windows() : [];
|
||||
},
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (action == Meta.KeyBindingAction.CYCLE_GROUP)
|
||||
@ -569,12 +552,10 @@ var GroupCyclerPopup = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var WindowSwitcherPopup = new Lang.Class({
|
||||
Name: 'WindowSwitcherPopup',
|
||||
Extends: SwitcherPopup.SwitcherPopup,
|
||||
|
||||
var WindowSwitcherPopup = GObject.registerClass(
|
||||
class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
|
||||
|
||||
let windows = this._getWindowList();
|
||||
@ -585,7 +566,7 @@ var WindowSwitcherPopup = new Lang.Class({
|
||||
let mode = this._settings.get_enum('app-icon-mode');
|
||||
this._switcherList = new WindowList(windows, mode);
|
||||
this._items = this._switcherList.icons;
|
||||
},
|
||||
}
|
||||
|
||||
_getWindowList() {
|
||||
let workspace = null;
|
||||
@ -597,7 +578,7 @@ var WindowSwitcherPopup = new Lang.Class({
|
||||
}
|
||||
|
||||
return getWindows(workspace);
|
||||
},
|
||||
}
|
||||
|
||||
_closeWindow(windowIndex) {
|
||||
let windowIcon = this._items[windowIndex];
|
||||
@ -605,7 +586,7 @@ var WindowSwitcherPopup = new Lang.Class({
|
||||
return;
|
||||
|
||||
windowIcon.window.delete(global.get_current_time());
|
||||
},
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
|
||||
@ -624,23 +605,21 @@ var WindowSwitcherPopup = new Lang.Class({
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
}
|
||||
|
||||
_finish() {
|
||||
Main.activateWindow(this._items[this._selectedIndex].window);
|
||||
|
||||
this.parent();
|
||||
super._finish();
|
||||
}
|
||||
});
|
||||
|
||||
var WindowCyclerPopup = new Lang.Class({
|
||||
Name: 'WindowCyclerPopup',
|
||||
Extends: CyclerPopup,
|
||||
|
||||
var WindowCyclerPopup = GObject.registerClass(
|
||||
class WindowCyclerPopup extends CyclerPopup {
|
||||
_init() {
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
|
||||
this.parent();
|
||||
},
|
||||
super._init();
|
||||
}
|
||||
|
||||
_getWindows() {
|
||||
let workspace = null;
|
||||
@ -652,7 +631,7 @@ var WindowCyclerPopup = new Lang.Class({
|
||||
}
|
||||
|
||||
return getWindows(workspace);
|
||||
},
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
|
||||
@ -666,12 +645,10 @@ var WindowCyclerPopup = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var AppIcon = new Lang.Class({
|
||||
Name: 'AppIcon',
|
||||
Extends: St.BoxLayout,
|
||||
|
||||
var AppIcon = GObject.registerClass(
|
||||
class AppIcon extends St.BoxLayout {
|
||||
_init(app) {
|
||||
this.parent({ style_class: 'alt-tab-app',
|
||||
super._init({ style_class: 'alt-tab-app',
|
||||
vertical: true });
|
||||
|
||||
this.app = app;
|
||||
@ -681,28 +658,18 @@ var AppIcon = new Lang.Class({
|
||||
this.add(this._iconBin, { x_fill: false, y_fill: false } );
|
||||
this.label = new St.Label({ text: this.app.get_name() });
|
||||
this.add(this.label, { x_fill: false });
|
||||
},
|
||||
}
|
||||
|
||||
set_size(size) {
|
||||
this.icon = this.app.create_icon_texture(size);
|
||||
this._iconBin.child = this.icon;
|
||||
this._iconBin.set_size(size, size);
|
||||
},
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
let [minWidth, ] = this.parent(forHeight);
|
||||
|
||||
minWidth = Math.max(minWidth, forHeight);
|
||||
return [minWidth, minWidth];
|
||||
}
|
||||
});
|
||||
|
||||
var AppSwitcher = new Lang.Class({
|
||||
Name: 'AppSwitcher',
|
||||
Extends: SwitcherPopup.SwitcherList,
|
||||
|
||||
var AppSwitcher = GObject.registerClass(
|
||||
class AppSwitcher extends SwitcherPopup.SwitcherList {
|
||||
_init(apps, altTabPopup) {
|
||||
this.parent(true);
|
||||
super._init(true);
|
||||
|
||||
this.icons = [];
|
||||
this._arrows = [];
|
||||
@ -736,7 +703,7 @@ var AppSwitcher = new Lang.Class({
|
||||
this._mouseTimeOutId = 0;
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._mouseTimeOutId != 0)
|
||||
@ -745,19 +712,20 @@ var AppSwitcher = new Lang.Class({
|
||||
this.icons.forEach(icon => {
|
||||
icon.app.disconnect(icon._stateChangedId);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_setIconSize() {
|
||||
let j = 0;
|
||||
while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
|
||||
j++;
|
||||
while (this._items.length > 1 && this._items[j].style_class != 'item-box') {
|
||||
j++;
|
||||
}
|
||||
let themeNode = this._items[j].get_theme_node();
|
||||
this._list.ensure_style();
|
||||
|
||||
let iconPadding = themeNode.get_horizontal_padding();
|
||||
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
|
||||
let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
|
||||
let iconSpacing = iconNaturalHeight + iconPadding + iconBorder;
|
||||
let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
|
||||
let iconSpacing = labelNaturalHeight + iconPadding + iconBorder;
|
||||
let totalSpacing = this._list.spacing * (this._items.length - 1);
|
||||
|
||||
// We just assume the whole screen here due to weirdness happing with the passed width
|
||||
@ -770,7 +738,7 @@ var AppSwitcher = new Lang.Class({
|
||||
let iconSize = baseIconSizes[0];
|
||||
|
||||
if (this._items.length > 1) {
|
||||
for(let i = 0; i < baseIconSizes.length; i++) {
|
||||
for (let i = 0; i < baseIconSizes.length; i++) {
|
||||
iconSize = baseIconSizes[i];
|
||||
let height = iconSizes[i] + iconSpacing;
|
||||
let w = height * this._items.length + totalSpacing;
|
||||
@ -781,21 +749,21 @@ var AppSwitcher = new Lang.Class({
|
||||
|
||||
this._iconSize = iconSize;
|
||||
|
||||
for(let i = 0; i < this.icons.length; i++) {
|
||||
for (let i = 0; i < this.icons.length; i++) {
|
||||
if (this.icons[i].icon != null)
|
||||
break;
|
||||
this.icons[i].set_size(iconSize);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
this._setIconSize();
|
||||
return this.parent(forWidth);
|
||||
},
|
||||
return super.vfunc_get_preferred_height(forWidth);
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
// Allocate the main list items
|
||||
this.parent(box, flags);
|
||||
super.vfunc_allocate(box, flags);
|
||||
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
|
||||
@ -812,7 +780,7 @@ var AppSwitcher = new Lang.Class({
|
||||
childBox.y2 = childBox.y1 + arrowHeight;
|
||||
this._arrows[i].allocate(childBox, flags);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// We override SwitcherList's _onItemEnter method to delay
|
||||
// activation when the thumbnail list is open
|
||||
@ -827,16 +795,17 @@ var AppSwitcher = new Lang.Class({
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
|
||||
} else
|
||||
this._itemEntered(index);
|
||||
},
|
||||
} else {
|
||||
this._itemEntered(index);
|
||||
}
|
||||
}
|
||||
|
||||
_enterItem(index) {
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
|
||||
if (this._items[index].contains(pickedActor))
|
||||
this._itemEntered(index);
|
||||
},
|
||||
}
|
||||
|
||||
// We override SwitcherList's highlight() method to also deal with
|
||||
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
|
||||
@ -853,7 +822,7 @@ var AppSwitcher = new Lang.Class({
|
||||
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
|
||||
}
|
||||
|
||||
this.parent(n, justOutline);
|
||||
super.highlight(n, justOutline);
|
||||
this._curApp = n;
|
||||
|
||||
if (this._curApp != -1) {
|
||||
@ -862,7 +831,7 @@ var AppSwitcher = new Lang.Class({
|
||||
else
|
||||
this._arrows[this._curApp].add_style_pseudo_class('highlighted');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_addIcon(appIcon) {
|
||||
this.icons.push(appIcon);
|
||||
@ -873,9 +842,8 @@ var AppSwitcher = new Lang.Class({
|
||||
this._removeIcon(app);
|
||||
});
|
||||
|
||||
let n = this._arrows.length;
|
||||
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
|
||||
arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
|
||||
arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM));
|
||||
this.add_actor(arrow);
|
||||
this._arrows.push(arrow);
|
||||
|
||||
@ -883,7 +851,7 @@ var AppSwitcher = new Lang.Class({
|
||||
arrow.hide();
|
||||
else
|
||||
item.add_accessible_state (Atk.StateType.EXPANDABLE);
|
||||
},
|
||||
}
|
||||
|
||||
_removeIcon(app) {
|
||||
let index = this.icons.findIndex(icon => {
|
||||
@ -894,15 +862,13 @@ var AppSwitcher = new Lang.Class({
|
||||
|
||||
this.icons.splice(index, 1);
|
||||
this.removeItem(index);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var ThumbnailList = new Lang.Class({
|
||||
Name: 'ThumbnailList',
|
||||
Extends: SwitcherPopup.SwitcherList,
|
||||
|
||||
var ThumbnailList = GObject.registerClass(
|
||||
class ThumbnailList extends SwitcherPopup.SwitcherList {
|
||||
_init(windows) {
|
||||
this.parent(false);
|
||||
super._init(false);
|
||||
|
||||
this._labels = new Array();
|
||||
this._thumbnailBins = new Array();
|
||||
@ -935,7 +901,7 @@ var ThumbnailList = new Lang.Class({
|
||||
}
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
addClones(availHeight) {
|
||||
if (!this._thumbnailBins.length)
|
||||
@ -968,7 +934,7 @@ var ThumbnailList = new Lang.Class({
|
||||
|
||||
// Make sure we only do this once
|
||||
this._thumbnailBins = new Array();
|
||||
},
|
||||
}
|
||||
|
||||
_removeThumbnail(source, clone) {
|
||||
let index = this._clones.indexOf(clone);
|
||||
@ -984,23 +950,20 @@ var ThumbnailList = new Lang.Class({
|
||||
this.highlight(SwitcherPopup.mod(index, this._clones.length));
|
||||
else
|
||||
this.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._clones.forEach(clone => {
|
||||
if (clone.source)
|
||||
clone.source.disconnect(clone._destroyId);
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
var WindowIcon = new Lang.Class({
|
||||
Name: 'WindowIcon',
|
||||
Extends: St.BoxLayout,
|
||||
|
||||
var WindowIcon = GObject.registerClass(
|
||||
class WindowIcon extends St.BoxLayout {
|
||||
_init(window, mode) {
|
||||
this.parent({ style_class: 'alt-tab-app',
|
||||
super._init({ style_class: 'alt-tab-app',
|
||||
vertical: true });
|
||||
|
||||
this.window = window;
|
||||
@ -1021,27 +984,27 @@ var WindowIcon = new Lang.Class({
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
|
||||
switch (mode) {
|
||||
case AppIconMode.THUMBNAIL_ONLY:
|
||||
size = WINDOW_PREVIEW_SIZE;
|
||||
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
|
||||
break;
|
||||
case AppIconMode.THUMBNAIL_ONLY:
|
||||
size = WINDOW_PREVIEW_SIZE;
|
||||
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
|
||||
break;
|
||||
|
||||
case AppIconMode.BOTH:
|
||||
size = WINDOW_PREVIEW_SIZE;
|
||||
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
|
||||
case AppIconMode.BOTH:
|
||||
size = WINDOW_PREVIEW_SIZE;
|
||||
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
|
||||
|
||||
if (this.app)
|
||||
this._icon.add_actor(this._createAppIcon(this.app,
|
||||
APP_ICON_SIZE_SMALL));
|
||||
break;
|
||||
if (this.app)
|
||||
this._icon.add_actor(this._createAppIcon(this.app,
|
||||
APP_ICON_SIZE_SMALL));
|
||||
break;
|
||||
|
||||
case AppIconMode.APP_ICON_ONLY:
|
||||
size = APP_ICON_SIZE;
|
||||
this._icon.add_actor(this._createAppIcon(this.app, size));
|
||||
case AppIconMode.APP_ICON_ONLY:
|
||||
size = APP_ICON_SIZE;
|
||||
this._icon.add_actor(this._createAppIcon(this.app, size));
|
||||
}
|
||||
|
||||
this._icon.set_size(size * scaleFactor, size * scaleFactor);
|
||||
},
|
||||
}
|
||||
|
||||
_createAppIcon(app, size) {
|
||||
let appIcon = app ? app.create_icon_texture(size)
|
||||
@ -1054,12 +1017,10 @@ var WindowIcon = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var WindowList = new Lang.Class({
|
||||
Name: 'WindowList',
|
||||
Extends: SwitcherPopup.SwitcherList,
|
||||
|
||||
var WindowList = GObject.registerClass(
|
||||
class WindowList extends SwitcherPopup.SwitcherList {
|
||||
_init(windows, mode) {
|
||||
this.parent(true);
|
||||
super._init(true);
|
||||
|
||||
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
@ -1076,21 +1037,21 @@ var WindowList = new Lang.Class({
|
||||
this.icons.push(icon);
|
||||
|
||||
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
|
||||
this._removeWindow(window)
|
||||
this._removeWindow(window);
|
||||
});
|
||||
}
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.icons.forEach(icon => {
|
||||
icon.window.disconnect(icon._unmanagedSignalId);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
let [minHeight, natHeight] = this.parent(forWidth);
|
||||
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
|
||||
let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM);
|
||||
let [labelMin, labelNat] = this._label.get_preferred_height(-1);
|
||||
@ -1099,7 +1060,7 @@ var WindowList = new Lang.Class({
|
||||
natHeight += labelNat + spacing;
|
||||
|
||||
return [minHeight, natHeight];
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -1112,24 +1073,24 @@ var WindowList = new Lang.Class({
|
||||
childBox.y1 = childBox.y2 - this._label.height;
|
||||
this._label.allocate(childBox, flags);
|
||||
|
||||
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM)
|
||||
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;
|
||||
this.parent(childBox, flags);
|
||||
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.
|
||||
this.set_allocation(box, flags);
|
||||
},
|
||||
}
|
||||
|
||||
highlight(index, justOutline) {
|
||||
this.parent(index, justOutline);
|
||||
super.highlight(index, justOutline);
|
||||
|
||||
this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
|
||||
},
|
||||
}
|
||||
|
||||
_removeWindow(window) {
|
||||
let index = this.icons.findIndex(icon => {
|
||||
|
@ -1,20 +1,27 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const { GLib, Gio, St } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
|
||||
var SPINNER_ANIMATION_TIME = 0.3;
|
||||
var SPINNER_ANIMATION_DELAY = 1.0;
|
||||
|
||||
var Animation = new Lang.Class({
|
||||
Name: 'Animation',
|
||||
|
||||
_init(file, width, height, speed) {
|
||||
var Animation = class {
|
||||
constructor(file, width, height, speed) {
|
||||
this.actor = new St.Bin();
|
||||
this.actor.set_size(width, height);
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
|
||||
this.actor.connect('resource-scale-changed',
|
||||
this._loadFile.bind(this, file, width, height));
|
||||
|
||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||
this._scaleChangedId = themeContext.connect('notify::scale-factor',
|
||||
this._loadFile.bind(this, file, width, height));
|
||||
|
||||
this._speed = speed;
|
||||
|
||||
this._isLoaded = false;
|
||||
@ -22,11 +29,8 @@ var Animation = new Lang.Class({
|
||||
this._timeoutId = 0;
|
||||
this._frame = 0;
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
|
||||
this._animationsLoaded.bind(this));
|
||||
this.actor.set_child(this._animations);
|
||||
},
|
||||
this._loadFile(file, width, height);
|
||||
}
|
||||
|
||||
play() {
|
||||
if (this._isLoaded && this._timeoutId == 0) {
|
||||
@ -38,7 +42,7 @@ var Animation = new Lang.Class({
|
||||
}
|
||||
|
||||
this._isPlaying = true;
|
||||
},
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this._timeoutId > 0) {
|
||||
@ -47,7 +51,24 @@ var Animation = new Lang.Class({
|
||||
}
|
||||
|
||||
this._isPlaying = false;
|
||||
},
|
||||
}
|
||||
|
||||
_loadFile(file, width, height) {
|
||||
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
|
||||
|
||||
this._isLoaded = false;
|
||||
this.actor.destroy_all_children();
|
||||
|
||||
if (!validResourceScale)
|
||||
return;
|
||||
|
||||
let textureCache = St.TextureCache.get_default();
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._animations = textureCache.load_sliced_image(file, width, height,
|
||||
scaleFactor, resourceScale,
|
||||
this._animationsLoaded.bind(this));
|
||||
this.actor.set_child(this._animations);
|
||||
}
|
||||
|
||||
_showFrame(frame) {
|
||||
let oldFrameActor = this._animations.get_child_at_index(this._frame);
|
||||
@ -59,30 +80,94 @@ var Animation = new Lang.Class({
|
||||
let newFrameActor = this._animations.get_child_at_index(this._frame);
|
||||
if (newFrameActor)
|
||||
newFrameActor.show();
|
||||
},
|
||||
}
|
||||
|
||||
_update() {
|
||||
this._showFrame(this._frame + 1);
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
},
|
||||
}
|
||||
|
||||
_syncAnimationSize() {
|
||||
if (!this._isLoaded)
|
||||
return;
|
||||
|
||||
let [width, height] = this.actor.get_size();
|
||||
|
||||
for (let i = 0; i < this._animations.get_n_children(); ++i)
|
||||
this._animations.get_child_at_index(i).set_size(width, height);
|
||||
}
|
||||
|
||||
_animationsLoaded() {
|
||||
this._isLoaded = this._animations.get_n_children() > 0;
|
||||
|
||||
this._syncAnimationSize();
|
||||
|
||||
if (this._isPlaying)
|
||||
this.play();
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.stop();
|
||||
}
|
||||
});
|
||||
|
||||
var AnimatedIcon = new Lang.Class({
|
||||
Name: 'AnimatedIcon',
|
||||
Extends: Animation,
|
||||
|
||||
_init(file, size) {
|
||||
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
|
||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||
if (this._scaleChangedId)
|
||||
themeContext.disconnect(this._scaleChangedId);
|
||||
this._scaleChangedId = 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var AnimatedIcon = class extends Animation {
|
||||
constructor(file, size) {
|
||||
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
|
||||
}
|
||||
};
|
||||
|
||||
var Spinner = class extends AnimatedIcon {
|
||||
constructor(size, animate = false) {
|
||||
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
super(file, size);
|
||||
|
||||
this.actor.opacity = 0;
|
||||
this._animate = animate;
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._animate = false;
|
||||
super._onDestroy();
|
||||
}
|
||||
|
||||
play() {
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
if (this._animate) {
|
||||
super.play();
|
||||
Tweener.addTween(this.actor, {
|
||||
opacity: 255,
|
||||
delay: SPINNER_ANIMATION_DELAY,
|
||||
time: SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
this.actor.opacity = 255;
|
||||
super.play();
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
if (this._animate) {
|
||||
Tweener.addTween(this.actor, {
|
||||
opacity: 0,
|
||||
time: SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onComplete: () => {
|
||||
super.stop();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.actor.opacity = 0;
|
||||
super.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
@ -15,53 +14,63 @@ const RENAMED_DESKTOP_IDS = {
|
||||
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
|
||||
'evolution.desktop': 'org.gnome.Evolution.desktop',
|
||||
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
|
||||
'five-or-more.desktop': 'org.gnome.five-or-more.desktop',
|
||||
'four-in-a-row.desktop': 'org.gnome.Four-in-a-row.desktop',
|
||||
'gcalctool.desktop': 'org.gnome.Calculator.desktop',
|
||||
'geary.desktop': 'org.gnome.Geary.desktop',
|
||||
'gedit.desktop': 'org.gnome.gedit.desktop',
|
||||
'glchess.desktop': 'gnome-chess.desktop',
|
||||
'glines.desktop': 'five-or-more.desktop',
|
||||
'gnect.desktop': 'four-in-a-row.desktop',
|
||||
'glchess.desktop': 'org.gnome.Chess.desktop',
|
||||
'glines.desktop': 'org.gnome.five-or-more.desktop',
|
||||
'gnect.desktop': 'org.gnome.Four-in-a-row.desktop',
|
||||
'gnibbles.desktop': 'org.gnome.Nibbles.desktop',
|
||||
'gnobots2.desktop': 'gnome-robots.desktop',
|
||||
'gnobots2.desktop': 'org.gnome.Robots.desktop',
|
||||
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
|
||||
'gnome-calculator.desktop': 'org.gnome.Calculator.desktop',
|
||||
'gnome-chess.desktop': 'org.gnome.Chess.desktop',
|
||||
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
|
||||
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
|
||||
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
|
||||
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
|
||||
'gnome-klotski.desktop': 'org.gnome.Klotski.desktop',
|
||||
'gnome-nibbles.desktop': 'org.gnome.Nibbles.desktop',
|
||||
'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop',
|
||||
'gnome-mines.desktop': 'org.gnome.Mines.desktop',
|
||||
'gnome-music.desktop': 'org.gnome.Music.desktop',
|
||||
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
|
||||
'gnome-robots.desktop': 'org.gnome.Robots.desktop',
|
||||
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
|
||||
'gnome-software.desktop': 'org.gnome.Software.desktop',
|
||||
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
|
||||
'gnome-tetravex.desktop': 'org.gnome.Tetravex.desktop',
|
||||
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
|
||||
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
|
||||
'gnomine.desktop': 'gnome-mines.desktop',
|
||||
'gnotravex.desktop': 'gnome-tetravex.desktop',
|
||||
'gnotski.desktop': 'gnome-klotski.desktop',
|
||||
'gtali.desktop': 'tali.desktop',
|
||||
'gnome-weather.desktop': 'org.gnome.Weather.desktop',
|
||||
'gnomine.desktop': 'org.gnome.Mines.desktop',
|
||||
'gnotravex.desktop': 'org.gnome.Tetravex.desktop',
|
||||
'gnotski.desktop': 'org.gnome.Klotski.desktop',
|
||||
'gtali.desktop': 'org.gnome.Tali.desktop',
|
||||
'iagno.desktop': 'org.gnome.Reversi.desktop',
|
||||
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
|
||||
'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop',
|
||||
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
|
||||
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
|
||||
'polari.desktop': 'org.gnome.Polari.desktop',
|
||||
'tali.desktop': 'org.gnome.Tali.desktop',
|
||||
'totem.desktop': 'org.gnome.Totem.desktop',
|
||||
'evince.desktop': 'org.gnome.Evince.desktop',
|
||||
};
|
||||
|
||||
var AppFavorites = new Lang.Class({
|
||||
Name: 'AppFavorites',
|
||||
|
||||
FAVORITE_APPS_KEY: 'favorite-apps',
|
||||
|
||||
_init() {
|
||||
class AppFavorites {
|
||||
constructor() {
|
||||
this.FAVORITE_APPS_KEY = 'favorite-apps';
|
||||
this._favorites = {};
|
||||
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
|
||||
global.settings.connect(`changed::${this.FAVORITE_APPS_KEY}`, this._onFavsChanged.bind(this));
|
||||
this.reload();
|
||||
},
|
||||
}
|
||||
|
||||
_onFavsChanged() {
|
||||
this.reload();
|
||||
this.emit('changed');
|
||||
},
|
||||
}
|
||||
|
||||
reload() {
|
||||
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
|
||||
@ -89,29 +98,29 @@ var AppFavorites = new Lang.Class({
|
||||
let app = apps[i];
|
||||
this._favorites[app.get_id()] = app;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getIds() {
|
||||
let ret = [];
|
||||
for (let id in this._favorites)
|
||||
ret.push(id);
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
|
||||
getFavoriteMap() {
|
||||
return this._favorites;
|
||||
},
|
||||
}
|
||||
|
||||
getFavorites() {
|
||||
let ret = [];
|
||||
for (let id in this._favorites)
|
||||
ret.push(this._favorites[id]);
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
|
||||
isFavorite(appId) {
|
||||
return appId in this._favorites;
|
||||
},
|
||||
}
|
||||
|
||||
_addFavorite(appId, pos) {
|
||||
if (appId in this._favorites)
|
||||
@ -129,7 +138,7 @@ var AppFavorites = new Lang.Class({
|
||||
ids.splice(pos, 0, appId);
|
||||
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
addFavoriteAtPos(appId, pos) {
|
||||
if (!this._addFavorite(appId, pos))
|
||||
@ -143,25 +152,25 @@ var AppFavorites = new Lang.Class({
|
||||
this._removeFavorite(appId);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
addFavorite(appId) {
|
||||
this.addFavoriteAtPos(appId, -1);
|
||||
},
|
||||
}
|
||||
|
||||
moveFavoriteToPos(appId, pos) {
|
||||
this._removeFavorite(appId);
|
||||
this._addFavorite(appId, pos);
|
||||
},
|
||||
}
|
||||
|
||||
_removeFavorite(appId) {
|
||||
if (!appId in this._favorites)
|
||||
if (!(appId in this._favorites))
|
||||
return false;
|
||||
|
||||
let ids = this._getIds().filter(id => id != appId);
|
||||
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
removeFavorite(appId) {
|
||||
let ids = this._getIds();
|
||||
@ -178,7 +187,7 @@ var AppFavorites = new Lang.Class({
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Signals.addSignalMethods(AppFavorites.prototype);
|
||||
|
||||
var appFavoritesInstance = null;
|
||||
|
@ -1,10 +1,4 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
@ -19,12 +13,11 @@ var AudioDevice = {
|
||||
|
||||
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
|
||||
|
||||
var AudioDeviceSelectionDialog = new Lang.Class({
|
||||
Name: 'AudioDeviceSelectionDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
var AudioDeviceSelectionDialog = GObject.registerClass({
|
||||
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } }
|
||||
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
|
||||
_init(devices) {
|
||||
this.parent({ styleClass: 'audio-device-selection-dialog' });
|
||||
super._init({ styleClass: 'audio-device-selection-dialog' });
|
||||
|
||||
this._deviceItems = {};
|
||||
|
||||
@ -39,11 +32,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
|
||||
|
||||
if (this._selectionBox.get_n_children() < 2)
|
||||
throw new Error('Too few devices for a selection');
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.parent();
|
||||
},
|
||||
}
|
||||
|
||||
_buildLayout(devices) {
|
||||
let title = new St.Label({ style_class: 'audio-selection-title',
|
||||
@ -56,38 +45,39 @@ var AudioDeviceSelectionDialog = new Lang.Class({
|
||||
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
|
||||
this.contentLayout.add(this._selectionBox, { expand: true });
|
||||
|
||||
this.addButton({ action: this._openSettings.bind(this),
|
||||
label: _("Sound Settings") });
|
||||
if (Main.sessionMode.allowSettings)
|
||||
this.addButton({ action: this._openSettings.bind(this),
|
||||
label: _("Sound Settings") });
|
||||
this.addButton({ action: this.close.bind(this),
|
||||
label: _("Cancel"),
|
||||
key: Clutter.Escape });
|
||||
},
|
||||
}
|
||||
|
||||
_getDeviceLabel(device) {
|
||||
switch(device) {
|
||||
case AudioDevice.HEADPHONES:
|
||||
return _("Headphones");
|
||||
case AudioDevice.HEADSET:
|
||||
return _("Headset");
|
||||
case AudioDevice.MICROPHONE:
|
||||
return _("Microphone");
|
||||
default:
|
||||
return null;
|
||||
switch (device) {
|
||||
case AudioDevice.HEADPHONES:
|
||||
return _("Headphones");
|
||||
case AudioDevice.HEADSET:
|
||||
return _("Headset");
|
||||
case AudioDevice.MICROPHONE:
|
||||
return _("Microphone");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getDeviceIcon(device) {
|
||||
switch(device) {
|
||||
case AudioDevice.HEADPHONES:
|
||||
return 'audio-headphones-symbolic';
|
||||
case AudioDevice.HEADSET:
|
||||
return 'audio-headset-symbolic';
|
||||
case AudioDevice.MICROPHONE:
|
||||
return 'audio-input-microphone-symbolic';
|
||||
default:
|
||||
return null;
|
||||
switch (device) {
|
||||
case AudioDevice.HEADPHONES:
|
||||
return 'audio-headphones-symbolic';
|
||||
case AudioDevice.HEADSET:
|
||||
return 'audio-headset-symbolic';
|
||||
case AudioDevice.MICROPHONE:
|
||||
return 'audio-input-microphone-symbolic';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_addDevice(device) {
|
||||
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
|
||||
@ -117,14 +107,14 @@ var AudioDeviceSelectionDialog = new Lang.Class({
|
||||
this.close();
|
||||
Main.overview.hide();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_openSettings() {
|
||||
let desktopFile = 'gnome-sound-panel.desktop'
|
||||
let desktopFile = 'gnome-sound-panel.desktop';
|
||||
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
|
||||
|
||||
if (!app) {
|
||||
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
|
||||
log(`Settings panel for desktop file ${desktopFile} could not be loaded!`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,21 +124,19 @@ var AudioDeviceSelectionDialog = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var AudioDeviceSelectionDBus = new Lang.Class({
|
||||
Name: 'AudioDeviceSelectionDBus',
|
||||
|
||||
_init() {
|
||||
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
|
||||
constructor() {
|
||||
this._audioSelectionDialog = null;
|
||||
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection');
|
||||
|
||||
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
},
|
||||
}
|
||||
|
||||
_onDialogClosed() {
|
||||
this._audioSelectionDialog = null;
|
||||
},
|
||||
}
|
||||
|
||||
_onDeviceSelected(dialog, device) {
|
||||
let connection = this._dbusImpl.get_connection();
|
||||
@ -161,7 +149,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
|
||||
info ? info.name : null,
|
||||
'DeviceSelected',
|
||||
GLib.Variant.new('(s)', [deviceName]));
|
||||
},
|
||||
}
|
||||
|
||||
OpenAsync(params, invocation) {
|
||||
if (this._audioSelectionDialog) {
|
||||
@ -171,12 +159,12 @@ var AudioDeviceSelectionDBus = new Lang.Class({
|
||||
|
||||
let [deviceNames] = params;
|
||||
let devices = 0;
|
||||
deviceNames.forEach(n => { devices |= AudioDevice[n.toUpperCase()]; });
|
||||
deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
|
||||
|
||||
let dialog;
|
||||
try {
|
||||
dialog = new AudioDeviceSelectionDialog(devices);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
invocation.return_value(null);
|
||||
return;
|
||||
}
|
||||
@ -189,7 +177,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
|
||||
|
||||
this._audioSelectionDialog = dialog;
|
||||
invocation.return_value(null);
|
||||
},
|
||||
}
|
||||
|
||||
CloseAsync(params, invocation) {
|
||||
if (this._audioSelectionDialog &&
|
||||
@ -198,4 +186,4 @@ var AudioDeviceSelectionDBus = new Lang.Class({
|
||||
|
||||
invocation.return_value(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -93,13 +93,7 @@
|
||||
// MetaBackgroundImage MetaBackgroundImage
|
||||
// MetaBackgroundImage MetaBackgroundImage
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GDesktopEnums = imports.gi.GDesktopEnums;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
@ -114,7 +108,6 @@ const PRIMARY_COLOR_KEY = 'primary-color';
|
||||
const SECONDARY_COLOR_KEY = 'secondary-color';
|
||||
const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
|
||||
const BACKGROUND_STYLE_KEY = 'picture-options';
|
||||
const PICTURE_OPACITY_KEY = 'picture-opacity';
|
||||
const PICTURE_URI_KEY = 'picture-uri';
|
||||
|
||||
var FADE_ANIMATION_TIME = 1.0;
|
||||
@ -138,14 +131,12 @@ function _fileEqual0(file1, file2) {
|
||||
return file1.equal(file2);
|
||||
}
|
||||
|
||||
var BackgroundCache = new Lang.Class({
|
||||
Name: 'BackgroundCache',
|
||||
|
||||
_init() {
|
||||
var BackgroundCache = class BackgroundCache {
|
||||
constructor() {
|
||||
this._fileMonitors = {};
|
||||
this._backgroundSources = {};
|
||||
this._animations = {};
|
||||
},
|
||||
}
|
||||
|
||||
monitorFile(file) {
|
||||
let key = file.hash();
|
||||
@ -163,7 +154,7 @@ var BackgroundCache = new Lang.Class({
|
||||
});
|
||||
|
||||
this._fileMonitors[key] = monitor;
|
||||
},
|
||||
}
|
||||
|
||||
getAnimation(params) {
|
||||
params = Params.parse(params, { file: null,
|
||||
@ -195,7 +186,7 @@ var BackgroundCache = new Lang.Class({
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
getBackgroundSource(layoutManager, settingsSchema) {
|
||||
// The layoutManager is always the same one; we pass in it since
|
||||
@ -209,7 +200,7 @@ var BackgroundCache = new Lang.Class({
|
||||
}
|
||||
|
||||
return this._backgroundSources[settingsSchema];
|
||||
},
|
||||
}
|
||||
|
||||
releaseBackgroundSource(settingsSchema) {
|
||||
if (settingsSchema in this._backgroundSources) {
|
||||
@ -221,7 +212,7 @@ var BackgroundCache = new Lang.Class({
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(BackgroundCache.prototype);
|
||||
|
||||
function getBackgroundCache() {
|
||||
@ -230,10 +221,8 @@ function getBackgroundCache() {
|
||||
return _backgroundCache;
|
||||
}
|
||||
|
||||
var Background = new Lang.Class({
|
||||
Name: 'Background',
|
||||
|
||||
_init(params) {
|
||||
var Background = class Background {
|
||||
constructor(params) {
|
||||
params = Params.parse(params, { monitorIndex: 0,
|
||||
layoutManager: Main.layoutManager,
|
||||
settings: null,
|
||||
@ -267,14 +256,15 @@ var Background = new Lang.Class({
|
||||
this._refreshAnimation();
|
||||
});
|
||||
|
||||
this._settingsChangedSignalId = this._settings.connect('changed', () => {
|
||||
this.emit('changed');
|
||||
});
|
||||
this._settingsChangedSignalId =
|
||||
this._settings.connect('changed', this._emitChangedSignal.bind(this));
|
||||
|
||||
this._load();
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.background = null;
|
||||
|
||||
this._cancellable.cancel();
|
||||
this._removeAnimationTimeout();
|
||||
|
||||
@ -298,12 +288,28 @@ var Background = new Lang.Class({
|
||||
if (this._settingsChangedSignalId != 0)
|
||||
this._settings.disconnect(this._settingsChangedSignalId);
|
||||
this._settingsChangedSignalId = 0;
|
||||
},
|
||||
|
||||
if (this._changedIdleId) {
|
||||
GLib.source_remove(this._changedIdleId);
|
||||
this._changedIdleId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_emitChangedSignal() {
|
||||
if (this._changedIdleId)
|
||||
return;
|
||||
|
||||
this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
|
||||
this._changedIdleId = 0;
|
||||
this.emit('changed');
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
updateResolution() {
|
||||
if (this._animation)
|
||||
this._refreshAnimation();
|
||||
},
|
||||
}
|
||||
|
||||
_refreshAnimation() {
|
||||
if (!this._animation)
|
||||
@ -311,7 +317,7 @@ var Background = new Lang.Class({
|
||||
|
||||
this._removeAnimationTimeout();
|
||||
this._updateAnimation();
|
||||
},
|
||||
}
|
||||
|
||||
_setLoaded() {
|
||||
if (this.isLoaded)
|
||||
@ -324,7 +330,7 @@ var Background = new Lang.Class({
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
|
||||
},
|
||||
}
|
||||
|
||||
_loadPattern() {
|
||||
let colorString, res, color, secondColor;
|
||||
@ -340,7 +346,7 @@ var Background = new Lang.Class({
|
||||
this.background.set_color(color);
|
||||
else
|
||||
this.background.set_gradient(shadingType, color, secondColor);
|
||||
},
|
||||
}
|
||||
|
||||
_watchFile(file) {
|
||||
let key = file.hash();
|
||||
@ -353,18 +359,18 @@ var Background = new Lang.Class({
|
||||
if (changedFile.equal(file)) {
|
||||
let imageCache = Meta.BackgroundImageCache.get_default();
|
||||
imageCache.purge(changedFile);
|
||||
this.emit('changed');
|
||||
this._emitChangedSignal();
|
||||
}
|
||||
});
|
||||
this._fileWatches[key] = signalId;
|
||||
},
|
||||
}
|
||||
|
||||
_removeAnimationTimeout() {
|
||||
if (this._updateAnimationTimeoutId) {
|
||||
GLib.source_remove(this._updateAnimationTimeoutId);
|
||||
this._updateAnimationTimeoutId = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateAnimation() {
|
||||
this._updateAnimationTimeoutId = 0;
|
||||
@ -404,7 +410,7 @@ var Background = new Lang.Class({
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_queueUpdateAnimation() {
|
||||
if (this._updateAnimationTimeoutId != 0)
|
||||
@ -426,14 +432,14 @@ var Background = new Lang.Class({
|
||||
return;
|
||||
|
||||
this._updateAnimationTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
|
||||
interval,
|
||||
() => {
|
||||
this._updateAnimationTimeoutId = 0;
|
||||
this._updateAnimation();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
interval,
|
||||
() => {
|
||||
this._updateAnimationTimeoutId = 0;
|
||||
this._updateAnimation();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
|
||||
},
|
||||
}
|
||||
|
||||
_loadAnimation(file) {
|
||||
this._cache.getAnimation({ file: file,
|
||||
@ -450,7 +456,7 @@ var Background = new Lang.Class({
|
||||
this._watchFile(file);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_loadImage(file) {
|
||||
this.background.set_file(file, this._style);
|
||||
@ -458,22 +464,22 @@ var Background = new Lang.Class({
|
||||
|
||||
let cache = Meta.BackgroundImageCache.get_default();
|
||||
let image = cache.load(file);
|
||||
if (image.is_loaded())
|
||||
if (image.is_loaded()) {
|
||||
this._setLoaded();
|
||||
else {
|
||||
} else {
|
||||
let id = image.connect('loaded', () => {
|
||||
this._setLoaded();
|
||||
image.disconnect(id);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_loadFile(file) {
|
||||
if (file.get_basename().endsWith('.xml'))
|
||||
this._loadAnimation(file);
|
||||
else
|
||||
this._loadImage(file);
|
||||
},
|
||||
}
|
||||
|
||||
_load() {
|
||||
this._cache = getBackgroundCache();
|
||||
@ -486,16 +492,14 @@ var Background = new Lang.Class({
|
||||
}
|
||||
|
||||
this._loadFile(this._file);
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Background.prototype);
|
||||
|
||||
let _systemBackground;
|
||||
|
||||
var SystemBackground = new Lang.Class({
|
||||
Name: 'SystemBackground',
|
||||
|
||||
_init() {
|
||||
var SystemBackground = class SystemBackground {
|
||||
constructor() {
|
||||
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
|
||||
|
||||
if (_systemBackground == null) {
|
||||
@ -524,14 +528,12 @@ var SystemBackground = new Lang.Class({
|
||||
image = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(SystemBackground.prototype);
|
||||
|
||||
var BackgroundSource = new Lang.Class({
|
||||
Name: 'BackgroundSource',
|
||||
|
||||
_init(layoutManager, settingsSchema) {
|
||||
var BackgroundSource = class BackgroundSource {
|
||||
constructor(layoutManager, settingsSchema) {
|
||||
// Allow override the background image setting for performance testing
|
||||
this._layoutManager = layoutManager;
|
||||
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
|
||||
@ -542,7 +544,7 @@ var BackgroundSource = new Lang.Class({
|
||||
this._monitorsChangedId =
|
||||
monitorManager.connect('monitors-changed',
|
||||
this._onMonitorsChanged.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onMonitorsChanged() {
|
||||
for (let monitorIndex in this._backgrounds) {
|
||||
@ -556,7 +558,7 @@ var BackgroundSource = new Lang.Class({
|
||||
delete this._backgrounds[monitorIndex];
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getBackground(monitorIndex) {
|
||||
let file = null;
|
||||
@ -603,7 +605,7 @@ var BackgroundSource = new Lang.Class({
|
||||
}
|
||||
|
||||
return this._backgrounds[monitorIndex];
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
let monitorManager = Meta.MonitorManager.get();
|
||||
@ -617,12 +619,10 @@ var BackgroundSource = new Lang.Class({
|
||||
|
||||
this._backgrounds = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Animation = new Lang.Class({
|
||||
Name: 'Animation',
|
||||
|
||||
_init(params) {
|
||||
var Animation = class Animation {
|
||||
constructor(params) {
|
||||
params = Params.parse(params, { file: null });
|
||||
|
||||
this.file = params.file;
|
||||
@ -630,7 +630,7 @@ var Animation = new Lang.Class({
|
||||
this.transitionProgress = 0.0;
|
||||
this.transitionDuration = 0.0;
|
||||
this.loaded = false;
|
||||
},
|
||||
}
|
||||
|
||||
load(callback) {
|
||||
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
|
||||
@ -640,7 +640,7 @@ var Animation = new Lang.Class({
|
||||
if (callback)
|
||||
callback();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
update(monitor) {
|
||||
this.keyFrameFiles = [];
|
||||
@ -661,14 +661,12 @@ var Animation = new Lang.Class({
|
||||
|
||||
if (filename2)
|
||||
this.keyFrameFiles.push(Gio.File.new_for_path(filename2));
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Animation.prototype);
|
||||
|
||||
var BackgroundManager = new Lang.Class({
|
||||
Name: 'BackgroundManager',
|
||||
|
||||
_init(params) {
|
||||
var BackgroundManager = class BackgroundManager {
|
||||
constructor(params) {
|
||||
params = Params.parse(params, { container: null,
|
||||
layoutManager: Main.layoutManager,
|
||||
monitorIndex: null,
|
||||
@ -688,7 +686,7 @@ var BackgroundManager = new Lang.Class({
|
||||
|
||||
this.backgroundActor = this._createBackgroundActor();
|
||||
this._newBackgroundActor = null;
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
let cache = getBackgroundCache();
|
||||
@ -704,7 +702,7 @@ var BackgroundManager = new Lang.Class({
|
||||
this.backgroundActor.destroy();
|
||||
this.backgroundActor = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_swapBackgroundActor() {
|
||||
let oldBackgroundActor = this.backgroundActor;
|
||||
@ -717,11 +715,10 @@ var BackgroundManager = new Lang.Class({
|
||||
time: FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete() {
|
||||
oldBackgroundActor.background.run_dispose();
|
||||
oldBackgroundActor.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_updateBackgroundActor() {
|
||||
if (this._newBackgroundActor) {
|
||||
@ -750,7 +747,7 @@ var BackgroundManager = new Lang.Class({
|
||||
this._swapBackgroundActor();
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_createBackgroundActor() {
|
||||
let background = this._backgroundSource.getBackground(this._monitorIndex);
|
||||
@ -764,10 +761,8 @@ var BackgroundManager = new Lang.Class({
|
||||
|
||||
this._container.add_child(backgroundActor);
|
||||
|
||||
let monitor = this._layoutManager.monitors[this._monitorIndex];
|
||||
|
||||
backgroundActor.set_size(monitor.width, monitor.height);
|
||||
if (this._controlPosition) {
|
||||
let monitor = this._layoutManager.monitors[this._monitorIndex];
|
||||
backgroundActor.set_position(monitor.x, monitor.y);
|
||||
backgroundActor.lower_bottom();
|
||||
}
|
||||
@ -787,6 +782,6 @@ var BackgroundManager = new Lang.Class({
|
||||
});
|
||||
|
||||
return backgroundActor;
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(BackgroundManager.prototype);
|
||||
|
@ -1,20 +1,14 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { Clutter, St } = imports.gi;
|
||||
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const Main = imports.ui.main;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
var BackgroundMenu = new Lang.Class({
|
||||
Name: 'BackgroundMenu',
|
||||
Extends: PopupMenu.PopupMenu,
|
||||
|
||||
_init(layoutManager) {
|
||||
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
|
||||
var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
|
||||
constructor(layoutManager) {
|
||||
super(layoutManager.dummyCursor, 0, St.Side.TOP);
|
||||
|
||||
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
@ -26,12 +20,12 @@ var BackgroundMenu = new Lang.Class({
|
||||
layoutManager.uiGroup.add_actor(this.actor);
|
||||
this.actor.hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function addBackgroundMenu(actor, layoutManager) {
|
||||
actor.reactive = true;
|
||||
actor._backgroundMenu = new BackgroundMenu(layoutManager);
|
||||
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
|
||||
actor._backgroundManager = new PopupMenu.PopupMenuManager(actor);
|
||||
actor._backgroundManager.addMenu(actor._backgroundMenu);
|
||||
|
||||
function openMenu(x, y) {
|
||||
|
@ -1,16 +1,10 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Atk = imports.gi.Atk;
|
||||
const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const { Atk, Clutter, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
var BarLevel = new Lang.Class({
|
||||
Name: "BarLevel",
|
||||
|
||||
_init(value, params) {
|
||||
var BarLevel = class {
|
||||
constructor(value, params) {
|
||||
if (isNaN(value))
|
||||
// Avoid spreading NaNs around
|
||||
throw TypeError('The bar level value must be a number');
|
||||
@ -20,7 +14,7 @@ var BarLevel = new Lang.Class({
|
||||
this._barLevelWidth = 0;
|
||||
|
||||
if (params == undefined)
|
||||
params = {}
|
||||
params = {};
|
||||
|
||||
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
|
||||
can_focus: params['canFocus'] || false,
|
||||
@ -40,7 +34,7 @@ var BarLevel = new Lang.Class({
|
||||
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
|
||||
|
||||
this.connect('value-changed', this._valueChanged.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
setValue(value) {
|
||||
if (isNaN(value))
|
||||
@ -48,7 +42,7 @@ var BarLevel = new Lang.Class({
|
||||
|
||||
this._value = Math.max(Math.min(value, this._maxValue), 0);
|
||||
this.actor.queue_repaint();
|
||||
},
|
||||
}
|
||||
|
||||
setMaximumValue(value) {
|
||||
if (isNaN(value))
|
||||
@ -57,7 +51,7 @@ var BarLevel = new Lang.Class({
|
||||
this._maxValue = Math.max(value, 1);
|
||||
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
|
||||
this.actor.queue_repaint();
|
||||
},
|
||||
}
|
||||
|
||||
setOverdriveStart(value) {
|
||||
if (isNaN(value))
|
||||
@ -69,7 +63,7 @@ var BarLevel = new Lang.Class({
|
||||
this._overdriveStart = value;
|
||||
this._value = Math.max(Math.min(value, this._maxValue), 0);
|
||||
this.actor.queue_repaint();
|
||||
},
|
||||
}
|
||||
|
||||
_barLevelRepaint(area) {
|
||||
let cr = area.get_context();
|
||||
@ -111,7 +105,7 @@ var BarLevel = new Lang.Class({
|
||||
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
|
||||
|
||||
/* background bar */
|
||||
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
|
||||
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
|
||||
cr.lineTo(endX, (height + barLevelHeight) / 2);
|
||||
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
||||
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
|
||||
@ -123,11 +117,12 @@ var BarLevel = new Lang.Class({
|
||||
|
||||
/* normal progress bar */
|
||||
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
|
||||
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
|
||||
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (1 / 4), TAU * (3 / 4));
|
||||
cr.lineTo(x, (height - barLevelHeight) / 2);
|
||||
cr.lineTo(x, (height + barLevelHeight) / 2);
|
||||
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
|
||||
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
||||
if (this._value > 0)
|
||||
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
||||
cr.fillPreserve();
|
||||
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
|
||||
cr.setLineWidth(barLevelBorderWidth);
|
||||
@ -149,17 +144,19 @@ var BarLevel = new Lang.Class({
|
||||
}
|
||||
|
||||
/* end progress bar arc */
|
||||
if (this._value <= this._overdriveStart)
|
||||
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
||||
else
|
||||
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
|
||||
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
|
||||
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
|
||||
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
|
||||
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
||||
cr.fillPreserve();
|
||||
cr.setLineWidth(barLevelBorderWidth);
|
||||
cr.stroke();
|
||||
if (this._value > 0) {
|
||||
if (this._value <= this._overdriveStart)
|
||||
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
|
||||
else
|
||||
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
|
||||
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
|
||||
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
|
||||
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
|
||||
cr.lineTo(endX, (height - barLevelHeight) / 2);
|
||||
cr.fillPreserve();
|
||||
cr.setLineWidth(barLevelBorderWidth);
|
||||
cr.stroke();
|
||||
}
|
||||
|
||||
/* draw overdrive separator */
|
||||
if (overdriveActive) {
|
||||
@ -176,35 +173,34 @@ var BarLevel = new Lang.Class({
|
||||
}
|
||||
|
||||
cr.$dispose();
|
||||
},
|
||||
}
|
||||
|
||||
_getCurrentValue(actor) {
|
||||
return this._value;
|
||||
},
|
||||
}
|
||||
|
||||
_getOverdriveStart(actor) {
|
||||
return this._overdriveStart;
|
||||
},
|
||||
}
|
||||
|
||||
_getMinimumValue(actor) {
|
||||
return 0;
|
||||
},
|
||||
}
|
||||
|
||||
_getMaximumValue(actor) {
|
||||
return this._maxValue;
|
||||
},
|
||||
}
|
||||
|
||||
_setCurrentValue(actor, value) {
|
||||
this._value = value;
|
||||
},
|
||||
}
|
||||
|
||||
_valueChanged(barLevel, value, property) {
|
||||
this._customAccessible.notify("accessible-value");
|
||||
},
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(BarLevel.prototype);
|
||||
|
@ -1,11 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, GObject, Shell, St } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@ -29,18 +24,14 @@ var POPUP_ANIMATION_TIME = 0.15;
|
||||
* placed. The arrow position may be controlled via
|
||||
* setArrowOrigin(). The arrow side might be temporarily flipped
|
||||
* depending on the box size and source position to keep the box
|
||||
* totally inside the monitor if possible.
|
||||
* totally inside the monitor workarea if possible.
|
||||
*
|
||||
*/
|
||||
var BoxPointer = new Lang.Class({
|
||||
Name: 'BoxPointer',
|
||||
Extends: St.Widget,
|
||||
var BoxPointer = GObject.registerClass({
|
||||
Signals: { 'arrow-side-changed': {} },
|
||||
|
||||
}, class BoxPointer extends St.Widget {
|
||||
_init(arrowSide, binProperties) {
|
||||
this.parent();
|
||||
|
||||
this.actor = this;
|
||||
super._init();
|
||||
|
||||
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
||||
|
||||
@ -54,61 +45,36 @@ var BoxPointer = new Lang.Class({
|
||||
this._border.connect('repaint', this._drawBorder.bind(this));
|
||||
this.add_actor(this._border);
|
||||
this.bin.raise(this._border);
|
||||
this._xOffset = 0;
|
||||
this._yOffset = 0;
|
||||
this._xPosition = 0;
|
||||
this._yPosition = 0;
|
||||
this._sourceAlignment = 0.5;
|
||||
this._capturedEventId = 0;
|
||||
this._muteInput();
|
||||
},
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._sourceActorDestroyId) {
|
||||
this._sourceActor.disconnect(this._sourceActorDestroyId);
|
||||
delete this._sourceActorDestroyId;
|
||||
}
|
||||
}
|
||||
|
||||
get arrowSide() {
|
||||
return this._arrowSide;
|
||||
},
|
||||
}
|
||||
|
||||
_muteInput() {
|
||||
if (this._capturedEventId == 0)
|
||||
this._capturedEventId = this.connect('captured-event',
|
||||
() => Clutter.EVENT_STOP);
|
||||
},
|
||||
}
|
||||
|
||||
_unmuteInput() {
|
||||
if (this._capturedEventId != 0) {
|
||||
this.disconnect(this._capturedEventId);
|
||||
this._capturedEventId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
// BoxPointer.show() and BoxPointer.hide() are here for only compatibility
|
||||
// purposes, and will be removed in 3.32.
|
||||
show(animate, onComplete) {
|
||||
if (animate !== undefined) {
|
||||
try {
|
||||
throw new Error('BoxPointer.show() has been moved to BoxPointer.open(), this code will break in the future.');
|
||||
} catch(e) {
|
||||
logError(e);
|
||||
this.open(animate, onComplete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.visible = true;
|
||||
},
|
||||
|
||||
hide(animate, onComplete) {
|
||||
if (animate !== undefined) {
|
||||
try {
|
||||
throw new Error('BoxPointer.hide() has been moved to BoxPointer.close(), this code will break in the future.');
|
||||
} catch(e) {
|
||||
logError(e);
|
||||
this.close(animate, onComplete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
},
|
||||
}
|
||||
|
||||
open(animate, onComplete) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -124,24 +90,24 @@ var BoxPointer = new Lang.Class({
|
||||
|
||||
if (animate & PopupAnimation.SLIDE) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
this.yOffset = -rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
this.yOffset = rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
this.xOffset = -rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
this.xOffset = rise;
|
||||
break;
|
||||
case St.Side.TOP:
|
||||
this.translation_y = -rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
this.translation_y = rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
this.translation_x = -rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
this.translation_x = rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tweener.addTween(this, { opacity: 255,
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
translation_x: 0,
|
||||
translation_y: 0,
|
||||
transition: 'linear',
|
||||
onComplete: () => {
|
||||
this._unmuteInput();
|
||||
@ -149,14 +115,14 @@ var BoxPointer = new Lang.Class({
|
||||
onComplete();
|
||||
},
|
||||
time: animationTime });
|
||||
},
|
||||
}
|
||||
|
||||
close(animate, onComplete) {
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
let xOffset = 0;
|
||||
let yOffset = 0;
|
||||
let translationX = 0;
|
||||
let translationY = 0;
|
||||
let themeNode = this.get_theme_node();
|
||||
let rise = themeNode.get_length('-arrow-rise');
|
||||
let fade = (animate & PopupAnimation.FADE);
|
||||
@ -164,18 +130,18 @@ var BoxPointer = new Lang.Class({
|
||||
|
||||
if (animate & PopupAnimation.SLIDE) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
yOffset = rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
yOffset = -rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
xOffset = rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
xOffset = -rise;
|
||||
break;
|
||||
case St.Side.TOP:
|
||||
translationY = rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
translationY = -rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
translationX = rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
translationX = -rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,20 +149,20 @@ var BoxPointer = new Lang.Class({
|
||||
|
||||
Tweener.removeTweens(this);
|
||||
Tweener.addTween(this, { opacity: fade ? 0 : 255,
|
||||
xOffset: xOffset,
|
||||
yOffset: yOffset,
|
||||
translation_x: translationX,
|
||||
translation_y: translationY,
|
||||
transition: 'linear',
|
||||
time: animationTime,
|
||||
onComplete: () => {
|
||||
this.hide();
|
||||
this.opacity = 0;
|
||||
this.xOffset = 0;
|
||||
this.yOffset = 0;
|
||||
this.translation_x = 0;
|
||||
this.translation_y = 0;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_adjustAllocationForArrow(isWidth, minSize, natSize) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -211,7 +177,7 @@ var BoxPointer = new Lang.Class({
|
||||
}
|
||||
|
||||
return [minSize, natSize];
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -221,7 +187,7 @@ var BoxPointer = new Lang.Class({
|
||||
width = this._adjustAllocationForArrow(true, ...width);
|
||||
|
||||
return themeNode.adjust_preferred_width(...width);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -232,19 +198,16 @@ var BoxPointer = new Lang.Class({
|
||||
height = this._adjustAllocationForArrow(false, ...height);
|
||||
|
||||
return themeNode.adjust_preferred_height(...height);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
this.set_allocation(box, flags);
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
box = themeNode.get_content_box(box);
|
||||
|
||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||
let rise = themeNode.get_length('-arrow-rise');
|
||||
let childBox = new Clutter.ActorBox();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
let [availWidth, availHeight] = themeNode.get_content_box(box).get_size();
|
||||
|
||||
childBox.x1 = 0;
|
||||
childBox.y1 = 0;
|
||||
@ -257,26 +220,27 @@ var BoxPointer = new Lang.Class({
|
||||
childBox.x2 = availWidth - borderWidth;
|
||||
childBox.y2 = availHeight - borderWidth;
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
childBox.y1 += rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
childBox.y2 -= rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
childBox.x1 += rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
childBox.x2 -= rise;
|
||||
break;
|
||||
case St.Side.TOP:
|
||||
childBox.y1 += rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
childBox.y2 -= rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
childBox.x1 += rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
childBox.x2 -= rise;
|
||||
break;
|
||||
}
|
||||
this.bin.allocate(childBox, flags);
|
||||
|
||||
if (this._sourceActor && this._sourceActor.mapped) {
|
||||
this._reposition();
|
||||
this._updateFlip();
|
||||
this._reposition(box);
|
||||
this._updateFlip(box);
|
||||
this.set_allocation(box, flags);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_drawBorder(area) {
|
||||
let themeNode = this.get_theme_node();
|
||||
@ -300,7 +264,7 @@ var BoxPointer = new Lang.Class({
|
||||
let borderRadius = themeNode.get_length('-arrow-border-radius');
|
||||
|
||||
let halfBorder = borderWidth / 2;
|
||||
let halfBase = Math.floor(base/2);
|
||||
let halfBase = Math.floor(base / 2);
|
||||
|
||||
let backgroundColor = themeNode.get_color('-arrow-background-color');
|
||||
|
||||
@ -381,7 +345,7 @@ var BoxPointer = new Lang.Class({
|
||||
if (!skipTopRight) {
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
|
||||
3*Math.PI/2, Math.PI*2);
|
||||
3 * Math.PI / 2, Math.PI * 2);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.RIGHT && rise) {
|
||||
@ -402,7 +366,7 @@ var BoxPointer = new Lang.Class({
|
||||
if (!skipBottomRight) {
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
|
||||
0, Math.PI/2);
|
||||
0, Math.PI / 2);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.BOTTOM && rise) {
|
||||
@ -423,7 +387,7 @@ var BoxPointer = new Lang.Class({
|
||||
if (!skipBottomLeft) {
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
|
||||
Math.PI/2, Math.PI);
|
||||
Math.PI / 2, Math.PI);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.LEFT && rise) {
|
||||
@ -432,7 +396,7 @@ var BoxPointer = new Lang.Class({
|
||||
cr.lineTo(x1 - rise, y1);
|
||||
cr.lineTo(x1 + borderRadius, y1);
|
||||
} else if (skipBottomLeft) {
|
||||
cr.lineTo(x1 - rise, y2)
|
||||
cr.lineTo(x1 - rise, y2);
|
||||
cr.lineTo(x1 - rise, y2 - halfBase);
|
||||
} else {
|
||||
cr.lineTo(x1, this._arrowOrigin + halfBase);
|
||||
@ -444,7 +408,7 @@ var BoxPointer = new Lang.Class({
|
||||
if (!skipTopLeft) {
|
||||
cr.lineTo(x1, y1 + borderRadius);
|
||||
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
|
||||
Math.PI, 3*Math.PI/2);
|
||||
Math.PI, 3 * Math.PI / 2);
|
||||
}
|
||||
|
||||
Clutter.cairo_set_source_color(cr, backgroundColor);
|
||||
@ -458,19 +422,29 @@ var BoxPointer = new Lang.Class({
|
||||
}
|
||||
|
||||
cr.$dispose();
|
||||
},
|
||||
}
|
||||
|
||||
setPosition(sourceActor, alignment) {
|
||||
// We need to show it now to force an allocation,
|
||||
// so that we can query the correct size.
|
||||
this.show();
|
||||
if (!this._sourceActor || sourceActor != this._sourceActor) {
|
||||
if (this._sourceActorDestroyId) {
|
||||
this._sourceActor.disconnect(this._sourceActorDestroyId);
|
||||
delete this._sourceActorDestroyId;
|
||||
}
|
||||
|
||||
this._sourceActor = sourceActor;
|
||||
|
||||
if (this._sourceActor) {
|
||||
this._sourceActorDestroyId = this._sourceActor.connect('destroy', () => {
|
||||
this._sourceActor = null;
|
||||
delete this._sourceActorDestroyId;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._sourceActor = sourceActor;
|
||||
this._arrowAlignment = alignment;
|
||||
|
||||
this._reposition();
|
||||
this._updateFlip();
|
||||
},
|
||||
this.queue_relayout();
|
||||
}
|
||||
|
||||
setSourceAlignment(alignment) {
|
||||
this._sourceAlignment = alignment;
|
||||
@ -479,16 +453,20 @@ var BoxPointer = new Lang.Class({
|
||||
return;
|
||||
|
||||
this.setPosition(this._sourceActor, this._arrowAlignment);
|
||||
},
|
||||
}
|
||||
|
||||
_reposition() {
|
||||
_reposition(allocationBox) {
|
||||
let sourceActor = this._sourceActor;
|
||||
let alignment = this._arrowAlignment;
|
||||
let monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
|
||||
|
||||
this._sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||
this._workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
|
||||
|
||||
// Position correctly relative to the sourceActor
|
||||
let sourceNode = sourceActor.get_theme_node();
|
||||
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
|
||||
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||
let sourceAllocation = this._sourceAllocation;
|
||||
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
|
||||
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
|
||||
@ -496,7 +474,7 @@ var BoxPointer = new Lang.Class({
|
||||
// We also want to keep it onscreen, and separated from the
|
||||
// edge by the same distance as the main part of the box is
|
||||
// separated from its sourceActor
|
||||
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
|
||||
let workarea = this._workArea;
|
||||
let themeNode = this.get_theme_node();
|
||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||
let arrowBase = themeNode.get_length('-arrow-base');
|
||||
@ -535,7 +513,7 @@ var BoxPointer = new Lang.Class({
|
||||
// of the box to maintain the arrow's accuracy.
|
||||
|
||||
let arrowOrigin;
|
||||
let halfBase = Math.floor(arrowBase/2);
|
||||
let halfBase = Math.floor(arrowBase / 2);
|
||||
let halfBorder = borderWidth / 2;
|
||||
let halfMargin = margin / 2;
|
||||
let [x1, y1] = [halfBorder, halfBorder];
|
||||
@ -546,8 +524,8 @@ var BoxPointer = new Lang.Class({
|
||||
case St.Side.BOTTOM:
|
||||
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
|
||||
|
||||
resX = Math.max(resX, monitor.x + padding);
|
||||
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
|
||||
resX = Math.max(resX, workarea.x + padding);
|
||||
resX = Math.min(resX, workarea.x + workarea.width - (padding + natWidth));
|
||||
|
||||
arrowOrigin = sourceCenterX - resX;
|
||||
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
|
||||
@ -565,8 +543,8 @@ var BoxPointer = new Lang.Class({
|
||||
case St.Side.RIGHT:
|
||||
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
|
||||
|
||||
resY = Math.max(resY, monitor.y + padding);
|
||||
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
|
||||
resY = Math.max(resY, workarea.y + padding);
|
||||
resY = Math.min(resY, workarea.y + workarea.height - (padding + natHeight));
|
||||
|
||||
arrowOrigin = sourceCenterY - resY;
|
||||
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
|
||||
@ -590,10 +568,9 @@ var BoxPointer = new Lang.Class({
|
||||
parent = parent.get_parent();
|
||||
}
|
||||
|
||||
this._xPosition = Math.floor(x);
|
||||
this._yPosition = Math.floor(y);
|
||||
this._shiftActor();
|
||||
},
|
||||
// Actually set the position
|
||||
allocationBox.set_origin(Math.floor(x), Math.floor(y));
|
||||
}
|
||||
|
||||
// @origin: Coordinate specifying middle of the arrow, along
|
||||
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
|
||||
@ -603,7 +580,7 @@ var BoxPointer = new Lang.Class({
|
||||
this._arrowOrigin = origin;
|
||||
this._border.queue_repaint();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// @actor: an actor relative to which the arrow is positioned.
|
||||
// Differently from setPosition, this will not move the boxpointer itself,
|
||||
@ -613,95 +590,59 @@ var BoxPointer = new Lang.Class({
|
||||
this._arrowActor = actor;
|
||||
this._border.queue_repaint();
|
||||
}
|
||||
},
|
||||
|
||||
_shiftActor() {
|
||||
// Since the position of the BoxPointer depends on the allocated size
|
||||
// of the BoxPointer and the position of the source actor, trying
|
||||
// to position the BoxPointer via the x/y properties will result in
|
||||
// allocation loops and warnings. Instead we do the positioning via
|
||||
// the anchor point, which is independent of allocation, and leave
|
||||
// x == y == 0.
|
||||
this.set_anchor_point(-(this._xPosition + this._xOffset),
|
||||
-(this._yPosition + this._yOffset));
|
||||
},
|
||||
}
|
||||
|
||||
_calculateArrowSide(arrowSide) {
|
||||
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
|
||||
let sourceAllocation = this._sourceAllocation;
|
||||
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
|
||||
let monitorActor = this.sourceActor;
|
||||
if (!monitorActor)
|
||||
monitorActor = this;
|
||||
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
|
||||
let workarea = this._workArea;
|
||||
|
||||
switch (arrowSide) {
|
||||
case St.Side.TOP:
|
||||
if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
|
||||
boxHeight < sourceAllocation.y1 - monitor.y)
|
||||
if (sourceAllocation.y2 + boxHeight > workarea.y + workarea.height &&
|
||||
boxHeight < sourceAllocation.y1 - workarea.y)
|
||||
return St.Side.BOTTOM;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
if (sourceAllocation.y1 - boxHeight < monitor.y &&
|
||||
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
|
||||
if (sourceAllocation.y1 - boxHeight < workarea.y &&
|
||||
boxHeight < workarea.y + workarea.height - sourceAllocation.y2)
|
||||
return St.Side.TOP;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
|
||||
boxWidth < sourceAllocation.x1 - monitor.x)
|
||||
if (sourceAllocation.x2 + boxWidth > workarea.x + workarea.width &&
|
||||
boxWidth < sourceAllocation.x1 - workarea.x)
|
||||
return St.Side.RIGHT;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
if (sourceAllocation.x1 - boxWidth < monitor.x &&
|
||||
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
|
||||
if (sourceAllocation.x1 - boxWidth < workarea.x &&
|
||||
boxWidth < workarea.x + workarea.width - sourceAllocation.x2)
|
||||
return St.Side.LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
return arrowSide;
|
||||
},
|
||||
}
|
||||
|
||||
_updateFlip() {
|
||||
_updateFlip(allocationBox) {
|
||||
let arrowSide = this._calculateArrowSide(this._userArrowSide);
|
||||
if (this._arrowSide != arrowSide) {
|
||||
this._arrowSide = arrowSide;
|
||||
this._reposition();
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this.queue_relayout();
|
||||
return false;
|
||||
});
|
||||
this._reposition(allocationBox);
|
||||
|
||||
this.emit('arrow-side-changed');
|
||||
}
|
||||
},
|
||||
|
||||
set xOffset(offset) {
|
||||
this._xOffset = offset;
|
||||
this._shiftActor();
|
||||
},
|
||||
|
||||
get xOffset() {
|
||||
return this._xOffset;
|
||||
},
|
||||
|
||||
set yOffset(offset) {
|
||||
this._yOffset = offset;
|
||||
this._shiftActor();
|
||||
},
|
||||
|
||||
get yOffset() {
|
||||
return this._yOffset;
|
||||
},
|
||||
}
|
||||
|
||||
updateArrowSide(side) {
|
||||
this._arrowSide = side;
|
||||
this._border.queue_repaint();
|
||||
|
||||
this.emit('arrow-side-changed');
|
||||
},
|
||||
}
|
||||
|
||||
getPadding(side) {
|
||||
return this.bin.get_theme_node().get_padding(side);
|
||||
},
|
||||
}
|
||||
|
||||
getArrowHeight() {
|
||||
return this.get_theme_node().get_length('-arrow-rise');
|
||||
|
@ -1,13 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageList = imports.ui.messageList;
|
||||
@ -15,13 +9,15 @@ const MessageTray = imports.ui.messageTray;
|
||||
const Mpris = imports.ui.mpris;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
var MSECS_IN_DAY = 24 * 60 * 60 * 1000;
|
||||
var SHOW_WEEKDATE_KEY = 'show-weekdate';
|
||||
var ELLIPSIS_CHAR = '\u2026';
|
||||
|
||||
var MESSAGE_ICON_SIZE = -1; // pick up from CSS
|
||||
|
||||
var NC_ = (context, str) => context + '\u0004' + str;
|
||||
var NC_ = (context, str) => `${context}\u0004${str}`;
|
||||
|
||||
function sameYear(dateA, dateB) {
|
||||
return (dateA.getYear() == dateB.getYear());
|
||||
@ -42,7 +38,7 @@ function isToday(date) {
|
||||
function _isWorkDay(date) {
|
||||
/* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */
|
||||
let days = C_('calendar-no-work', "06");
|
||||
return days.indexOf(date.getDay().toString()) == -1;
|
||||
return !days.includes(date.getDay().toString());
|
||||
}
|
||||
|
||||
function _getBeginningOfDay(date) {
|
||||
@ -89,64 +85,45 @@ function _getCalendarDayAbbreviation(dayNumber) {
|
||||
|
||||
// Abstraction for an appointment/event in a calendar
|
||||
|
||||
var CalendarEvent = new Lang.Class({
|
||||
Name: 'CalendarEvent',
|
||||
|
||||
_init(id, date, end, summary, allDay) {
|
||||
var CalendarEvent = class CalendarEvent {
|
||||
constructor(id, date, end, summary, allDay) {
|
||||
this.id = id;
|
||||
this.date = date;
|
||||
this.end = end;
|
||||
this.summary = summary;
|
||||
this.allDay = allDay;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Interface for appointments/events - e.g. the contents of a calendar
|
||||
//
|
||||
|
||||
// First, an implementation with no events
|
||||
var EmptyEventSource = new Lang.Class({
|
||||
Name: 'EmptyEventSource',
|
||||
|
||||
_init() {
|
||||
var EmptyEventSource = class EmptyEventSource {
|
||||
constructor() {
|
||||
this.isLoading = false;
|
||||
this.isDummy = true;
|
||||
this.hasCalendars = false;
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
},
|
||||
|
||||
ignoreEvent(event) {
|
||||
},
|
||||
}
|
||||
|
||||
requestRange(begin, end) {
|
||||
},
|
||||
}
|
||||
|
||||
getEvents(begin, end) {
|
||||
let result = [];
|
||||
return result;
|
||||
},
|
||||
}
|
||||
|
||||
hasEvents(day) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(EmptyEventSource.prototype);
|
||||
|
||||
const CalendarServerIface = `
|
||||
<node>
|
||||
<interface name="org.gnome.Shell.CalendarServer">
|
||||
<method name="GetEvents">
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="a(sssbxxa{sv})" direction="out" />
|
||||
</method>
|
||||
<property name="HasCalendars" type="b" access="read" />
|
||||
<signal name="Changed" />
|
||||
</interface>
|
||||
</node>`;
|
||||
const CalendarServerIface = loadInterfaceXML('org.gnome.Shell.CalendarServer');
|
||||
|
||||
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
|
||||
|
||||
@ -166,8 +143,7 @@ function _datesEqual(a, b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function _dateIntervalsOverlap(a0, a1, b0, b1)
|
||||
{
|
||||
function _dateIntervalsOverlap(a0, a1, b0, b1) {
|
||||
if (a1 <= b0)
|
||||
return false;
|
||||
else if (b1 <= a0)
|
||||
@ -177,22 +153,12 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
|
||||
}
|
||||
|
||||
// an implementation that reads data from a session bus service
|
||||
var DBusEventSource = new Lang.Class({
|
||||
Name: 'DBusEventSource',
|
||||
|
||||
_init() {
|
||||
var DBusEventSource = class DBusEventSource {
|
||||
constructor() {
|
||||
this._resetCache();
|
||||
this.isLoading = false;
|
||||
this.isDummy = false;
|
||||
|
||||
this._ignoredEvents = new Map();
|
||||
|
||||
let savedState = global.get_persistent_state('as', 'ignored_events');
|
||||
if (savedState)
|
||||
savedState.deep_unpack().forEach(eventId => {
|
||||
this._ignoredEvents.set(eventId, true);
|
||||
});
|
||||
|
||||
this._initialized = false;
|
||||
this._dbusProxy = new CalendarServer();
|
||||
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
|
||||
@ -201,7 +167,7 @@ var DBusEventSource = new Lang.Class({
|
||||
try {
|
||||
this._dbusProxy.init_finish(result);
|
||||
loaded = true;
|
||||
} catch(e) {
|
||||
} 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
|
||||
@ -211,7 +177,7 @@ var DBusEventSource = new Lang.Class({
|
||||
// about the HasCalendars property and would cause an exception trying
|
||||
// to read it)
|
||||
} else {
|
||||
log('Error loading calendars: ' + e.message);
|
||||
log(`Error loading calendars: ${e.message}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -235,39 +201,39 @@ var DBusEventSource = new Lang.Class({
|
||||
this._onNameAppeared();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._dbusProxy.run_dispose();
|
||||
},
|
||||
}
|
||||
|
||||
get hasCalendars() {
|
||||
if (this._initialized)
|
||||
return this._dbusProxy.HasCalendars;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
_resetCache() {
|
||||
this._events = [];
|
||||
this._lastRequestBegin = null;
|
||||
this._lastRequestEnd = null;
|
||||
},
|
||||
}
|
||||
|
||||
_onNameAppeared(owner) {
|
||||
this._initialized = true;
|
||||
this._resetCache();
|
||||
this._loadEvents(true);
|
||||
},
|
||||
}
|
||||
|
||||
_onNameVanished(oldOwner) {
|
||||
this._resetCache();
|
||||
this.emit('changed');
|
||||
},
|
||||
}
|
||||
|
||||
_onChanged() {
|
||||
this._loadEvents(false);
|
||||
},
|
||||
}
|
||||
|
||||
_onEventsReceived(results, error) {
|
||||
let newEvents = [];
|
||||
@ -289,31 +255,21 @@ var DBusEventSource = new Lang.Class({
|
||||
this._events = newEvents;
|
||||
this.isLoading = false;
|
||||
this.emit('changed');
|
||||
},
|
||||
}
|
||||
|
||||
_loadEvents(forceReload) {
|
||||
// Ignore while loading
|
||||
if (!this._initialized)
|
||||
return;
|
||||
|
||||
if (this._curRequestBegin && this._curRequestEnd){
|
||||
if (this._curRequestBegin && this._curRequestEnd) {
|
||||
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload,
|
||||
this._onEventsReceived.bind(this),
|
||||
Gio.DBusCallFlags.NONE);
|
||||
}
|
||||
},
|
||||
|
||||
ignoreEvent(event) {
|
||||
if (this._ignoredEvents.get(event.id))
|
||||
return;
|
||||
|
||||
this._ignoredEvents.set(event.id, true);
|
||||
let savedState = new GLib.Variant('as', [...this._ignoredEvents.keys()]);
|
||||
global.set_persistent_state('ignored_events', savedState);
|
||||
this.emit('changed');
|
||||
},
|
||||
}
|
||||
|
||||
requestRange(begin, end) {
|
||||
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
|
||||
@ -324,16 +280,13 @@ var DBusEventSource = new Lang.Class({
|
||||
this._curRequestEnd = end;
|
||||
this._loadEvents(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getEvents(begin, end) {
|
||||
let result = [];
|
||||
for(let n = 0; n < this._events.length; n++) {
|
||||
for (let n = 0; n < this._events.length; n++) {
|
||||
let event = this._events[n];
|
||||
|
||||
if (this._ignoredEvents.has(event.id))
|
||||
continue;
|
||||
|
||||
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
|
||||
result.push(event);
|
||||
}
|
||||
@ -345,7 +298,7 @@ var DBusEventSource = new Lang.Class({
|
||||
return d1.getTime() - d2.getTime();
|
||||
});
|
||||
return result;
|
||||
},
|
||||
}
|
||||
|
||||
hasEvents(day) {
|
||||
let dayBegin = _getBeginningOfDay(day);
|
||||
@ -358,17 +311,15 @@ var DBusEventSource = new Lang.Class({
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(DBusEventSource.prototype);
|
||||
|
||||
var Calendar = new Lang.Class({
|
||||
Name: 'Calendar',
|
||||
|
||||
_init() {
|
||||
var Calendar = class Calendar {
|
||||
constructor() {
|
||||
this._weekStart = Shell.util_get_week_start();
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
|
||||
|
||||
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, this._onSettingsChange.bind(this));
|
||||
this._settings.connect(`changed::${SHOW_WEEKDATE_KEY}`, this._onSettingsChange.bind(this));
|
||||
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
|
||||
|
||||
/**
|
||||
@ -402,7 +353,7 @@ var Calendar = new Lang.Class({
|
||||
this._onScroll.bind(this));
|
||||
|
||||
this._buildHeader ();
|
||||
},
|
||||
}
|
||||
|
||||
// @eventSource: is an object implementing the EventSource API, e.g. the
|
||||
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
|
||||
@ -414,7 +365,7 @@ var Calendar = new Lang.Class({
|
||||
});
|
||||
this._rebuildCalendar();
|
||||
this._update();
|
||||
},
|
||||
}
|
||||
|
||||
// Sets the calendar to show a specific date
|
||||
setDate(date) {
|
||||
@ -424,14 +375,14 @@ var Calendar = new Lang.Class({
|
||||
this._selectedDate = date;
|
||||
this._update();
|
||||
this.emit('selected-date-changed', new Date(this._selectedDate));
|
||||
},
|
||||
}
|
||||
|
||||
updateTimeZone() {
|
||||
// The calendar need to be rebuilt after a time zone update because
|
||||
// the date might have changed.
|
||||
this._rebuildCalendar();
|
||||
this._update();
|
||||
},
|
||||
}
|
||||
|
||||
_buildHeader() {
|
||||
let layout = this.actor.layout_manager;
|
||||
@ -450,8 +401,8 @@ var Calendar = new Lang.Class({
|
||||
this._topBox.add(this._backButton);
|
||||
this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this));
|
||||
|
||||
this._monthLabel = new St.Label({style_class: 'calendar-month-label',
|
||||
can_focus: true });
|
||||
this._monthLabel = new St.Label({ style_class: 'calendar-month-label',
|
||||
can_focus: true });
|
||||
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
|
||||
|
||||
this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward pager-button',
|
||||
@ -488,7 +439,7 @@ var Calendar = new Lang.Class({
|
||||
|
||||
// All the children after this are days, and get removed when we update the calendar
|
||||
this._firstDayIndex = this.actor.get_n_children();
|
||||
},
|
||||
}
|
||||
|
||||
_onScroll(actor, event) {
|
||||
switch (event.get_scroll_direction()) {
|
||||
@ -502,7 +453,7 @@ var Calendar = new Lang.Class({
|
||||
break;
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
_onPrevMonthButtonClicked() {
|
||||
let newDate = new Date(this._selectedDate);
|
||||
@ -514,8 +465,7 @@ var Calendar = new Lang.Class({
|
||||
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear() - 1, 11, day);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newDate.setMonth(oldMonth - 1);
|
||||
if (newDate.getMonth() != oldMonth - 1) {
|
||||
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
|
||||
@ -526,7 +476,7 @@ var Calendar = new Lang.Class({
|
||||
this._backButton.grab_key_focus();
|
||||
|
||||
this.setDate(newDate);
|
||||
},
|
||||
}
|
||||
|
||||
_onNextMonthButtonClicked() {
|
||||
let newDate = new Date(this._selectedDate);
|
||||
@ -538,8 +488,7 @@ var Calendar = new Lang.Class({
|
||||
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear() + 1, 0, day);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newDate.setMonth(oldMonth + 1);
|
||||
if (newDate.getMonth() != oldMonth + 1) {
|
||||
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
|
||||
@ -550,14 +499,14 @@ var Calendar = new Lang.Class({
|
||||
this._forwardButton.grab_key_focus();
|
||||
|
||||
this.setDate(newDate);
|
||||
},
|
||||
}
|
||||
|
||||
_onSettingsChange() {
|
||||
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
|
||||
this._buildHeader();
|
||||
this._rebuildCalendar();
|
||||
this._update();
|
||||
},
|
||||
}
|
||||
|
||||
_rebuildCalendar() {
|
||||
let now = new Date();
|
||||
@ -594,8 +543,6 @@ var Calendar = new Lang.Class({
|
||||
this._calendarBegin = new Date(beginDate);
|
||||
this._markedAsToday = now;
|
||||
|
||||
let year = beginDate.getYear();
|
||||
|
||||
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
|
||||
let startsOnWeekStart = daysToWeekStart == 0;
|
||||
let weekPadding = startsOnWeekStart ? 7 : 0;
|
||||
@ -607,7 +554,7 @@ var Calendar = new Lang.Class({
|
||||
let row = 2;
|
||||
// nRows here means 6 weeks + one header + one navbar
|
||||
let nRows = 8;
|
||||
while (row < 8) {
|
||||
while (row < nRows) {
|
||||
// xgettext:no-javascript-format
|
||||
let button = new St.Button({ label: iter.toLocaleFormat(C_("date day number format", "%d")),
|
||||
can_focus: true });
|
||||
@ -633,12 +580,12 @@ var Calendar = new Lang.Class({
|
||||
|
||||
// Hack used in lieu of border-collapse - see gnome-shell.css
|
||||
if (row == 2)
|
||||
styleClass = 'calendar-day-top ' + styleClass;
|
||||
styleClass = `calendar-day-top ${styleClass}`;
|
||||
|
||||
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
|
||||
: iter.getDay() == this._weekStart;
|
||||
if (leftMost)
|
||||
styleClass = 'calendar-day-left ' + styleClass;
|
||||
styleClass = `calendar-day-left ${styleClass}`;
|
||||
|
||||
if (sameDay(now, iter))
|
||||
styleClass += ' calendar-today';
|
||||
@ -678,7 +625,7 @@ var Calendar = new Lang.Class({
|
||||
// Signal to the event source that we are interested in events
|
||||
// only from this date range
|
||||
this._eventSource.requestRange(beginDate, iter);
|
||||
},
|
||||
}
|
||||
|
||||
_update() {
|
||||
let now = new Date();
|
||||
@ -696,23 +643,22 @@ var Calendar = new Lang.Class({
|
||||
button.add_style_pseudo_class('selected');
|
||||
if (this._shouldDateGrabFocus)
|
||||
button.grab_key_focus();
|
||||
}
|
||||
else
|
||||
} else {
|
||||
button.remove_style_pseudo_class('selected');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Signals.addSignalMethods(Calendar.prototype);
|
||||
|
||||
var EventMessage = new Lang.Class({
|
||||
Name: 'EventMessage',
|
||||
Extends: MessageList.Message,
|
||||
var EventMessage = class EventMessage extends MessageList.Message {
|
||||
constructor(event, date) {
|
||||
super('', event.summary);
|
||||
|
||||
_init(event, date) {
|
||||
this._event = event;
|
||||
this._date = date;
|
||||
|
||||
this.parent(this._formatEventTime(), event.summary);
|
||||
this.setTitle(this._formatEventTime());
|
||||
|
||||
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
|
||||
this.setIcon(this._icon);
|
||||
@ -721,7 +667,7 @@ var EventMessage = new Lang.Class({
|
||||
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
|
||||
this._icon.opacity = (iconVisible ? 255 : 0);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_formatEventTime() {
|
||||
let periodBegin = _getBeginningOfDay(this._date);
|
||||
@ -754,23 +700,17 @@ var EventMessage = new Lang.Class({
|
||||
title = title + ELLIPSIS_CHAR;
|
||||
}
|
||||
return title;
|
||||
},
|
||||
|
||||
canClose() {
|
||||
return isToday(this._date);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var NotificationMessage = new Lang.Class({
|
||||
Name: 'NotificationMessage',
|
||||
Extends: MessageList.Message,
|
||||
|
||||
_init(notification) {
|
||||
this.notification = notification;
|
||||
|
||||
this.parent(notification.title, notification.bannerBodyText);
|
||||
var NotificationMessage =
|
||||
class NotificationMessage extends MessageList.Message {
|
||||
constructor(notification) {
|
||||
super(notification.title, notification.bannerBodyText);
|
||||
this.setUseBodyMarkup(notification.bannerBodyMarkup);
|
||||
|
||||
this.notification = notification;
|
||||
|
||||
this.setIcon(this._getIcon());
|
||||
|
||||
this.connect('close', () => {
|
||||
@ -779,13 +719,14 @@ var NotificationMessage = new Lang.Class({
|
||||
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
|
||||
});
|
||||
this._destroyId = notification.connect('destroy', () => {
|
||||
this._disconnectNotificationSignals();
|
||||
this.notification = null;
|
||||
if (!this._closed)
|
||||
this.close();
|
||||
});
|
||||
this._updatedId = notification.connect('updated',
|
||||
this._onUpdated.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_getIcon() {
|
||||
if (this.notification.gicon)
|
||||
@ -793,22 +734,25 @@ var NotificationMessage = new Lang.Class({
|
||||
icon_size: MESSAGE_ICON_SIZE });
|
||||
else
|
||||
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
|
||||
},
|
||||
}
|
||||
|
||||
_onUpdated(n, clear) {
|
||||
this.setIcon(this._getIcon());
|
||||
this.setTitle(n.title);
|
||||
this.setBody(n.bannerBodyText);
|
||||
this.setUseBodyMarkup(n.bannerBodyMarkup);
|
||||
},
|
||||
}
|
||||
|
||||
_onClicked() {
|
||||
this.notification.activate();
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.parent();
|
||||
super._onDestroy();
|
||||
this._disconnectNotificationSignals();
|
||||
}
|
||||
|
||||
_disconnectNotificationSignals() {
|
||||
if (this._updatedId)
|
||||
this.notification.disconnect(this._updatedId);
|
||||
this._updatedId = 0;
|
||||
@ -817,21 +761,22 @@ var NotificationMessage = new Lang.Class({
|
||||
this.notification.disconnect(this._destroyId);
|
||||
this._destroyId = 0;
|
||||
}
|
||||
});
|
||||
|
||||
var EventsSection = new Lang.Class({
|
||||
Name: 'EventsSection',
|
||||
Extends: MessageList.MessageListSection,
|
||||
canClose() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var EventsSection = class EventsSection extends MessageList.MessageListSection {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
_init() {
|
||||
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
|
||||
this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
|
||||
this._eventSource = new EmptyEventSource();
|
||||
|
||||
this._messageById = new Map();
|
||||
|
||||
this.parent();
|
||||
|
||||
this._title = new St.Button({ style_class: 'events-section-title',
|
||||
label: '',
|
||||
x_align: St.Align.START,
|
||||
@ -844,20 +789,16 @@ var EventsSection = new Lang.Class({
|
||||
Shell.AppSystem.get_default().connect('installed-changed',
|
||||
this._appInstalledChanged.bind(this));
|
||||
this._appInstalledChanged();
|
||||
},
|
||||
|
||||
_ignoreEvent(event) {
|
||||
this._eventSource.ignoreEvent(event);
|
||||
},
|
||||
}
|
||||
|
||||
setEventSource(eventSource) {
|
||||
this._eventSource = eventSource;
|
||||
this._eventSource.connect('changed', this._reloadEvents.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
get allowed() {
|
||||
return Main.sessionMode.showCalendarEvents;
|
||||
},
|
||||
}
|
||||
|
||||
_updateTitle() {
|
||||
this._title.visible = !isToday(this._date);
|
||||
@ -876,7 +817,7 @@ var EventsSection = new Lang.Class({
|
||||
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
|
||||
"%A, %B %-d, %Y"));
|
||||
this._title.label = this._date.toLocaleFormat(dayFormat);
|
||||
},
|
||||
}
|
||||
|
||||
_reloadEvents() {
|
||||
if (this._eventSource.isLoading)
|
||||
@ -902,9 +843,6 @@ var EventsSection = new Lang.Class({
|
||||
let message = this._messageById.get(event.id);
|
||||
if (!message) {
|
||||
message = new EventMessage(event, this._date);
|
||||
message.connect('close', () => {
|
||||
this._ignoreEvent(event);
|
||||
});
|
||||
this._messageById.set(event.id, message);
|
||||
this.addMessage(message, false);
|
||||
} else {
|
||||
@ -914,12 +852,12 @@ var EventsSection = new Lang.Class({
|
||||
|
||||
this._reloading = false;
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_appInstalledChanged() {
|
||||
this._calendarApp = undefined;
|
||||
this._title.reactive = (this._getCalendarApp() != null);
|
||||
},
|
||||
}
|
||||
|
||||
_getCalendarApp() {
|
||||
if (this._calendarApp !== undefined)
|
||||
@ -934,7 +872,7 @@ var EventsSection = new Lang.Class({
|
||||
this._calendarApp = null;
|
||||
}
|
||||
return this._calendarApp;
|
||||
},
|
||||
}
|
||||
|
||||
_onTitleClicked() {
|
||||
Main.overview.hide();
|
||||
@ -944,32 +882,30 @@ var EventsSection = new Lang.Class({
|
||||
if (app.get_id() == 'evolution.desktop')
|
||||
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
|
||||
app.launch([], global.create_app_launch_context(0, -1));
|
||||
},
|
||||
}
|
||||
|
||||
setDate(date) {
|
||||
this.parent(date);
|
||||
super.setDate(date);
|
||||
this._updateTitle();
|
||||
this._reloadEvents();
|
||||
},
|
||||
}
|
||||
|
||||
_shouldShow() {
|
||||
return !this.empty || !isToday(this._date);
|
||||
},
|
||||
}
|
||||
|
||||
_sync() {
|
||||
if (this._reloading)
|
||||
return;
|
||||
|
||||
this.parent();
|
||||
super._sync();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var NotificationSection = new Lang.Class({
|
||||
Name: 'NotificationSection',
|
||||
Extends: MessageList.MessageListSection,
|
||||
|
||||
_init() {
|
||||
this.parent();
|
||||
var NotificationSection =
|
||||
class NotificationSection extends MessageList.MessageListSection {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._sources = new Map();
|
||||
this._nUrgent = 0;
|
||||
@ -980,12 +916,12 @@ var NotificationSection = new Lang.Class({
|
||||
});
|
||||
|
||||
this.actor.connect('notify::mapped', this._onMapped.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
get allowed() {
|
||||
return Main.sessionMode.hasNotifications &&
|
||||
!Main.sessionMode.isGreeter;
|
||||
},
|
||||
}
|
||||
|
||||
_createTimeLabel(datetime) {
|
||||
let label = new St.Label({ style_class: 'event-time',
|
||||
@ -996,7 +932,7 @@ var NotificationSection = new Lang.Class({
|
||||
label.text = Util.formatTimeSpan(datetime);
|
||||
});
|
||||
return label;
|
||||
},
|
||||
}
|
||||
|
||||
_sourceAdded(tray, source) {
|
||||
let obj = {
|
||||
@ -1011,7 +947,7 @@ var NotificationSection = new Lang.Class({
|
||||
this._onNotificationAdded.bind(this));
|
||||
|
||||
this._sources.set(source, obj);
|
||||
},
|
||||
}
|
||||
|
||||
_onNotificationAdded(source, notification) {
|
||||
let message = new NotificationMessage(notification);
|
||||
@ -1042,14 +978,14 @@ var NotificationSection = new Lang.Class({
|
||||
|
||||
let index = isUrgent ? 0 : this._nUrgent;
|
||||
this.addMessageAtIndex(message, index, this.actor.mapped);
|
||||
},
|
||||
}
|
||||
|
||||
_onSourceDestroy(source, obj) {
|
||||
source.disconnect(obj.destroyId);
|
||||
source.disconnect(obj.notificationAddedId);
|
||||
|
||||
this._sources.delete(source);
|
||||
},
|
||||
}
|
||||
|
||||
_onMapped() {
|
||||
if (!this.actor.mapped)
|
||||
@ -1058,17 +994,15 @@ var NotificationSection = new Lang.Class({
|
||||
for (let message of this._messages.keys())
|
||||
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
|
||||
message.notification.acknowledged = true;
|
||||
},
|
||||
}
|
||||
|
||||
_shouldShow() {
|
||||
return !this.empty && isToday(this._date);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Placeholder = new Lang.Class({
|
||||
Name: 'Placeholder',
|
||||
|
||||
_init() {
|
||||
var Placeholder = class Placeholder {
|
||||
constructor() {
|
||||
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
|
||||
vertical: true });
|
||||
|
||||
@ -1086,14 +1020,14 @@ var Placeholder = new Lang.Class({
|
||||
this.actor.add_actor(this._label);
|
||||
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
setDate(date) {
|
||||
if (sameDay(this._date, date))
|
||||
return;
|
||||
this._date = date;
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_sync() {
|
||||
let today = isToday(this._date);
|
||||
@ -1110,12 +1044,10 @@ var Placeholder = new Lang.Class({
|
||||
this._label.text = _("No Events");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var CalendarMessageList = new Lang.Class({
|
||||
Name: 'CalendarMessageList',
|
||||
|
||||
_init() {
|
||||
var CalendarMessageList = class CalendarMessageList {
|
||||
constructor() {
|
||||
this.actor = new St.Widget({ style_class: 'message-list',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
@ -1131,16 +1063,16 @@ var CalendarMessageList = new Lang.Class({
|
||||
overlay_scrollbars: true,
|
||||
x_expand: true, y_expand: true,
|
||||
x_fill: true, y_fill: true });
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
box.add_actor(this._scrollView);
|
||||
|
||||
this._clearButton = new St.Button({ style_class: 'message-list-clear-button button',
|
||||
label: _("Clear All"),
|
||||
label: _("Clear"),
|
||||
can_focus: true });
|
||||
this._clearButton.set_x_align(Clutter.ActorAlign.END);
|
||||
this._clearButton.connect('clicked', () => {
|
||||
let sections = [...this._sections.keys()];
|
||||
sections.forEach((s) => { s.clear(); });
|
||||
sections.forEach((s) => s.clear());
|
||||
});
|
||||
box.add_actor(this._clearButton);
|
||||
|
||||
@ -1161,12 +1093,12 @@ var CalendarMessageList = new Lang.Class({
|
||||
this._addSection(this._eventsSection);
|
||||
|
||||
Main.sessionMode.connect('updated', this._sync.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_addSection(section) {
|
||||
let obj = {
|
||||
destroyId: 0,
|
||||
visibleId: 0,
|
||||
visibleId: 0,
|
||||
emptyChangedId: 0,
|
||||
canClearChangedId: 0,
|
||||
keyFocusId: 0
|
||||
@ -1186,7 +1118,7 @@ var CalendarMessageList = new Lang.Class({
|
||||
this._sections.set(section, obj);
|
||||
this._sectionList.add_actor(section.actor);
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_removeSection(section) {
|
||||
let obj = this._sections.get(section);
|
||||
@ -1199,11 +1131,11 @@ var CalendarMessageList = new Lang.Class({
|
||||
this._sections.delete(section);
|
||||
this._sectionList.remove_actor(section.actor);
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_onKeyFocusIn(section, actor) {
|
||||
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
|
||||
},
|
||||
}
|
||||
|
||||
_sync() {
|
||||
let sections = [...this._sections.keys()];
|
||||
@ -1218,15 +1150,15 @@ var CalendarMessageList = new Lang.Class({
|
||||
|
||||
let canClear = sections.some(s => s.canClear && s.actor.visible);
|
||||
this._clearButton.reactive = canClear;
|
||||
},
|
||||
}
|
||||
|
||||
setEventSource(eventSource) {
|
||||
this._eventsSection.setEventSource(eventSource);
|
||||
},
|
||||
}
|
||||
|
||||
setDate(date) {
|
||||
for (let section of this._sections.keys())
|
||||
section.setDate(date);
|
||||
this._placeholder.setDate(date);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,13 +1,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, Pango, St } = imports.gi;
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
var CheckBox = new Lang.Class({
|
||||
Name: 'CheckBox',
|
||||
|
||||
_init(label) {
|
||||
var CheckBox = class CheckBox {
|
||||
constructor(label) {
|
||||
let container = new St.BoxLayout();
|
||||
this.actor = new St.Button({ style_class: 'check-box',
|
||||
child: container,
|
||||
@ -28,13 +22,13 @@ var CheckBox = new Lang.Class({
|
||||
|
||||
if (label)
|
||||
this.setLabel(label);
|
||||
},
|
||||
}
|
||||
|
||||
setLabel(label) {
|
||||
this._label.set_text(label);
|
||||
},
|
||||
}
|
||||
|
||||
getLabelActor() {
|
||||
return this._label;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,46 +1,38 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
|
||||
|
||||
const Dialog = imports.ui.dialog;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var FROZEN_WINDOW_BRIGHTNESS = -0.3
|
||||
var DIALOG_TRANSITION_TIME = 0.15
|
||||
var FROZEN_WINDOW_BRIGHTNESS = -0.3;
|
||||
var DIALOG_TRANSITION_TIME = 0.15;
|
||||
var ALIVE_TIMEOUT = 5000;
|
||||
|
||||
var CloseDialog = new Lang.Class({
|
||||
Name: 'CloseDialog',
|
||||
Extends: GObject.Object,
|
||||
Implements: [ Meta.CloseDialog ],
|
||||
var CloseDialog = GObject.registerClass({
|
||||
Implements: [Meta.CloseDialog],
|
||||
Properties: {
|
||||
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
|
||||
},
|
||||
|
||||
}, class CloseDialog extends GObject.Object {
|
||||
_init(window) {
|
||||
this.parent();
|
||||
super._init();
|
||||
this._window = window;
|
||||
this._dialog = null;
|
||||
this._tracked = undefined;
|
||||
this._timeoutId = 0;
|
||||
this._windowFocusChangedId = 0;
|
||||
this._keyFocusChangedId = 0;
|
||||
},
|
||||
}
|
||||
|
||||
get window() {
|
||||
return this._window;
|
||||
},
|
||||
}
|
||||
|
||||
set window(window) {
|
||||
this._window = window;
|
||||
},
|
||||
}
|
||||
|
||||
_createDialogContent() {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
@ -52,7 +44,7 @@ var CloseDialog = new Lang.Class({
|
||||
"continue or force the application to quit entirely.");
|
||||
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
|
||||
return new Dialog.MessageDialogContent({ icon, title, subtitle });
|
||||
},
|
||||
}
|
||||
|
||||
_initDialog() {
|
||||
if (this._dialog)
|
||||
@ -64,15 +56,15 @@ var CloseDialog = new Lang.Class({
|
||||
this._dialog.height = windowActor.height;
|
||||
|
||||
this._dialog.addContent(this._createDialogContent());
|
||||
this._dialog.addButton({ label: _('Force Quit'),
|
||||
action: this._onClose.bind(this),
|
||||
this._dialog.addButton({ label: _('Force Quit'),
|
||||
action: this._onClose.bind(this),
|
||||
default: true });
|
||||
this._dialog.addButton({ label: _('Wait'),
|
||||
this._dialog.addButton({ label: _('Wait'),
|
||||
action: this._onWait.bind(this),
|
||||
key: Clutter.Escape });
|
||||
key: Clutter.Escape });
|
||||
|
||||
global.focus_manager.add_group(this._dialog);
|
||||
},
|
||||
}
|
||||
|
||||
_addWindowEffect() {
|
||||
// We set the effect on the surface actor, so the dialog itself
|
||||
@ -83,21 +75,21 @@ var CloseDialog = new Lang.Class({
|
||||
let effect = new Clutter.BrightnessContrastEffect();
|
||||
effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS);
|
||||
surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
|
||||
},
|
||||
}
|
||||
|
||||
_removeWindowEffect() {
|
||||
let windowActor = this._window.get_compositor_private();
|
||||
let surfaceActor = windowActor.get_first_child();
|
||||
surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
|
||||
},
|
||||
}
|
||||
|
||||
_onWait() {
|
||||
this.response(Meta.CloseDialogResponse.WAIT);
|
||||
},
|
||||
}
|
||||
|
||||
_onClose() {
|
||||
this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
|
||||
},
|
||||
}
|
||||
|
||||
_onFocusChanged() {
|
||||
if (Meta.is_wayland_compositor())
|
||||
@ -128,7 +120,7 @@ var CloseDialog = new Lang.Class({
|
||||
});
|
||||
|
||||
this._tracked = shouldTrack;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_show() {
|
||||
if (this._dialog != null)
|
||||
@ -162,7 +154,7 @@ var CloseDialog = new Lang.Class({
|
||||
time: DIALOG_TRANSITION_TIME,
|
||||
onComplete: this._onFocusChanged.bind(this)
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_hide() {
|
||||
if (this._dialog == null)
|
||||
@ -173,7 +165,7 @@ var CloseDialog = new Lang.Class({
|
||||
GLib.source_remove(this._timeoutId);
|
||||
this._timeoutId = 0;
|
||||
|
||||
global.display.disconnect(this._windowFocusChangedId)
|
||||
global.display.disconnect(this._windowFocusChangedId);
|
||||
this._windowFocusChangedId = 0;
|
||||
|
||||
global.stage.disconnect(this._keyFocusChangedId);
|
||||
@ -191,7 +183,7 @@ var CloseDialog = new Lang.Class({
|
||||
dialog.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_focus() {
|
||||
if (this._dialog)
|
||||
|
@ -1,60 +1,56 @@
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
var ComponentManager = new Lang.Class({
|
||||
Name: 'ComponentManager',
|
||||
|
||||
_init() {
|
||||
var ComponentManager = class {
|
||||
constructor() {
|
||||
this._allComponents = {};
|
||||
this._enabledComponents = [];
|
||||
|
||||
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
||||
this._sessionUpdated();
|
||||
},
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
let newEnabledComponents = Main.sessionMode.components;
|
||||
|
||||
newEnabledComponents.filter(
|
||||
name => this._enabledComponents.indexOf(name) == -1
|
||||
name => !this._enabledComponents.includes(name)
|
||||
).forEach(name => {
|
||||
this._enableComponent(name);
|
||||
});
|
||||
|
||||
this._enabledComponents.filter(
|
||||
name => newEnabledComponents.indexOf(name) == -1
|
||||
name => !newEnabledComponents.includes(name)
|
||||
).forEach(name => {
|
||||
this._disableComponent(name);
|
||||
});
|
||||
|
||||
this._enabledComponents = newEnabledComponents;
|
||||
},
|
||||
}
|
||||
|
||||
_importComponent(name) {
|
||||
let module = imports.ui.components[name];
|
||||
return module.Component;
|
||||
},
|
||||
}
|
||||
|
||||
_ensureComponent(name) {
|
||||
let component = this._allComponents[name];
|
||||
if (component)
|
||||
return component;
|
||||
|
||||
if (Main.sessionMode.isLocked)
|
||||
return null;
|
||||
if (Main.sessionMode.isLocked)
|
||||
return null;
|
||||
|
||||
let constructor = this._importComponent(name);
|
||||
component = new constructor();
|
||||
this._allComponents[name] = component;
|
||||
return component;
|
||||
},
|
||||
}
|
||||
|
||||
_enableComponent(name) {
|
||||
let component = this._ensureComponent(name);
|
||||
if (component)
|
||||
if (component)
|
||||
component.enable();
|
||||
},
|
||||
}
|
||||
|
||||
_disableComponent(name) {
|
||||
let component = this._allComponents[name];
|
||||
@ -62,4 +58,4 @@ var ComponentManager = new Lang.Class({
|
||||
return;
|
||||
component.disable();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,11 +1,8 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const { Gio, GLib } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Params = imports.misc.params;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Main = imports.ui.main;
|
||||
@ -19,10 +16,8 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
|
||||
|
||||
var AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
|
||||
|
||||
var AutomountManager = new Lang.Class({
|
||||
Name: 'AutomountManager',
|
||||
|
||||
_init() {
|
||||
var AutomountManager = class {
|
||||
constructor() {
|
||||
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
|
||||
this._volumeQueue = [];
|
||||
this._activeOperations = new Map();
|
||||
@ -34,7 +29,7 @@ var AutomountManager = new Lang.Class({
|
||||
this._inhibited = false;
|
||||
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._volumeAddedId = this._volumeMonitor.connect('volume-added', this._onVolumeAdded.bind(this));
|
||||
@ -45,7 +40,7 @@ var AutomountManager = new Lang.Class({
|
||||
|
||||
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
|
||||
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._volumeMonitor.disconnect(this._volumeAddedId);
|
||||
@ -58,7 +53,7 @@ var AutomountManager = new Lang.Class({
|
||||
Mainloop.source_remove(this._mountAllId);
|
||||
this._mountAllId = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_InhibitorsChanged(object, senderName, [inhibtor]) {
|
||||
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
|
||||
@ -67,7 +62,7 @@ var AutomountManager = new Lang.Class({
|
||||
this._inhibited = result[0];
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_startupMountAll() {
|
||||
let volumes = this._volumeMonitor.get_volumes();
|
||||
@ -79,7 +74,7 @@ var AutomountManager = new Lang.Class({
|
||||
|
||||
this._mountAllId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
_onDriveConnected() {
|
||||
// if we're not in the current ConsoleKit session,
|
||||
@ -91,7 +86,7 @@ var AutomountManager = new Lang.Class({
|
||||
player.play_from_theme('device-added-media',
|
||||
_("External drive connected"),
|
||||
null);
|
||||
},
|
||||
}
|
||||
|
||||
_onDriveDisconnected() {
|
||||
// if we're not in the current ConsoleKit session,
|
||||
@ -99,11 +94,11 @@ var AutomountManager = new Lang.Class({
|
||||
if (!this._session.SessionIsActive)
|
||||
return;
|
||||
|
||||
let sound = global.display.get_sound();
|
||||
sound.play_from_theme('device-removed-media',
|
||||
_("External drive disconnected"),
|
||||
null);
|
||||
},
|
||||
let player = global.display.get_sound_player();
|
||||
player.play_from_theme('device-removed-media',
|
||||
_("External drive disconnected"),
|
||||
null);
|
||||
}
|
||||
|
||||
_onDriveEjectButton(monitor, drive) {
|
||||
// TODO: this code path is not tested, as the GVfs volume monitor
|
||||
@ -114,31 +109,29 @@ var AutomountManager = new Lang.Class({
|
||||
// we force stop/eject in this case, so we don't have to pass a
|
||||
// mount operation object
|
||||
if (drive.can_stop()) {
|
||||
drive.stop
|
||||
(Gio.MountUnmountFlags.FORCE, null, null,
|
||||
(drive, res) => {
|
||||
try {
|
||||
drive.stop_finish(res);
|
||||
} catch (e) {
|
||||
log("Unable to stop the drive after drive-eject-button " + e.toString());
|
||||
}
|
||||
});
|
||||
drive.stop(Gio.MountUnmountFlags.FORCE, null, null,
|
||||
(drive, res) => {
|
||||
try {
|
||||
drive.stop_finish(res);
|
||||
} catch (e) {
|
||||
log(`Unable to stop the drive after drive-eject-button ${e.toString()}`);
|
||||
}
|
||||
});
|
||||
} else if (drive.can_eject()) {
|
||||
drive.eject_with_operation
|
||||
(Gio.MountUnmountFlags.FORCE, null, null,
|
||||
(drive, res) => {
|
||||
try {
|
||||
drive.eject_with_operation_finish(res);
|
||||
} catch (e) {
|
||||
log("Unable to eject the drive after drive-eject-button " + e.toString());
|
||||
}
|
||||
});
|
||||
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE, null, null,
|
||||
(drive, res) => {
|
||||
try {
|
||||
drive.eject_with_operation_finish(res);
|
||||
} catch (e) {
|
||||
log(`Unable to eject the drive after drive-eject-button ${e.toString()}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onVolumeAdded(monitor, volume) {
|
||||
this._checkAndMountVolume(volume);
|
||||
},
|
||||
}
|
||||
|
||||
_checkAndMountVolume(volume, params) {
|
||||
params = Params.parse(params, { checkSession: true,
|
||||
@ -178,7 +171,7 @@ var AutomountManager = new Lang.Class({
|
||||
} else {
|
||||
this._mountVolume(volume, null, params.allowAutorun);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_mountVolume(volume, operation, allowAutorun) {
|
||||
if (allowAutorun)
|
||||
@ -189,7 +182,7 @@ var AutomountManager = new Lang.Class({
|
||||
|
||||
volume.mount(0, mountOp, null,
|
||||
this._onVolumeMounted.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_onVolumeMounted(volume, res) {
|
||||
this._allowAutorunExpire(volume);
|
||||
@ -205,16 +198,24 @@ var AutomountManager = new Lang.Class({
|
||||
// error strings are not unique for the cases in the comments below.
|
||||
if (e.message.includes('No key available with this passphrase') || // cryptsetup
|
||||
e.message.includes('No key available to unlock device') || // udisks (no password)
|
||||
e.message.includes('Error unlocking')) { // udisks (wrong password)
|
||||
// libblockdev wrong password opening LUKS device
|
||||
e.message.includes('Failed to activate device: Incorrect passphrase') ||
|
||||
// cryptsetup returns EINVAL in many cases, including wrong TCRYPT password/parameters
|
||||
e.message.includes('Failed to load device\'s parameters: Invalid argument')) {
|
||||
|
||||
this._reaskPassword(volume);
|
||||
} else {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
||||
log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString());
|
||||
if (e.message.includes('Compiled against a version of libcryptsetup that does not support the VeraCrypt PIM setting')) {
|
||||
Main.notifyError(_("Unable to unlock volume"),
|
||||
_("The installed udisks version does not support the PIM setting"));
|
||||
}
|
||||
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
||||
log(`Unable to mount volume ${volume.get_name()}: ${e.toString()}`);
|
||||
this._closeOperation(volume);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onVolumeRemoved(monitor, volume) {
|
||||
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
|
||||
@ -223,7 +224,7 @@ var AutomountManager = new Lang.Class({
|
||||
}
|
||||
this._volumeQueue =
|
||||
this._volumeQueue.filter(element => (element != volume));
|
||||
},
|
||||
}
|
||||
|
||||
_reaskPassword(volume) {
|
||||
let prevOperation = this._activeOperations.get(volume);
|
||||
@ -232,7 +233,7 @@ var AutomountManager = new Lang.Class({
|
||||
new ShellMountOperation.ShellMountOperation(volume,
|
||||
{ existingDialog: existingDialog });
|
||||
this._mountVolume(volume, operation);
|
||||
},
|
||||
}
|
||||
|
||||
_closeOperation(volume) {
|
||||
let operation = this._activeOperations.get(volume);
|
||||
@ -240,11 +241,11 @@ var AutomountManager = new Lang.Class({
|
||||
return;
|
||||
operation.close();
|
||||
this._activeOperations.delete(volume);
|
||||
},
|
||||
}
|
||||
|
||||
_allowAutorun(volume) {
|
||||
volume.allowAutorun = true;
|
||||
},
|
||||
}
|
||||
|
||||
_allowAutorunExpire(volume) {
|
||||
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
|
||||
@ -255,5 +256,5 @@ var AutomountManager = new Lang.Class({
|
||||
volume._allowAutorunExpireId = id;
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
|
||||
}
|
||||
});
|
||||
};
|
||||
var Component = AutomountManager;
|
||||
|
@ -1,8 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Gio = imports.gi.Gio;
|
||||
const St = imports.gi.St;
|
||||
const { Gio, St } = imports.gi;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Main = imports.ui.main;
|
||||
@ -42,7 +40,7 @@ function isMountRootHidden(root) {
|
||||
let path = root.get_path();
|
||||
|
||||
// skip any mounts in hidden directory hierarchies
|
||||
return (path.indexOf('/.') != -1);
|
||||
return (path.includes('/.'));
|
||||
}
|
||||
|
||||
function isMountNonLocal(mount) {
|
||||
@ -67,8 +65,7 @@ function startAppForMount(app, mount) {
|
||||
retval = app.launch(files,
|
||||
global.create_app_launch_context(0, -1));
|
||||
} catch (e) {
|
||||
log('Unable to launch the application ' + app.get_name()
|
||||
+ ': ' + e.toString());
|
||||
log(`Unable to launch the application ${app.get_name()}: ${e}`);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -84,13 +81,11 @@ function HotplugSniffer() {
|
||||
'/org/gnome/Shell/HotplugSniffer');
|
||||
}
|
||||
|
||||
var ContentTypeDiscoverer = new Lang.Class({
|
||||
Name: 'ContentTypeDiscoverer',
|
||||
|
||||
_init(callback) {
|
||||
var ContentTypeDiscoverer = class {
|
||||
constructor(callback) {
|
||||
this._callback = callback;
|
||||
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
|
||||
},
|
||||
}
|
||||
|
||||
guessContentTypes(mount) {
|
||||
let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN);
|
||||
@ -103,7 +98,7 @@ var ContentTypeDiscoverer = new Lang.Class({
|
||||
} else {
|
||||
this._emitCallback(mount, []);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onContentTypeGuessed(mount, res) {
|
||||
let contentTypes = [];
|
||||
@ -111,8 +106,7 @@ var ContentTypeDiscoverer = new Lang.Class({
|
||||
try {
|
||||
contentTypes = mount.guess_content_type_finish(res);
|
||||
} catch (e) {
|
||||
log('Unable to guess content types on added mount ' + mount.get_name()
|
||||
+ ': ' + e.toString());
|
||||
log(`Unable to guess content types on added mount ${mount.get_name()}: ${e}`);
|
||||
}
|
||||
|
||||
if (contentTypes.length) {
|
||||
@ -126,7 +120,7 @@ var ContentTypeDiscoverer = new Lang.Class({
|
||||
this._emitCallback(mount, contentTypes);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_emitCallback(mount, contentTypes) {
|
||||
if (!contentTypes)
|
||||
@ -150,27 +144,25 @@ var ContentTypeDiscoverer = new Lang.Class({
|
||||
|
||||
this._callback(mount, apps, contentTypes);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var AutorunManager = new Lang.Class({
|
||||
Name: 'AutorunManager',
|
||||
|
||||
_init() {
|
||||
var AutorunManager = class {
|
||||
constructor() {
|
||||
this._session = new GnomeSession.SessionManager();
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
|
||||
this._dispatcher = new AutorunDispatcher(this);
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._mountAddedId = this._volumeMonitor.connect('mount-added', this._onMountAdded.bind(this));
|
||||
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', this._onMountRemoved.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._volumeMonitor.disconnect(this._mountAddedId);
|
||||
this._volumeMonitor.disconnect(this._mountRemovedId);
|
||||
},
|
||||
}
|
||||
|
||||
_onMountAdded(monitor, mount) {
|
||||
// don't do anything if our session is not the currently
|
||||
@ -182,37 +174,35 @@ var AutorunManager = new Lang.Class({
|
||||
this._dispatcher.addMount(mount, apps, contentTypes);
|
||||
});
|
||||
discoverer.guessContentTypes(mount);
|
||||
},
|
||||
}
|
||||
|
||||
_onMountRemoved(monitor, mount) {
|
||||
this._dispatcher.removeMount(mount);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var AutorunDispatcher = new Lang.Class({
|
||||
Name: 'AutorunDispatcher',
|
||||
|
||||
_init(manager) {
|
||||
var AutorunDispatcher = class {
|
||||
constructor(manager) {
|
||||
this._manager = manager;
|
||||
this._sources = [];
|
||||
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
|
||||
},
|
||||
}
|
||||
|
||||
_getAutorunSettingForType(contentType) {
|
||||
let runApp = this._settings.get_strv(SETTING_START_APP);
|
||||
if (runApp.indexOf(contentType) != -1)
|
||||
if (runApp.includes(contentType))
|
||||
return AutorunSetting.RUN;
|
||||
|
||||
let ignore = this._settings.get_strv(SETTING_IGNORE);
|
||||
if (ignore.indexOf(contentType) != -1)
|
||||
if (ignore.includes(contentType))
|
||||
return AutorunSetting.IGNORE;
|
||||
|
||||
let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER);
|
||||
if (openFiles.indexOf(contentType) != -1)
|
||||
if (openFiles.includes(contentType))
|
||||
return AutorunSetting.FILES;
|
||||
|
||||
return AutorunSetting.ASK;
|
||||
},
|
||||
}
|
||||
|
||||
_getSourceForMount(mount) {
|
||||
let filtered = this._sources.filter(source => (source.mount == mount));
|
||||
@ -224,7 +214,7 @@ var AutorunDispatcher = new Lang.Class({
|
||||
return filtered[0];
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
|
||||
_addSource(mount, apps) {
|
||||
// if we already have a source showing for this
|
||||
@ -234,7 +224,7 @@ var AutorunDispatcher = new Lang.Class({
|
||||
|
||||
// add a new source
|
||||
this._sources.push(new AutorunSource(this._manager, mount, apps));
|
||||
},
|
||||
}
|
||||
|
||||
addMount(mount, apps, contentTypes) {
|
||||
// if autorun is disabled globally, return
|
||||
@ -272,7 +262,7 @@ var AutorunDispatcher = new Lang.Class({
|
||||
// but we failed launching the default app or the default file manager
|
||||
if (!success)
|
||||
this._addSource(mount, apps);
|
||||
},
|
||||
}
|
||||
|
||||
removeMount(mount) {
|
||||
let source = this._getSourceForMount(mount);
|
||||
@ -284,45 +274,39 @@ var AutorunDispatcher = new Lang.Class({
|
||||
// destroy the notification source
|
||||
source.destroy();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var AutorunSource = new Lang.Class({
|
||||
Name: 'AutorunSource',
|
||||
Extends: MessageTray.Source,
|
||||
var AutorunSource = class extends MessageTray.Source {
|
||||
constructor(manager, mount, apps) {
|
||||
super(mount.get_name());
|
||||
|
||||
_init(manager, mount, apps) {
|
||||
this._manager = manager;
|
||||
this.mount = mount;
|
||||
this.apps = apps;
|
||||
|
||||
this.parent(mount.get_name());
|
||||
|
||||
this._notification = new AutorunNotification(this._manager, this);
|
||||
|
||||
// add ourselves as a source, and popup the notification
|
||||
Main.messageTray.add(this);
|
||||
this.notify(this._notification);
|
||||
},
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return this.mount.get_icon();
|
||||
},
|
||||
}
|
||||
|
||||
_createPolicy() {
|
||||
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var AutorunNotification = new Lang.Class({
|
||||
Name: 'AutorunNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init(manager, source) {
|
||||
this.parent(source, source.title);
|
||||
var AutorunNotification = class extends MessageTray.Notification {
|
||||
constructor(manager, source) {
|
||||
super(source, source.title);
|
||||
|
||||
this._manager = manager;
|
||||
this._mount = source.mount;
|
||||
},
|
||||
}
|
||||
|
||||
createBanner() {
|
||||
let banner = new MessageTray.NotificationBanner(this);
|
||||
@ -335,7 +319,7 @@ var AutorunNotification = new Lang.Class({
|
||||
});
|
||||
|
||||
return banner;
|
||||
},
|
||||
}
|
||||
|
||||
_buttonForApp(app) {
|
||||
let box = new St.BoxLayout();
|
||||
@ -362,14 +346,14 @@ var AutorunNotification = new Lang.Class({
|
||||
});
|
||||
|
||||
return button;
|
||||
},
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.parent();
|
||||
super.activate();
|
||||
|
||||
let app = Gio.app_info_get_default_for_type('inode/directory', false);
|
||||
startAppForMount(app, this._mount);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Component = AutorunManager;
|
||||
|
@ -1,31 +1,19 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gcr = imports.gi.Gcr;
|
||||
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Dialog = imports.ui.dialog;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const CheckBox = imports.ui.checkBox;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var WORK_SPINNER_ICON_SIZE = 16;
|
||||
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
var WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
var KeyringDialog = new Lang.Class({
|
||||
Name: 'KeyringDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
var KeyringDialog = GObject.registerClass(
|
||||
class KeyringDialog extends ModalDialog.ModalDialog {
|
||||
_init() {
|
||||
this.parent({ styleClass: 'prompt-dialog' });
|
||||
super._init({ styleClass: 'prompt-dialog' });
|
||||
|
||||
this.prompt = new Shell.KeyringPrompt();
|
||||
this.prompt.connect('show-password', this._onShowPassword.bind(this));
|
||||
@ -36,20 +24,8 @@ var KeyringDialog = new Lang.Class({
|
||||
this._content = new Dialog.MessageDialogContent({ icon });
|
||||
this.contentLayout.add(this._content);
|
||||
|
||||
// FIXME: Why does this break now?
|
||||
/*
|
||||
this.prompt.bind_property('message', this._content, 'title', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('description', this._content, 'body', GObject.BindingFlags.SYNC_CREATE);
|
||||
*/
|
||||
this.prompt.connect('notify::message', () => {
|
||||
this._content.title = this.prompt.message;
|
||||
});
|
||||
this._content.title = this.prompt.message;
|
||||
|
||||
this.prompt.connect('notify::description', () => {
|
||||
this._content.body = this.prompt.description;
|
||||
});
|
||||
this._content.body = this.prompt.description;
|
||||
|
||||
this._workSpinner = null;
|
||||
this._controlTable = null;
|
||||
@ -63,34 +39,17 @@ var KeyringDialog = new Lang.Class({
|
||||
|
||||
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
},
|
||||
}
|
||||
|
||||
_setWorking(working) {
|
||||
if (!this._workSpinner)
|
||||
return;
|
||||
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
if (working) {
|
||||
if (working)
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
else
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
|
||||
_buildControlTable() {
|
||||
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
|
||||
@ -114,9 +73,7 @@ var KeyringDialog = new Lang.Class({
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
|
||||
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
|
||||
|
||||
if (rtl) {
|
||||
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
|
||||
@ -183,7 +140,7 @@ var KeyringDialog = new Lang.Class({
|
||||
|
||||
this._controlTable = table;
|
||||
this._content.messageBox.add(table, { x_fill: true, y_fill: true });
|
||||
},
|
||||
}
|
||||
|
||||
_updateSensitivity(sensitive) {
|
||||
if (this._passwordEntry) {
|
||||
@ -199,13 +156,13 @@ var KeyringDialog = new Lang.Class({
|
||||
this._continueButton.can_focus = sensitive;
|
||||
this._continueButton.reactive = sensitive;
|
||||
this._setWorking(!sensitive);
|
||||
},
|
||||
}
|
||||
|
||||
_ensureOpen() {
|
||||
// NOTE: ModalDialog.open() is safe to call if the dialog is
|
||||
// already open - it just returns true without side-effects
|
||||
if (this.open())
|
||||
return true;
|
||||
return true;
|
||||
|
||||
// The above fail if e.g. unable to get input grab
|
||||
//
|
||||
@ -215,67 +172,63 @@ var KeyringDialog = new Lang.Class({
|
||||
|
||||
log('keyringPrompt: Failed to show modal dialog.' +
|
||||
' Dismissing prompt request');
|
||||
this.prompt.cancel()
|
||||
this.prompt.cancel();
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
_onShowPassword(prompt) {
|
||||
this._buildControlTable();
|
||||
this._ensureOpen();
|
||||
this._updateSensitivity(true);
|
||||
this._passwordEntry.grab_key_focus();
|
||||
},
|
||||
}
|
||||
|
||||
_onShowConfirm(prompt) {
|
||||
this._buildControlTable();
|
||||
this._ensureOpen();
|
||||
this._updateSensitivity(true);
|
||||
this._continueButton.grab_key_focus();
|
||||
},
|
||||
}
|
||||
|
||||
_onHidePrompt(prompt) {
|
||||
this.close();
|
||||
},
|
||||
}
|
||||
|
||||
_onPasswordActivate() {
|
||||
if (this.prompt.confirm_visible)
|
||||
this._confirmEntry.grab_key_focus();
|
||||
else
|
||||
this._onContinueButton();
|
||||
},
|
||||
}
|
||||
|
||||
_onConfirmActivate() {
|
||||
this._onContinueButton();
|
||||
},
|
||||
}
|
||||
|
||||
_onContinueButton() {
|
||||
this._updateSensitivity(false);
|
||||
this.prompt.complete();
|
||||
},
|
||||
}
|
||||
|
||||
_onCancelButton() {
|
||||
this.prompt.cancel();
|
||||
},
|
||||
});
|
||||
|
||||
var KeyringDummyDialog = new Lang.Class({
|
||||
Name: 'KeyringDummyDialog',
|
||||
|
||||
_init() {
|
||||
this.prompt = new Shell.KeyringPrompt();
|
||||
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
|
||||
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
|
||||
},
|
||||
|
||||
_cancelPrompt() {
|
||||
this.prompt.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
var KeyringPrompter = new Lang.Class({
|
||||
Name: 'KeyringPrompter',
|
||||
var KeyringDummyDialog = class {
|
||||
constructor() {
|
||||
this.prompt = new Shell.KeyringPrompt();
|
||||
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
|
||||
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
|
||||
}
|
||||
|
||||
_init() {
|
||||
_cancelPrompt() {
|
||||
this.prompt.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
var KeyringPrompter = class {
|
||||
constructor() {
|
||||
this._prompter = new Gcr.SystemPrompter();
|
||||
this._prompter.connect('new-prompt', () => {
|
||||
let dialog = this._enabled ? new KeyringDialog()
|
||||
@ -287,7 +240,7 @@ var KeyringPrompter = new Lang.Class({
|
||||
this._registered = false;
|
||||
this._enabled = false;
|
||||
this._currentPrompt = null;
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
if (!this._registered) {
|
||||
@ -297,7 +250,7 @@ var KeyringPrompter = new Lang.Class({
|
||||
this._registered = true;
|
||||
}
|
||||
this._enabled = true;
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._enabled = false;
|
||||
@ -306,6 +259,6 @@ var KeyringPrompter = new Lang.Class({
|
||||
this._currentPrompt.cancel();
|
||||
this._currentPrompt = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Component = KeyringPrompter;
|
||||
|
@ -1,32 +1,21 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const NM = imports.gi.NM;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const Dialog = imports.ui.dialog;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
|
||||
const VPN_UI_GROUP = 'VPN Plugin UI';
|
||||
|
||||
var NetworkSecretDialog = new Lang.Class({
|
||||
Name: 'NetworkSecretDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
_init(agent, requestId, connection, settingName, hints, contentOverride) {
|
||||
this.parent({ styleClass: 'prompt-dialog' });
|
||||
var NetworkSecretDialog = GObject.registerClass(
|
||||
class NetworkSecretDialog extends ModalDialog.ModalDialog {
|
||||
_init(agent, requestId, connection, settingName, hints, flags, contentOverride) {
|
||||
super._init({ styleClass: 'prompt-dialog' });
|
||||
|
||||
this._agent = agent;
|
||||
this._requestId = requestId;
|
||||
@ -91,8 +80,9 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
secret.valid = secret.value.length > 0;
|
||||
this._updateOkButton();
|
||||
});
|
||||
} else
|
||||
} else {
|
||||
secret.valid = true;
|
||||
}
|
||||
|
||||
if (rtl) {
|
||||
layout.attach(secret.entry, 0, pos, 1, 1);
|
||||
@ -109,19 +99,31 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
|
||||
contentBox.messageBox.add(secretTable);
|
||||
|
||||
this._okButton = { label: _("Connect"),
|
||||
if (flags & NM.SecretAgentGetSecretsFlags.WPS_PBC_ACTIVE) {
|
||||
let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
|
||||
text: _("Alternatively you can connect by pushing the “WPS” button on your router.") });
|
||||
descriptionLabel.clutter_text.line_wrap = true;
|
||||
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
|
||||
contentBox.messageBox.add(descriptionLabel,
|
||||
{ y_fill: true,
|
||||
y_align: St.Align.START,
|
||||
expand: true });
|
||||
}
|
||||
|
||||
this._okButton = { label: _("Connect"),
|
||||
action: this._onOk.bind(this),
|
||||
default: true
|
||||
};
|
||||
|
||||
this.setButtons([{ label: _("Cancel"),
|
||||
action: this.cancel.bind(this),
|
||||
key: Clutter.KEY_Escape,
|
||||
key: Clutter.KEY_Escape,
|
||||
},
|
||||
this._okButton]);
|
||||
|
||||
this._updateOkButton();
|
||||
},
|
||||
}
|
||||
|
||||
_updateOkButton() {
|
||||
let valid = true;
|
||||
@ -132,7 +134,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
|
||||
this._okButton.button.reactive = valid;
|
||||
this._okButton.button.can_focus = valid;
|
||||
},
|
||||
}
|
||||
|
||||
_onOk() {
|
||||
let valid = true;
|
||||
@ -148,12 +150,12 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
this.close(global.get_current_time());
|
||||
}
|
||||
// do nothing if not valid
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
||||
this.close(global.get_current_time());
|
||||
},
|
||||
}
|
||||
|
||||
_validateWpaPsk(secret) {
|
||||
let value = secret.value;
|
||||
@ -169,32 +171,33 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
}
|
||||
|
||||
return (value.length >= 8 && value.length <= 63);
|
||||
},
|
||||
}
|
||||
|
||||
_validateStaticWep(secret) {
|
||||
let value = secret.value;
|
||||
if (secret.wep_key_type == NM.WepKeyType.KEY) {
|
||||
if (value.length == 10 || value.length == 26) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (!((value[i] >= 'a' && value[i] <= 'f')
|
||||
|| (value[i] >= 'A' && value[i] <= 'F')
|
||||
|| (value[i] >= '0' && value[i] <= '9')))
|
||||
return false;
|
||||
}
|
||||
} else if (value.length == 5 || value.length == 13) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
}
|
||||
} else if (value.length == 5 || value.length == 13) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (!((value[i] >= 'a' && value[i] <= 'z')
|
||||
|| (value[i] >= 'A' && value[i] <= 'Z')))
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
return false;
|
||||
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
|
||||
if (value.length < 0 || value.length > 64)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
|
||||
if (value.length < 0 || value.length > 64)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_getWirelessSecrets(secrets, wirelessSetting) {
|
||||
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
|
||||
@ -213,7 +216,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
validate: this._validateWpaPsk, password: true });
|
||||
break;
|
||||
case 'none': // static WEP
|
||||
secrets.push({ label: _("Key: "), key: 'wep-key' + wirelessSecuritySetting.wep_tx_keyidx,
|
||||
secrets.push({ label: _("Key: "), key: `wep-key${wirelessSecuritySetting.wep_tx_keyidx}`,
|
||||
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
|
||||
wep_key_type: wirelessSecuritySetting.wep_key_type,
|
||||
validate: this._validateStaticWep, password: true });
|
||||
@ -229,13 +232,12 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
this._get8021xSecrets(secrets);
|
||||
break;
|
||||
default:
|
||||
log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
|
||||
log(`Invalid wireless key management: ${wirelessSecuritySetting.key_mgmt}`);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_get8021xSecrets(secrets) {
|
||||
let ieee8021xSetting = this._connection.get_setting_802_1x();
|
||||
let phase2method;
|
||||
|
||||
/* If hints were given we know exactly what we need to ask */
|
||||
if (this._settingName == "802-1x" && this._hints.length) {
|
||||
@ -272,9 +274,9 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
value: ieee8021xSetting.private_key_password || '', password: true });
|
||||
break;
|
||||
default:
|
||||
log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
|
||||
log(`Invalid EAP/IEEE802.1x method: ${ieee8021xSetting.get_eap_method(0)}`);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getPPPoESecrets(secrets) {
|
||||
let pppoeSetting = this._connection.get_setting_pppoe();
|
||||
@ -284,7 +286,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
value: pppoeSetting.service || '', password: false });
|
||||
secrets.push({ label: _("Password: "), key: 'password',
|
||||
value: pppoeSetting.password || '', password: true });
|
||||
},
|
||||
}
|
||||
|
||||
_getMobileSecrets(secrets, connectionType) {
|
||||
let setting;
|
||||
@ -294,7 +296,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
setting = this._connection.get_setting_by_name(connectionType);
|
||||
secrets.push({ label: _("Password: "), key: 'password',
|
||||
value: setting.value || '', password: true });
|
||||
},
|
||||
}
|
||||
|
||||
_getContent() {
|
||||
let connectionSetting = this._connection.get_setting_connection();
|
||||
@ -303,7 +305,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
let ssid;
|
||||
|
||||
let content = { };
|
||||
content.secrets = [ ];
|
||||
content.secrets = [];
|
||||
|
||||
switch (connectionType) {
|
||||
case '802-11-wireless':
|
||||
@ -326,7 +328,7 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
this._getPPPoESecrets(content.secrets);
|
||||
break;
|
||||
case 'gsm':
|
||||
if (this._hints.indexOf('pin') != -1) {
|
||||
if (this._hints.includes('pin')) {
|
||||
let gsmSetting = this._connection.get_setting_gsm();
|
||||
content.title = _("PIN code required");
|
||||
content.message = _("PIN code is needed for the mobile broadband device");
|
||||
@ -342,33 +344,31 @@ var NetworkSecretDialog = new Lang.Class({
|
||||
this._getMobileSecrets(content.secrets, connectionType);
|
||||
break;
|
||||
default:
|
||||
log('Invalid connection type: ' + connectionType);
|
||||
};
|
||||
log(`Invalid connection type: ${connectionType}`);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
});
|
||||
|
||||
var VPNRequestHandler = new Lang.Class({
|
||||
Name: 'VPNRequestHandler',
|
||||
|
||||
_init(agent, requestId, authHelper, serviceType, connection, hints, flags) {
|
||||
var VPNRequestHandler = class {
|
||||
constructor(agent, requestId, authHelper, serviceType, connection, hints, flags) {
|
||||
this._agent = agent;
|
||||
this._requestId = requestId;
|
||||
this._connection = connection;
|
||||
this._flags = flags;
|
||||
this._pluginOutBuffer = [];
|
||||
this._title = null;
|
||||
this._description = null;
|
||||
this._content = [ ];
|
||||
this._content = [];
|
||||
this._shellDialog = null;
|
||||
|
||||
let connectionSetting = connection.get_setting_connection();
|
||||
|
||||
let argv = [ authHelper.fileName,
|
||||
'-u', connectionSetting.uuid,
|
||||
'-n', connectionSetting.id,
|
||||
'-s', serviceType
|
||||
];
|
||||
let argv = [authHelper.fileName,
|
||||
'-u', connectionSetting.uuid,
|
||||
'-n', connectionSetting.id,
|
||||
'-s', serviceType];
|
||||
if (authHelper.externalUIMode)
|
||||
argv.push('--external-ui-mode');
|
||||
if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
|
||||
@ -407,12 +407,12 @@ var VPNRequestHandler = new Lang.Class({
|
||||
this._vpnChildFinished.bind(this));
|
||||
|
||||
this._writeConnection();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
logError(e, 'error while spawning VPN auth helper');
|
||||
|
||||
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cancel(respond) {
|
||||
if (respond)
|
||||
@ -424,11 +424,11 @@ var VPNRequestHandler = new Lang.Class({
|
||||
} else {
|
||||
try {
|
||||
this._stdin.write('QUIT\n\n', null);
|
||||
} catch(e) { /* ignore broken pipe errors */ }
|
||||
} catch (e) { /* ignore broken pipe errors */ }
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this._destroyed)
|
||||
@ -442,7 +442,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
// Stdout is closed when we finish reading from it
|
||||
|
||||
this._destroyed = true;
|
||||
},
|
||||
}
|
||||
|
||||
_vpnChildFinished(pid, status, requestObj) {
|
||||
this._childWatch = 0;
|
||||
@ -459,11 +459,12 @@ var VPNRequestHandler = new Lang.Class({
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
||||
else
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
|
||||
} else
|
||||
} else {
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
this.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
_vpnChildProcessLineOldStyle(line) {
|
||||
if (this._previousLine != undefined) {
|
||||
@ -473,7 +474,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
if (line == '' && this._previousLine == '') {
|
||||
try {
|
||||
this._stdin.write('QUIT\n\n', null);
|
||||
} catch(e) { /* ignore broken pipe errors */ }
|
||||
} catch (e) { /* ignore broken pipe errors */ }
|
||||
} else {
|
||||
this._agent.set_password(this._requestId, this._previousLine, line);
|
||||
this._previousLine = undefined;
|
||||
@ -481,7 +482,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
} else {
|
||||
this._previousLine = line;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_readStdoutOldStyle() {
|
||||
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
|
||||
@ -498,7 +499,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
// try to read more!
|
||||
this._readStdoutOldStyle();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_readStdoutNewStyle() {
|
||||
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
|
||||
@ -516,7 +517,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
|
||||
this._readStdoutNewStyle();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_showNewStyleDialog() {
|
||||
let keyfile = new GLib.KeyFile();
|
||||
@ -561,7 +562,7 @@ var VPNRequestHandler = new Lang.Class({
|
||||
this._agent.set_password(this._requestId, groups[i], value);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// No output is a valid case it means "both secrets are stored"
|
||||
if (data.length > 0) {
|
||||
logError(e, 'error while reading VPN plugin output keyfile');
|
||||
@ -574,41 +575,39 @@ var VPNRequestHandler = new Lang.Class({
|
||||
|
||||
if (contentOverride && contentOverride.secrets.length) {
|
||||
// Only show the dialog if we actually have something to ask
|
||||
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride);
|
||||
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], this._flags, contentOverride);
|
||||
this._shellDialog.open(global.get_current_time());
|
||||
} else {
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_writeConnection() {
|
||||
let vpnSetting = this._connection.get_setting_vpn();
|
||||
|
||||
try {
|
||||
vpnSetting.foreach_data_item((key, value) => {
|
||||
this._stdin.write('DATA_KEY=' + key + '\n', null);
|
||||
this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
|
||||
this._stdin.write(`DATA_KEY=${key}\n`, null);
|
||||
this._stdin.write(`DATA_VAL=${value || ''}\n\n`, null);
|
||||
});
|
||||
vpnSetting.foreach_secret((key, value) => {
|
||||
this._stdin.write('SECRET_KEY=' + key + '\n', null);
|
||||
this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
|
||||
this._stdin.write(`SECRET_KEY=${key}\n`, null);
|
||||
this._stdin.write(`SECRET_VAL=${value || ''}\n\n`, null);
|
||||
});
|
||||
this._stdin.write('DONE\n\n', null);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
logError(e, 'internal error while writing connection to helper');
|
||||
|
||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(VPNRequestHandler.prototype);
|
||||
|
||||
var NetworkAgent = new Lang.Class({
|
||||
Name: 'NetworkAgent',
|
||||
|
||||
_init() {
|
||||
var NetworkAgent = class {
|
||||
constructor() {
|
||||
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
|
||||
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
|
||||
auto_register: false
|
||||
@ -621,9 +620,9 @@ var NetworkAgent = new Lang.Class({
|
||||
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
|
||||
try {
|
||||
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
|
||||
monitor.connect('changed', () => { this._vpnCacheBuilt = false; });
|
||||
} catch(e) {
|
||||
log('Failed to create monitor for VPN plugin dir: ' + e.message);
|
||||
monitor.connect('changed', () => this._vpnCacheBuilt = false);
|
||||
} catch (e) {
|
||||
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
|
||||
}
|
||||
|
||||
this._native.connect('new-request', this._newRequest.bind(this));
|
||||
@ -634,12 +633,12 @@ var NetworkAgent = new Lang.Class({
|
||||
try {
|
||||
this._native.init_finish(res);
|
||||
this._initialized = true;
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
this._native = null;
|
||||
logError(e, 'error initializing the NetworkManager Agent');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
if (!this._native)
|
||||
@ -648,7 +647,7 @@ var NetworkAgent = new Lang.Class({
|
||||
this._native.auto_register = true;
|
||||
if (this._initialized && !this._native.registered)
|
||||
this._native.register_async(null, null);
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
let requestId;
|
||||
@ -671,7 +670,7 @@ var NetworkAgent = new Lang.Class({
|
||||
this._native.auto_register = false;
|
||||
if (this._initialized && this._native.registered)
|
||||
this._native.unregister_async(null, null);
|
||||
},
|
||||
}
|
||||
|
||||
_showNotification(requestId, connection, settingName, hints, flags) {
|
||||
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
|
||||
@ -682,12 +681,13 @@ var NetworkAgent = new Lang.Class({
|
||||
let connectionSetting = connection.get_setting_connection();
|
||||
let connectionType = connectionSetting.get_connection_type();
|
||||
switch (connectionType) {
|
||||
case '802-11-wireless':
|
||||
case '802-11-wireless': {
|
||||
let wirelessSetting = connection.get_setting_wireless();
|
||||
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
|
||||
title = _("Authentication required by wireless network");
|
||||
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
|
||||
break;
|
||||
}
|
||||
case '802-3-ethernet':
|
||||
title = _("Wired 802.1X authentication");
|
||||
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
|
||||
@ -697,20 +697,19 @@ var NetworkAgent = new Lang.Class({
|
||||
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
|
||||
break;
|
||||
case 'gsm':
|
||||
if (hints.indexOf('pin') != -1) {
|
||||
let gsmSetting = connection.get_setting_gsm();
|
||||
if (hints.includes('pin')) {
|
||||
title = _("PIN code required");
|
||||
message = _("PIN code is needed for the mobile broadband device");
|
||||
body = _("PIN code is needed for the mobile broadband device");
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case 'cdma':
|
||||
case 'bluetooth':
|
||||
title = _("Mobile broadband network password");
|
||||
message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
break;
|
||||
default:
|
||||
log('Invalid connection type: ' + connectionType);
|
||||
log(`Invalid connection type: ${connectionType}`);
|
||||
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
@ -731,14 +730,14 @@ var NetworkAgent = new Lang.Class({
|
||||
|
||||
Main.messageTray.add(source);
|
||||
source.notify(notification);
|
||||
},
|
||||
}
|
||||
|
||||
_newRequest(agent, requestId, connection, settingName, hints, flags) {
|
||||
if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED))
|
||||
this._showNotification(requestId, connection, settingName, hints, flags);
|
||||
else
|
||||
this._handleRequest(requestId, connection, settingName, hints, flags);
|
||||
},
|
||||
}
|
||||
|
||||
_handleRequest(requestId, connection, settingName, hints, flags) {
|
||||
if (settingName == 'vpn') {
|
||||
@ -746,13 +745,13 @@ var NetworkAgent = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
|
||||
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints, flags);
|
||||
dialog.connect('destroy', () => {
|
||||
delete this._dialogs[requestId];
|
||||
});
|
||||
this._dialogs[requestId] = dialog;
|
||||
dialog.open(global.get_current_time());
|
||||
},
|
||||
}
|
||||
|
||||
_cancelRequest(agent, requestId) {
|
||||
if (this._dialogs[requestId]) {
|
||||
@ -763,7 +762,7 @@ var NetworkAgent = new Lang.Class({
|
||||
this._vpnRequests[requestId].cancel(false);
|
||||
delete this._vpnRequests[requestId];
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_vpnRequest(requestId, connection, hints, flags) {
|
||||
let vpnSetting = connection.get_setting_vpn();
|
||||
@ -785,7 +784,7 @@ var NetworkAgent = new Lang.Class({
|
||||
delete this._vpnRequests[requestId];
|
||||
});
|
||||
this._vpnRequests[requestId] = vpnRequest;
|
||||
},
|
||||
}
|
||||
|
||||
_buildVPNServiceCache() {
|
||||
if (this._vpnCacheBuilt)
|
||||
@ -818,5 +817,5 @@ var NetworkAgent = new Lang.Class({
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
var Component = NetworkAgent;
|
||||
|
@ -1,39 +1,24 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
const Pango = imports.gi.Pango;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Polkit = imports.gi.Polkit;
|
||||
const PolkitAgent = imports.gi.PolkitAgent;
|
||||
const { AccountsService, Clutter, Gio, GLib,
|
||||
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Components = imports.ui.components;
|
||||
const Dialog = imports.ui.dialog;
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const UserWidget = imports.ui.userWidget;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var DIALOG_ICON_SIZE = 48;
|
||||
|
||||
var WORK_SPINNER_ICON_SIZE = 16;
|
||||
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
var WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
var AuthenticationDialog = new Lang.Class({
|
||||
Name: 'AuthenticationDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
var AuthenticationDialog = GObject.registerClass({
|
||||
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }
|
||||
}, class AuthenticationDialog extends ModalDialog.ModalDialog {
|
||||
_init(actionId, body, cookie, userNames) {
|
||||
this.parent({ styleClass: 'prompt-dialog' });
|
||||
super._init({ styleClass: 'prompt-dialog' });
|
||||
|
||||
this.actionId = actionId;
|
||||
this.message = body;
|
||||
@ -41,9 +26,11 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._wasDismissed = false;
|
||||
|
||||
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
|
||||
this._group.visible = !Main.sessionMode.isLocked;
|
||||
this.visible = !Main.sessionMode.isLocked;
|
||||
});
|
||||
|
||||
this.connect('closed', this._onDialogClosed.bind(this));
|
||||
|
||||
let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
|
||||
let title = _("Authentication Required");
|
||||
|
||||
@ -51,19 +38,19 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this.contentLayout.add_actor(content);
|
||||
|
||||
if (userNames.length > 1) {
|
||||
log('polkitAuthenticationAgent: Received ' + userNames.length +
|
||||
' identities that can be used for authentication. Only ' +
|
||||
log(`polkitAuthenticationAgent: Received ${userNames.length} ` +
|
||||
'identities that can be used for authentication. Only ' +
|
||||
'considering one.');
|
||||
}
|
||||
|
||||
let userName = GLib.get_user_name();
|
||||
if (userNames.indexOf(userName) < 0)
|
||||
if (!userNames.includes(userName))
|
||||
userName = 'root';
|
||||
if (userNames.indexOf(userName) < 0)
|
||||
if (!userNames.includes(userName))
|
||||
userName = userNames[0];
|
||||
|
||||
this._user = AccountsService.UserManager.get_default().get_user(userName);
|
||||
let userRealName = this._user.get_real_name()
|
||||
let userRealName = this._user.get_real_name();
|
||||
this._userLoadedId = this._user.connect('notify::is_loaded',
|
||||
this._onUserChanged.bind(this));
|
||||
this._userChangedId = this._user.connect('changed',
|
||||
@ -90,15 +77,15 @@ var AuthenticationDialog = new Lang.Class({
|
||||
styleClass: 'polkit-dialog-user-icon' });
|
||||
this._userAvatar.actor.hide();
|
||||
userBox.add(this._userAvatar.actor,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
|
||||
text: userRealName }));
|
||||
userBox.add(userLabel,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
}
|
||||
@ -111,16 +98,13 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
|
||||
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
||||
text: "",
|
||||
can_focus: true});
|
||||
can_focus: true });
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
|
||||
this._passwordBox.add(this._passwordEntry,
|
||||
{ expand: true });
|
||||
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
|
||||
this._passwordBox.add(this._workSpinner.actor);
|
||||
|
||||
this.setInitialKeyFocus(this._passwordEntry);
|
||||
@ -143,7 +127,7 @@ var AuthenticationDialog = new Lang.Class({
|
||||
* gnome-shell.css sets the color to be transparent
|
||||
*/
|
||||
this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label',
|
||||
text: 'abc'});
|
||||
text: 'abc' });
|
||||
this._nullMessageLabel.add_style_class_name('hidden');
|
||||
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._nullMessageLabel.clutter_text.line_wrap = true;
|
||||
@ -153,7 +137,7 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._cancelButton = this.addButton({ label: _("Cancel"),
|
||||
action: this.cancel.bind(this),
|
||||
key: Clutter.Escape });
|
||||
this._okButton = this.addButton({ label: _("Authenticate"),
|
||||
this._okButton = this.addButton({ label: _("Authenticate"),
|
||||
action: this._onAuthenticateButtonPressed.bind(this),
|
||||
default: true });
|
||||
|
||||
@ -161,50 +145,25 @@ var AuthenticationDialog = new Lang.Class({
|
||||
|
||||
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
|
||||
this._cookie = cookie;
|
||||
},
|
||||
}
|
||||
|
||||
_setWorking(working) {
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
if (working) {
|
||||
if (working)
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
else
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
|
||||
performAuthentication() {
|
||||
this.destroySession();
|
||||
this._destroySession();
|
||||
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
|
||||
cookie: this._cookie });
|
||||
this._session.connect('completed', this._onSessionCompleted.bind(this));
|
||||
this._session.connect('request', this._onSessionRequest.bind(this));
|
||||
this._session.connect('show-error', this._onSessionShowError.bind(this));
|
||||
this._session.connect('show-info', this._onSessionShowInfo.bind(this));
|
||||
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this));
|
||||
this._sessionRequestId = this._session.connect('request', this._onSessionRequest.bind(this));
|
||||
this._sessionShowErrorId = this._session.connect('show-error', this._onSessionShowError.bind(this));
|
||||
this._sessionShowInfoId = this._session.connect('show-info', this._onSessionShowInfo.bind(this));
|
||||
this._session.initiate();
|
||||
},
|
||||
|
||||
close(timestamp) {
|
||||
this.parent(timestamp);
|
||||
|
||||
if (this._sessionUpdatedId)
|
||||
Main.sessionMode.disconnect(this._sessionUpdatedId);
|
||||
this._sessionUpdatedId = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_ensureOpen() {
|
||||
// NOTE: ModalDialog.open() is safe to call if the dialog is
|
||||
@ -221,19 +180,19 @@ var AuthenticationDialog = new Lang.Class({
|
||||
//
|
||||
// We could add retrying if this turns out to be a problem
|
||||
|
||||
log('polkitAuthenticationAgent: Failed to show modal dialog.' +
|
||||
' Dismissing authentication request for action-id ' + this.actionId +
|
||||
' cookie ' + this._cookie);
|
||||
log('polkitAuthenticationAgent: Failed to show modal dialog. ' +
|
||||
`Dismissing authentication request for action-id ${this.actionId} ` +
|
||||
`cookie ${this._cookie}`);
|
||||
this._emitDone(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_emitDone(dismissed) {
|
||||
if (!this._doneEmitted) {
|
||||
this._doneEmitted = true;
|
||||
this.emit('done', dismissed);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_updateSensitivity(sensitive) {
|
||||
this._passwordEntry.reactive = sensitive;
|
||||
@ -242,7 +201,7 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._okButton.can_focus = sensitive;
|
||||
this._okButton.reactive = sensitive;
|
||||
this._setWorking(!sensitive);
|
||||
},
|
||||
}
|
||||
|
||||
_onEntryActivate() {
|
||||
let response = this._passwordEntry.get_text();
|
||||
@ -253,11 +212,11 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._errorMessageLabel.hide();
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.show();
|
||||
},
|
||||
}
|
||||
|
||||
_onAuthenticateButtonPressed() {
|
||||
this._onEntryActivate();
|
||||
},
|
||||
}
|
||||
|
||||
_onSessionCompleted(session, gainedAuthorization) {
|
||||
if (this._completed || this._doneEmitted)
|
||||
@ -289,16 +248,16 @@ var AuthenticationDialog = new Lang.Class({
|
||||
/* Try and authenticate again */
|
||||
this.performAuthentication();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onSessionRequest(session, request, echo_on) {
|
||||
_onSessionRequest(session, request, echoOn) {
|
||||
// Cheap localization trick
|
||||
if (request == 'Password:' || request == 'Password: ')
|
||||
this._passwordLabel.set_text(_("Password:"));
|
||||
else
|
||||
this._passwordLabel.set_text(request);
|
||||
|
||||
if (echo_on)
|
||||
if (echoOn)
|
||||
this._passwordEntry.clutter_text.set_password_char('');
|
||||
else
|
||||
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
||||
@ -308,7 +267,7 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._passwordEntry.grab_key_focus();
|
||||
this._updateSensitivity(true);
|
||||
this._ensureOpen();
|
||||
},
|
||||
}
|
||||
|
||||
_onSessionShowError(session, text) {
|
||||
this._passwordEntry.set_text('');
|
||||
@ -317,7 +276,7 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
this._ensureOpen();
|
||||
},
|
||||
}
|
||||
|
||||
_onSessionShowInfo(session, text) {
|
||||
this._passwordEntry.set_text('');
|
||||
@ -326,59 +285,75 @@ var AuthenticationDialog = new Lang.Class({
|
||||
this._errorMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
this._ensureOpen();
|
||||
},
|
||||
}
|
||||
|
||||
destroySession() {
|
||||
_destroySession() {
|
||||
if (this._session) {
|
||||
if (!this._completed)
|
||||
this._session.cancel();
|
||||
this._completed = false;
|
||||
|
||||
this._session.disconnect(this._sessionCompletedId);
|
||||
this._session.disconnect(this._sessionRequestId);
|
||||
this._session.disconnect(this._sessionShowErrorId);
|
||||
this._session.disconnect(this._sessionShowInfoId);
|
||||
this._session = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onUserChanged() {
|
||||
if (this._user.is_loaded && this._userAvatar) {
|
||||
this._userAvatar.update();
|
||||
this._userAvatar.actor.show();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._wasDismissed = true;
|
||||
this.close(global.get_current_time());
|
||||
this._emitDone(true);
|
||||
},
|
||||
}
|
||||
|
||||
_onDialogClosed() {
|
||||
if (this._sessionUpdatedId)
|
||||
Main.sessionMode.disconnect(this._sessionUpdatedId);
|
||||
this._sessionUpdatedId = 0;
|
||||
|
||||
if (this._user) {
|
||||
this._user.disconnect(this._userLoadedId);
|
||||
this._user.disconnect(this._userChangedId);
|
||||
this._user = null;
|
||||
}
|
||||
|
||||
this._destroySession();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(AuthenticationDialog.prototype);
|
||||
|
||||
var AuthenticationAgent = new Lang.Class({
|
||||
Name: 'AuthenticationAgent',
|
||||
|
||||
_init() {
|
||||
var AuthenticationAgent = class {
|
||||
constructor() {
|
||||
this._currentDialog = null;
|
||||
this._handle = null;
|
||||
this._native = new Shell.PolkitAuthenticationAgent();
|
||||
this._native.connect('initiate', this._onInitiate.bind(this));
|
||||
this._native.connect('cancel', this._onCancel.bind(this));
|
||||
this._sessionUpdatedId = 0;
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
try {
|
||||
this._native.register();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
log('Failed to register AuthenticationAgent');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
try {
|
||||
this._native.unregister();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
log('Failed to unregister AuthenticationAgent');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) {
|
||||
// Don't pop up a dialog while locked
|
||||
@ -406,19 +381,18 @@ var AuthenticationAgent = new Lang.Class({
|
||||
|
||||
this._currentDialog.connect('done', this._onDialogDone.bind(this));
|
||||
this._currentDialog.performAuthentication();
|
||||
},
|
||||
}
|
||||
|
||||
_onCancel(nativeAgent) {
|
||||
this._completeRequest(false);
|
||||
},
|
||||
}
|
||||
|
||||
_onDialogDone(dialog, dismissed) {
|
||||
this._completeRequest(dismissed);
|
||||
},
|
||||
}
|
||||
|
||||
_completeRequest(dismissed) {
|
||||
this._currentDialog.close();
|
||||
this._currentDialog.destroySession();
|
||||
this._currentDialog = null;
|
||||
|
||||
if (this._sessionUpdatedId)
|
||||
@ -426,7 +400,7 @@ var AuthenticationAgent = new Lang.Class({
|
||||
this._sessionUpdatedId = 0;
|
||||
|
||||
this._native.complete(dismissed);
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var Component = AuthenticationAgent;
|
||||
|
@ -1,20 +1,14 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
var Tpl = null;
|
||||
var Tp = null;
|
||||
try {
|
||||
Tpl = imports.gi.TelepathyLogger;
|
||||
Tp = imports.gi.TelepathyGLib;
|
||||
} catch(e) {
|
||||
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
|
||||
} catch (e) {
|
||||
log('Telepathy is not available, chat integration will be disabled.');
|
||||
}
|
||||
|
||||
@ -23,7 +17,6 @@ const Main = imports.ui.main;
|
||||
const MessageList = imports.ui.messageList;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const Params = imports.misc.params;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const HAVE_TP = (Tp != null && Tpl != null);
|
||||
@ -47,8 +40,6 @@ var NotificationDirection = {
|
||||
RECEIVED: 'chat-received'
|
||||
};
|
||||
|
||||
var N_ = s => s;
|
||||
|
||||
function makeMessageFromTpMessage(tpMessage, direction) {
|
||||
let [text, flags] = tpMessage.to_text();
|
||||
|
||||
@ -79,17 +70,15 @@ function makeMessageFromTplEvent(event) {
|
||||
};
|
||||
}
|
||||
|
||||
var TelepathyComponent = new Lang.Class({
|
||||
Name: 'TelepathyComponent',
|
||||
|
||||
_init() {
|
||||
var TelepathyComponent = class {
|
||||
constructor() {
|
||||
this._client = null;
|
||||
|
||||
if (!HAVE_TP)
|
||||
return; // Telepathy isn't available
|
||||
|
||||
this._client = new TelepathyClient();
|
||||
},
|
||||
}
|
||||
|
||||
enable() {
|
||||
if (!this._client)
|
||||
@ -98,12 +87,12 @@ var TelepathyComponent = new Lang.Class({
|
||||
try {
|
||||
this._client.register();
|
||||
} catch (e) {
|
||||
throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
|
||||
throw new Error(`Could not register Telepathy client. Error: ${e}`);
|
||||
}
|
||||
|
||||
if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
|
||||
this._client.account_manager.prepare_async(null, null);
|
||||
},
|
||||
}
|
||||
|
||||
disable() {
|
||||
if (!this._client)
|
||||
@ -111,12 +100,10 @@ var TelepathyComponent = new Lang.Class({
|
||||
|
||||
this._client.unregister();
|
||||
}
|
||||
});
|
||||
|
||||
var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
Name: 'TelepathyClient',
|
||||
Extends: Tp.BaseClient,
|
||||
};
|
||||
|
||||
var TelepathyClient = HAVE_TP ? GObject.registerClass(
|
||||
class TelepathyClient extends Tp.BaseClient {
|
||||
_init() {
|
||||
// channel path -> ChatSource
|
||||
this._chatSources = {};
|
||||
@ -140,7 +127,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
// channel matching its filters is detected.
|
||||
// The second argument, recover, means _observeChannels will be run
|
||||
// for any existing channel as well.
|
||||
this.parent({ name: 'GnomeShell',
|
||||
super._init({ name: 'GnomeShell',
|
||||
account_manager: this._accountManager,
|
||||
uniquify_name: true });
|
||||
|
||||
@ -158,28 +145,28 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
// needed
|
||||
this.set_delegated_channels_callback(
|
||||
this._delegatedChannelsCb.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_observe_channels(account, conn, channels,
|
||||
dispatchOp, requests, context) {
|
||||
vfunc_observe_channels(...args) {
|
||||
let [account, conn, channels, dispatchOp, requests, context] = args;
|
||||
let len = channels.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
let channel = channels[i];
|
||||
let [targetHandle, targetHandleType] = channel.get_handle();
|
||||
|
||||
if (channel.get_invalidated())
|
||||
continue;
|
||||
continue;
|
||||
|
||||
/* Only observe contact text channels */
|
||||
if ((!(channel instanceof Tp.TextChannel)) ||
|
||||
targetHandleType != Tp.HandleType.CONTACT)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
this._createChatSource(account, conn, channel, channel.get_target_contact());
|
||||
}
|
||||
|
||||
context.accept();
|
||||
},
|
||||
}
|
||||
|
||||
_createChatSource(account, conn, channel, contact) {
|
||||
if (this._chatSources[channel.get_object_path()])
|
||||
@ -191,13 +178,13 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
source.connect('destroy', () => {
|
||||
delete this._chatSources[channel.get_object_path()];
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_handle_channels(account, conn, channels, requests,
|
||||
user_action_time, context) {
|
||||
vfunc_handle_channels(...args) {
|
||||
let [account, conn, channels, requests, userActionTime, context] = args;
|
||||
this._handlingChannels(account, conn, channels, true);
|
||||
context.accept();
|
||||
},
|
||||
}
|
||||
|
||||
_handlingChannels(account, conn, channels, notify) {
|
||||
let len = channels.length;
|
||||
@ -211,7 +198,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
}
|
||||
|
||||
if (channel.get_invalidated())
|
||||
continue;
|
||||
continue;
|
||||
|
||||
// 'notify' will be true when coming from an actual HandleChannels
|
||||
// call, and not when from a successful Claim call. The point is
|
||||
@ -231,10 +218,10 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
source.notify();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_add_dispatch_operation(account, conn, channels,
|
||||
dispatchOp, context) {
|
||||
vfunc_add_dispatch_operation(...args) {
|
||||
let [account, conn, channels, dispatchOp, context] = args;
|
||||
let channel = channels[0];
|
||||
let chanType = channel.get_channel_type();
|
||||
|
||||
@ -249,7 +236,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
else
|
||||
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
|
||||
message: 'Unsupported channel type' }));
|
||||
},
|
||||
}
|
||||
|
||||
_approveTextChannel(account, conn, channel, dispatchOp, context) {
|
||||
let [targetHandle, targetHandleType] = channel.get_handle();
|
||||
@ -266,30 +253,27 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
|
||||
dispatchOp.claim_with_finish(result);
|
||||
this._handlingChannels(account, conn, [channel], false);
|
||||
} catch (err) {
|
||||
log('Failed to Claim channel: ' + err);
|
||||
log(`Failed to Claim channel: ${err}`);
|
||||
}
|
||||
});
|
||||
|
||||
context.accept();
|
||||
},
|
||||
}
|
||||
|
||||
_delegatedChannelsCb(client, channels) {
|
||||
// Nothing to do as we don't make a distinction between observed and
|
||||
// handled channels.
|
||||
},
|
||||
}
|
||||
}) : null;
|
||||
|
||||
var ChatSource = new Lang.Class({
|
||||
Name: 'ChatSource',
|
||||
Extends: MessageTray.Source,
|
||||
var ChatSource = class extends MessageTray.Source {
|
||||
constructor(account, conn, channel, contact, client) {
|
||||
super(contact.get_alias());
|
||||
|
||||
_init(account, conn, channel, contact, client) {
|
||||
this._account = account;
|
||||
this._contact = contact;
|
||||
this._client = client;
|
||||
|
||||
this.parent(contact.get_alias());
|
||||
|
||||
this.isChat = true;
|
||||
this._pendingMessages = [];
|
||||
|
||||
@ -313,7 +297,7 @@ var ChatSource = new Lang.Class({
|
||||
Main.messageTray.add(this);
|
||||
|
||||
this._getLogMessages();
|
||||
},
|
||||
}
|
||||
|
||||
_ensureNotification() {
|
||||
if (this._notification)
|
||||
@ -329,13 +313,13 @@ var ChatSource = new Lang.Class({
|
||||
this._notification = null;
|
||||
});
|
||||
this.pushNotification(this._notification);
|
||||
},
|
||||
}
|
||||
|
||||
_createPolicy() {
|
||||
if (this._account.protocol_name == 'irc')
|
||||
return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari');
|
||||
return new MessageTray.NotificationApplicationPolicy('empathy');
|
||||
},
|
||||
}
|
||||
|
||||
createBanner() {
|
||||
this._banner = new ChatNotificationBanner(this._notification);
|
||||
@ -348,7 +332,7 @@ var ChatSource = new Lang.Class({
|
||||
});
|
||||
|
||||
return this._banner;
|
||||
},
|
||||
}
|
||||
|
||||
_updateAlias() {
|
||||
let oldAlias = this.title;
|
||||
@ -360,7 +344,7 @@ var ChatSource = new Lang.Class({
|
||||
this.setTitle(newAlias);
|
||||
if (this._notification)
|
||||
this._notification.appendAliasChange(oldAlias, newAlias);
|
||||
},
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
let file = this._contact.get_avatar_file();
|
||||
@ -369,36 +353,36 @@ var ChatSource = new Lang.Class({
|
||||
} else {
|
||||
return new Gio.ThemedIcon({ name: 'avatar-default' });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getSecondaryIcon() {
|
||||
let iconName;
|
||||
let presenceType = this._contact.get_presence_type();
|
||||
|
||||
switch (presenceType) {
|
||||
case Tp.ConnectionPresenceType.AVAILABLE:
|
||||
iconName = 'user-available';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.BUSY:
|
||||
iconName = 'user-busy';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.OFFLINE:
|
||||
iconName = 'user-offline';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.HIDDEN:
|
||||
iconName = 'user-invisible';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.AWAY:
|
||||
iconName = 'user-away';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
|
||||
iconName = 'user-idle';
|
||||
break;
|
||||
default:
|
||||
iconName = 'user-offline';
|
||||
}
|
||||
return new Gio.ThemedIcon({ name: iconName });
|
||||
},
|
||||
case Tp.ConnectionPresenceType.AVAILABLE:
|
||||
iconName = 'user-available';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.BUSY:
|
||||
iconName = 'user-busy';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.OFFLINE:
|
||||
iconName = 'user-offline';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.HIDDEN:
|
||||
iconName = 'user-invisible';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.AWAY:
|
||||
iconName = 'user-away';
|
||||
break;
|
||||
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
|
||||
iconName = 'user-idle';
|
||||
break;
|
||||
default:
|
||||
iconName = 'user-offline';
|
||||
}
|
||||
return new Gio.ThemedIcon({ name: iconName });
|
||||
}
|
||||
|
||||
_updateAvatarIcon() {
|
||||
this.iconUpdated();
|
||||
@ -406,7 +390,7 @@ var ChatSource = new Lang.Class({
|
||||
this._notification.update(this._notification.title,
|
||||
this._notification.bannerBodyText,
|
||||
{ gicon: this.getIcon() });
|
||||
},
|
||||
}
|
||||
|
||||
open() {
|
||||
Main.overview.hide();
|
||||
@ -415,7 +399,7 @@ var ChatSource = new Lang.Class({
|
||||
if (this._client.is_handling_channel(this._channel)) {
|
||||
// We are handling the channel, try to pass it to Empathy or Polari
|
||||
// (depending on the channel type)
|
||||
// We don't check if either app is availble - mission control will
|
||||
// We don't check if either app is available - mission control will
|
||||
// fallback to something else if activation fails
|
||||
|
||||
let target;
|
||||
@ -431,7 +415,7 @@ var ChatSource = new Lang.Class({
|
||||
|
||||
cd.present_channel_async(this._channel, global.get_current_time(), null);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getLogMessages() {
|
||||
let logManager = Tpl.LogManager.dup_singleton();
|
||||
@ -440,7 +424,7 @@ var ChatSource = new Lang.Class({
|
||||
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);
|
||||
@ -493,7 +477,7 @@ var ChatSource = new Lang.Class({
|
||||
|
||||
if (pendingMessages.length > 0)
|
||||
this.notify();
|
||||
},
|
||||
}
|
||||
|
||||
destroy(reason) {
|
||||
if (this._client.is_handling_channel(this._channel)) {
|
||||
@ -527,25 +511,25 @@ var ChatSource = new Lang.Class({
|
||||
this._contact.disconnect(this._notifyAvatarId);
|
||||
this._contact.disconnect(this._presenceChangedId);
|
||||
|
||||
this.parent(reason);
|
||||
},
|
||||
super.destroy(reason);
|
||||
}
|
||||
|
||||
_channelClosed() {
|
||||
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
|
||||
},
|
||||
}
|
||||
|
||||
/* All messages are new messages for Telepathy sources */
|
||||
get count() {
|
||||
return this._pendingMessages.length;
|
||||
},
|
||||
}
|
||||
|
||||
get unseenCount() {
|
||||
return this.count;
|
||||
},
|
||||
}
|
||||
|
||||
get countVisible() {
|
||||
return this.count > 0;
|
||||
},
|
||||
}
|
||||
|
||||
_messageReceived(channel, message) {
|
||||
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
|
||||
@ -565,7 +549,7 @@ var ChatSource = new Lang.Class({
|
||||
this._notifyTimeoutId = Mainloop.timeout_add(500,
|
||||
this._notifyTimeout.bind(this));
|
||||
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
|
||||
},
|
||||
}
|
||||
|
||||
_notifyTimeout() {
|
||||
if (this._pendingMessages.length != 0)
|
||||
@ -574,7 +558,7 @@ var ChatSource = new Lang.Class({
|
||||
this._notifyTimeoutId = 0;
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
// This is called for both messages we send from
|
||||
// our client and other clients as well.
|
||||
@ -582,11 +566,11 @@ var ChatSource = new Lang.Class({
|
||||
this._ensureNotification();
|
||||
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
|
||||
this._notification.appendMessage(message);
|
||||
},
|
||||
}
|
||||
|
||||
notify() {
|
||||
this.parent(this._notification);
|
||||
},
|
||||
super.notify(this._notification);
|
||||
}
|
||||
|
||||
respond(text) {
|
||||
let type;
|
||||
@ -601,7 +585,7 @@ var ChatSource = new Lang.Class({
|
||||
this._channel.send_message_async(msg, 0, (src, result) => {
|
||||
this._channel.send_message_finish(result);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setChatState(state) {
|
||||
// We don't want to send COMPOSING every time a letter is typed into
|
||||
@ -611,17 +595,17 @@ var ChatSource = new Lang.Class({
|
||||
// keep track of it with the ChatStateChanged signal but it is good
|
||||
// enough right now.
|
||||
if (state != this._chatState) {
|
||||
this._chatState = state;
|
||||
this._channel.set_chat_state_async(state, null);
|
||||
this._chatState = state;
|
||||
this._channel.set_chat_state_async(state, null);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_presenceChanged(contact, presence, status, message) {
|
||||
if (this._notification)
|
||||
this._notification.update(this._notification.title,
|
||||
this._notification.bannerBodyText,
|
||||
{ secondaryGIcon: this.getSecondaryIcon() });
|
||||
},
|
||||
}
|
||||
|
||||
_pendingRemoved(channel, message) {
|
||||
let idx = this._pendingMessages.indexOf(message);
|
||||
@ -634,35 +618,32 @@ var ChatSource = new Lang.Class({
|
||||
if (this._pendingMessages.length == 0 &&
|
||||
this._banner && !this._banner.expanded)
|
||||
this._banner.hide();
|
||||
},
|
||||
}
|
||||
|
||||
_ackMessages() {
|
||||
// Don't clear our messages here, tp-glib will send a
|
||||
// 'pending-message-removed' for each one.
|
||||
this._channel.ack_all_pending_messages_async(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var ChatNotification = new Lang.Class({
|
||||
Name: 'ChatNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init(source) {
|
||||
this.parent(source, source.title, null,
|
||||
{ secondaryGIcon: source.getSecondaryIcon() });
|
||||
var ChatNotification = class extends MessageTray.Notification {
|
||||
constructor(source) {
|
||||
super(source, source.title, null,
|
||||
{ secondaryGIcon: source.getSecondaryIcon() });
|
||||
this.setUrgency(MessageTray.Urgency.HIGH);
|
||||
this.setResident(true);
|
||||
|
||||
this.messages = [];
|
||||
this._timestampTimeoutId = 0;
|
||||
},
|
||||
}
|
||||
|
||||
destroy(reason) {
|
||||
if (this._timestampTimeoutId)
|
||||
Mainloop.source_remove(this._timestampTimeoutId);
|
||||
this._timestampTimeoutId = 0;
|
||||
this.parent(reason);
|
||||
},
|
||||
super.destroy(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* appendMessage:
|
||||
@ -700,7 +681,7 @@ var ChatNotification = new Lang.Class({
|
||||
styles: styles,
|
||||
timestamp: message.timestamp,
|
||||
noTimestamp: noTimestamp });
|
||||
},
|
||||
}
|
||||
|
||||
_filterMessages() {
|
||||
if (this.messages.length < 1)
|
||||
@ -725,7 +706,7 @@ var ChatNotification = new Lang.Class({
|
||||
for (let i = 0; i < expired.length; i++)
|
||||
this.emit('message-removed', expired[i]);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* _append:
|
||||
@ -773,7 +754,7 @@ var ChatNotification = new Lang.Class({
|
||||
}
|
||||
|
||||
this._filterMessages();
|
||||
},
|
||||
}
|
||||
|
||||
appendTimestamp() {
|
||||
this._timestampTimeoutId = 0;
|
||||
@ -784,7 +765,7 @@ var ChatNotification = new Lang.Class({
|
||||
this._filterMessages();
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
appendAliasChange(oldAlias, newAlias) {
|
||||
oldAlias = GLib.markup_escape_text(oldAlias, -1);
|
||||
@ -800,24 +781,19 @@ var ChatNotification = new Lang.Class({
|
||||
|
||||
this._filterMessages();
|
||||
}
|
||||
});
|
||||
|
||||
var ChatLineBox = new Lang.Class({
|
||||
Name: 'ChatLineBox',
|
||||
Extends: St.BoxLayout,
|
||||
};
|
||||
|
||||
var ChatLineBox = GObject.registerClass(
|
||||
class ChatLineBox extends St.BoxLayout {
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
let [, natHeight] = this.parent(forWidth);
|
||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
return [natHeight, natHeight];
|
||||
}
|
||||
});
|
||||
|
||||
var ChatNotificationBanner = new Lang.Class({
|
||||
Name: 'ChatNotificationBanner',
|
||||
Extends: MessageTray.NotificationBanner,
|
||||
|
||||
_init(notification) {
|
||||
this.parent(notification);
|
||||
var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
|
||||
constructor(notification) {
|
||||
super(notification);
|
||||
|
||||
this._responseEntry = new St.Entry({ style_class: 'chat-response',
|
||||
x_expand: true,
|
||||
@ -835,8 +811,8 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
});
|
||||
|
||||
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vscrollbar_policy: St.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: St.PolicyType.NEVER,
|
||||
visible: this.expanded });
|
||||
this._contentArea = new St.BoxLayout({ style_class: 'chat-body',
|
||||
vertical: true });
|
||||
@ -880,14 +856,14 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
|
||||
for (let i = this.notification.messages.length - 1; i >= 0; i--)
|
||||
this._addMessage(this.notification.messages[i]);
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.parent();
|
||||
super._onDestroy();
|
||||
this.notification.disconnect(this._messageAddedId);
|
||||
this.notification.disconnect(this._messageRemovedId);
|
||||
this.notification.disconnect(this._timestampChangedId);
|
||||
},
|
||||
}
|
||||
|
||||
scrollTo(side) {
|
||||
let adjustment = this._scrollArea.vscroll.adjustment;
|
||||
@ -895,11 +871,11 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
adjustment.value = adjustment.lower;
|
||||
else if (side == St.Side.BOTTOM)
|
||||
adjustment.value = adjustment.upper;
|
||||
},
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.emit('done-displaying');
|
||||
},
|
||||
}
|
||||
|
||||
_addMessage(message) {
|
||||
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
|
||||
@ -921,7 +897,7 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
this._messageActors.set(message, lineBox);
|
||||
|
||||
this._updateTimestamp(message);
|
||||
},
|
||||
}
|
||||
|
||||
_updateTimestamp(message) {
|
||||
let actor = this._messageActors.get(message);
|
||||
@ -942,7 +918,7 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
|
||||
actor.add_actor(timeLabel);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onEntryActivated() {
|
||||
let text = this._responseEntry.get_text();
|
||||
@ -955,7 +931,7 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
// see Source._messageSent
|
||||
this._responseEntry.set_text('');
|
||||
this.notification.source.respond(text);
|
||||
},
|
||||
}
|
||||
|
||||
_composingStopTimeout() {
|
||||
this._composingTimeoutId = 0;
|
||||
@ -963,7 +939,7 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
this.notification.source.setChatState(Tp.ChannelChatState.PAUSED);
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
_onEntryChanged() {
|
||||
let text = this._responseEntry.get_text();
|
||||
@ -990,6 +966,6 @@ var ChatNotificationBanner = new Lang.Class({
|
||||
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Component = TelepathyComponent;
|
||||
|
@ -1,19 +1,12 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const SwitcherPopup = imports.ui.switcherPopup;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
var POPUP_APPICON_SIZE = 96;
|
||||
var POPUP_FADE_TIME = 0.1; // seconds
|
||||
|
||||
var SortGroup = {
|
||||
TOP: 0,
|
||||
@ -21,15 +14,13 @@ var SortGroup = {
|
||||
BOTTOM: 2
|
||||
};
|
||||
|
||||
var CtrlAltTabManager = new Lang.Class({
|
||||
Name: 'CtrlAltTabManager',
|
||||
|
||||
_init() {
|
||||
var CtrlAltTabManager = class CtrlAltTabManager {
|
||||
constructor() {
|
||||
this._items = [];
|
||||
this.addGroup(global.window_group, _("Windows"),
|
||||
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
|
||||
focusCallback: this._focusWindows.bind(this) });
|
||||
},
|
||||
}
|
||||
|
||||
addGroup(root, name, icon, params) {
|
||||
let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE,
|
||||
@ -41,10 +32,10 @@ var CtrlAltTabManager = new Lang.Class({
|
||||
item.iconName = icon;
|
||||
|
||||
this._items.push(item);
|
||||
root.connect('destroy', () => { this.removeGroup(root); });
|
||||
root.connect('destroy', () => this.removeGroup(root));
|
||||
if (root instanceof St.Widget)
|
||||
global.focus_manager.add_group(root);
|
||||
},
|
||||
}
|
||||
|
||||
removeGroup(root) {
|
||||
if (root instanceof St.Widget)
|
||||
@ -55,14 +46,14 @@ var CtrlAltTabManager = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
focusGroup(item, timestamp) {
|
||||
if (item.focusCallback)
|
||||
item.focusCallback(timestamp);
|
||||
else
|
||||
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
},
|
||||
item.root.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
|
||||
// Sort the items into a consistent order; panel first, tray last,
|
||||
// and everything else in between, sorted by X coordinate, so that
|
||||
@ -77,7 +68,7 @@ var CtrlAltTabManager = new Lang.Class({
|
||||
[bx, y] = b.proxy.get_transformed_position();
|
||||
|
||||
return ax - bx;
|
||||
},
|
||||
}
|
||||
|
||||
popup(backward, binding, mask) {
|
||||
// Start with the set of focus groups that are currently mapped
|
||||
@ -102,7 +93,9 @@ var CtrlAltTabManager = new Lang.Class({
|
||||
if (app)
|
||||
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
|
||||
else
|
||||
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
|
||||
icon = textureCache.bind_cairo_surface_property(windows[i],
|
||||
'icon',
|
||||
POPUP_APPICON_SIZE);
|
||||
}
|
||||
|
||||
items.push({ name: windows[i].title,
|
||||
@ -130,22 +123,20 @@ var CtrlAltTabManager = new Lang.Class({
|
||||
this._popup = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_focusWindows(timestamp) {
|
||||
global.display.focus_default_window(timestamp);
|
||||
}
|
||||
});
|
||||
|
||||
var CtrlAltTabPopup = new Lang.Class({
|
||||
Name: 'CtrlAltTabPopup',
|
||||
Extends: SwitcherPopup.SwitcherPopup,
|
||||
};
|
||||
|
||||
var CtrlAltTabPopup = GObject.registerClass(
|
||||
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
|
||||
_init(items) {
|
||||
this.parent(items);
|
||||
super._init(items);
|
||||
|
||||
this._switcherList = new CtrlAltTabSwitcher(this._items);
|
||||
},
|
||||
}
|
||||
|
||||
_keyPressHandler(keysym, action) {
|
||||
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
|
||||
@ -160,24 +151,22 @@ var CtrlAltTabPopup = new Lang.Class({
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
}
|
||||
|
||||
_finish(time) {
|
||||
this.parent(time);
|
||||
super._finish(time);
|
||||
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var CtrlAltTabSwitcher = new Lang.Class({
|
||||
Name: 'CtrlAltTabSwitcher',
|
||||
Extends: SwitcherPopup.SwitcherList,
|
||||
|
||||
var CtrlAltTabSwitcher = GObject.registerClass(
|
||||
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
|
||||
_init(items) {
|
||||
this.parent(true);
|
||||
super._init(true);
|
||||
|
||||
for (let i = 0; i < items.length; i++)
|
||||
this._addIcon(items[i]);
|
||||
},
|
||||
}
|
||||
|
||||
_addIcon(item) {
|
||||
let box = new St.BoxLayout({ style_class: 'alt-tab-app',
|
||||
|
182
js/ui/dash.js
@ -1,14 +1,8 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
@ -16,7 +10,6 @@ const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
var DASH_ANIMATION_TIME = 0.2;
|
||||
var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
|
||||
@ -33,18 +26,16 @@ function getAppFromSource(source) {
|
||||
|
||||
// A container like StBin, but taking the child's scale into account
|
||||
// when requesting a size
|
||||
var DashItemContainer = new Lang.Class({
|
||||
Name: 'DashItemContainer',
|
||||
Extends: St.Widget,
|
||||
|
||||
var DashItemContainer = GObject.registerClass(
|
||||
class DashItemContainer extends St.Widget {
|
||||
_init() {
|
||||
this.parent({ style_class: 'dash-item-container',
|
||||
super._init({ style_class: 'dash-item-container',
|
||||
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
|
||||
x_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
this._labelText = "";
|
||||
this.label = new St.Label({ style_class: 'dash-label'});
|
||||
this.label = new St.Label({ style_class: 'dash-label' });
|
||||
this.label.hide();
|
||||
Main.layoutManager.addChrome(this.label);
|
||||
this.label_actor = this.label;
|
||||
@ -59,23 +50,23 @@ var DashItemContainer = new Lang.Class({
|
||||
this.child.destroy();
|
||||
this.label.destroy();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
let themeNode = this.get_theme_node();
|
||||
forWidth = themeNode.adjust_for_width(forWidth);
|
||||
let [minHeight, natHeight] = this.parent(forWidth);
|
||||
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
return themeNode.adjust_preferred_height(minHeight * this.scale_y,
|
||||
natHeight * this.scale_y);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
let themeNode = this.get_theme_node();
|
||||
forHeight = themeNode.adjust_for_height(forHeight);
|
||||
let [minWidth, natWidth] = this.parent(forHeight);
|
||||
let [minWidth, natWidth] = super.vfunc_get_preferred_width(forHeight);
|
||||
return themeNode.adjust_preferred_width(minWidth * this.scale_x,
|
||||
natWidth * this.scale_x);
|
||||
},
|
||||
}
|
||||
|
||||
showLabel() {
|
||||
if (!this._labelText)
|
||||
@ -90,7 +81,7 @@ var DashItemContainer = new Lang.Class({
|
||||
let itemHeight = this.allocation.y2 - this.allocation.y1;
|
||||
|
||||
let labelHeight = this.label.get_height();
|
||||
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
|
||||
let yOffset = Math.floor((itemHeight - labelHeight) / 2);
|
||||
|
||||
let y = stageY + yOffset;
|
||||
|
||||
@ -109,12 +100,12 @@ var DashItemContainer = new Lang.Class({
|
||||
time: DASH_ITEM_LABEL_SHOW_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setLabelText(text) {
|
||||
this._labelText = text;
|
||||
this.child.accessible_name = text;
|
||||
},
|
||||
}
|
||||
|
||||
hideLabel() {
|
||||
Tweener.addTween(this.label,
|
||||
@ -125,7 +116,7 @@ var DashItemContainer = new Lang.Class({
|
||||
this.label.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setChild(actor) {
|
||||
if (this.child == actor)
|
||||
@ -138,7 +129,7 @@ var DashItemContainer = new Lang.Class({
|
||||
|
||||
this.set_scale(this._childScale, this._childScale);
|
||||
this.set_opacity(this._childOpacity);
|
||||
},
|
||||
}
|
||||
|
||||
show(animate) {
|
||||
if (this.child == null)
|
||||
@ -151,7 +142,7 @@ var DashItemContainer = new Lang.Class({
|
||||
time: time,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
animateOutAndDestroy() {
|
||||
this.label.hide();
|
||||
@ -171,37 +162,35 @@ var DashItemContainer = new Lang.Class({
|
||||
this.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
set childScale(scale) {
|
||||
this._childScale = scale;
|
||||
|
||||
this.set_scale(scale, scale);
|
||||
this.queue_relayout();
|
||||
},
|
||||
}
|
||||
|
||||
get childScale() {
|
||||
return this._childScale;
|
||||
},
|
||||
}
|
||||
|
||||
set childOpacity(opacity) {
|
||||
this._childOpacity = opacity;
|
||||
|
||||
this.set_opacity(opacity);
|
||||
this.queue_redraw();
|
||||
},
|
||||
}
|
||||
|
||||
get childOpacity() {
|
||||
return this._childOpacity;
|
||||
}
|
||||
});
|
||||
|
||||
var ShowAppsIcon = new Lang.Class({
|
||||
Name: 'ShowAppsIcon',
|
||||
Extends: DashItemContainer,
|
||||
|
||||
var ShowAppsIcon = GObject.registerClass(
|
||||
class ShowAppsIcon extends DashItemContainer {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this.toggleButton = new St.Button({ style_class: 'show-apps',
|
||||
track_hover: true,
|
||||
@ -209,15 +198,15 @@ var ShowAppsIcon = new Lang.Class({
|
||||
toggle_mode: true });
|
||||
this._iconActor = null;
|
||||
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
|
||||
{ setSizeManually: true,
|
||||
showLabel: false,
|
||||
createIcon: this._createIcon.bind(this) });
|
||||
{ setSizeManually: true,
|
||||
showLabel: false,
|
||||
createIcon: this._createIcon.bind(this) });
|
||||
this.toggleButton.add_actor(this.icon);
|
||||
this.toggleButton._delegate = this;
|
||||
|
||||
this.setChild(this.toggleButton);
|
||||
this.setDragApp(null);
|
||||
},
|
||||
}
|
||||
|
||||
_createIcon(size) {
|
||||
this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
|
||||
@ -225,7 +214,7 @@ var ShowAppsIcon = new Lang.Class({
|
||||
style_class: 'show-apps-icon',
|
||||
track_hover: true });
|
||||
return this._iconActor;
|
||||
},
|
||||
}
|
||||
|
||||
_canRemoveApp(app) {
|
||||
if (app == null)
|
||||
@ -237,7 +226,7 @@ var ShowAppsIcon = new Lang.Class({
|
||||
let id = app.get_id();
|
||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
|
||||
return isFavorite;
|
||||
},
|
||||
}
|
||||
|
||||
setDragApp(app) {
|
||||
let canRemove = this._canRemoveApp(app);
|
||||
@ -250,14 +239,14 @@ var ShowAppsIcon = new Lang.Class({
|
||||
this.setLabelText(_("Remove from Favorites"));
|
||||
else
|
||||
this.setLabelText(_("Show Applications"));
|
||||
},
|
||||
}
|
||||
|
||||
handleDragOver(source, actor, x, y, time) {
|
||||
if (!this._canRemoveApp(getAppFromSource(source)))
|
||||
return DND.DragMotionResult.NO_DROP;
|
||||
|
||||
return DND.DragMotionResult.MOVE_DROP;
|
||||
},
|
||||
}
|
||||
|
||||
acceptDrop(source, actor, x, y, time) {
|
||||
let app = getAppFromSource(source);
|
||||
@ -275,36 +264,30 @@ var ShowAppsIcon = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var DragPlaceholderItem = new Lang.Class({
|
||||
Name: 'DragPlaceholderItem',
|
||||
Extends: DashItemContainer,
|
||||
|
||||
var DragPlaceholderItem = GObject.registerClass(
|
||||
class DragPlaceholderItem extends DashItemContainer {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
this.setChild(new St.Bin({ style_class: 'placeholder' }));
|
||||
}
|
||||
});
|
||||
|
||||
var EmptyDropTargetItem = new Lang.Class({
|
||||
Name: 'EmptyDropTargetItem',
|
||||
Extends: DashItemContainer,
|
||||
|
||||
var EmptyDropTargetItem = GObject.registerClass(
|
||||
class EmptyDropTargetItem extends DashItemContainer {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
|
||||
}
|
||||
});
|
||||
|
||||
var DashActor = new Lang.Class({
|
||||
Name: 'DashActor',
|
||||
Extends: St.Widget,
|
||||
|
||||
var DashActor = GObject.registerClass(
|
||||
class DashActor extends St.Widget {
|
||||
_init() {
|
||||
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
|
||||
this.parent({ name: 'dash',
|
||||
super._init({ name: 'dash',
|
||||
layout_manager: layout,
|
||||
clip_to_allocation: true });
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(box, flags) {
|
||||
let contentBox = this.get_theme_node().get_content_box(box);
|
||||
@ -325,7 +308,7 @@ var DashActor = new Lang.Class({
|
||||
childBox.y1 = contentBox.y2 - showAppsNatHeight;
|
||||
childBox.y2 = contentBox.y2;
|
||||
showAppsButton.allocate(childBox, flags);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
// We want to request the natural height of all our children
|
||||
@ -333,24 +316,22 @@ var DashActor = new Lang.Class({
|
||||
// then calls BoxLayout), but we only request the showApps
|
||||
// button as the minimum size
|
||||
|
||||
let [, natHeight] = this.parent(forWidth);
|
||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
let adjustedForWidth = themeNode.adjust_for_width(forWidth);
|
||||
let [, showAppsButton] = this.get_children();
|
||||
let [minHeight, ] = showAppsButton.get_preferred_height(adjustedForWidth);
|
||||
[minHeight, ] = themeNode.adjust_preferred_height(minHeight, natHeight);
|
||||
let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth);
|
||||
[minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight);
|
||||
|
||||
return [minHeight, natHeight];
|
||||
}
|
||||
});
|
||||
|
||||
const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
|
||||
const baseIconSizes = [16, 22, 24, 32, 48, 64];
|
||||
|
||||
var Dash = new Lang.Class({
|
||||
Name: 'Dash',
|
||||
|
||||
_init() {
|
||||
var Dash = class Dash {
|
||||
constructor() {
|
||||
this._maxHeight = -1;
|
||||
this.iconSize = 64;
|
||||
this._shownInitially = false;
|
||||
@ -407,7 +388,7 @@ var Dash = new Lang.Class({
|
||||
// Translators: this is the name of the dock/favorites area on
|
||||
// the left of the overview
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
|
||||
},
|
||||
}
|
||||
|
||||
_onDragBegin() {
|
||||
this._dragCancelled = false;
|
||||
@ -421,26 +402,26 @@ var Dash = new Lang.Class({
|
||||
this._box.insert_child_at_index(this._emptyDropTarget, 0);
|
||||
this._emptyDropTarget.show(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_onDragCancelled() {
|
||||
this._dragCancelled = true;
|
||||
this._endDrag();
|
||||
},
|
||||
}
|
||||
|
||||
_onDragEnd() {
|
||||
if (this._dragCancelled)
|
||||
return;
|
||||
|
||||
this._endDrag();
|
||||
},
|
||||
}
|
||||
|
||||
_endDrag() {
|
||||
this._clearDragPlaceholder();
|
||||
this._clearEmptyDropTarget();
|
||||
this._showAppsIcon.setDragApp(null);
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
},
|
||||
}
|
||||
|
||||
_onDragMotion(dragEvent) {
|
||||
let app = getAppFromSource(dragEvent.source);
|
||||
@ -459,18 +440,18 @@ var Dash = new Lang.Class({
|
||||
this._showAppsIcon.setDragApp(null);
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
}
|
||||
|
||||
_appIdListToHash(apps) {
|
||||
let ids = {};
|
||||
for (let i = 0; i < apps.length; i++)
|
||||
ids[apps[i].get_id()] = apps[i];
|
||||
return ids;
|
||||
},
|
||||
}
|
||||
|
||||
_queueRedisplay() {
|
||||
Main.queueDeferredWork(this._workId);
|
||||
},
|
||||
}
|
||||
|
||||
_hookUpLabel(item, appIcon) {
|
||||
item.child.connect('notify::hover', () => {
|
||||
@ -490,7 +471,7 @@ var Dash = new Lang.Class({
|
||||
this._syncLabel(item, appIcon);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_createAppItem(app) {
|
||||
let appIcon = new AppDisplay.AppIcon(app,
|
||||
@ -524,7 +505,7 @@ var Dash = new Lang.Class({
|
||||
this._hookUpLabel(item, appIcon);
|
||||
|
||||
return item;
|
||||
},
|
||||
}
|
||||
|
||||
_itemMenuStateChanged(item, opened) {
|
||||
// When the menu closes, it calls sync_hover, which means
|
||||
@ -537,7 +518,7 @@ var Dash = new Lang.Class({
|
||||
|
||||
item.hideLabel();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_syncLabel(item, appIcon) {
|
||||
let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover();
|
||||
@ -573,7 +554,7 @@ var Dash = new Lang.Class({
|
||||
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_adjustIconSize() {
|
||||
// For the icon size, we only consider children which are "proper"
|
||||
@ -603,22 +584,18 @@ var Dash = new Lang.Class({
|
||||
let firstButton = iconChildren[0].child;
|
||||
let firstIcon = firstButton._delegate.icon;
|
||||
|
||||
let minHeight, natHeight;
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
|
||||
// Enforce the current icon size during the size request
|
||||
// Enforce valid spacings during the size request
|
||||
firstIcon.icon.ensure_style();
|
||||
let [, currentHeight] = firstIcon.icon.get_size();
|
||||
firstIcon.icon.set_height(this.iconSize * scaleFactor);
|
||||
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
|
||||
firstIcon.icon.set_height(currentHeight);
|
||||
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
|
||||
let [, buttonHeight] = firstButton.get_preferred_height(-1);
|
||||
|
||||
// Subtract icon padding and box spacing from the available height
|
||||
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
|
||||
availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
|
||||
(iconChildren.length - 1) * spacing;
|
||||
|
||||
let availSize = availHeight / iconChildren.length;
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
|
||||
|
||||
let newIconSize = baseIconSizes[0];
|
||||
@ -663,7 +640,7 @@ var Dash = new Lang.Class({
|
||||
transition: 'easeOutQuad',
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_redisplay() {
|
||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||
@ -671,10 +648,10 @@ var Dash = new Lang.Class({
|
||||
let running = this._appSystem.get_running();
|
||||
|
||||
let children = this._box.get_children().filter(actor => {
|
||||
return actor.child &&
|
||||
actor.child._delegate &&
|
||||
actor.child._delegate.app;
|
||||
});
|
||||
return actor.child &&
|
||||
actor.child._delegate &&
|
||||
actor.child._delegate.app;
|
||||
});
|
||||
// Apps currently in the dash
|
||||
let oldApps = children.map(actor => actor.child._delegate.app);
|
||||
// Apps supposed to be in the dash
|
||||
@ -723,14 +700,14 @@ var Dash = new Lang.Class({
|
||||
}
|
||||
|
||||
// App removed at oldIndex
|
||||
if (oldApp && newApps.indexOf(oldApp) == -1) {
|
||||
if (oldApp && !newApps.includes(oldApp)) {
|
||||
removedActors.push(children[oldIndex]);
|
||||
oldIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// App added at newIndex
|
||||
if (newApp && oldApps.indexOf(newApp) == -1) {
|
||||
if (newApp && !oldApps.includes(newApp)) {
|
||||
addedItems.push({ app: newApp,
|
||||
item: this._createAppItem(newApp),
|
||||
pos: newIndex });
|
||||
@ -792,7 +769,7 @@ var Dash = new Lang.Class({
|
||||
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
|
||||
// Without it, StBoxLayout may use a stale size cache
|
||||
this._box.queue_relayout();
|
||||
},
|
||||
}
|
||||
|
||||
_clearDragPlaceholder() {
|
||||
if (this._dragPlaceholder) {
|
||||
@ -804,14 +781,14 @@ var Dash = new Lang.Class({
|
||||
this._dragPlaceholder = null;
|
||||
}
|
||||
this._dragPlaceholderPos = -1;
|
||||
},
|
||||
}
|
||||
|
||||
_clearEmptyDropTarget() {
|
||||
if (this._emptyDropTarget) {
|
||||
this._emptyDropTarget.animateOutAndDestroy();
|
||||
this._emptyDropTarget = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
handleDragOver(source, actor, x, y, time) {
|
||||
let app = getAppFromSource(source);
|
||||
@ -888,7 +865,7 @@ var Dash = new Lang.Class({
|
||||
return DND.DragMotionResult.MOVE_DROP;
|
||||
|
||||
return DND.DragMotionResult.COPY_DROP;
|
||||
},
|
||||
}
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop(source, actor, x, y, time) {
|
||||
@ -922,7 +899,7 @@ var Dash = new Lang.Class({
|
||||
favPos++;
|
||||
}
|
||||
|
||||
// No drag placeholder means we don't wan't to favorite the app
|
||||
// No drag placeholder means we don't want to favorite the app
|
||||
// and we are dragging it to its original position
|
||||
if (!this._dragPlaceholder)
|
||||
return true;
|
||||
@ -938,6 +915,5 @@ var Dash = new Lang.Class({
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(Dash.prototype);
|
||||
|
@ -1,29 +1,17 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GWeather = imports.gi.GWeather;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
const { Clutter, GLib, GnomeDesktop,
|
||||
GObject, GWeather, Shell, St } = imports.gi;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
const Util = imports.misc.util;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Calendar = imports.ui.calendar;
|
||||
const Weather = imports.misc.weather;
|
||||
const System = imports.system;
|
||||
|
||||
const MAX_FORECASTS = 5;
|
||||
|
||||
function _isToday(date) {
|
||||
let now = new Date();
|
||||
return now.getYear() == date.getYear() &&
|
||||
@ -31,10 +19,8 @@ function _isToday(date) {
|
||||
now.getDate() == date.getDate();
|
||||
}
|
||||
|
||||
var TodayButton = new Lang.Class({
|
||||
Name: 'TodayButton',
|
||||
|
||||
_init(calendar) {
|
||||
var TodayButton = class TodayButton {
|
||||
constructor(calendar) {
|
||||
// Having the ability to go to the current date if the user is already
|
||||
// on the current date can be confusing. So don't make the button reactive
|
||||
// until the selected date changes.
|
||||
@ -61,9 +47,9 @@ var TodayButton = new Lang.Class({
|
||||
this._calendar.connect('selected-date-changed', (calendar, date) => {
|
||||
// Make the button reactive only if the selected date is not the
|
||||
// current date.
|
||||
this.actor.reactive = !_isToday(date)
|
||||
this.actor.reactive = !_isToday(date);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setDate(date) {
|
||||
this._dayLabel.set_text(date.toLocaleFormat('%A'));
|
||||
@ -83,12 +69,10 @@ var TodayButton = new Lang.Class({
|
||||
dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
|
||||
this.actor.accessible_name = date.toLocaleFormat(dateFormat);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var WorldClocksSection = new Lang.Class({
|
||||
Name: 'WorldClocksSection',
|
||||
|
||||
_init() {
|
||||
var WorldClocksSection = class WorldClocksSection {
|
||||
constructor() {
|
||||
this._clock = new GnomeDesktop.WallClock();
|
||||
this._clockNotifyId = 0;
|
||||
|
||||
@ -118,11 +102,11 @@ var WorldClocksSection = new Lang.Class({
|
||||
this._clockAppMon.watchSetting('world-clocks',
|
||||
this._clocksChanged.bind(this));
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_sync() {
|
||||
this.actor.visible = this._clockAppMon.available;
|
||||
},
|
||||
}
|
||||
|
||||
_clocksChanged(settings) {
|
||||
this._grid.destroy_all_children();
|
||||
@ -134,7 +118,7 @@ var WorldClocksSection = new Lang.Class({
|
||||
if (!clocks[i].location)
|
||||
continue;
|
||||
let l = world.deserialize(clocks[i].location);
|
||||
if (l)
|
||||
if (l && l.get_timezone() != null)
|
||||
this._locations.push({ location: l });
|
||||
}
|
||||
|
||||
@ -152,26 +136,37 @@ var WorldClocksSection = new Lang.Class({
|
||||
layout.attach(header, 0, 0, 2, 1);
|
||||
this.actor.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;
|
||||
|
||||
let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
|
||||
: l.get_city_name();
|
||||
let name = l.get_city_name() || l.get_name();
|
||||
let label = new St.Label({ style_class: 'world-clocks-city',
|
||||
text: name,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true });
|
||||
|
||||
let time = new St.Label({ style_class: 'world-clocks-time',
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
x_expand: true });
|
||||
let time = new St.Label({ style_class: 'world-clocks-time' });
|
||||
|
||||
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
|
||||
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
|
||||
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
|
||||
let prefix = (offset >= 0) ? '+' : '-';
|
||||
let tz = new St.Label({ style_class: 'world-clocks-timezone',
|
||||
text: fmt.format(prefix, Math.abs(offset)),
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
|
||||
layout.attach(time, 0, i + 1, 1, 1);
|
||||
layout.attach(label, 1, i + 1, 1, 1);
|
||||
layout.attach(tz, 0, i + 1, 1, 1);
|
||||
layout.attach(time, 1, i + 1, 1, 1);
|
||||
layout.attach(label, 2, i + 1, 1, 1);
|
||||
} else {
|
||||
layout.attach(label, 0, i + 1, 1, 1);
|
||||
layout.attach(time, 1, i + 1, 1, 1);
|
||||
layout.attach(tz, 2, i + 1, 1, 1);
|
||||
}
|
||||
|
||||
this._locations[i].actor = time;
|
||||
@ -187,22 +182,24 @@ var WorldClocksSection = new Lang.Class({
|
||||
this._clock.disconnect(this._clockNotifyId);
|
||||
this._clockNotifyId = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_getTimeAtLocation(location) {
|
||||
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
|
||||
return GLib.DateTime.new_now(tz);
|
||||
}
|
||||
|
||||
_updateLabels() {
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i];
|
||||
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
|
||||
let now = GLib.DateTime.new_now(tz);
|
||||
let now = this._getTimeAtLocation(l.location);
|
||||
l.actor.text = Util.formatTime(now, { timeOnly: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var WeatherSection = new Lang.Class({
|
||||
Name: 'WeatherSection',
|
||||
|
||||
_init() {
|
||||
var WeatherSection = class WeatherSection {
|
||||
constructor() {
|
||||
this._weatherClient = new Weather.WeatherClient();
|
||||
|
||||
this.actor = new St.Button({ style_class: 'weather-button',
|
||||
@ -220,115 +217,119 @@ var WeatherSection = new Lang.Class({
|
||||
});
|
||||
|
||||
let box = new St.BoxLayout({ style_class: 'weather-box',
|
||||
vertical: true });
|
||||
vertical: true });
|
||||
|
||||
this.actor.child = box;
|
||||
|
||||
box.add_child(new St.Label({ style_class: 'weather-header',
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
text: _("Weather") }));
|
||||
let titleBox = new St.BoxLayout();
|
||||
titleBox.add_child(new St.Label({ style_class: 'weather-header',
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
x_expand: true,
|
||||
text: _("Weather") }));
|
||||
box.add_child(titleBox);
|
||||
|
||||
this._conditionsLabel = new St.Label({ style_class: 'weather-conditions',
|
||||
x_align: Clutter.ActorAlign.START });
|
||||
this._conditionsLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._conditionsLabel.clutter_text.line_wrap = true;
|
||||
box.add_child(this._conditionsLabel);
|
||||
this._titleLocation = new St.Label({ style_class: 'weather-header location',
|
||||
x_align: Clutter.ActorAlign.END });
|
||||
titleBox.add_child(this._titleLocation);
|
||||
|
||||
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
|
||||
this._forecastGrid = new St.Widget({ style_class: 'weather-grid',
|
||||
layout_manager: layout });
|
||||
layout.hookup_style(this._forecastGrid);
|
||||
box.add_child(this._forecastGrid);
|
||||
|
||||
this._weatherClient.connect('changed', this._sync.bind(this));
|
||||
this._sync();
|
||||
},
|
||||
}
|
||||
|
||||
_getSummary(info, capitalize=false) {
|
||||
let options = capitalize ? GWeather.FormatOptions.SENTENCE_CAPITALIZATION
|
||||
: GWeather.FormatOptions.NO_CAPITALIZATION;
|
||||
|
||||
let [ok, phenomenon, qualifier] = info.get_value_conditions();
|
||||
if (ok)
|
||||
return new GWeather.Conditions({ significant: true,
|
||||
phenomenon,
|
||||
qualifier }).to_string_full(options);
|
||||
|
||||
let [, sky] = info.get_value_sky();
|
||||
return GWeather.Sky.to_string_full(sky, options);
|
||||
},
|
||||
|
||||
_sameSummary(info1, info2) {
|
||||
let [ok1, phenom1, qualifier1] = info1.get_value_conditions();
|
||||
let [ok2, phenom2, qualifier2] = info2.get_value_conditions();
|
||||
if (ok1 || ok2)
|
||||
return ok1 == ok2 && phenom1 == phenom2 && qualifier1 == qualifier2;
|
||||
|
||||
let [, sky1] = info1.get_value_sky();
|
||||
let [, sky2] = info2.get_value_sky();
|
||||
return sky1 == sky2;
|
||||
},
|
||||
|
||||
_getSummaryText() {
|
||||
_getInfos() {
|
||||
let info = this._weatherClient.info;
|
||||
let forecasts = info.get_forecast_list();
|
||||
if (forecasts.length == 0) // No forecasts, just current conditions
|
||||
return '%s.'.format(this._getSummary(info, true));
|
||||
|
||||
let current = info;
|
||||
let infos = [info];
|
||||
for (let i = 0; i < forecasts.length; i++) {
|
||||
let [ok, timestamp] = forecasts[i].get_value_update();
|
||||
if (!_isToday(new Date(timestamp * 1000)))
|
||||
let datetime = new Date(timestamp * 1000);
|
||||
if (!_isToday(datetime))
|
||||
continue; // Ignore forecasts from other days
|
||||
|
||||
if (this._sameSummary(current, forecasts[i]))
|
||||
continue; // Ignore consecutive runs of equal summaries
|
||||
[ok, timestamp] = current.get_value_update();
|
||||
let currenttime = new Date(timestamp * 1000);
|
||||
if (currenttime.getHours() == datetime.getHours())
|
||||
continue; // Enforce a minimum interval of 1h
|
||||
|
||||
current = forecasts[i];
|
||||
if (infos.push(current) == 3)
|
||||
break; // Use a maximum of three summaries
|
||||
if (infos.push(current) == MAX_FORECASTS)
|
||||
break; // Use a maximum of five forecasts
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
let fmt;
|
||||
switch(infos.length) {
|
||||
/* Translators: %s is a weather condition like "Clear sky"; see
|
||||
libgweather for the possible condition strings. If at all
|
||||
possible, the sentence should match the grammatical case etc. of
|
||||
the inserted conditions. */
|
||||
case 1: fmt = _("%s all day."); break;
|
||||
_addForecasts() {
|
||||
let layout = this._forecastGrid.layout_manager;
|
||||
|
||||
/* Translators: %s is a weather condition like "Clear sky"; see
|
||||
libgweather for the possible condition strings. If at all
|
||||
possible, the sentence should match the grammatical case etc. of
|
||||
the inserted conditions. */
|
||||
case 2: fmt = _("%s, then %s later."); break;
|
||||
let infos = this._getInfos();
|
||||
if (this._forecastGrid.text_direction == Clutter.TextDirection.RTL)
|
||||
infos.reverse();
|
||||
|
||||
/* Translators: %s is a weather condition like "Clear sky"; see
|
||||
libgweather for the possible condition strings. If at all
|
||||
possible, the sentence should match the grammatical case etc. of
|
||||
the inserted conditions. */
|
||||
case 3: fmt = _("%s, then %s, followed by %s later."); break;
|
||||
}
|
||||
let summaries = infos.map((info, i) => {
|
||||
let capitalize = i == 0 && fmt.startsWith('%s');
|
||||
return this._getSummary(info, capitalize);
|
||||
let col = 0;
|
||||
infos.forEach(fc => {
|
||||
let [ok, timestamp] = fc.get_value_update();
|
||||
let timeStr = Util.formatTime(new Date(timestamp * 1000), {
|
||||
timeOnly: true
|
||||
});
|
||||
|
||||
let icon = new St.Icon({ style_class: 'weather-forecast-icon',
|
||||
icon_name: fc.get_symbolic_icon_name(),
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true });
|
||||
let temp = new St.Label({ style_class: 'weather-forecast-temp',
|
||||
text: fc.get_temp_summary(),
|
||||
x_align: Clutter.ActorAlign.CENTER });
|
||||
let time = new St.Label({ style_class: 'weather-forecast-time',
|
||||
text: timeStr,
|
||||
x_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
layout.attach(icon, col, 0, 1, 1);
|
||||
layout.attach(temp, col, 1, 1, 1);
|
||||
layout.attach(time, col, 2, 1, 1);
|
||||
col++;
|
||||
});
|
||||
return String.prototype.format.apply(fmt, summaries);
|
||||
},
|
||||
}
|
||||
|
||||
_getLabelText() {
|
||||
if (!this._weatherClient.hasLocation)
|
||||
return _("Select a location…");
|
||||
_setStatusLabel(text) {
|
||||
let layout = this._forecastGrid.layout_manager;
|
||||
let label = new St.Label({ text });
|
||||
layout.attach(label, 0, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (this._weatherClient.loading)
|
||||
return _("Loading…");
|
||||
_updateForecasts() {
|
||||
this._forecastGrid.destroy_all_children();
|
||||
|
||||
if (!this._weatherClient.hasLocation) {
|
||||
this._setStatusLabel(_("Select a location…"));
|
||||
return;
|
||||
}
|
||||
|
||||
let info = this._weatherClient.info;
|
||||
if (info.is_valid())
|
||||
return this._getSummaryText() + ' ' +
|
||||
/* Translators: %s is a temperature with unit, e.g. "23℃" */
|
||||
_("Feels like %s.").format(info.get_apparent());
|
||||
this._titleLocation.text = info.get_location().get_name();
|
||||
|
||||
if (this._weatherClient.loading) {
|
||||
this._setStatusLabel(_("Loading…"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.is_valid()) {
|
||||
this._addForecasts();
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.network_error())
|
||||
return _("Go online for weather information");
|
||||
|
||||
return _("Weather information is currently unavailable");
|
||||
},
|
||||
this._setStatusLabel(_("Go online for weather information"));
|
||||
else
|
||||
this._setStatusLabel(_("Weather information is currently unavailable"));
|
||||
}
|
||||
|
||||
_sync() {
|
||||
this.actor.visible = this._weatherClient.available;
|
||||
@ -336,14 +337,14 @@ var WeatherSection = new Lang.Class({
|
||||
if (!this.actor.visible)
|
||||
return;
|
||||
|
||||
this._conditionsLabel.text = this._getLabelText();
|
||||
this._titleLocation.visible = this._weatherClient.hasLocation;
|
||||
|
||||
this._updateForecasts();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var MessagesIndicator = new Lang.Class({
|
||||
Name: 'MessagesIndicator',
|
||||
|
||||
_init() {
|
||||
var MessagesIndicator = class MessagesIndicator {
|
||||
constructor() {
|
||||
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
|
||||
icon_size: 16,
|
||||
visible: false, y_expand: true,
|
||||
@ -356,63 +357,60 @@ var MessagesIndicator = new Lang.Class({
|
||||
Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
|
||||
|
||||
let sources = Main.messageTray.getSources();
|
||||
sources.forEach(source => { this._onSourceAdded(null, source); });
|
||||
},
|
||||
sources.forEach(source => this._onSourceAdded(null, source));
|
||||
}
|
||||
|
||||
_onSourceAdded(tray, source) {
|
||||
source.connect('count-updated', this._updateCount.bind(this));
|
||||
this._sources.push(source);
|
||||
this._updateCount();
|
||||
},
|
||||
}
|
||||
|
||||
_onSourceRemoved(tray, source) {
|
||||
this._sources.splice(this._sources.indexOf(source), 1);
|
||||
this._updateCount();
|
||||
},
|
||||
}
|
||||
|
||||
_updateCount() {
|
||||
let count = 0;
|
||||
this._sources.forEach(source => { count += source.unseenCount; });
|
||||
this._sources.forEach(source => count += source.unseenCount);
|
||||
count -= Main.messageTray.queueCount;
|
||||
|
||||
this.actor.visible = (count > 0);
|
||||
}
|
||||
});
|
||||
|
||||
var IndicatorPad = new Lang.Class({
|
||||
Name: 'IndicatorPad',
|
||||
Extends: St.Widget,
|
||||
};
|
||||
|
||||
var IndicatorPad = GObject.registerClass(
|
||||
class IndicatorPad extends St.Widget {
|
||||
_init(actor) {
|
||||
this._source = actor;
|
||||
this._source.connect('notify::visible', () => { this.queue_relayout(); });
|
||||
this.parent();
|
||||
},
|
||||
this._source.connect('notify::visible', () => this.queue_relayout());
|
||||
this._source.connect('notify::size', () => this.queue_relayout());
|
||||
super._init();
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_width(forHeight);
|
||||
return [0, 0];
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(container, forWidth) {
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_height(forWidth);
|
||||
return [0, 0];
|
||||
}
|
||||
});
|
||||
|
||||
var FreezableBinLayout = new Lang.Class({
|
||||
Name: 'FreezableBinLayout',
|
||||
Extends: Clutter.BinLayout,
|
||||
|
||||
var FreezableBinLayout = GObject.registerClass(
|
||||
class FreezableBinLayout extends Clutter.BinLayout {
|
||||
_init() {
|
||||
this.parent();
|
||||
super._init();
|
||||
|
||||
this._frozen = false;
|
||||
this._savedWidth = [NaN, NaN];
|
||||
this._savedHeight = [NaN, NaN];
|
||||
},
|
||||
}
|
||||
|
||||
set frozen(v) {
|
||||
if (this._frozen == v)
|
||||
@ -421,22 +419,22 @@ var FreezableBinLayout = new Lang.Class({
|
||||
this._frozen = v;
|
||||
if (!this._frozen)
|
||||
this.layout_changed();
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
if (!this._frozen || this._savedWidth.some(isNaN))
|
||||
return this.parent(container, forHeight);
|
||||
return super.vfunc_get_preferred_width(container, forHeight);
|
||||
return this._savedWidth;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height(container, forWidth) {
|
||||
if (!this._frozen || this._savedHeight.some(isNaN))
|
||||
return this.parent(container, forWidth);
|
||||
return super.vfunc_get_preferred_height(container, forWidth);
|
||||
return this._savedHeight;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_allocate(container, allocation, flags) {
|
||||
this.parent(container, allocation, flags);
|
||||
super.vfunc_allocate(container, allocation, flags);
|
||||
|
||||
let [width, height] = allocation.get_size();
|
||||
this._savedWidth = [width, width];
|
||||
@ -444,35 +442,30 @@ var FreezableBinLayout = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
var CalendarColumnLayout = new Lang.Class({
|
||||
Name: 'CalendarColumnLayout',
|
||||
Extends: Clutter.BoxLayout,
|
||||
|
||||
var CalendarColumnLayout = GObject.registerClass(
|
||||
class CalendarColumnLayout extends Clutter.BoxLayout {
|
||||
_init(actor) {
|
||||
this.parent({ orientation: Clutter.Orientation.VERTICAL });
|
||||
super._init({ orientation: Clutter.Orientation.VERTICAL });
|
||||
this._calActor = actor;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_get_preferred_width(container, forHeight) {
|
||||
if (!this._calActor || this._calActor.get_parent() != container)
|
||||
return this.parent(container, forHeight);
|
||||
return super.vfunc_get_preferred_width(container, forHeight);
|
||||
return this._calActor.get_preferred_width(forHeight);
|
||||
}
|
||||
});
|
||||
|
||||
var DateMenuButton = new Lang.Class({
|
||||
Name: 'DateMenuButton',
|
||||
Extends: PanelMenu.Button,
|
||||
|
||||
var DateMenuButton = GObject.registerClass(
|
||||
class DateMenuButton extends PanelMenu.Button {
|
||||
_init() {
|
||||
let item;
|
||||
let hbox;
|
||||
let vbox;
|
||||
|
||||
let menuAlignment = 0.5;
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
menuAlignment = 1.0 - menuAlignment;
|
||||
this.parent(menuAlignment);
|
||||
super._init(menuAlignment);
|
||||
|
||||
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
|
||||
this._indicator = new MessagesIndicator();
|
||||
@ -482,10 +475,9 @@ var DateMenuButton = new Lang.Class({
|
||||
box.add_actor(this._clockDisplay);
|
||||
box.add_actor(this._indicator.actor);
|
||||
|
||||
this.actor.label_actor = this._clockDisplay;
|
||||
this.actor.add_actor(box);
|
||||
this.actor.add_style_class_name ('clock-display');
|
||||
|
||||
this.label_actor = this._clockDisplay;
|
||||
this.add_actor(box);
|
||||
this.add_style_class_name ('clock-display');
|
||||
|
||||
let layout = new FreezableBinLayout();
|
||||
let bin = new St.Widget({ layout_manager: layout });
|
||||
@ -532,7 +524,7 @@ var DateMenuButton = new Lang.Class({
|
||||
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
|
||||
x_expand: true, x_fill: true,
|
||||
overlay_scrollbars: true });
|
||||
this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
|
||||
vbox.add_actor(this._displaysSection);
|
||||
|
||||
let displaysBox = new St.BoxLayout({ vertical: true,
|
||||
@ -553,11 +545,11 @@ var DateMenuButton = new Lang.Class({
|
||||
|
||||
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
||||
this._sessionUpdated();
|
||||
},
|
||||
}
|
||||
|
||||
_getEventSource() {
|
||||
return new Calendar.DBusEventSource();
|
||||
},
|
||||
}
|
||||
|
||||
_setEventSource(eventSource) {
|
||||
if (this._eventSource)
|
||||
@ -567,7 +559,7 @@ var DateMenuButton = new Lang.Class({
|
||||
this._messageList.setEventSource(eventSource);
|
||||
|
||||
this._eventSource = eventSource;
|
||||
},
|
||||
}
|
||||
|
||||
_updateTimeZone() {
|
||||
// SpiderMonkey caches the time zone so we must explicitly clear it
|
||||
@ -576,7 +568,7 @@ var DateMenuButton = new Lang.Class({
|
||||
System.clearDateCaches();
|
||||
|
||||
this._calendar.updateTimeZone();
|
||||
},
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
let eventSource;
|
||||
|
103
js/ui/dialog.js
@ -1,18 +1,11 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Lang = imports.lang;
|
||||
|
||||
var Dialog = new Lang.Class({
|
||||
Name: 'Dialog',
|
||||
Extends: St.Widget,
|
||||
const { Clutter, Gio, GObject, Pango, St } = imports.gi;
|
||||
|
||||
var Dialog = GObject.registerClass(
|
||||
class Dialog extends St.Widget {
|
||||
_init(parentActor, styleClass) {
|
||||
this.parent({ layout_manager: new Clutter.BinLayout() });
|
||||
super._init({ layout_manager: new Clutter.BinLayout() });
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._initialKeyFocus = null;
|
||||
@ -28,13 +21,13 @@ var Dialog = new Lang.Class({
|
||||
this._parentActor = parentActor;
|
||||
this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this));
|
||||
this._parentActor.add_child(this);
|
||||
},
|
||||
}
|
||||
|
||||
_createDialog() {
|
||||
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
vertical: true });
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
vertical: true });
|
||||
|
||||
// modal dialogs are fixed width and grow vertically; set the request
|
||||
// mode accordingly so wrapped labels are handled correctly during
|
||||
@ -45,23 +38,23 @@ var Dialog = new Lang.Class({
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true,
|
||||
style_class: "modal-dialog-content-box" });
|
||||
this._dialog.add(this.contentLayout,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous:true }) });
|
||||
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
|
||||
this._dialog.add(this.buttonLayout,
|
||||
{ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
},
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._eventId != 0)
|
||||
this._parentActor.disconnect(this._eventId);
|
||||
this._eventId = 0;
|
||||
},
|
||||
}
|
||||
|
||||
_modalEventHandler(actor, event) {
|
||||
if (event.type() == Clutter.EventType.KEY_PRESS) {
|
||||
@ -87,7 +80,7 @@ var Dialog = new Lang.Class({
|
||||
}
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
_setInitialKeyFocus(actor) {
|
||||
if (this._initialKeyFocus)
|
||||
@ -99,15 +92,15 @@ var Dialog = new Lang.Class({
|
||||
this._initialKeyFocus = null;
|
||||
this._initialKeyFocusDestroyId = 0;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
get initialKeyFocus() {
|
||||
return this._initialKeyFocus || this;
|
||||
},
|
||||
}
|
||||
|
||||
addContent(actor) {
|
||||
this.contentLayout.add (actor, { expand: true });
|
||||
},
|
||||
}
|
||||
|
||||
addButton(buttonInfo) {
|
||||
let { label, action, key } = buttonInfo;
|
||||
@ -123,11 +116,11 @@ var Dialog = new Lang.Class({
|
||||
|
||||
let button = new St.Button({ style_class: 'modal-dialog-linked-button',
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
label: label });
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
label: label });
|
||||
button.connect('clicked', action);
|
||||
|
||||
buttonInfo['button'] = button;
|
||||
@ -144,17 +137,15 @@ var Dialog = new Lang.Class({
|
||||
this.buttonLayout.add_actor(button);
|
||||
|
||||
return button;
|
||||
},
|
||||
}
|
||||
|
||||
clearButtons() {
|
||||
this.buttonLayout.destroy_all_children();
|
||||
this._buttonKeys = {};
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var MessageDialogContent = new Lang.Class({
|
||||
Name: 'MessageDialogContent',
|
||||
Extends: St.BoxLayout,
|
||||
var MessageDialogContent = GObject.registerClass({
|
||||
Properties: {
|
||||
'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
|
||||
GObject.ParamFlags.READWRITE |
|
||||
@ -172,8 +163,8 @@ var MessageDialogContent = new Lang.Class({
|
||||
GObject.ParamFlags.READWRITE |
|
||||
GObject.ParamFlags.CONSTRUCT,
|
||||
null)
|
||||
},
|
||||
|
||||
}
|
||||
}, class MessageDialogContent extends St.BoxLayout {
|
||||
_init(params) {
|
||||
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
|
||||
this._title = new St.Label({ style_class: 'headline' });
|
||||
@ -184,15 +175,15 @@ var MessageDialogContent = new Lang.Class({
|
||||
this[`_${prop}`].add_style_class_name(`message-dialog-${prop}`);
|
||||
});
|
||||
|
||||
let textProps = { ellipsize_mode: Pango.EllipsizeMode.NONE,
|
||||
let textProps = { ellipsize: Pango.EllipsizeMode.NONE,
|
||||
line_wrap: true };
|
||||
Object.assign(this._subtitle.clutter_text, textProps);
|
||||
Object.assign(this._body.clutter_text, textProps);
|
||||
this._subtitle.clutter_text.set(textProps);
|
||||
this._body.clutter_text.set(textProps);
|
||||
|
||||
if (!params.hasOwnProperty('style_class'))
|
||||
params.style_class = 'message-dialog-main-layout';
|
||||
|
||||
this.parent(params);
|
||||
super._init(params);
|
||||
|
||||
this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
|
||||
x_expand: true,
|
||||
@ -204,45 +195,51 @@ var MessageDialogContent = new Lang.Class({
|
||||
|
||||
this.add_actor(this._icon);
|
||||
this.add_actor(this.messageBox);
|
||||
},
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this._icon.gicon;
|
||||
},
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this._title.text;
|
||||
},
|
||||
}
|
||||
|
||||
get subtitle() {
|
||||
return this._subtitle.text;
|
||||
},
|
||||
}
|
||||
|
||||
get body() {
|
||||
return this._body.text;
|
||||
},
|
||||
}
|
||||
|
||||
set icon(icon) {
|
||||
Object.assign(this._icon, { gicon: icon, visible: icon != null });
|
||||
this._icon.set({
|
||||
gicon: icon,
|
||||
visible: icon != null
|
||||
});
|
||||
this.notify('icon');
|
||||
},
|
||||
}
|
||||
|
||||
set title(title) {
|
||||
this._setLabel(this._title, 'title', title);
|
||||
},
|
||||
}
|
||||
|
||||
set subtitle(subtitle) {
|
||||
this._setLabel(this._subtitle, 'subtitle', subtitle);
|
||||
},
|
||||
}
|
||||
|
||||
set body(body) {
|
||||
this._setLabel(this._body, 'body', body);
|
||||
},
|
||||
}
|
||||
|
||||
_setLabel(label, prop, value) {
|
||||
Object.assign(label, { text: value || '', visible: value != null });
|
||||
label.set({
|
||||
text: value || '',
|
||||
visible: value != null
|
||||
});
|
||||
this.notify(prop);
|
||||
},
|
||||
}
|
||||
|
||||
insertBeforeBody(actor) {
|
||||
this.messageBox.insert_child_below(actor, this._body);
|
||||
|
198
js/ui/dnd.js
@ -1,17 +1,11 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
// Time to scale down to maxDragActorSize
|
||||
var SCALE_ANIMATION_TIME = 0.25;
|
||||
@ -74,10 +68,8 @@ function removeDragMonitor(monitor) {
|
||||
}
|
||||
}
|
||||
|
||||
var _Draggable = new Lang.Class({
|
||||
Name: 'Draggable',
|
||||
|
||||
_init(actor, params) {
|
||||
var _Draggable = class _Draggable {
|
||||
constructor(actor, params) {
|
||||
params = Params.parse(params, { manualMode: false,
|
||||
restoreOnSuccess: false,
|
||||
dragActorMaxSize: undefined,
|
||||
@ -112,7 +104,8 @@ var _Draggable = new Lang.Class({
|
||||
this._dragCancellable = true;
|
||||
|
||||
this._eventsGrabbed = false;
|
||||
},
|
||||
this._capturedEventId = 0;
|
||||
}
|
||||
|
||||
_onButtonPress(actor, event) {
|
||||
if (event.get_button() != 1)
|
||||
@ -122,16 +115,26 @@ var _Draggable = new Lang.Class({
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._buttonDown = true;
|
||||
this._grabActor();
|
||||
this._grabActor(event.get_device());
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
_onTouchEvent(actor, event) {
|
||||
// We only handle touch events here on wayland. On X11
|
||||
// we do get emulated pointer events, which already works
|
||||
// for single-touch cases. Besides, the X11 passive touch grab
|
||||
// set up by Mutter will make us see first the touch events
|
||||
// and later the pointer events, so it will look like two
|
||||
// unrelated series of events, we want to avoid double handling
|
||||
// in these cases.
|
||||
if (!Meta.is_wayland_compositor())
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
|
||||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
@ -139,31 +142,40 @@ var _Draggable = new Lang.Class({
|
||||
if (Tweener.getTweenCount(actor))
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._touchSequence = event.get_event_sequence();
|
||||
|
||||
this._buttonDown = true;
|
||||
this._grabActor();
|
||||
this._grabActor(event.get_device(), event.get_event_sequence());
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
_grabDevice(actor) {
|
||||
let manager = Clutter.DeviceManager.get_default();
|
||||
let pointer = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
|
||||
|
||||
if (pointer && this._touchSequence)
|
||||
pointer.sequence_grab(this._touchSequence, actor);
|
||||
_grabDevice(actor, pointer, touchSequence) {
|
||||
if (touchSequence)
|
||||
pointer.sequence_grab(touchSequence, actor);
|
||||
else if (pointer)
|
||||
pointer.grab (actor);
|
||||
|
||||
this._grabbedDevice = pointer;
|
||||
},
|
||||
this._touchSequence = touchSequence;
|
||||
|
||||
this._capturedEventId = global.stage.connect('captured-event', (actor, event) => {
|
||||
let device = event.get_device();
|
||||
if (device != this._grabbedDevice &&
|
||||
device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
|
||||
return Clutter.EVENT_STOP;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
}
|
||||
|
||||
_ungrabDevice() {
|
||||
if (this._capturedEventId != 0) {
|
||||
global.stage.disconnect(this._capturedEventId);
|
||||
this._capturedEventId = 0;
|
||||
}
|
||||
|
||||
if (this._touchSequence)
|
||||
this._grabbedDevice.sequence_ungrab (this._touchSequence);
|
||||
else
|
||||
@ -171,13 +183,13 @@ var _Draggable = new Lang.Class({
|
||||
|
||||
this._touchSequence = null;
|
||||
this._grabbedDevice = null;
|
||||
},
|
||||
}
|
||||
|
||||
_grabActor() {
|
||||
this._grabDevice(this.actor);
|
||||
_grabActor(device, touchSequence) {
|
||||
this._grabDevice(this.actor, device, touchSequence);
|
||||
this._onEventId = this.actor.connect('event',
|
||||
this._onEvent.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
_ungrabActor() {
|
||||
if (!this._onEventId)
|
||||
@ -186,15 +198,15 @@ var _Draggable = new Lang.Class({
|
||||
this._ungrabDevice();
|
||||
this.actor.disconnect(this._onEventId);
|
||||
this._onEventId = null;
|
||||
},
|
||||
}
|
||||
|
||||
_grabEvents() {
|
||||
_grabEvents(device, touchSequence) {
|
||||
if (!this._eventsGrabbed) {
|
||||
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
|
||||
if (this._eventsGrabbed)
|
||||
this._grabDevice(_getEventHandlerActor());
|
||||
this._grabDevice(_getEventHandlerActor(), device, touchSequence);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_ungrabEvents() {
|
||||
if (this._eventsGrabbed) {
|
||||
@ -202,16 +214,38 @@ var _Draggable = new Lang.Class({
|
||||
Main.popModal(_getEventHandlerActor());
|
||||
this._eventsGrabbed = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_eventIsRelease(event) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
|
||||
let buttonMask = (Clutter.ModifierType.BUTTON1_MASK |
|
||||
Clutter.ModifierType.BUTTON2_MASK |
|
||||
Clutter.ModifierType.BUTTON3_MASK);
|
||||
/* We only obey the last button release from the device,
|
||||
* other buttons may get pressed/released during the DnD op.
|
||||
*/
|
||||
return (event.get_state() & buttonMask) == 0;
|
||||
} else if (event.type() == Clutter.EventType.TOUCH_END) {
|
||||
/* For touch, we only obey the pointer emulating sequence */
|
||||
return global.display.is_pointer_emulating_sequence(event.get_event_sequence());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_onEvent(actor, event) {
|
||||
let device = event.get_device();
|
||||
|
||||
if (this._grabbedDevice &&
|
||||
device != this._grabbedDevice &&
|
||||
device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
// We intercept BUTTON_RELEASE event to know that the button was released in case we
|
||||
// didn't start the drag, to drop the draggable in case the drag was in progress, and
|
||||
// to complete the drag and ensure that whatever happens to be under the pointer does
|
||||
// not get triggered if the drag was cancelled with Esc.
|
||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE ||
|
||||
(event.type() == Clutter.EventType.TOUCH_END &&
|
||||
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
|
||||
if (this._eventIsRelease(event)) {
|
||||
this._buttonDown = false;
|
||||
if (this._dragState == DragState.DRAGGING) {
|
||||
return this._dragActorDropped(event);
|
||||
@ -246,7 +280,7 @@ var _Draggable = new Lang.Class({
|
||||
}
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* fakeRelease:
|
||||
@ -259,7 +293,7 @@ var _Draggable = new Lang.Class({
|
||||
fakeRelease() {
|
||||
this._buttonDown = false;
|
||||
this._ungrabActor();
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* startDrag:
|
||||
@ -271,7 +305,22 @@ var _Draggable = new Lang.Class({
|
||||
* This function is useful to call if you've specified manualMode
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag(stageX, stageY, time, sequence) {
|
||||
startDrag(stageX, stageY, time, sequence, device) {
|
||||
if (currentDraggable)
|
||||
return;
|
||||
|
||||
if (device == undefined) {
|
||||
let event = Clutter.get_current_event();
|
||||
|
||||
if (event)
|
||||
device = event.get_device();
|
||||
|
||||
if (device == undefined) {
|
||||
let manager = Clutter.DeviceManager.get_default();
|
||||
device = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
currentDraggable = this;
|
||||
this._dragState = DragState.DRAGGING;
|
||||
|
||||
@ -286,8 +335,7 @@ var _Draggable = new Lang.Class({
|
||||
if (this._onEventId)
|
||||
this._ungrabActor();
|
||||
|
||||
this._touchSequence = sequence;
|
||||
this._grabEvents();
|
||||
this._grabEvents(device, sequence);
|
||||
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
|
||||
this._dragX = this._dragStartX = stageX;
|
||||
@ -355,7 +403,8 @@ var _Draggable = new Lang.Class({
|
||||
this._finishAnimation();
|
||||
|
||||
this._dragActor = null;
|
||||
this._dragState = DragState.CANCELLED;
|
||||
if (this._dragState == DragState.DRAGGING)
|
||||
this._dragState = DragState.CANCELLED;
|
||||
});
|
||||
this._dragOrigOpacity = this._dragActor.opacity;
|
||||
if (this._dragActorOpacity != undefined)
|
||||
@ -385,36 +434,37 @@ var _Draggable = new Lang.Class({
|
||||
scale_y: scale * origScale,
|
||||
time: SCALE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onUpdate() {
|
||||
onUpdate: () => {
|
||||
let currentScale = this._dragActor.scale_x / origScale;
|
||||
this._dragOffsetX = currentScale * origDragOffsetX;
|
||||
this._dragOffsetY = currentScale * origDragOffsetY;
|
||||
this._dragActor.set_position(this._dragX + this._dragOffsetX,
|
||||
this._dragY + this._dragOffsetY);
|
||||
},
|
||||
onUpdateScope: this });
|
||||
} });
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_maybeStartDrag(event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
// See if the user has moved the mouse enough to trigger a drag
|
||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
||||
if ((Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let threshold = St.Settings.get().drag_threshold * scaleFactor;
|
||||
if (!currentDraggable &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence);
|
||||
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence, event.get_device());
|
||||
this._updateDragPosition(event);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_pickTargetActor() {
|
||||
return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
||||
this._dragX, this._dragY);
|
||||
},
|
||||
}
|
||||
|
||||
_updateDragHover() {
|
||||
this._updateHoverId = 0;
|
||||
@ -471,7 +521,7 @@ var _Draggable = new Lang.Class({
|
||||
}
|
||||
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
}
|
||||
|
||||
_queueUpdateDragHover() {
|
||||
if (this._updateHoverId)
|
||||
@ -480,7 +530,7 @@ var _Draggable = new Lang.Class({
|
||||
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
|
||||
this._updateDragHover.bind(this));
|
||||
GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover');
|
||||
},
|
||||
}
|
||||
|
||||
_updateDragPosition(event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
@ -491,7 +541,7 @@ var _Draggable = new Lang.Class({
|
||||
|
||||
this._queueUpdateDragHover();
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_dragActorDropped(event) {
|
||||
let [dropX, dropY] = event.get_coords();
|
||||
@ -510,11 +560,11 @@ var _Draggable = new Lang.Class({
|
||||
let dropFunc = dragMonitors[i].dragDrop;
|
||||
if (dropFunc)
|
||||
switch (dropFunc(dropEvent)) {
|
||||
case DragDropResult.FAILURE:
|
||||
case DragDropResult.SUCCESS:
|
||||
return true;
|
||||
case DragDropResult.CONTINUE:
|
||||
continue;
|
||||
case DragDropResult.FAILURE:
|
||||
case DragDropResult.SUCCESS:
|
||||
return true;
|
||||
case DragDropResult.CONTINUE:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,8 +587,9 @@ var _Draggable = new Lang.Class({
|
||||
if (this._restoreOnSuccess) {
|
||||
this._restoreDragActor(event.get_time());
|
||||
return true;
|
||||
} else
|
||||
} else {
|
||||
this._dragActor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
this._dragState = DragState.INIT;
|
||||
@ -554,7 +605,7 @@ var _Draggable = new Lang.Class({
|
||||
this._cancelDrag(event.get_time());
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
_getRestoreLocation() {
|
||||
let x, y, scale;
|
||||
@ -586,7 +637,7 @@ var _Draggable = new Lang.Class({
|
||||
}
|
||||
|
||||
return [x, y, scale];
|
||||
},
|
||||
}
|
||||
|
||||
_cancelDrag(eventTime) {
|
||||
this.emit('drag-cancelled', eventTime);
|
||||
@ -613,7 +664,7 @@ var _Draggable = new Lang.Class({
|
||||
scale_y: snapBackScale,
|
||||
time: SNAP_BACK_ANIMATION_TIME,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_restoreDragActor(eventTime) {
|
||||
this._dragState = DragState.INIT;
|
||||
@ -626,7 +677,7 @@ var _Draggable = new Lang.Class({
|
||||
|
||||
this._animateDragEnd(eventTime,
|
||||
{ time: REVERT_ANIMATION_TIME });
|
||||
},
|
||||
}
|
||||
|
||||
_animateDragEnd(eventTime, params) {
|
||||
this._animationInProgress = true;
|
||||
@ -638,19 +689,19 @@ var _Draggable = new Lang.Class({
|
||||
params['onCompleteParams'] = [this._dragActor, eventTime];
|
||||
|
||||
// start the animation
|
||||
Tweener.addTween(this._dragActor, params)
|
||||
},
|
||||
Tweener.addTween(this._dragActor, params);
|
||||
}
|
||||
|
||||
_finishAnimation() {
|
||||
if (!this._animationInProgress)
|
||||
return
|
||||
return;
|
||||
|
||||
this._animationInProgress = false;
|
||||
if (!this._buttonDown)
|
||||
this._dragComplete();
|
||||
|
||||
global.display.set_cursor(Meta.Cursor.DEFAULT);
|
||||
},
|
||||
}
|
||||
|
||||
_onAnimationComplete(dragActor, eventTime) {
|
||||
if (this._dragOrigParent) {
|
||||
@ -664,7 +715,7 @@ var _Draggable = new Lang.Class({
|
||||
|
||||
this.emit('drag-end', eventTime, false);
|
||||
this._finishAnimation();
|
||||
},
|
||||
}
|
||||
|
||||
_dragComplete() {
|
||||
if (!this._actorDestroyed && this._dragActor)
|
||||
@ -686,8 +737,7 @@ var _Draggable = new Lang.Class({
|
||||
this._dragState = DragState.INIT;
|
||||
currentDraggable = null;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(_Draggable.prototype);
|
||||
|
||||
/**
|
||||
|
@ -1,38 +1,32 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
const { Clutter, GObject, Meta, St } = imports.gi;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
var EDGE_THRESHOLD = 20;
|
||||
var DRAG_DISTANCE = 80;
|
||||
|
||||
var EdgeDragAction = new Lang.Class({
|
||||
Name: 'EdgeDragAction',
|
||||
Extends: Clutter.GestureAction,
|
||||
var EdgeDragAction = GObject.registerClass({
|
||||
Signals: { 'activated': {} },
|
||||
|
||||
}, class EdgeDragAction extends Clutter.GestureAction {
|
||||
_init(side, allowedModes) {
|
||||
this.parent();
|
||||
super._init();
|
||||
this._side = side;
|
||||
this._allowedModes = allowedModes;
|
||||
this.set_n_touch_points(1);
|
||||
|
||||
global.display.connect('grab-op-begin', () => { this.cancel(); });
|
||||
},
|
||||
global.display.connect('grab-op-begin', () => this.cancel());
|
||||
}
|
||||
|
||||
_getMonitorRect(x, y) {
|
||||
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
|
||||
let monitorIndex = global.display.get_monitor_index_for_rect(rect);
|
||||
|
||||
return global.display.get_monitor_geometry(monitorIndex);
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_gesture_prepare(action, actor) {
|
||||
vfunc_gesture_prepare(actor) {
|
||||
if (this.get_n_current_points() == 0)
|
||||
return false;
|
||||
|
||||
@ -46,9 +40,9 @@ var EdgeDragAction = new Lang.Class({
|
||||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
|
||||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
|
||||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_gesture_progress(action, actor) {
|
||||
vfunc_gesture_progress(actor) {
|
||||
let [startX, startY] = this.get_press_coords(0);
|
||||
let [x, y] = this.get_motion_coords(0);
|
||||
let offsetX = Math.abs (x - startX);
|
||||
@ -66,9 +60,9 @@ var EdgeDragAction = new Lang.Class({
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
vfunc_gesture_end(action, actor) {
|
||||
vfunc_gesture_end(actor) {
|
||||
let [startX, startY] = this.get_press_coords(0);
|
||||
let [x, y] = this.get_motion_coords(0);
|
||||
let monitorRect = this._getMonitorRect(startX, startY);
|
||||
|