Compare commits
	
		
			322 Commits
		
	
	
		
			wip/fmuell
			...
			1151-movin
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					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 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -80,3 +80,4 @@ tests/run-test.sh
 | 
			
		||||
*~
 | 
			
		||||
*.patch
 | 
			
		||||
*.sw?
 | 
			
		||||
.vscode
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										86
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
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:v1
 | 
			
		||||
    stage: review
 | 
			
		||||
    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/gnome-shell/master:v1
 | 
			
		||||
    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/gnome-shell/master:v1
 | 
			
		||||
    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/gnome-shell/master:v1
 | 
			
		||||
    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
 | 
			
		||||
							
								
								
									
										19
									
								
								.gitlab-ci/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.gitlab-ci/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
FROM registry.gitlab.gnome.org/gnome/mutter/master:v1
 | 
			
		||||
 | 
			
		||||
RUN dnf -y update && dnf -y upgrade && \
 | 
			
		||||
    dnf install -y 'dnf-command(copr)' && \
 | 
			
		||||
    dnf copr enable -y fmuellner/gnome-shell-ci && \
 | 
			
		||||
    dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
 | 
			
		||||
 | 
			
		||||
    # bt only exports HAVE_BLUETOOTH to js, rest are outdated build-requires
 | 
			
		||||
    dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel \
 | 
			
		||||
                  upower-devel python3-devel && \
 | 
			
		||||
 | 
			
		||||
    # We'll build mutter ourselves
 | 
			
		||||
    dnf remove -y --noautoremove mutter mutter-devel && \
 | 
			
		||||
 | 
			
		||||
    # Needed for tests
 | 
			
		||||
    dnf install -y '*/xvfb-run' gdm-lib accountsservice-libs && \
 | 
			
		||||
 | 
			
		||||
    dnf clean all && \
 | 
			
		||||
    rm -rf /var/cache/dnf
 | 
			
		||||
							
								
								
									
										18
									
								
								.gitlab-ci/Dockerfile.extension-ci
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.gitlab-ci/Dockerfile.extension-ci
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
FROM registry.fedoraproject.org/fedora:latest
 | 
			
		||||
 | 
			
		||||
RUN dnf -y update && dnf -y upgrade && \
 | 
			
		||||
    dnf install -y 'dnf-command(copr)' && \
 | 
			
		||||
 | 
			
		||||
    # 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
									
								
							
							
						
						
									
										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
 | 
			
		||||
							
								
								
									
										31
									
								
								.gitlab-ci/checkout-mutter.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								.gitlab-ci/checkout-mutter.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#!/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 $merge_request_remote $merge_request_branch >/dev/null 2>&1; then
 | 
			
		||||
    mutter_target=FETCH_HEAD
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$mutter_target" ]; then
 | 
			
		||||
  mutter_target=$(git branch -r -l $shell_branch)
 | 
			
		||||
  mutter_target=${mutter_target:-origin/master}
 | 
			
		||||
  echo Using $mutter_target instead
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
git checkout $mutter_target
 | 
			
		||||
							
								
								
									
										31
									
								
								.project
									
									
									
									
									
								
							
							
						
						
									
										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
 | 
			
		||||
							
								
								
									
										10
									
								
								HACKING.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								HACKING.md
									
									
									
									
									
								
							@@ -80,9 +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 St = imports.gi.St;
 | 
			
		||||
    const { GLib, Gio, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
    const Main = imports.ui.main;
 | 
			
		||||
    const Params = imports.misc.params;
 | 
			
		||||
@@ -158,15 +156,15 @@ you to inherit from a type to use it, you can do so:
 | 
			
		||||
    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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,98 @@
 | 
			
		||||
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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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>
 | 
			
		||||
@@ -22,17 +22,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
									
								
							
							
						
						
									
										15740
									
								
								data/emoji.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -145,6 +145,42 @@
 | 
			
		||||
      <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
 | 
			
		||||
      <description></description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <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>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										599
									
								
								data/osk-layouts/ca.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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"
 | 
			
		||||
}
 | 
			
		||||
@@ -2,26 +2,23 @@
 | 
			
		||||
// 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, desaturate(#3d3846, 10%));
 | 
			
		||||
$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, 20%));
 | 
			
		||||
$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;
 | 
			
		||||
 
 | 
			
		||||
@@ -267,8 +267,7 @@ StScrollBar {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .end-session-dialog-logout-icon {
 | 
			
		||||
    //border: 2px solid #8b8b8b;
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    border-radius: 99px;
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    height: 48px;
 | 
			
		||||
    background-size: contain;
 | 
			
		||||
@@ -393,7 +392,7 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  .prompt-dialog-error-label {
 | 
			
		||||
    font-size: 10pt;
 | 
			
		||||
    color: $error_color;
 | 
			
		||||
    color: $warning_color;
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -428,7 +427,7 @@ StScrollBar {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .polkit-dialog-user-icon {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    border-radius: 99px;
 | 
			
		||||
    background-size: contain;
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    height: 48px;
 | 
			
		||||
@@ -508,6 +507,7 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  .popup-menu-arrow { } //defined globally in the TOP BAR
 | 
			
		||||
  .popup-sub-menu {
 | 
			
		||||
    padding-bottom: 1px;
 | 
			
		||||
    background-color: darken($bg_color,2%);
 | 
			
		||||
    box-shadow: inset 0 -1px 0px lighten($borders_color,5%);
 | 
			
		||||
  }
 | 
			
		||||
@@ -729,9 +729,7 @@ StScrollBar {
 | 
			
		||||
/* TOP BAR */
 | 
			
		||||
 | 
			
		||||
#panel {
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.35);
 | 
			
		||||
  /* transition from solid to transparent */
 | 
			
		||||
  transition-duration: 500ms;
 | 
			
		||||
  background-color: black;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  height: 1.86em;
 | 
			
		||||
  font-feature-settings: "tnum";
 | 
			
		||||
@@ -748,7 +746,7 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  .panel-corner {
 | 
			
		||||
    -panel-corner-radius: $panel-corner-radius;
 | 
			
		||||
    -panel-corner-background-color: rgba(0, 0, 0, 0.35);
 | 
			
		||||
    -panel-corner-background-color: black;
 | 
			
		||||
    -panel-corner-border-width: 2px;
 | 
			
		||||
    -panel-corner-border-color: transparent;
 | 
			
		||||
 | 
			
		||||
@@ -767,9 +765,7 @@ StScrollBar {
 | 
			
		||||
    -natural-hpadding: 12px;
 | 
			
		||||
    -minimum-hpadding: 6px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #eee;
 | 
			
		||||
    text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.9);
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
 | 
			
		||||
    .app-menu-icon {
 | 
			
		||||
      -st-icon-style: symbolic;
 | 
			
		||||
@@ -778,21 +774,8 @@ StScrollBar {
 | 
			
		||||
      //dimensions of the icon are hardcoded
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .system-status-icon,
 | 
			
		||||
    .app-menu-icon > StIcon,
 | 
			
		||||
    .popup-menu-arrow {
 | 
			
		||||
      icon-shadow: 0px 1px 2px rgba(0, 0, 0, 0.9);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      color: lighten($fg_color, 10%);
 | 
			
		||||
      text-shadow: 0px 1px 6px rgba(0, 0, 0, 1);
 | 
			
		||||
 | 
			
		||||
      .system-status-icon,
 | 
			
		||||
      .app-menu-icon > StIcon,
 | 
			
		||||
      .popup-menu-arrow {
 | 
			
		||||
        icon-shadow: 0px 1px 6px rgba(0, 0, 0, 1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:active, &:overview, &:focus, &:checked {
 | 
			
		||||
@@ -801,8 +784,6 @@ StScrollBar {
 | 
			
		||||
      background-color: rgba(0, 0, 0, 0.01);
 | 
			
		||||
      box-shadow: inset 0 -2px 0px lighten($selected_bg_color,5%);
 | 
			
		||||
      color: lighten($fg_color,10%);
 | 
			
		||||
 | 
			
		||||
      & > .system-status-icon { icon-shadow: black 0 2px 2px; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .system-status-icon { icon-size: 1.09em; padding: 0 5px; }
 | 
			
		||||
@@ -827,31 +808,6 @@ StScrollBar {
 | 
			
		||||
  .screencast-indicator { color: $warning_color; }
 | 
			
		||||
 | 
			
		||||
  .remote-access-indicator { color: $warning_color; }
 | 
			
		||||
 | 
			
		||||
  &.solid {
 | 
			
		||||
    background-color: black;
 | 
			
		||||
    /* transition from transparent to solid */
 | 
			
		||||
    transition-duration: 300ms;
 | 
			
		||||
 | 
			
		||||
    .panel-corner {
 | 
			
		||||
      -panel-corner-background-color: black;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .panel-button {
 | 
			
		||||
      color: #ccc;
 | 
			
		||||
      text-shadow: none;
 | 
			
		||||
 | 
			
		||||
      &:hover, &:active, &:overview, &:focus, &:checked {
 | 
			
		||||
        color: lighten($fg_color, 10%);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .system-status-icon,
 | 
			
		||||
    .app-menu-icon > StIcon,
 | 
			
		||||
    .popup-menu-arrow {
 | 
			
		||||
      icon-shadow: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  // calendar popover
 | 
			
		||||
@@ -922,14 +878,47 @@ StScrollBar {
 | 
			
		||||
      font-weight: bold;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .world-clocks-grid {
 | 
			
		||||
    .weather-header.location {
 | 
			
		||||
      font-weight: normal;
 | 
			
		||||
      font-size: 0.9em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .world-clocks-grid,
 | 
			
		||||
    .weather-grid {
 | 
			
		||||
      spacing-rows: 0.4em;
 | 
			
		||||
      spacing-columns: 0.8em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .weather-box {
 | 
			
		||||
      spacing: 0.4em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .world-clocks-city {
 | 
			
		||||
      font-weight: bold;
 | 
			
		||||
      font-size: 0.9em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .world-clocks-time {
 | 
			
		||||
      color: darken($fg_color,20%);
 | 
			
		||||
      font-feature-settings: "tnum";
 | 
			
		||||
      font-size: 1.2em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .world-clocks-timezone {
 | 
			
		||||
      color: darken($fg_color,40%);
 | 
			
		||||
      font-feature-settings: "tnum";
 | 
			
		||||
      font-size: 0.9em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .weather-forecast-icon {
 | 
			
		||||
      icon-size: 2.18em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .weather-forecast-time {
 | 
			
		||||
      color: darken($fg_color,40%);
 | 
			
		||||
      font-size: 0.8em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .calendar-month-label {
 | 
			
		||||
      color: darken($fg_color,5%);
 | 
			
		||||
      font-weight: bold;
 | 
			
		||||
@@ -1042,6 +1031,11 @@ StScrollBar {
 | 
			
		||||
            -st-icon-style: symbolic;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .message-icon-bin > .fallback-window-icon {
 | 
			
		||||
            width: 1.09em;
 | 
			
		||||
            height: 1.09em;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .message-secondary-bin {
 | 
			
		||||
            padding: 0 0.82em;;
 | 
			
		||||
          }
 | 
			
		||||
@@ -1091,11 +1085,7 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  // a little unstructured mess:
 | 
			
		||||
 | 
			
		||||
  .system-switch-user-submenu-icon.user-icon {
 | 
			
		||||
    icon-size: 20px;
 | 
			
		||||
    padding: 0 2px;
 | 
			
		||||
  }
 | 
			
		||||
  .system-switch-user-submenu-icon.default-icon {
 | 
			
		||||
  .system-switch-user-submenu-icon {
 | 
			
		||||
    icon-size: 16px;
 | 
			
		||||
    padding: 0 4px;
 | 
			
		||||
  }
 | 
			
		||||
@@ -1107,6 +1097,11 @@ StScrollBar {
 | 
			
		||||
    .label-shadow { color: transparent; }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .app-menu,
 | 
			
		||||
  .app-well-menu {
 | 
			
		||||
    max-width: 27.25em;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .aggregate-menu {
 | 
			
		||||
    min-width: 21em;
 | 
			
		||||
    .popup-menu-icon { padding: 0 4px; }
 | 
			
		||||
@@ -1148,7 +1143,7 @@ StScrollBar {
 | 
			
		||||
.ripple-box:rtl { border-radius: 0 0 0 52px; } // just a simple change to the border radius position
 | 
			
		||||
 | 
			
		||||
// not really top bar only
 | 
			
		||||
.popup-menu-arrow { width: 16px; height: 16px; }
 | 
			
		||||
.popup-menu-arrow { icon-size: 1.09em; }
 | 
			
		||||
.popup-menu-icon { icon-size: 1.09em; }
 | 
			
		||||
 | 
			
		||||
//close buttons
 | 
			
		||||
@@ -1294,6 +1289,8 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  .search-section-separator { height: 2px; background-color: rgba(255, 255, 255, 0.2); }
 | 
			
		||||
 | 
			
		||||
  .search-section:last-child .search-section-separator { background-color: transparent; }
 | 
			
		||||
 | 
			
		||||
  .list-search-result-content { spacing: 30px; }
 | 
			
		||||
  .list-search-result-title { color: darken($osd_fg_color,5%); spacing: 12px; }
 | 
			
		||||
  .list-search-result-description { color: transparentize(darken($osd_fg_color,15%), 0.5); }
 | 
			
		||||
@@ -1456,13 +1453,13 @@ StScrollBar {
 | 
			
		||||
      height: 12px;
 | 
			
		||||
      background-color: transparent;
 | 
			
		||||
      border: 2px solid rgba(255, 255, 255, 0.4);
 | 
			
		||||
      border-radius:12px;
 | 
			
		||||
      border-radius: 12px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:hover .page-indicator-icon { border-color: white; }
 | 
			
		||||
    &:active .page-indicator-icon { border: none; margin: 2px; background-color:#fff; }
 | 
			
		||||
    &:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
 | 
			
		||||
    &:checked .page-indicator-icon,
 | 
			
		||||
    &:checked:active { background-color: #fff;}
 | 
			
		||||
    &:checked:active .page-indicator-icon { background-color: white;}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .no-frequent-applications-label { @extend %status_text; }
 | 
			
		||||
@@ -1646,6 +1643,15 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
#keyboard {
 | 
			
		||||
    background-color: transparentize($osd_bg_color, 0.3);
 | 
			
		||||
 | 
			
		||||
    .page-indicator {
 | 
			
		||||
        padding: 4px 4px;
 | 
			
		||||
 | 
			
		||||
        .page-indicator-icon {
 | 
			
		||||
            width: 6px;
 | 
			
		||||
            height: 6px
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  .key-container {
 | 
			
		||||
@@ -1655,8 +1661,8 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  .keyboard-key {
 | 
			
		||||
    background-color: #393f3f;
 | 
			
		||||
    min-height: 2em;
 | 
			
		||||
    min-width: 2em;
 | 
			
		||||
    min-height: 1.2em;
 | 
			
		||||
    min-width: 1.2em;
 | 
			
		||||
    font-size: 16pt;
 | 
			
		||||
    border-radius: 3px;
 | 
			
		||||
    border: 1px solid #464d4d;
 | 
			
		||||
@@ -1707,6 +1713,20 @@ StScrollBar {
 | 
			
		||||
    -boxpointer-gap: 5px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
.emoji-page {
 | 
			
		||||
  .keyboard-key {
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    border: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.emoji-panel {
 | 
			
		||||
  .keyboard-key:latched {
 | 
			
		||||
    border-color: #005684;
 | 
			
		||||
    background-color: #006098;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IBus Candidate Popup
 | 
			
		||||
 | 
			
		||||
.candidate-popup-content {
 | 
			
		||||
@@ -1741,13 +1761,11 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
/* Auth Dialogs & Screen Shield */
 | 
			
		||||
 | 
			
		||||
.framed-user-icon {
 | 
			
		||||
.user-icon {
 | 
			
		||||
  background-size: contain;
 | 
			
		||||
  border: 2px solid $osd_fg_color;
 | 
			
		||||
  color: $osd_fg_color;
 | 
			
		||||
  border-radius: 3px;
 | 
			
		||||
  border-radius: 99px;
 | 
			
		||||
  &:hover {
 | 
			
		||||
    border-color: lighten($osd_fg_color,30%);
 | 
			
		||||
    color: lighten($osd_fg_color,30%);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ do
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
cat >>$TMP_GRESOURCE_FILE <<EOF
 | 
			
		||||
    <file>emoji.json</file>
 | 
			
		||||
  </gresource>
 | 
			
		||||
</gresources>
 | 
			
		||||
EOF
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,5 @@
 | 
			
		||||
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;
 | 
			
		||||
@@ -104,29 +99,111 @@ var Application = class {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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());
 | 
			
		||||
            let backticks = '```';
 | 
			
		||||
            clipboard.set_text(
 | 
			
		||||
                // markdown for pasting in gitlab issues
 | 
			
		||||
                `The settings of extension ${extension.uuid} had an error:\n${
 | 
			
		||||
                backticks}\n${exc}\n${backticks}\n\nStack trace:\n${
 | 
			
		||||
                backticks}\n${exc.stack}${backticks}\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) {
 | 
			
		||||
@@ -147,8 +224,12 @@ var Application = 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));
 | 
			
		||||
@@ -156,6 +237,8 @@ var Application = 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]) => {
 | 
			
		||||
@@ -200,6 +283,11 @@ var Application = class {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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;
 | 
			
		||||
@@ -239,6 +327,171 @@ var Application = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Expander = GObject.registerClass({
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'label': GObject.ParamSpec.string(
 | 
			
		||||
            'label', 'label', 'label',
 | 
			
		||||
            GObject.ParamFlags.READWRITE,
 | 
			
		||||
            null
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}, class Expander extends Gtk.Box {
 | 
			
		||||
    _init(params = {}) {
 | 
			
		||||
        this._labelText = null;
 | 
			
		||||
 | 
			
		||||
        super._init(Object.assign(params, {
 | 
			
		||||
            orientation: Gtk.Orientation.VERTICAL,
 | 
			
		||||
            spacing: 0
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._frame = new Gtk.Frame({
 | 
			
		||||
            shadow_type: Gtk.ShadowType.IN,
 | 
			
		||||
            hexpand: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let eventBox = new Gtk.EventBox();
 | 
			
		||||
        this._frame.add(eventBox);
 | 
			
		||||
 | 
			
		||||
        let hbox = new Gtk.Box({
 | 
			
		||||
            spacing: 6,
 | 
			
		||||
            margin: 12
 | 
			
		||||
        });
 | 
			
		||||
        eventBox.add(hbox);
 | 
			
		||||
 | 
			
		||||
        this._arrow = new Gtk.Image({
 | 
			
		||||
            icon_name: 'pan-end-symbolic'
 | 
			
		||||
        });
 | 
			
		||||
        hbox.add(this._arrow);
 | 
			
		||||
 | 
			
		||||
        this._label = new Gtk.Label({ label: this._labelText });
 | 
			
		||||
        hbox.add(this._label);
 | 
			
		||||
 | 
			
		||||
        this._revealer = new Gtk.Revealer();
 | 
			
		||||
 | 
			
		||||
        this._childBin = new Gtk.Frame({
 | 
			
		||||
            shadow_type: Gtk.ShadowType.IN
 | 
			
		||||
        });
 | 
			
		||||
        this._revealer.add(this._childBin);
 | 
			
		||||
 | 
			
		||||
        // Directly chain up to parent for internal children
 | 
			
		||||
        super.add(this._frame);
 | 
			
		||||
        super.add(this._revealer);
 | 
			
		||||
 | 
			
		||||
        let provider = new Gtk.CssProvider();
 | 
			
		||||
        provider.load_from_data('* { border-top-width: 0; }');
 | 
			
		||||
        this._childBin.get_style_context().add_provider(
 | 
			
		||||
            provider,
 | 
			
		||||
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        this._gesture = new Gtk.GestureMultiPress({
 | 
			
		||||
            widget: this._frame,
 | 
			
		||||
            button: 0,
 | 
			
		||||
            exclusive: true
 | 
			
		||||
        });
 | 
			
		||||
        this._gesture.connect('released', (gesture, nPress) => {
 | 
			
		||||
            if (nPress == 1)
 | 
			
		||||
                this._revealer.reveal_child = !this._revealer.reveal_child;
 | 
			
		||||
        });
 | 
			
		||||
        this._revealer.connect('notify::reveal-child', () => {
 | 
			
		||||
            if (this._revealer.reveal_child)
 | 
			
		||||
                this._arrow.icon_name = 'pan-down-symbolic';
 | 
			
		||||
            else
 | 
			
		||||
                this._arrow.icon_name = 'pan-end-symbolic';
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get label() {
 | 
			
		||||
        return this._labelText;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set label(text) {
 | 
			
		||||
        if (this._labelText == text)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._label)
 | 
			
		||||
            this._label.label = text;
 | 
			
		||||
        this._labelText = text;
 | 
			
		||||
        this.notify('label');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add(child) {
 | 
			
		||||
        // set expanded child
 | 
			
		||||
        this._childBin.get_children().forEach(c => {
 | 
			
		||||
            this._childBin.remove(c);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (child)
 | 
			
		||||
            this._childBin.add(child);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var 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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
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;
 | 
			
		||||
@@ -96,7 +93,7 @@ var AuthPrompt = 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,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const FprintManagerIface = `
 | 
			
		||||
<node>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,19 +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 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;
 | 
			
		||||
@@ -161,8 +151,8 @@ Signals.addSignalMethods(UserListItem.prototype);
 | 
			
		||||
var UserList = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                              Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.actor.set_policy(St.PolicyType.NEVER,
 | 
			
		||||
                              St.PolicyType.AUTOMATIC);
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                       style_class: 'login-dialog-user-list',
 | 
			
		||||
@@ -183,7 +173,7 @@ var UserList = 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();
 | 
			
		||||
@@ -335,7 +325,8 @@ var SessionMenuButton = class {
 | 
			
		||||
                 this._button.remove_style_pseudo_class('active');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
 | 
			
		||||
        this._manager = new PopupMenu.PopupMenuManager({ actor: this._button },
 | 
			
		||||
                                                       { actionMode: Shell.ActionMode.NONE });
 | 
			
		||||
        this._manager.addMenu(this._menu);
 | 
			
		||||
 | 
			
		||||
        this._button.connect('clicked', () => { this._menu.toggle(); });
 | 
			
		||||
@@ -473,8 +464,8 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        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 });
 | 
			
		||||
@@ -490,6 +481,9 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
        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();
 | 
			
		||||
 | 
			
		||||
@@ -787,11 +781,12 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
            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));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +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 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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -78,11 +78,11 @@
 | 
			
		||||
    <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/pointerWatcher.js</file>
 | 
			
		||||
    <file>ui/popupMenu.js</file>
 | 
			
		||||
    <file>ui/remoteMenu.js</file>
 | 
			
		||||
    <file>ui/remoteSearch.js</file>
 | 
			
		||||
    <file>ui/runDialog.js</file>
 | 
			
		||||
    <file>ui/screenShield.js</file>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
// Common utils for the extension system and the extension
 | 
			
		||||
// preferences tool
 | 
			
		||||
 | 
			
		||||
const Gettext = imports.gettext;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -63,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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
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();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const IBus = imports.gi.IBus;
 | 
			
		||||
const { Clutter, GLib, GObject, IBus } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Keyboard = imports.ui.status.keyboard;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
var HIDE_PANEL_TIME = 50;
 | 
			
		||||
 | 
			
		||||
var InputMethod = GObject.registerClass(
 | 
			
		||||
class InputMethod extends Clutter.InputMethod {
 | 
			
		||||
@@ -15,6 +15,7 @@ class InputMethod extends Clutter.InputMethod {
 | 
			
		||||
        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));
 | 
			
		||||
@@ -138,6 +139,11 @@ class InputMethod extends Clutter.InputMethod {
 | 
			
		||||
            this._updateCapabilities();
 | 
			
		||||
            this._emitRequestSurrounding();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._hidePanelId) {
 | 
			
		||||
            GLib.source_remove(this._hidePanelId);
 | 
			
		||||
            this._hidePanelId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_focus_out() {
 | 
			
		||||
@@ -152,6 +158,12 @@ class InputMethod extends Clutter.InputMethod {
 | 
			
		||||
            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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,4 @@
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
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';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GnomeDesktop = imports.gi.GnomeDesktop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const { GLib, GnomeDesktop, Meta } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { GLib, Gio } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const NMA = imports.gi.NMA;
 | 
			
		||||
const { Gio, NMA } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const { Gio, GLib } = imports.gi;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
@@ -160,7 +159,7 @@ var ObjectManager = class {
 | 
			
		||||
        try {
 | 
			
		||||
            initable.init_finish(result);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            logError(e, 'could not initialize object manager for object ' + params.name);
 | 
			
		||||
            logError(e, 'could not initialize object manager for object ' + this._serviceName);
 | 
			
		||||
 | 
			
		||||
            this._tryToCompleteLoad();
 | 
			
		||||
            return;
 | 
			
		||||
@@ -281,8 +280,8 @@ var ObjectManager = 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));
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const ObjectManager = imports.misc.objectManager;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +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 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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 GObject = imports.gi.GObject;
 | 
			
		||||
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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +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 { Geoclue, Gio, GLib, GWeather } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const PermissionStore = imports.misc.permissionStore;
 | 
			
		||||
@@ -33,6 +30,14 @@ var WeatherClient = class {
 | 
			
		||||
                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);
 | 
			
		||||
@@ -61,8 +66,8 @@ var WeatherClient = class {
 | 
			
		||||
            this.emit('changed');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
 | 
			
		||||
                                                          'org.gnome.Weather.Application');
 | 
			
		||||
        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));
 | 
			
		||||
@@ -234,7 +239,7 @@ var WeatherClient = 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';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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" },
 | 
			
		||||
@@ -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");
 | 
			
		||||
 
 | 
			
		||||
@@ -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, Gtk, 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" },
 | 
			
		||||
@@ -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");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +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 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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,4 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, Gio, GLib, Shell } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const CheckBox = imports.ui.checkBox;
 | 
			
		||||
const Dialog = imports.ui.dialog;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +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 { 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;
 | 
			
		||||
@@ -626,9 +619,8 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
 | 
			
		||||
var WindowCyclerPopup = GObject.registerClass(
 | 
			
		||||
class WindowCyclerPopup extends CyclerPopup {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
 | 
			
		||||
        super._init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getWindows() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@@ -16,7 +12,16 @@ var SPINNER_ANIMATION_DELAY = 1.0;
 | 
			
		||||
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;
 | 
			
		||||
@@ -24,10 +29,7 @@ var Animation = 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() {
 | 
			
		||||
@@ -51,6 +53,23 @@ var Animation = 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 texture_cache = St.TextureCache.get_default();
 | 
			
		||||
        let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
 | 
			
		||||
        this._animations = texture_cache.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);
 | 
			
		||||
        if (oldFrameActor)
 | 
			
		||||
@@ -68,15 +87,32 @@ var Animation = class {
 | 
			
		||||
        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();
 | 
			
		||||
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
        if (this._scaleChangedId)
 | 
			
		||||
            themeContext.disconnect(this._scaleChangedId);
 | 
			
		||||
        this._scaleChangedId = 0;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +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 GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const AppFavorites = imports.ui.appFavorites;
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
@@ -18,13 +10,10 @@ const DND = imports.ui.dnd;
 | 
			
		||||
const GrabHelper = imports.ui.grabHelper;
 | 
			
		||||
const IconGrid = imports.ui.iconGrid;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Overview = imports.ui.overview;
 | 
			
		||||
const OverviewControls = imports.ui.overviewControls;
 | 
			
		||||
const PageIndicators = imports.ui.pageIndicators;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Workspace = imports.ui.workspace;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
const System = imports.ui.status.system;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
const SystemActions = imports.misc.systemActions;
 | 
			
		||||
@@ -175,7 +164,7 @@ class BaseAppView {
 | 
			
		||||
 | 
			
		||||
    _selectAppInternal(id) {
 | 
			
		||||
        if (this._items[id])
 | 
			
		||||
            this._items[id].actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
            this._items[id].actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        else
 | 
			
		||||
            log('No such application ' + id);
 | 
			
		||||
    }
 | 
			
		||||
@@ -246,116 +235,6 @@ class BaseAppView {
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(BaseAppView.prototype);
 | 
			
		||||
 | 
			
		||||
var PageIndicatorsActor = GObject.registerClass(
 | 
			
		||||
class PageIndicatorsActor extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'page-indicators',
 | 
			
		||||
                      vertical: true,
 | 
			
		||||
                      x_expand: true, y_expand: true,
 | 
			
		||||
                      x_align: Clutter.ActorAlign.END,
 | 
			
		||||
                      y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                      reactive: true,
 | 
			
		||||
                      clip_to_allocation: true });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_preferred_height(forWidth) {
 | 
			
		||||
        // We want to request the natural height of all our children as our
 | 
			
		||||
        // natural height, so we chain up to St.BoxLayout, but we only request 0
 | 
			
		||||
        // as minimum height, since it's not that important if some indicators
 | 
			
		||||
        // are not shown
 | 
			
		||||
        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
 | 
			
		||||
        return [0, natHeight];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
class PageIndicators {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new PageIndicatorsActor();
 | 
			
		||||
        this._nPages = 0;
 | 
			
		||||
        this._currentPage = undefined;
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('notify::mapped', () => {
 | 
			
		||||
            this.animateIndicators(IconGrid.AnimationDirection.IN);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setNPages(nPages) {
 | 
			
		||||
        if (this._nPages == nPages)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let diff = nPages - this._nPages;
 | 
			
		||||
        if (diff > 0) {
 | 
			
		||||
            for (let i = 0; i < diff; i++) {
 | 
			
		||||
                let pageIndex = this._nPages + i;
 | 
			
		||||
                let indicator = new St.Button({ style_class: 'page-indicator',
 | 
			
		||||
                                                button_mask: St.ButtonMask.ONE |
 | 
			
		||||
                                                             St.ButtonMask.TWO |
 | 
			
		||||
                                                             St.ButtonMask.THREE,
 | 
			
		||||
                                                toggle_mode: true,
 | 
			
		||||
                                                checked: pageIndex == this._currentPage });
 | 
			
		||||
                indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
 | 
			
		||||
                indicator.connect('clicked', () => {
 | 
			
		||||
                    this.emit('page-activated', pageIndex);
 | 
			
		||||
                });
 | 
			
		||||
                this.actor.add_actor(indicator);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            let children = this.actor.get_children().splice(diff);
 | 
			
		||||
            for (let i = 0; i < children.length; i++)
 | 
			
		||||
                children[i].destroy();
 | 
			
		||||
        }
 | 
			
		||||
        this._nPages = nPages;
 | 
			
		||||
        this.actor.visible = (this._nPages > 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setCurrentPage(currentPage) {
 | 
			
		||||
        this._currentPage = currentPage;
 | 
			
		||||
 | 
			
		||||
        let children = this.actor.get_children();
 | 
			
		||||
        for (let i = 0; i < children.length; i++)
 | 
			
		||||
            children[i].set_checked(i == this._currentPage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    animateIndicators(animationDirection) {
 | 
			
		||||
        if (!this.actor.mapped)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let children = this.actor.get_children();
 | 
			
		||||
        if (children.length == 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._nPages; i++)
 | 
			
		||||
            Tweener.removeTweens(children[i]);
 | 
			
		||||
 | 
			
		||||
        let offset;
 | 
			
		||||
        if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            offset = -children[0].width;
 | 
			
		||||
        else
 | 
			
		||||
            offset = children[0].width;
 | 
			
		||||
 | 
			
		||||
        let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN;
 | 
			
		||||
        let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
 | 
			
		||||
                                    INDICATORS_ANIMATION_DELAY_OUT;
 | 
			
		||||
        let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
 | 
			
		||||
        let totalAnimationTime = baseTime + delay * this._nPages;
 | 
			
		||||
        let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
 | 
			
		||||
                                      INDICATORS_ANIMATION_MAX_TIME_OUT;
 | 
			
		||||
        if (totalAnimationTime > maxTime)
 | 
			
		||||
            delay -= (totalAnimationTime - maxTime) / this._nPages;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._nPages; i++) {
 | 
			
		||||
            children[i].translation_x = isAnimationIn ? offset : 0;
 | 
			
		||||
            Tweener.addTween(children[i],
 | 
			
		||||
                             { translation_x: isAnimationIn ? 0 : offset,
 | 
			
		||||
                               time: baseTime + delay * i,
 | 
			
		||||
                               transition: 'easeInOutQuad',
 | 
			
		||||
                               delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(PageIndicators.prototype);
 | 
			
		||||
 | 
			
		||||
var AllView = class AllView extends BaseAppView {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super({ usePagination: true }, null);
 | 
			
		||||
@@ -370,17 +249,17 @@ var AllView = class AllView extends BaseAppView {
 | 
			
		||||
                                     x_expand:true, y_expand:true });
 | 
			
		||||
        this.actor.add_actor(this._scrollView);
 | 
			
		||||
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
                                    Gtk.PolicyType.EXTERNAL);
 | 
			
		||||
        this._scrollView.set_policy(St.PolicyType.NEVER,
 | 
			
		||||
                                    St.PolicyType.EXTERNAL);
 | 
			
		||||
        this._adjustment = this._scrollView.vscroll.adjustment;
 | 
			
		||||
 | 
			
		||||
        this._pageIndicators = new PageIndicators();
 | 
			
		||||
        this._pageIndicators = new PageIndicators.AnimatedPageIndicators();
 | 
			
		||||
        this._pageIndicators.connect('page-activated',
 | 
			
		||||
            (indicators, pageIndex) => {
 | 
			
		||||
                this.goToPage(pageIndex);
 | 
			
		||||
            });
 | 
			
		||||
        this._pageIndicators.actor.connect('scroll-event', this._onScroll.bind(this));
 | 
			
		||||
        this.actor.add_actor(this._pageIndicators.actor);
 | 
			
		||||
        this._pageIndicators.connect('scroll-event', this._onScroll.bind(this));
 | 
			
		||||
        this.actor.add_actor(this._pageIndicators);
 | 
			
		||||
 | 
			
		||||
        this.folderIcons = [];
 | 
			
		||||
 | 
			
		||||
@@ -487,15 +366,21 @@ var AllView = class AllView extends BaseAppView {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getAppInfos() {
 | 
			
		||||
        return this._appInfoList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _loadApps() {
 | 
			
		||||
        let apps = Gio.AppInfo.get_all().filter(appInfo => {
 | 
			
		||||
        this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
 | 
			
		||||
            try {
 | 
			
		||||
                let id = appInfo.get_id(); // catch invalid file encodings
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return appInfo.should_show();
 | 
			
		||||
        }).map(app => app.get_id());
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let apps = this._appInfoList.map(app => app.get_id());
 | 
			
		||||
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
 | 
			
		||||
@@ -1118,7 +1003,7 @@ var FolderView = class FolderView extends BaseAppView {
 | 
			
		||||
        this._grid.x_expand = true;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.ScrollView({ overlay_scrollbars: true });
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.actor.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
 | 
			
		||||
        let scrollableContainer = new St.BoxLayout({ vertical: true, reactive: true });
 | 
			
		||||
        scrollableContainer.add_actor(this._grid);
 | 
			
		||||
        this.actor.add_actor(scrollableContainer);
 | 
			
		||||
@@ -1298,15 +1183,13 @@ var FolderIcon = class FolderIcon {
 | 
			
		||||
        folderApps.forEach(addAppId);
 | 
			
		||||
 | 
			
		||||
        let folderCategories = this._folder.get_strv('categories');
 | 
			
		||||
        Gio.AppInfo.get_all().forEach(appInfo => {
 | 
			
		||||
        let appInfos = this._parentView.getAppInfos();
 | 
			
		||||
        appInfos.forEach(appInfo => {
 | 
			
		||||
            let appCategories = _getCategories(appInfo);
 | 
			
		||||
            if (!_listsIntersect(folderCategories, appCategories))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                addAppId(appInfo.get_id()); // catch invalid file encodings
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
            }
 | 
			
		||||
            addAppId(appInfo.get_id());
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor.visible = this.view.getAllItems().length > 0;
 | 
			
		||||
@@ -1464,18 +1347,18 @@ var AppFolderPopup = class AppFolderPopup {
 | 
			
		||||
        let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR;
 | 
			
		||||
        switch (event.get_key_symbol()) {
 | 
			
		||||
            case Clutter.Down:
 | 
			
		||||
                direction = Gtk.DirectionType.TAB_FORWARD;
 | 
			
		||||
                direction = St.DirectionType.TAB_FORWARD;
 | 
			
		||||
                break;
 | 
			
		||||
            case Clutter.Right:
 | 
			
		||||
                direction = isLtr ? Gtk.DirectionType.TAB_FORWARD :
 | 
			
		||||
                                    Gtk.DirectionType.TAB_BACKWARD;
 | 
			
		||||
                direction = isLtr ? St.DirectionType.TAB_FORWARD :
 | 
			
		||||
                                    St.DirectionType.TAB_BACKWARD;
 | 
			
		||||
                break;
 | 
			
		||||
            case Clutter.Up:
 | 
			
		||||
                direction = Gtk.DirectionType.TAB_BACKWARD;
 | 
			
		||||
                direction = St.DirectionType.TAB_BACKWARD;
 | 
			
		||||
                break;
 | 
			
		||||
            case Clutter.Left:
 | 
			
		||||
                direction = isLtr ? Gtk.DirectionType.TAB_BACKWARD :
 | 
			
		||||
                                    Gtk.DirectionType.TAB_FORWARD;
 | 
			
		||||
                direction = isLtr ? St.DirectionType.TAB_BACKWARD :
 | 
			
		||||
                                    St.DirectionType.TAB_FORWARD;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
@@ -1686,7 +1569,7 @@ var AppIcon = class AppIcon {
 | 
			
		||||
 | 
			
		||||
    _onKeyboardPopupMenu() {
 | 
			
		||||
        this.popupMenu();
 | 
			
		||||
        this._menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        this._menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getId() {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,13 +36,16 @@ const RENAMED_DESKTOP_IDS = {
 | 
			
		||||
    'gnome-software.desktop': 'org.gnome.Software.desktop',
 | 
			
		||||
    'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
 | 
			
		||||
    'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
 | 
			
		||||
    'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
 | 
			
		||||
    'gnome-weather.desktop': 'org.gnome.Weather.desktop',
 | 
			
		||||
    'gnomine.desktop': 'gnome-mines.desktop',
 | 
			
		||||
    'gnotravex.desktop': 'gnome-tetravex.desktop',
 | 
			
		||||
    'gnotski.desktop': 'gnome-klotski.desktop',
 | 
			
		||||
    'gtali.desktop': 'tali.desktop',
 | 
			
		||||
    'iagno.desktop': 'org.gnome.Iagno.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',
 | 
			
		||||
    'totem.desktop': 'org.gnome.Totem.desktop',
 | 
			
		||||
    'evince.desktop': 'org.gnome.Evince.desktop',
 | 
			
		||||
@@ -153,7 +156,7 @@ class AppFavorites {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _removeFavorite(appId) {
 | 
			
		||||
        if (!appId in this._favorites)
 | 
			
		||||
        if (!(appId in this._favorites))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let ids = this._getIds().filter(id => id != appId);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,4 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
 
 | 
			
		||||
@@ -93,12 +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 Meta = imports.gi.Meta;
 | 
			
		||||
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const LoginManager = imports.misc.loginManager;
 | 
			
		||||
@@ -751,10 +746,8 @@ var BackgroundManager = class BackgroundManager {
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
/* -*- 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 St = imports.gi.St;
 | 
			
		||||
const { Atk, Clutter, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
var BarLevel = class {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -29,7 +24,7 @@ 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 = GObject.registerClass({
 | 
			
		||||
@@ -494,7 +489,8 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        // 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 monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
 | 
			
		||||
        let workarea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
 | 
			
		||||
        let themeNode = this.get_theme_node();
 | 
			
		||||
        let borderWidth = themeNode.get_length('-arrow-border-width');
 | 
			
		||||
        let arrowBase = themeNode.get_length('-arrow-base');
 | 
			
		||||
@@ -544,8 +540,8 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        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))) {
 | 
			
		||||
@@ -563,8 +559,8 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        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))) {
 | 
			
		||||
@@ -630,27 +626,28 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        let monitorActor = this.sourceActor;
 | 
			
		||||
        if (!monitorActor)
 | 
			
		||||
            monitorActor = this;
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
 | 
			
		||||
        let monitorIndex = Main.layoutManager.findIndexForActor(monitorActor);
 | 
			
		||||
        let workarea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +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 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;
 | 
			
		||||
@@ -14,6 +9,8 @@ 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';
 | 
			
		||||
@@ -126,19 +123,7 @@ var EmptyEventSource = class EmptyEventSource {
 | 
			
		||||
};
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
@@ -1083,7 +1068,7 @@ var CalendarMessageList = class CalendarMessageList {
 | 
			
		||||
                                               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',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,4 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, Pango, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
var CheckBox = class CheckBox {
 | 
			
		||||
    constructor(label) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,6 @@
 | 
			
		||||
// -*- 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 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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,10 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
const ShellMountOperation = imports.ui.shellMountOperation;
 | 
			
		||||
 | 
			
		||||
var GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
 | 
			
		||||
@@ -96,10 +93,10 @@ var AutomountManager = 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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,12 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +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 GObject = imports.gi.GObject;
 | 
			
		||||
const NM = imports.gi.NM;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Clutter, Gio, GLib, 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';
 | 
			
		||||
@@ -111,10 +103,10 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
 | 
			
		||||
            descriptionLabel.clutter_text.line_wrap = true;
 | 
			
		||||
            descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
 | 
			
		||||
            messageBox.add(descriptionLabel,
 | 
			
		||||
                           { y_fill:  true,
 | 
			
		||||
                             y_align: St.Align.START,
 | 
			
		||||
                             expand: true });
 | 
			
		||||
            contentBox.messageBox.add(descriptionLabel,
 | 
			
		||||
                                      { y_fill:  true,
 | 
			
		||||
                                        y_align: St.Align.START,
 | 
			
		||||
                                        expand: true });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._okButton = { label:  _("Connect"),
 | 
			
		||||
@@ -705,14 +697,14 @@ var NetworkAgent = class {
 | 
			
		||||
            if (hints.indexOf('pin') != -1) {
 | 
			
		||||
                let gsmSetting = connection.get_setting_gsm();
 | 
			
		||||
                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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +1,15 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const { AccountsService, Clutter, Gio, GLib,
 | 
			
		||||
        Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
 | 
			
		||||
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 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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +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 GObject = imports.gi.GObject;
 | 
			
		||||
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;
 | 
			
		||||
    ({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
 | 
			
		||||
} catch(e) {
 | 
			
		||||
    log('Telepathy is not available, chat integration will be disabled.');
 | 
			
		||||
}
 | 
			
		||||
@@ -24,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);
 | 
			
		||||
@@ -821,8 +813,8 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        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 });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,10 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
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
 | 
			
		||||
@@ -58,7 +53,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
 | 
			
		||||
        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,
 | 
			
		||||
@@ -99,7 +94,9 @@ var CtrlAltTabManager = class CtrlAltTabManager {
 | 
			
		||||
                    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,
 | 
			
		||||
@@ -134,10 +131,10 @@ var CtrlAltTabManager = class CtrlAltTabManager {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var CtrlAltTabPopup =
 | 
			
		||||
var CtrlAltTabPopup = GObject.registerClass(
 | 
			
		||||
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
 | 
			
		||||
    constructor(items) {
 | 
			
		||||
        super(items);
 | 
			
		||||
    _init(items) {
 | 
			
		||||
        super._init(items);
 | 
			
		||||
 | 
			
		||||
        this._switcherList = new CtrlAltTabSwitcher(this._items);
 | 
			
		||||
    }
 | 
			
		||||
@@ -161,12 +158,12 @@ class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
 | 
			
		||||
        super._finish(time);
 | 
			
		||||
        Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var CtrlAltTabSwitcher =
 | 
			
		||||
var CtrlAltTabSwitcher = GObject.registerClass(
 | 
			
		||||
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
 | 
			
		||||
    constructor(items) {
 | 
			
		||||
        super(true);
 | 
			
		||||
    _init(items) {
 | 
			
		||||
        super._init(true);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < items.length; i++)
 | 
			
		||||
            this._addIcon(items[i]);
 | 
			
		||||
@@ -188,4 +185,4 @@ class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
 | 
			
		||||
 | 
			
		||||
        this.addItem(box, text);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -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 GObject = imports.gi.GObject;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +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 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() &&
 | 
			
		||||
@@ -155,18 +144,27 @@ var WorldClocksSection = class WorldClocksSection {
 | 
			
		||||
            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 offset = l.get_timezone().get_offset() / 60.;
 | 
			
		||||
            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;
 | 
			
		||||
@@ -217,110 +215,114 @@ var WeatherSection = class WeatherSection {
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
            /* 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;
 | 
			
		||||
 | 
			
		||||
            /* 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);
 | 
			
		||||
        });
 | 
			
		||||
        return String.prototype.format.apply(fmt, summaries);
 | 
			
		||||
        return infos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getLabelText() {
 | 
			
		||||
        if (!this._weatherClient.hasLocation)
 | 
			
		||||
            return _("Select a location…");
 | 
			
		||||
    _addForecasts() {
 | 
			
		||||
        let layout = this._forecastGrid.layout_manager;
 | 
			
		||||
 | 
			
		||||
        if (this._weatherClient.loading)
 | 
			
		||||
            return _("Loading…");
 | 
			
		||||
        let infos = this._getInfos();
 | 
			
		||||
        if (this._forecastGrid.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            infos.reverse();
 | 
			
		||||
 | 
			
		||||
        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++;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setStatusLabel(text) {
 | 
			
		||||
        let layout = this._forecastGrid.layout_manager;
 | 
			
		||||
        let label = new St.Label({ text });
 | 
			
		||||
        layout.attach(label, 0, 0, 1, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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() {
 | 
			
		||||
@@ -329,7 +331,9 @@ var WeatherSection = class WeatherSection {
 | 
			
		||||
        if (!this.actor.visible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._conditionsLabel.text = this._getLabelText();
 | 
			
		||||
        this._titleLocation.visible = this._weatherClient.hasLocation;
 | 
			
		||||
 | 
			
		||||
        this._updateForecasts();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -375,16 +379,17 @@ class IndicatorPad extends St.Widget {
 | 
			
		||||
    _init(actor) {
 | 
			
		||||
        this._source = actor;
 | 
			
		||||
        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];
 | 
			
		||||
@@ -515,7 +520,7 @@ class DateMenuButton extends PanelMenu.Button {
 | 
			
		||||
        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,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,6 @@
 | 
			
		||||
// -*- 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 { Clutter, Gio, GObject, Pango, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
var Dialog = GObject.registerClass(
 | 
			
		||||
class Dialog extends St.Widget {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							@@ -1,16 +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 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;
 | 
			
		||||
@@ -109,6 +104,7 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        this._dragCancellable = true;
 | 
			
		||||
 | 
			
		||||
        this._eventsGrabbed = false;
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onButtonPress(actor, event) {
 | 
			
		||||
@@ -119,7 +115,7 @@ var _Draggable = class _Draggable {
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        this._buttonDown = true;
 | 
			
		||||
        this._grabActor();
 | 
			
		||||
        this._grabActor(event.get_device());
 | 
			
		||||
 | 
			
		||||
        let [stageX, stageY] = event.get_coords();
 | 
			
		||||
        this._dragStartX = stageX;
 | 
			
		||||
@@ -129,6 +125,16 @@ var _Draggable = class _Draggable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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;
 | 
			
		||||
@@ -136,10 +142,8 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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;
 | 
			
		||||
@@ -148,19 +152,30 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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
 | 
			
		||||
@@ -170,8 +185,8 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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));
 | 
			
		||||
    }
 | 
			
		||||
@@ -185,11 +200,11 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -201,14 +216,36 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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);
 | 
			
		||||
@@ -268,7 +305,22 @@ var _Draggable = class _Draggable {
 | 
			
		||||
     * 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;
 | 
			
		||||
 | 
			
		||||
@@ -283,8 +335,7 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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;
 | 
			
		||||
@@ -352,7 +403,8 @@ var _Draggable = class _Draggable {
 | 
			
		||||
            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)
 | 
			
		||||
@@ -398,10 +450,12 @@ var _Draggable = class _Draggable {
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +26,7 @@ var EdgeDragAction = GObject.registerClass({
 | 
			
		||||
        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,7 +42,7 @@ var EdgeDragAction = GObject.registerClass({
 | 
			
		||||
                (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,7 +62,7 @@ var EdgeDragAction = GObject.registerClass({
 | 
			
		||||
        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);
 | 
			
		||||
 
 | 
			
		||||
@@ -18,21 +18,13 @@
 | 
			
		||||
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Polkit = imports.gi.Polkit;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { AccountsService, Clutter, Gio,
 | 
			
		||||
        GLib, Pango, Polkit, Shell, St }  = imports.gi;
 | 
			
		||||
 | 
			
		||||
const CheckBox = imports.ui.checkBox;
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const LoginManager = imports.misc.loginManager;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserWidget = imports.ui.userWidget;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
@@ -320,7 +312,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        messageLayout.add(this._batteryWarning);
 | 
			
		||||
 | 
			
		||||
        this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.contentLayout.add(this._scrollView,
 | 
			
		||||
                               { x_fill: true,
 | 
			
		||||
                                 y_fill: true });
 | 
			
		||||
 
 | 
			
		||||
@@ -4,18 +4,13 @@ const Config = imports.misc.config;
 | 
			
		||||
 | 
			
		||||
imports.gi.versions.Clutter = Config.LIBMUTTER_API_VERSION;
 | 
			
		||||
imports.gi.versions.Gio = '2.0';
 | 
			
		||||
imports.gi.versions.Gdk = '3.0';
 | 
			
		||||
imports.gi.versions.GdkPixbuf = '2.0';
 | 
			
		||||
imports.gi.versions.Gtk = '3.0';
 | 
			
		||||
imports.gi.versions.TelepathyGLib = '0.12';
 | 
			
		||||
imports.gi.versions.TelepathyLogger = '0.2';
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const { Clutter, GLib, Shell, St } = imports.gi;
 | 
			
		||||
const Gettext = imports.gettext;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
// We can't import shell JS modules yet, because they may have
 | 
			
		||||
// variable initializations, etc, that depend on init() already having
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Soup = imports.gi.Soup;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Clutter, Gio, GLib, Soup, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const ExtensionUtils = imports.misc.extensionUtils;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const { Gio, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const ExtensionUtils = imports.misc.extensionUtils;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
@@ -187,7 +183,7 @@ var GrabHelper = class GrabHelper {
 | 
			
		||||
        if (params.focus) {
 | 
			
		||||
            params.focus.grab_key_focus();
 | 
			
		||||
        } else if (newFocus && hadFocus) {
 | 
			
		||||
            if (!newFocus.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
            if (!newFocus.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
                newFocus.grab_key_focus();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const IBus = imports.gi.IBus;
 | 
			
		||||
const { Clutter, IBus, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -236,7 +234,7 @@ var CandidatePopup = class CandidatePopup {
 | 
			
		||||
 | 
			
		||||
            let indexes = [];
 | 
			
		||||
            let indexLabel;
 | 
			
		||||
            for (let i = 0; indexLabel = lookupTable.get_label(i); ++i)
 | 
			
		||||
            for (let i = 0; (indexLabel = lookupTable.get_label(i)); ++i)
 | 
			
		||||
                 indexes.push(indexLabel.get_text());
 | 
			
		||||
 | 
			
		||||
            Main.keyboard.resetSuggestions();
 | 
			
		||||
@@ -295,7 +293,7 @@ var CandidatePopup = class CandidatePopup {
 | 
			
		||||
 | 
			
		||||
    _setTextAttributes(clutterText, ibusAttrList) {
 | 
			
		||||
        let attr;
 | 
			
		||||
        for (let i = 0; attr = ibusAttrList.get(i); ++i)
 | 
			
		||||
        for (let i = 0; (attr = ibusAttrList.get(i)); ++i)
 | 
			
		||||
            if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
 | 
			
		||||
                clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, GObject, Meta, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -110,6 +104,7 @@ class BaseIcon extends St.Bin {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_style_changed() {
 | 
			
		||||
        super.vfunc_style_changed();
 | 
			
		||||
        let node = this.get_theme_node();
 | 
			
		||||
 | 
			
		||||
        let size;
 | 
			
		||||
@@ -670,7 +665,7 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addItem(item, index) {
 | 
			
		||||
        if (!item.icon instanceof BaseIcon)
 | 
			
		||||
        if (!(item.icon instanceof BaseIcon))
 | 
			
		||||
            throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
 | 
			
		||||
 | 
			
		||||
        this._items.push(item);
 | 
			
		||||
@@ -906,10 +901,8 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
    getItemPage(item) {
 | 
			
		||||
        let children = this._getVisibleChildren();
 | 
			
		||||
        let index = children.indexOf(item);
 | 
			
		||||
        if (index == -1) {
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            throw new Error('Item not found.');
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        return Math.floor(index / this._childrenPerPage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -924,10 +917,9 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
    openExtraSpace(sourceItem, side, nRows) {
 | 
			
		||||
        let children = this._getVisibleChildren();
 | 
			
		||||
        let index = children.indexOf(sourceItem.actor);
 | 
			
		||||
        if (index == -1) {
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            throw new Error('Item not found.');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let pageIndex = Math.floor(index / this._childrenPerPage);
 | 
			
		||||
        let pageOffset = pageIndex * this._childrenPerPage;
 | 
			
		||||
 | 
			
		||||
@@ -959,8 +951,8 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
            this._translatedChildren = [];
 | 
			
		||||
            this.emit('space-opened');
 | 
			
		||||
        } else {
 | 
			
		||||
            this._translateChildren(childrenUp, Gtk.DirectionType.UP, nRowsUp);
 | 
			
		||||
            this._translateChildren(childrenDown, Gtk.DirectionType.DOWN, nRowsDown);
 | 
			
		||||
            this._translateChildren(childrenUp, St.DirectionType.UP, nRowsUp);
 | 
			
		||||
            this._translateChildren(childrenDown, St.DirectionType.DOWN, nRowsDown);
 | 
			
		||||
            this._translatedChildren = childrenUp.concat(childrenDown);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -970,7 +962,7 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
        if (translationY == 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (direction == Gtk.DirectionType.UP)
 | 
			
		||||
        if (direction == St.DirectionType.UP)
 | 
			
		||||
            translationY *= -1;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < children.length; i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,16 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Dialog = imports.ui.dialog;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const PermissionStore = imports.misc.permissionStore;
 | 
			
		||||
 | 
			
		||||
const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
 | 
			
		||||
 | 
			
		||||
const APP_WHITELIST = ['gnome-control-center.desktop'];
 | 
			
		||||
const APP_PERMISSIONS_TABLE = 'gnome';
 | 
			
		||||
const APP_PERMISSIONS_ID = 'shortcuts-inhibitor';
 | 
			
		||||
const GRANTED = 'GRANTED';
 | 
			
		||||
const DENIED = 'DENIED';
 | 
			
		||||
 | 
			
		||||
var DialogResponse = Meta.InhibitShortcutsDialogResponse;
 | 
			
		||||
 | 
			
		||||
@@ -49,6 +48,29 @@ var InhibitShortcutsDialog = GObject.registerClass({
 | 
			
		||||
                                               Gtk.accelerator_parse(accel));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldUsePermStore() {
 | 
			
		||||
        return this._app && !this._app.is_window_backed();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _saveToPermissionStore(grant) {
 | 
			
		||||
        if (!this._shouldUsePermStore() || this._permStore == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let permissions = {};
 | 
			
		||||
        permissions[this._app.get_id()] = [grant];
 | 
			
		||||
        let data = GLib.Variant.new('av', {});
 | 
			
		||||
 | 
			
		||||
        this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
 | 
			
		||||
                                  true,
 | 
			
		||||
                                  APP_PERMISSIONS_ID,
 | 
			
		||||
                                  permissions,
 | 
			
		||||
                                  data,
 | 
			
		||||
            (result, error) => {
 | 
			
		||||
                if (error != null)
 | 
			
		||||
                    log(error.message);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _buildLayout() {
 | 
			
		||||
        let name = this._app ? this._app.get_name() : this._window.title;
 | 
			
		||||
 | 
			
		||||
@@ -70,12 +92,14 @@ var InhibitShortcutsDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._dialog.addButton({ label: _("Deny"),
 | 
			
		||||
                                 action: () => {
 | 
			
		||||
                                     this._saveToPermissionStore(DENIED);
 | 
			
		||||
                                     this._emitResponse(DialogResponse.DENY);
 | 
			
		||||
                                 },
 | 
			
		||||
                                 key: Clutter.KEY_Escape });
 | 
			
		||||
 | 
			
		||||
        this._dialog.addButton({ label: _("Allow"),
 | 
			
		||||
                                 action: () => {
 | 
			
		||||
                                     this._saveToPermissionStore(GRANTED);
 | 
			
		||||
                                     this._emitResponse(DialogResponse.ALLOW);
 | 
			
		||||
                                 },
 | 
			
		||||
                                 default: true });
 | 
			
		||||
@@ -87,10 +111,43 @@ var InhibitShortcutsDialog = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_show() {
 | 
			
		||||
        if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1)
 | 
			
		||||
        if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1) {
 | 
			
		||||
            this._emitResponse(DialogResponse.ALLOW);
 | 
			
		||||
        else
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._shouldUsePermStore()) {
 | 
			
		||||
            this._dialog.open();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Check with the permission store */
 | 
			
		||||
        let appId = this._app.get_id();
 | 
			
		||||
        this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
 | 
			
		||||
            if (error) {
 | 
			
		||||
                log(error.message);
 | 
			
		||||
                this._dialog.open();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._permStore.LookupRemote(APP_PERMISSIONS_TABLE,
 | 
			
		||||
                                         APP_PERMISSIONS_ID,
 | 
			
		||||
                (res, error) => {
 | 
			
		||||
                    if (error) {
 | 
			
		||||
                        this._dialog.open();
 | 
			
		||||
                        log(error.message);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    let [permissions, data] = res;
 | 
			
		||||
                    if (permissions[appId] === undefined) // Not found
 | 
			
		||||
                        this._dialog.open();
 | 
			
		||||
                    else if (permissions[appId] == GRANTED)
 | 
			
		||||
                        this._emitResponse(DialogResponse.ALLOW);
 | 
			
		||||
                    else
 | 
			
		||||
                        this._emitResponse(DialogResponse.DENY);
 | 
			
		||||
                });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_hide() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const { Clutter, Gio, GObject } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Dialog = imports.ui.dialog;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
 | 
			
		||||
@@ -8,7 +7,7 @@ const KEYBOARD_A11Y_SCHEMA    = 'org.gnome.desktop.a11y.keyboard';
 | 
			
		||||
const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
 | 
			
		||||
const KEY_SLOW_KEYS_ENABLED   = 'slowkeys-enable';
 | 
			
		||||
 | 
			
		||||
var KbdA11yDialog = new GObject.registerClass(
 | 
			
		||||
var KbdA11yDialog = GObject.registerClass(
 | 
			
		||||
class KbdA11yDialog extends GObject.Object {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +1,21 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Atspi = imports.gi.Atspi;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const InputSourceManager = imports.ui.status.keyboard;
 | 
			
		||||
 | 
			
		||||
const InputSourceManager = imports.ui.status.keyboard;
 | 
			
		||||
const IBusManager = imports.misc.ibusManager;
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PageIndicators = imports.ui.pageIndicators;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
 | 
			
		||||
var KEY_LONG_PRESS_TIME = 250;
 | 
			
		||||
var PANEL_SWITCH_ANIMATION_TIME = 0.5;
 | 
			
		||||
var PANEL_SWITCH_RELATIVE_DISTANCE = 1 / 3; /* A third of the actor width */
 | 
			
		||||
 | 
			
		||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
 | 
			
		||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
 | 
			
		||||
@@ -40,28 +34,63 @@ const defaultKeysPost = [
 | 
			
		||||
    [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
 | 
			
		||||
      [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
 | 
			
		||||
      [{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
 | 
			
		||||
      [{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
      [{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
    [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
 | 
			
		||||
      [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
 | 
			
		||||
      [{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
 | 
			
		||||
      [{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
      [{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
    [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
 | 
			
		||||
      [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
 | 
			
		||||
      [{ label: '=/<', width: 3, level: 3, right: true }],
 | 
			
		||||
      [{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
      [{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
    [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
 | 
			
		||||
      [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
 | 
			
		||||
      [{ label: '?123', width: 3, level: 2, right: true }],
 | 
			
		||||
      [{ width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }, { width: 1.5, action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
      [{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
var KeyContainer = new GObject.registerClass(
 | 
			
		||||
var AspectContainer = GObject.registerClass(
 | 
			
		||||
class AspectContainer extends St.Widget {
 | 
			
		||||
    _init(params) {
 | 
			
		||||
        super._init(params);
 | 
			
		||||
        this._ratio = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setRatio(relWidth, relHeight) {
 | 
			
		||||
        this._ratio = relWidth / relHeight;
 | 
			
		||||
        this.queue_relayout();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_allocate(box, flags) {
 | 
			
		||||
        if (box.get_width() > 0 && box.get_height() > 0) {
 | 
			
		||||
            let sizeRatio = box.get_width() / box.get_height();
 | 
			
		||||
 | 
			
		||||
            if (sizeRatio >= this._ratio) {
 | 
			
		||||
                /* Restrict horizontally */
 | 
			
		||||
                let width = box.get_height() * this._ratio;
 | 
			
		||||
                let diff = box.get_width() - width;
 | 
			
		||||
 | 
			
		||||
                box.x1 += Math.floor(diff / 2);
 | 
			
		||||
                box.x2 -= Math.ceil(diff / 2);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Restrict vertically, align to bottom */
 | 
			
		||||
                let height = box.get_width() / this._ratio;
 | 
			
		||||
                box.y1 = box.y2 - Math.floor(height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        super.vfunc_allocate(box, flags);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var KeyContainer = GObject.registerClass(
 | 
			
		||||
class KeyContainer extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                  column_homogeneous: true,
 | 
			
		||||
                                                  row_homogeneous: true });
 | 
			
		||||
        super._init({ layout_manager: gridLayout });
 | 
			
		||||
        super._init({ layout_manager: gridLayout,
 | 
			
		||||
                      x_expand: true, y_expand: true });
 | 
			
		||||
        this._gridLayout = gridLayout;
 | 
			
		||||
        this._currentRow = 0;
 | 
			
		||||
        this._currentCol = 0;
 | 
			
		||||
@@ -98,32 +127,7 @@ class KeyContainer extends St.Widget {
 | 
			
		||||
        this._maxCols = Math.max(this._currentCol, this._maxCols);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_allocate(box, flags) {
 | 
			
		||||
        if (box.get_width() > 0 && box.get_height() > 0 && this._maxCols > 0) {
 | 
			
		||||
            let keyboardRatio = this._maxCols / this._rows.length;
 | 
			
		||||
            let sizeRatio = box.get_width() / box.get_height();
 | 
			
		||||
 | 
			
		||||
            if (sizeRatio >= keyboardRatio) {
 | 
			
		||||
                /* Restrict horizontally */
 | 
			
		||||
                let width = box.get_height() * keyboardRatio;
 | 
			
		||||
                let diff = box.get_width() - width;
 | 
			
		||||
 | 
			
		||||
                box.x1 += Math.floor(diff / 2);
 | 
			
		||||
                box.x2 -= Math.ceil(diff / 2);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Restrict vertically */
 | 
			
		||||
                let height = box.get_width() / keyboardRatio;
 | 
			
		||||
                let diff = box.get_height() - height;
 | 
			
		||||
 | 
			
		||||
                box.y1 += Math.floor(diff / 2);
 | 
			
		||||
                box.y2 -= Math.floor(diff / 2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        super.vfunc_allocate(box, flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    layoutButtons() {
 | 
			
		||||
    layoutButtons(container) {
 | 
			
		||||
        let nCol = 0, nRow = 0;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._rows.length; i++) {
 | 
			
		||||
@@ -150,6 +154,9 @@ class KeyContainer extends St.Widget {
 | 
			
		||||
            nRow += KEY_SIZE;
 | 
			
		||||
            nCol = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (container)
 | 
			
		||||
            container.setRatio(this._maxCols, this._rows.length);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -179,16 +186,20 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
 | 
			
		||||
        let inputSourceManager = InputSourceManager.getInputSourceManager();
 | 
			
		||||
        let inputSources = inputSourceManager.inputSources;
 | 
			
		||||
 | 
			
		||||
        let item;
 | 
			
		||||
        for (let i in inputSources) {
 | 
			
		||||
            let is = inputSources[i];
 | 
			
		||||
 | 
			
		||||
            this.addAction(is.displayName, () => {
 | 
			
		||||
            item = this.addAction(is.displayName, () => {
 | 
			
		||||
                inputSourceManager.activateInputSource(is, true);
 | 
			
		||||
            });
 | 
			
		||||
            item.actor.can_focus = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
        this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop');
 | 
			
		||||
        item = this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop');
 | 
			
		||||
        item.actor.can_focus = false;
 | 
			
		||||
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
 | 
			
		||||
        this._unmapId = actor.connect('notify::mapped', () => {
 | 
			
		||||
@@ -232,7 +243,7 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Key = class Key {
 | 
			
		||||
    constructor(key) {
 | 
			
		||||
    constructor(key, extendedKeys) {
 | 
			
		||||
        this.key = key || "";
 | 
			
		||||
        this.keyButton = this._makeKey(this.key);
 | 
			
		||||
 | 
			
		||||
@@ -258,6 +269,8 @@ var Key = class Key {
 | 
			
		||||
            this._boxPointer.destroy();
 | 
			
		||||
            this._boxPointer = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.cancel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _ensureExtendedKeysPopup() {
 | 
			
		||||
@@ -279,11 +292,13 @@ var Key = class Key {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getKeyval(key) {
 | 
			
		||||
        let unicode = String.charCodeAt(key, 0);
 | 
			
		||||
        return Gdk.unicode_to_keyval(unicode);
 | 
			
		||||
        let unicode = key.charCodeAt(0);
 | 
			
		||||
        return Clutter.unicode_to_keysym(unicode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _press(key) {
 | 
			
		||||
        this.emit('activated')
 | 
			
		||||
 | 
			
		||||
        if (key != this.key || this._extended_keys.length == 0) {
 | 
			
		||||
            this.emit('pressed', this._getKeyval(key), key);
 | 
			
		||||
        }
 | 
			
		||||
@@ -324,6 +339,16 @@ var Key = class Key {
 | 
			
		||||
        this._longPress = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cancel() {
 | 
			
		||||
        if (this._pressTimeoutId != 0) {
 | 
			
		||||
            GLib.source_remove(this._pressTimeoutId);
 | 
			
		||||
            this._pressTimeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._touchPressed = false;
 | 
			
		||||
        this.keyButton.set_hover(false);
 | 
			
		||||
        this.keyButton.fake_release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onCapturedEvent(actor, event) {
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
        let press = (type == Clutter.EventType.BUTTON_PRESS || type == Clutter.EventType.TOUCH_BEGIN);
 | 
			
		||||
@@ -395,13 +420,10 @@ var Key = class Key {
 | 
			
		||||
 | 
			
		||||
            if (!this._touchPressed &&
 | 
			
		||||
                event.type() == Clutter.EventType.TOUCH_BEGIN) {
 | 
			
		||||
                device.sequence_grab(sequence, actor);
 | 
			
		||||
                this._touchPressed = true;
 | 
			
		||||
                this._press(key);
 | 
			
		||||
            } else if (this._touchPressed &&
 | 
			
		||||
                       event.type() == Clutter.EventType.TOUCH_END &&
 | 
			
		||||
                       device.sequence_get_grabbed_actor(sequence) == actor) {
 | 
			
		||||
                device.sequence_ungrab(sequence);
 | 
			
		||||
                       event.type() == Clutter.EventType.TOUCH_END) {
 | 
			
		||||
                this._touchPressed = false;
 | 
			
		||||
                this._release(key);
 | 
			
		||||
            }
 | 
			
		||||
@@ -550,10 +572,469 @@ var FocusTracker = class {
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(FocusTracker.prototype);
 | 
			
		||||
 | 
			
		||||
var EmojiPager = class EmojiPager {
 | 
			
		||||
    constructor(sections, nCols, nRows) {
 | 
			
		||||
        this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     clip_to_allocation: true });
 | 
			
		||||
        this._sections = sections;
 | 
			
		||||
        this._nCols = nCols;
 | 
			
		||||
        this._nRows = nRows;
 | 
			
		||||
 | 
			
		||||
        this._pages = [];
 | 
			
		||||
        this._panel = null;
 | 
			
		||||
        this._curPage = null;
 | 
			
		||||
        this._followingPage = null;
 | 
			
		||||
        this._followingPanel = null;
 | 
			
		||||
        this._currentKey = null;
 | 
			
		||||
        this._delta = 0;
 | 
			
		||||
        this._width = null;
 | 
			
		||||
 | 
			
		||||
        this._initPagingInfo();
 | 
			
		||||
 | 
			
		||||
        let panAction = new Clutter.PanAction({ interpolate: false });
 | 
			
		||||
        panAction.connect('pan', this._onPan.bind(this));
 | 
			
		||||
        panAction.connect('gesture-begin', this._onPanBegin.bind(this));
 | 
			
		||||
        panAction.connect('gesture-cancel', this._onPanCancel.bind(this));
 | 
			
		||||
        panAction.connect('gesture-end', this._onPanEnd.bind(this));
 | 
			
		||||
        this._panAction = panAction;
 | 
			
		||||
        this.actor.add_action(panAction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get delta() {
 | 
			
		||||
        return this._delta;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set delta(value) {
 | 
			
		||||
        if (value > this._width)
 | 
			
		||||
            value = this._width;
 | 
			
		||||
        else if (value < -this._width)
 | 
			
		||||
            value = -this._width;
 | 
			
		||||
 | 
			
		||||
        this._delta = value;
 | 
			
		||||
 | 
			
		||||
        if (value == 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let relValue = Math.abs(value / this._width);
 | 
			
		||||
        let followingPage = this.getFollowingPage();
 | 
			
		||||
 | 
			
		||||
        if (this._followingPage != followingPage) {
 | 
			
		||||
            if (this._followingPanel) {
 | 
			
		||||
                this._followingPanel.destroy();
 | 
			
		||||
                this._followingPanel = null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (followingPage != null) {
 | 
			
		||||
                this._followingPanel = this._generatePanel(followingPage);
 | 
			
		||||
                this._followingPanel.set_pivot_point(0.5, 0.5);
 | 
			
		||||
                this.actor.add_child(this._followingPanel);
 | 
			
		||||
                this.actor.set_child_below_sibling(this._followingPanel, this._panel);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._followingPage = followingPage;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._panel.translation_x = value;
 | 
			
		||||
        this._panel.opacity = 255 * (1 - Math.pow(relValue, 3));
 | 
			
		||||
 | 
			
		||||
        if (this._followingPanel) {
 | 
			
		||||
            this._followingPanel.scale_x = 0.8 + (0.2 * relValue);
 | 
			
		||||
            this._followingPanel.scale_y = 0.8 + (0.2 * relValue);
 | 
			
		||||
            this._followingPanel.opacity = 255 * relValue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _prevPage(nPage) {
 | 
			
		||||
        return (nPage + this._pages.length - 1) % this._pages.length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _nextPage(nPage) {
 | 
			
		||||
        return (nPage + 1) % this._pages.length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getFollowingPage() {
 | 
			
		||||
        if (this.delta == 0)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        if ((this.delta < 0 && global.stage.text_direction == Clutter.TextDirection.LTR) ||
 | 
			
		||||
            (this.delta > 0 && global.stage.text_direction == Clutter.TextDirection.RTL))
 | 
			
		||||
            return this._nextPage(this._curPage);
 | 
			
		||||
        else
 | 
			
		||||
            return this._prevPage(this._curPage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPan(action) {
 | 
			
		||||
        let [dist, dx, dy] = action.get_motion_delta(0);
 | 
			
		||||
        this.delta = this.delta + dx;
 | 
			
		||||
 | 
			
		||||
        if (this._currentKey != null) {
 | 
			
		||||
            this._currentKey.cancel();
 | 
			
		||||
            this._currentKey = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPanBegin() {
 | 
			
		||||
        this._width = this.actor.width;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPanEnd() {
 | 
			
		||||
        if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
 | 
			
		||||
            this._onPanCancel()
 | 
			
		||||
        } else {
 | 
			
		||||
            let value;
 | 
			
		||||
            if (this._delta > 0)
 | 
			
		||||
                value = this._width;
 | 
			
		||||
            else if (this._delta < 0)
 | 
			
		||||
                value = -this._width;
 | 
			
		||||
 | 
			
		||||
            let relDelta = Math.abs(this._delta - value) / this._width;
 | 
			
		||||
            let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
 | 
			
		||||
 | 
			
		||||
            Tweener.removeTweens(this);
 | 
			
		||||
            Tweener.addTween(this,
 | 
			
		||||
                             { delta: value,
 | 
			
		||||
                               time: time,
 | 
			
		||||
                               transition: 'easeInOutQuad',
 | 
			
		||||
                               onComplete() {
 | 
			
		||||
                                   this.setCurrentPage(this.getFollowingPage());
 | 
			
		||||
                               }
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPanCancel() {
 | 
			
		||||
        let relDelta = Math.abs(this._delta) / this.actor.width;
 | 
			
		||||
        let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
 | 
			
		||||
 | 
			
		||||
        Tweener.removeTweens(this);
 | 
			
		||||
        Tweener.addTween(this,
 | 
			
		||||
                         { delta: 0,
 | 
			
		||||
                           time: time,
 | 
			
		||||
                           transition: 'easeInOutQuad',
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _initPagingInfo() {
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            let section = this._sections[i];
 | 
			
		||||
            let itemsPerPage = this._nCols * this._nRows;
 | 
			
		||||
            let nPages = Math.ceil(section.keys.length / itemsPerPage);
 | 
			
		||||
            let page = -1;
 | 
			
		||||
            let pageKeys;
 | 
			
		||||
 | 
			
		||||
            for (let j = 0; j < section.keys.length; j++) {
 | 
			
		||||
                if (j % itemsPerPage == 0) {
 | 
			
		||||
                    page++;
 | 
			
		||||
                    pageKeys = [];
 | 
			
		||||
                    this._pages.push({ pageKeys, nPages, page, section: this._sections[i] });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                pageKeys.push(section.keys[j]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lookupSection(section, nPage) {
 | 
			
		||||
        for (let i = 0; i < this._pages.length; i++) {
 | 
			
		||||
            let page = this._pages[i];
 | 
			
		||||
 | 
			
		||||
            if (page.section == section && page.page == nPage)
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _generatePanel(nPage) {
 | 
			
		||||
        let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                  column_homogeneous: true,
 | 
			
		||||
                                                  row_homogeneous: true });
 | 
			
		||||
        let panel = new St.Widget({ layout_manager: gridLayout,
 | 
			
		||||
                                    style_class: 'emoji-page',
 | 
			
		||||
                                    x_expand: true,
 | 
			
		||||
                                    y_expand: true });
 | 
			
		||||
 | 
			
		||||
        /* Set an expander actor so all proportions are right despite the panel
 | 
			
		||||
         * not having all rows/cols filled in.
 | 
			
		||||
         */
 | 
			
		||||
        let expander = new Clutter.Actor();
 | 
			
		||||
        gridLayout.attach(expander, 0, 0, this._nCols, this._nRows);
 | 
			
		||||
 | 
			
		||||
        let page = this._pages[nPage];
 | 
			
		||||
        let col = 0;
 | 
			
		||||
        let row = 0;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < page.pageKeys.length; i++) {
 | 
			
		||||
            let modelKey = page.pageKeys[i];
 | 
			
		||||
            let key = new Key(modelKey.label, modelKey.variants);
 | 
			
		||||
 | 
			
		||||
            key.keyButton.set_button_mask(0);
 | 
			
		||||
 | 
			
		||||
            key.connect('activated', () => {
 | 
			
		||||
                this._currentKey = key;
 | 
			
		||||
            });
 | 
			
		||||
            key.connect('long-press', () => {
 | 
			
		||||
                this._panAction.cancel();
 | 
			
		||||
            });
 | 
			
		||||
            key.connect('released', (actor, keyval, str) => {
 | 
			
		||||
                if (this._currentKey != key)
 | 
			
		||||
                    return;
 | 
			
		||||
                this._currentKey = null;
 | 
			
		||||
                this.emit('emoji', str);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            gridLayout.attach(key.actor, col, row, 1, 1);
 | 
			
		||||
 | 
			
		||||
            col++;
 | 
			
		||||
            if (col >= this._nCols) {
 | 
			
		||||
                col = 0;
 | 
			
		||||
                row++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return panel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setCurrentPage(nPage) {
 | 
			
		||||
        if (this._curPage == nPage)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._curPage = nPage;
 | 
			
		||||
 | 
			
		||||
        if (this._panel) {
 | 
			
		||||
            this._panel.destroy();
 | 
			
		||||
            this._panel = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Reuse followingPage if possible */
 | 
			
		||||
        if (nPage == this._followingPage) {
 | 
			
		||||
            this._panel = this._followingPanel;
 | 
			
		||||
            this._followingPanel = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._followingPanel)
 | 
			
		||||
            this._followingPanel.destroy();
 | 
			
		||||
 | 
			
		||||
        this._followingPanel = null;
 | 
			
		||||
        this._followingPage = null;
 | 
			
		||||
        this._delta = 0;
 | 
			
		||||
 | 
			
		||||
        if (!this._panel) {
 | 
			
		||||
            this._panel = this._generatePanel(nPage);
 | 
			
		||||
            this.actor.add_child(this._panel);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let page = this._pages[nPage];
 | 
			
		||||
        this.emit('page-changed', page.section, page.page, page.nPages);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setCurrentSection(section, nPage) {
 | 
			
		||||
        for (let i = 0; i < this._pages.length; i++) {
 | 
			
		||||
            let page = this._pages[i];
 | 
			
		||||
 | 
			
		||||
            if (page.section == section && page.page == nPage) {
 | 
			
		||||
                this.setCurrentPage(i);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(EmojiPager.prototype);
 | 
			
		||||
 | 
			
		||||
var EmojiSelection = class EmojiSelection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._sections = [
 | 
			
		||||
            { first: 'grinning face', label: '🙂️' },
 | 
			
		||||
            { first: 'selfie', label: '👍️' },
 | 
			
		||||
            { first: 'monkey face', label: '🌷️' },
 | 
			
		||||
            { first: 'grapes', label: '🍴️' },
 | 
			
		||||
            { first: 'globe showing Europe-Africa', label: '✈️' },
 | 
			
		||||
            { first: 'jack-o-lantern', label: '🏃️' },
 | 
			
		||||
            { first: 'muted speaker', label: '🔔️' },
 | 
			
		||||
            { first: 'ATM sign', label: '❤️' },
 | 
			
		||||
            { first: 'chequered flag', label: '🚩️' },
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        this._populateSections();
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'emoji-panel',
 | 
			
		||||
                                        x_expand: true,
 | 
			
		||||
                                        y_expand: true,
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
        this.actor.connect('notify::mapped', () => { this._emojiPager.setCurrentPage(0); });
 | 
			
		||||
 | 
			
		||||
        this._emojiPager = new EmojiPager(this._sections, 11, 3);
 | 
			
		||||
        this._emojiPager.connect('page-changed', (pager, section, page, nPages) => {
 | 
			
		||||
            this._onPageChanged(section, page, nPages);
 | 
			
		||||
        });
 | 
			
		||||
        this._emojiPager.connect('emoji', (pager, str) => {
 | 
			
		||||
            this.emit('emoji-selected', str);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.add(this._emojiPager.actor, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._pageIndicator = new PageIndicators.PageIndicators(false);
 | 
			
		||||
        this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
        this._pageIndicator.setReactive(false);
 | 
			
		||||
 | 
			
		||||
        let bottomRow = this._createBottomRow();
 | 
			
		||||
        this.actor.add(bottomRow, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._emojiPager.setCurrentPage(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPageChanged(section, page, nPages) {
 | 
			
		||||
        this._pageIndicator.setNPages(nPages);
 | 
			
		||||
        this._pageIndicator.setCurrentPage(page);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            let sect = this._sections[i];
 | 
			
		||||
            sect.button.setLatched(section == sect);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _findSection(emoji) {
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            if (this._sections[i].first == emoji)
 | 
			
		||||
                return this._sections[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _populateSections() {
 | 
			
		||||
        let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json');
 | 
			
		||||
        let [success, contents] = file.load_contents(null);
 | 
			
		||||
 | 
			
		||||
        if (contents instanceof Uint8Array)
 | 
			
		||||
            contents = imports.byteArray.toString(contents);
 | 
			
		||||
        let emoji = JSON.parse(contents);
 | 
			
		||||
 | 
			
		||||
        let pages = [];
 | 
			
		||||
        let variants = [];
 | 
			
		||||
        let currentKey = 0;
 | 
			
		||||
        let currentSection = null;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < emoji.length; i++) {
 | 
			
		||||
            /* Group variants of a same emoji so they appear on the key popover */
 | 
			
		||||
            if (emoji[i].name.startsWith(emoji[currentKey].name)) {
 | 
			
		||||
                variants.push(emoji[i].char);
 | 
			
		||||
                if (i < emoji.length - 1)
 | 
			
		||||
                    continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let newSection = this._findSection(emoji[currentKey].name);
 | 
			
		||||
            if (newSection != null) {
 | 
			
		||||
                currentSection = newSection;
 | 
			
		||||
                currentSection.keys = [];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Create the key */
 | 
			
		||||
            let label = emoji[currentKey].char + String.fromCharCode(0xFE0F);
 | 
			
		||||
            currentSection.keys.push({ label, variants });
 | 
			
		||||
            currentKey = i;
 | 
			
		||||
            variants = [];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _createBottomRow() {
 | 
			
		||||
        let row = new KeyContainer();
 | 
			
		||||
        let key;
 | 
			
		||||
 | 
			
		||||
        row.appendRow();
 | 
			
		||||
 | 
			
		||||
        key = new Key('ABC', []);
 | 
			
		||||
        key.keyButton.add_style_class_name('default-key');
 | 
			
		||||
        key.connect('released', () => { this.emit('toggle'); });
 | 
			
		||||
        row.appendKey(key.actor, 1.5);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            let section = this._sections[i];
 | 
			
		||||
 | 
			
		||||
            key = new Key(section.label, []);
 | 
			
		||||
            key.connect('released', () => { this._emojiPager.setCurrentSection(section, 0) });
 | 
			
		||||
            row.appendKey(key.actor);
 | 
			
		||||
 | 
			
		||||
            section.button = key;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        key = new Key(null, []);
 | 
			
		||||
        key.keyButton.add_style_class_name('default-key');
 | 
			
		||||
        key.keyButton.add_style_class_name('hide-key');
 | 
			
		||||
        key.connect('released', () => {
 | 
			
		||||
            this.emit('hide');
 | 
			
		||||
        });
 | 
			
		||||
        row.appendKey(key.actor);
 | 
			
		||||
        row.layoutButtons();
 | 
			
		||||
 | 
			
		||||
        let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                          x_expand: true, y_expand: true });
 | 
			
		||||
        actor.add_child(row);
 | 
			
		||||
        /* Regular keyboard layouts are 11.5×4 grids, optimize for that
 | 
			
		||||
         * at the moment. Ideally this should be as wide as the current
 | 
			
		||||
         * keymap.
 | 
			
		||||
         */
 | 
			
		||||
        actor.setRatio(11.5, 1);
 | 
			
		||||
 | 
			
		||||
        return actor;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(EmojiSelection.prototype);
 | 
			
		||||
 | 
			
		||||
var Keypad = class Keypad {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        let keys = [
 | 
			
		||||
            { label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 },
 | 
			
		||||
            { label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 },
 | 
			
		||||
            { label: '3', keyval: Clutter.KEY_3, left: 2, top: 0 },
 | 
			
		||||
            { label: '4', keyval: Clutter.KEY_4, left: 0, top: 1 },
 | 
			
		||||
            { label: '5', keyval: Clutter.KEY_5, left: 1, top: 1 },
 | 
			
		||||
            { label: '6', keyval: Clutter.KEY_6, left: 2, top: 1 },
 | 
			
		||||
            { label: '7', keyval: Clutter.KEY_7, left: 0, top: 2 },
 | 
			
		||||
            { label: '8', keyval: Clutter.KEY_8, left: 1, top: 2 },
 | 
			
		||||
            { label: '9', keyval: Clutter.KEY_9, left: 2, top: 2 },
 | 
			
		||||
            { label: '0', keyval: Clutter.KEY_0, left: 1, top: 3 },
 | 
			
		||||
            { label: '⌫', keyval: Clutter.KEY_BackSpace, left: 3, top: 0 },
 | 
			
		||||
            { keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 },
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                           x_expand: true, y_expand: true });
 | 
			
		||||
 | 
			
		||||
        let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                  column_homogeneous: true,
 | 
			
		||||
                                                  row_homogeneous: true });
 | 
			
		||||
        this._box = new St.Widget({ layout_manager: gridLayout, x_expand: true, y_expand: true });
 | 
			
		||||
        this.actor.add_child(this._box);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < keys.length; i++) {
 | 
			
		||||
            let cur = keys[i];
 | 
			
		||||
            let key = new Key(cur.label || "", []);
 | 
			
		||||
 | 
			
		||||
            if (keys[i].extraClassName)
 | 
			
		||||
                key.keyButton.add_style_class_name(cur.extraClassName);
 | 
			
		||||
 | 
			
		||||
            let w, h;
 | 
			
		||||
            w = cur.width || 1;
 | 
			
		||||
            h = cur.height || 1;
 | 
			
		||||
            gridLayout.attach(key.actor, cur.left, cur.top, w, h);
 | 
			
		||||
 | 
			
		||||
            key.connect('released', () => {
 | 
			
		||||
                this.emit('keyval', cur.keyval);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Keypad.prototype);
 | 
			
		||||
 | 
			
		||||
var Keyboard = class Keyboard {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
        this._focusInExtendedKeys = false;
 | 
			
		||||
        this._emojiActive = false;
 | 
			
		||||
 | 
			
		||||
        this._languagePopup = null;
 | 
			
		||||
        this._currentFocusWindow = null;
 | 
			
		||||
@@ -568,6 +1049,7 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
 | 
			
		||||
        this._lastDeviceId = null;
 | 
			
		||||
        this._suggestions = null;
 | 
			
		||||
        this._emojiKeyVisible = true;
 | 
			
		||||
 | 
			
		||||
        this._focusTracker = new FocusTracker();
 | 
			
		||||
        this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
 | 
			
		||||
@@ -656,6 +1138,10 @@ var Keyboard = class Keyboard {
 | 
			
		||||
            this._keyboardController.disconnect(this._keyboardGroupsChangedId);
 | 
			
		||||
        if (this._keyboardStateId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keyboardStateId);
 | 
			
		||||
        if (this._emojiKeyVisibleId)
 | 
			
		||||
            this._keyboardController.disconnect(this._emojiKeyVisibleId);
 | 
			
		||||
        if (this._keypadVisibleId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keypadVisibleId);
 | 
			
		||||
        if (this._focusNotifyId)
 | 
			
		||||
            global.stage.disconnect(this._focusNotifyId);
 | 
			
		||||
        this._keyboard = null;
 | 
			
		||||
@@ -679,13 +1165,32 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        this._current_page = null;
 | 
			
		||||
 | 
			
		||||
        this._suggestions = new Suggestions();
 | 
			
		||||
        this._suggestions.connect('suggestion-clicked', (suggestions, str) => {
 | 
			
		||||
            this._keyboardController.commitString(str);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.add(this._suggestions.actor,
 | 
			
		||||
                       { x_align: St.Align.MIDDLE,
 | 
			
		||||
                         x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this.actor.add(this._aspectContainer, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._emojiSelection = new EmojiSelection();
 | 
			
		||||
        this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
 | 
			
		||||
        this._emojiSelection.connect('hide', (selection) => { this.hide(); });
 | 
			
		||||
        this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
 | 
			
		||||
            this._keyboardController.commitString(emoji);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._aspectContainer.add_child(this._emojiSelection.actor);
 | 
			
		||||
        this._emojiSelection.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._keypad = new Keypad();
 | 
			
		||||
        this._keypad.connect('keyval', (keypad, keyval) => {
 | 
			
		||||
            this._keyboardController.keyvalPress(keyval);
 | 
			
		||||
            this._keyboardController.keyvalRelease(keyval);
 | 
			
		||||
        });
 | 
			
		||||
        this._aspectContainer.add_child(this._keypad.actor);
 | 
			
		||||
        this._keypad.actor.hide();
 | 
			
		||||
        this._keypadVisible = false;
 | 
			
		||||
 | 
			
		||||
        this._ensureKeysForGroup(this._keyboardController.getCurrentGroup());
 | 
			
		||||
        this._setActiveLayer(0);
 | 
			
		||||
 | 
			
		||||
@@ -697,6 +1202,8 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        this._keyboardNotifyId = this._keyboardController.connect('active-group', this._onGroupChanged.bind(this));
 | 
			
		||||
        this._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed', this._onKeyboardGroupsChanged.bind(this));
 | 
			
		||||
        this._keyboardStateId = this._keyboardController.connect('panel-state', this._onKeyboardStateChanged.bind(this));
 | 
			
		||||
        this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this));
 | 
			
		||||
        this._keypadVisibleId = this._keyboardController.connect('keypad-visible', this._onKeypadVisible.bind(this));
 | 
			
		||||
        this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._relayout();
 | 
			
		||||
@@ -743,11 +1250,12 @@ var Keyboard = class Keyboard {
 | 
			
		||||
 | 
			
		||||
            this._loadRows(currentLevel, level, levels.length, layout);
 | 
			
		||||
            layers[level] = layout;
 | 
			
		||||
            this.actor.add(layout, { expand: true });
 | 
			
		||||
            layout.layoutButtons();
 | 
			
		||||
            this._aspectContainer.add_child(layout);
 | 
			
		||||
            layout.layoutButtons(this._aspectContainer);
 | 
			
		||||
 | 
			
		||||
            layout.hide();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return layers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -806,7 +1314,11 @@ var Keyboard = class Keyboard {
 | 
			
		||||
            let switchToLevel = key.level;
 | 
			
		||||
            let action = key.action;
 | 
			
		||||
 | 
			
		||||
            extraButton = new Key(key.label, []);
 | 
			
		||||
            /* Skip emoji button if necessary */
 | 
			
		||||
            if (!this._emojiKeyVisible && action == 'emoji')
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            extraButton = new Key(key.label || '', []);
 | 
			
		||||
 | 
			
		||||
            extraButton.keyButton.add_style_class_name('default-key');
 | 
			
		||||
            if (key.extraClassName != null)
 | 
			
		||||
@@ -832,6 +1344,8 @@ var Keyboard = class Keyboard {
 | 
			
		||||
                    this.hide();
 | 
			
		||||
                else if (action == 'languageMenu')
 | 
			
		||||
                    this._popupLanguageMenu(actor);
 | 
			
		||||
                else if (action == 'emoji')
 | 
			
		||||
                    this._toggleEmoji();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            if (switchToLevel == 0) {
 | 
			
		||||
@@ -857,14 +1371,31 @@ var Keyboard = class Keyboard {
 | 
			
		||||
                extraButton.setWidth(2);
 | 
			
		||||
            } else if (keyval == Clutter.KEY_Return && numKeys > 9) {
 | 
			
		||||
                extraButton.setWidth(1.5);
 | 
			
		||||
            } else if (!this._emojiKeyVisible && (action == 'hide' || action == 'languageMenu')) {
 | 
			
		||||
                extraButton.setWidth(1.5);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateCurrentPageVisible() {
 | 
			
		||||
        if (this._current_page)
 | 
			
		||||
            this._current_page.visible = !this._emojiActive && !this._keypadVisible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setEmojiActive(active) {
 | 
			
		||||
        this._emojiActive = active;
 | 
			
		||||
        this._emojiSelection.actor.visible = this._emojiActive;
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _toggleEmoji() {
 | 
			
		||||
        this._setEmojiActive(!this._emojiActive);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setCurrentLevelLatched(layout, latched) {
 | 
			
		||||
        for (let i = 0; layout.shiftKeys[i]; i++) {
 | 
			
		||||
        for (let i = 0; i < layout.shiftKeys.length; i++) {
 | 
			
		||||
            let key = layout.shiftKeys[i];
 | 
			
		||||
            key.setLatched(latched);
 | 
			
		||||
        }
 | 
			
		||||
@@ -943,6 +1474,24 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        this._onGroupChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeypadVisible(controller, visible) {
 | 
			
		||||
        if (visible == this._keypadVisible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._keypadVisible = visible;
 | 
			
		||||
        this._keypad.actor.visible = this._keypadVisible;
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onEmojiKeyVisible(controller, visible) {
 | 
			
		||||
        if (visible == this._emojiKeyVisible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._emojiKeyVisible = visible;
 | 
			
		||||
        /* Rebuild keyboard widgetry to include emoji button */
 | 
			
		||||
        this._onKeyboardGroupsChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyboardStateChanged(controller, state) {
 | 
			
		||||
        let enabled;
 | 
			
		||||
        if (state == Clutter.InputPanelState.OFF)
 | 
			
		||||
@@ -970,7 +1519,7 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._current_page = layers[activeLevel];
 | 
			
		||||
        this._current_page.show();
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shouldTakeEvent(event) {
 | 
			
		||||
@@ -1020,6 +1569,8 @@ var Keyboard = class Keyboard {
 | 
			
		||||
        this._relayout();
 | 
			
		||||
        Main.layoutManager.showKeyboard();
 | 
			
		||||
 | 
			
		||||
        this._setEmojiActive(false);
 | 
			
		||||
 | 
			
		||||
        if (this._delayedAnimFocusWindow) {
 | 
			
		||||
            this._setAnimationWindow(this._delayedAnimFocusWindow);
 | 
			
		||||
            this._delayedAnimFocusWindow = null;
 | 
			
		||||
@@ -1187,8 +1738,21 @@ var KeyboardController = class {
 | 
			
		||||
    _onContentPurposeHintsChanged(method) {
 | 
			
		||||
        let hints = method.content_hints;
 | 
			
		||||
        let purpose = method.content_purpose;
 | 
			
		||||
        let emojiVisible = false;
 | 
			
		||||
        let keypadVisible = false;
 | 
			
		||||
 | 
			
		||||
        // XXX: hook numeric/emoji/etc special keyboards
 | 
			
		||||
        if (purpose == Clutter.InputContentPurpose.NORMAL ||
 | 
			
		||||
            purpose == Clutter.InputContentPurpose.ALPHA ||
 | 
			
		||||
            purpose == Clutter.InputContentPurpose.PASSWORD ||
 | 
			
		||||
            purpose == Clutter.InputContentPurpose.TERMINAL)
 | 
			
		||||
            emojiVisible = true;
 | 
			
		||||
        if (purpose == Clutter.InputContentPurpose.DIGITS ||
 | 
			
		||||
            purpose == Clutter.InputContentPurpose.NUMBER ||
 | 
			
		||||
            purpose == Clutter.InputContentPurpose.PHONE)
 | 
			
		||||
            keypadVisible = true;
 | 
			
		||||
 | 
			
		||||
        this.emit('emoji-visible', emojiVisible)
 | 
			
		||||
        this.emit('keypad-visible', keypadVisible);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getGroups() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Background = imports.ui.background;
 | 
			
		||||
const BackgroundMenu = imports.ui.backgroundMenu;
 | 
			
		||||
@@ -151,12 +146,13 @@ var MonitorConstraint = GObject.registerClass({
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Monitor = class Monitor {
 | 
			
		||||
    constructor(index, geometry) {
 | 
			
		||||
    constructor(index, geometry, geometry_scale) {
 | 
			
		||||
        this.index = index;
 | 
			
		||||
        this.x = geometry.x;
 | 
			
		||||
        this.y = geometry.y;
 | 
			
		||||
        this.width = geometry.width;
 | 
			
		||||
        this.height = geometry.height;
 | 
			
		||||
        this.geometry_scale = geometry_scale;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get inFullscreen() {
 | 
			
		||||
@@ -164,6 +160,19 @@ var Monitor = class Monitor {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const UiActor = GObject.registerClass(
 | 
			
		||||
class UiActor extends St.Widget {
 | 
			
		||||
    vfunc_get_preferred_width (forHeight) {
 | 
			
		||||
        let width = global.stage.width;
 | 
			
		||||
        return [width, width];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_preferred_height (forWidth) {
 | 
			
		||||
        let height = global.stage.height;
 | 
			
		||||
        return [height, height];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const defaultParams = {
 | 
			
		||||
    trackFullscreen: false,
 | 
			
		||||
    affectsStruts: false,
 | 
			
		||||
@@ -204,12 +213,8 @@ var LayoutManager = GObject.registerClass({
 | 
			
		||||
        global.stage.no_clear_hint = true;
 | 
			
		||||
 | 
			
		||||
        // Set up stage hierarchy to group all UI actors under one container.
 | 
			
		||||
        this.uiGroup = new St.Widget({ name: 'uiGroup' });
 | 
			
		||||
        this.uiGroup = new UiActor({ name: 'uiGroup' });
 | 
			
		||||
        this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
 | 
			
		||||
        this.uiGroup.add_constraint(new Clutter.BindConstraint({
 | 
			
		||||
            source: global.stage,
 | 
			
		||||
            coordinate: Clutter.BindCoordinate.ALL,
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        global.stage.remove_actor(global.window_group);
 | 
			
		||||
        this.uiGroup.add_actor(global.window_group);
 | 
			
		||||
@@ -323,7 +328,9 @@ var LayoutManager = GObject.registerClass({
 | 
			
		||||
        this.monitors = [];
 | 
			
		||||
        let nMonitors = display.get_n_monitors();
 | 
			
		||||
        for (let i = 0; i < nMonitors; i++)
 | 
			
		||||
            this.monitors.push(new Monitor(i, display.get_monitor_geometry(i)));
 | 
			
		||||
            this.monitors.push(new Monitor(i,
 | 
			
		||||
                                           display.get_monitor_geometry(i),
 | 
			
		||||
                                           display.get_monitor_scale(i)));
 | 
			
		||||
 | 
			
		||||
        if (nMonitors == 0) {
 | 
			
		||||
            this.primaryIndex = this.bottomIndex = -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const { Clutter, GObject, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,9 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Cogl = imports.gi.Cogl;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const { Clutter, Cogl, Gio, GLib,
 | 
			
		||||
        GObject, Meta, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const System = imports.system;
 | 
			
		||||
 | 
			
		||||
const History = imports.misc.history;
 | 
			
		||||
@@ -25,15 +17,9 @@ const JsParse = imports.misc.jsParse;
 | 
			
		||||
const CHEVRON = '>>> ';
 | 
			
		||||
 | 
			
		||||
/* Imports...feel free to add here as needed */
 | 
			
		||||
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
 | 
			
		||||
                    'const GLib = imports.gi.GLib; ' +
 | 
			
		||||
                    'const GObject = imports.gi.GObject; ' +
 | 
			
		||||
                    'const Gio = imports.gi.Gio; ' +
 | 
			
		||||
                    'const Gtk = imports.gi.Gtk; ' +
 | 
			
		||||
                    'const Mainloop = imports.mainloop; ' +
 | 
			
		||||
                    'const Meta = imports.gi.Meta; ' +
 | 
			
		||||
                    'const Shell = imports.gi.Shell; ' +
 | 
			
		||||
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
 | 
			
		||||
                    'const Main = imports.ui.main; ' +
 | 
			
		||||
                    'const Mainloop = imports.mainloop; ' +
 | 
			
		||||
                    'const Tweener = imports.ui.tweener; ' +
 | 
			
		||||
                    /* Utility functions...we should probably be able to use these
 | 
			
		||||
                     * in the shell core code too. */
 | 
			
		||||
@@ -187,7 +173,7 @@ var Notebook = class Notebook {
 | 
			
		||||
 | 
			
		||||
        // Focus the new tab before unmapping the old one
 | 
			
		||||
        let tabData = this._tabs[index];
 | 
			
		||||
        if (!tabData.scrollView.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
        if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
            this.actor.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
        this._unselect();
 | 
			
		||||
@@ -396,6 +382,7 @@ var ObjInspector = class ObjInspector {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        button = new St.Button({ style_class: 'window-close' });
 | 
			
		||||
        button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
 | 
			
		||||
        button.connect('clicked', this.close.bind(this));
 | 
			
		||||
        hbox.add(button);
 | 
			
		||||
        if (typeof(obj) == typeof({})) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Atspi = imports.gi.Atspi;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GDesktopEnums = imports.gi.GDesktopEnums;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Atspi, Clutter, GDesktopEnums,
 | 
			
		||||
        Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Background = imports.ui.background;
 | 
			
		||||
@@ -24,9 +18,6 @@ var NO_CHANGE = 0.0;
 | 
			
		||||
var POINTER_REST_TIME = 1000; // milliseconds
 | 
			
		||||
 | 
			
		||||
// Settings
 | 
			
		||||
const APPLICATIONS_SCHEMA       = 'org.gnome.desktop.a11y.applications';
 | 
			
		||||
const SHOW_KEY                  = 'screen-magnifier-enabled';
 | 
			
		||||
 | 
			
		||||
const MAGNIFIER_SCHEMA          = 'org.gnome.desktop.a11y.magnifier';
 | 
			
		||||
const SCREEN_POSITION_KEY       = 'screen-position';
 | 
			
		||||
const MAG_FACTOR_KEY            = 'mag-factor';
 | 
			
		||||
@@ -52,6 +43,54 @@ const CROSS_HAIRS_CLIP_KEY      = 'cross-hairs-clip';
 | 
			
		||||
 | 
			
		||||
let magDBusService = null;
 | 
			
		||||
 | 
			
		||||
var MouseSpriteContent = GObject.registerClass({
 | 
			
		||||
    Implements: [ Clutter.Content ],
 | 
			
		||||
}, class MouseSpriteContent extends GObject.Object {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
        this._texture = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_preferred_size() {
 | 
			
		||||
        if (!this._texture)
 | 
			
		||||
            return [false, 0, 0];
 | 
			
		||||
 | 
			
		||||
        return [true, this._texture.get_width(), this._texture.get_height()];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_paint_content(actor, node) {
 | 
			
		||||
        if (!this._texture)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let color = Clutter.Color.get_static(Clutter.StaticColor.WHITE);
 | 
			
		||||
        let [minFilter, magFilter] = actor.get_content_scaling_filters();
 | 
			
		||||
        let textureNode = new Clutter.TextureNode(this._texture,
 | 
			
		||||
                                                  color, minFilter, magFilter);
 | 
			
		||||
        textureNode.set_name('MouseSpriteContent');
 | 
			
		||||
        node.add_child(textureNode);
 | 
			
		||||
 | 
			
		||||
        textureNode.add_rectangle(actor.get_content_box());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get texture() {
 | 
			
		||||
        return this._texture;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set texture(coglTexture) {
 | 
			
		||||
        if (this._texture == coglTexture)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let oldTexture = this._texture;
 | 
			
		||||
        this._texture = coglTexture;
 | 
			
		||||
        this.invalidate();
 | 
			
		||||
 | 
			
		||||
        if (!oldTexture || !coglTexture ||
 | 
			
		||||
            oldTexture.get_width() != coglTexture.get_width() ||
 | 
			
		||||
            oldTexture.get_height() != coglTexture.get_height())
 | 
			
		||||
            this.invalidate_size();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Magnifier = class Magnifier {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        // Magnifier is a manager of ZoomRegions.
 | 
			
		||||
@@ -59,8 +98,11 @@ var Magnifier = class Magnifier {
 | 
			
		||||
 | 
			
		||||
        // Create small clutter tree for the magnified mouse.
 | 
			
		||||
        let cursorTracker = Meta.CursorTracker.get_for_display(global.display);
 | 
			
		||||
        this._mouseSprite = new Clutter.Texture();
 | 
			
		||||
        Shell.util_cursor_tracker_to_clutter(cursorTracker, this._mouseSprite);
 | 
			
		||||
        this._cursorTracker = cursorTracker;
 | 
			
		||||
 | 
			
		||||
        this._mouseSprite = new Clutter.Actor({ request_mode: Clutter.RequestMode.CONTENT_SIZE });
 | 
			
		||||
        this._mouseSprite.content = new MouseSpriteContent();
 | 
			
		||||
 | 
			
		||||
        this._cursorRoot = new Clutter.Actor();
 | 
			
		||||
        this._cursorRoot.add_actor(this._mouseSprite);
 | 
			
		||||
 | 
			
		||||
@@ -72,15 +114,16 @@ var Magnifier = class Magnifier {
 | 
			
		||||
 | 
			
		||||
        let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
 | 
			
		||||
        this._zoomRegions.push(aZoomRegion);
 | 
			
		||||
        let showAtLaunch = this._settingsInit(aZoomRegion);
 | 
			
		||||
        this._settingsInit(aZoomRegion);
 | 
			
		||||
        aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
 | 
			
		||||
 | 
			
		||||
        cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this));
 | 
			
		||||
        this._cursorTracker = cursorTracker;
 | 
			
		||||
        St.Settings.get().connect('notify::magnifier-active', () => {
 | 
			
		||||
            this.setActive(St.Settings.get().magnifier_active);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Export to dbus.
 | 
			
		||||
        magDBusService = new MagnifierDBus.ShellMagnifier();
 | 
			
		||||
        this.setActive(showAtLaunch);
 | 
			
		||||
        this.setActive(St.Settings.get().magnifier_active);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -113,9 +156,15 @@ var Magnifier = class Magnifier {
 | 
			
		||||
 | 
			
		||||
        if (isActive != activate) {
 | 
			
		||||
            if (activate) {
 | 
			
		||||
                this._updateMouseSprite();
 | 
			
		||||
                this._cursorSpriteChangedId =
 | 
			
		||||
                    this._cursorTracker.connect('cursor-changed',
 | 
			
		||||
                                                this._updateMouseSprite.bind(this));
 | 
			
		||||
                Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
                this.startTrackingMouse();
 | 
			
		||||
            } else {
 | 
			
		||||
                this._cursorTracker.disconnect(this._cursorSpriteChangedId);
 | 
			
		||||
                this._mouseSprite.content.texture = null;
 | 
			
		||||
                Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
                this.stopTrackingMouse();
 | 
			
		||||
            }
 | 
			
		||||
@@ -436,18 +485,24 @@ var Magnifier = class Magnifier {
 | 
			
		||||
    //// Private methods ////
 | 
			
		||||
 | 
			
		||||
    _updateMouseSprite() {
 | 
			
		||||
        Shell.util_cursor_tracker_to_clutter(this._cursorTracker, this._mouseSprite);
 | 
			
		||||
        this._updateSpriteTexture();
 | 
			
		||||
        let [xHot, yHot] = this._cursorTracker.get_hot();
 | 
			
		||||
        this._mouseSprite.set_anchor_point(xHot, yHot);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _settingsInit(zoomRegion) {
 | 
			
		||||
        this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA });
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
 | 
			
		||||
    _updateSpriteTexture() {
 | 
			
		||||
        let sprite = this._cursorTracker.get_sprite();
 | 
			
		||||
 | 
			
		||||
        this._appSettings.connect('changed::' + SHOW_KEY, () => {
 | 
			
		||||
            this.setActive(this._appSettings.get_boolean(SHOW_KEY));
 | 
			
		||||
        });
 | 
			
		||||
        if (sprite) {
 | 
			
		||||
            this._mouseSprite.content.texture = sprite;
 | 
			
		||||
            this._mouseSprite.show();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._mouseSprite.hide();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _settingsInit(zoomRegion) {
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this._settings.connect('changed::' + SCREEN_POSITION_KEY,
 | 
			
		||||
                               this._updateScreenPosition.bind(this));
 | 
			
		||||
@@ -555,8 +610,6 @@ var Magnifier = class Magnifier {
 | 
			
		||||
        let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
 | 
			
		||||
        this.addCrosshairs();
 | 
			
		||||
        this.setCrosshairsVisible(showCrosshairs);
 | 
			
		||||
 | 
			
		||||
        return this._appSettings.get_boolean(SHOW_KEY);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
    _updateScreenPosition() {
 | 
			
		||||
@@ -703,13 +756,41 @@ var ZoomRegion = class ZoomRegion {
 | 
			
		||||
 | 
			
		||||
        this._pointerIdleMonitor = Meta.IdleMonitor.get_for_device(Meta.VIRTUAL_CORE_POINTER_ID);
 | 
			
		||||
        this._scrollContentsTimerId = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed',
 | 
			
		||||
                                   this._monitorsChanged.bind(this));
 | 
			
		||||
        this._focusCaretTracker.connect('caret-moved',
 | 
			
		||||
                                    this._updateCaret.bind(this));
 | 
			
		||||
        this._focusCaretTracker.connect('focus-changed',
 | 
			
		||||
                                    this._updateFocus.bind(this));
 | 
			
		||||
    _connectSignals() {
 | 
			
		||||
        if (this._signalConnections)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._signalConnections = [];
 | 
			
		||||
        let id = Main.layoutManager.connect('monitors-changed',
 | 
			
		||||
                                            this._monitorsChanged.bind(this));
 | 
			
		||||
        this._signalConnections.push([Main.layoutManager, id]);
 | 
			
		||||
 | 
			
		||||
        id = this._focusCaretTracker.connect('caret-moved', this._updateCaret.bind(this));
 | 
			
		||||
        this._signalConnections.push([this._focusCaretTracker, id]);
 | 
			
		||||
 | 
			
		||||
        id = this._focusCaretTracker.connect('focus-changed', this._updateFocus.bind(this));
 | 
			
		||||
        this._signalConnections.push([this._focusCaretTracker, id]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _disconnectSignals() {
 | 
			
		||||
        for (let [obj, id] of this._signalConnections)
 | 
			
		||||
            obj.disconnect(id);
 | 
			
		||||
 | 
			
		||||
        delete this._signalConnections;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateScreenPosition() {
 | 
			
		||||
        if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
 | 
			
		||||
            this._setViewPort({
 | 
			
		||||
                x: this._viewPortX,
 | 
			
		||||
                y: this._viewPortY,
 | 
			
		||||
                width: this._viewPortWidth,
 | 
			
		||||
                height: this._viewPortHeight
 | 
			
		||||
            });
 | 
			
		||||
        else
 | 
			
		||||
            this.setScreenPosition(this._screenPosition);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateFocus(caller, event) {
 | 
			
		||||
@@ -757,10 +838,13 @@ var ZoomRegion = class ZoomRegion {
 | 
			
		||||
            this._createActors();
 | 
			
		||||
            if (this._isMouseOverRegion())
 | 
			
		||||
                this._magnifier.hideSystemCursor();
 | 
			
		||||
            this._updateScreenPosition();
 | 
			
		||||
            this._updateMagViewGeometry();
 | 
			
		||||
            this._updateCloneGeometry();
 | 
			
		||||
            this._updateMousePosition();
 | 
			
		||||
            this._connectSignals();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._disconnectSignals();
 | 
			
		||||
            this._destroyActors();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1510,18 +1594,8 @@ var ZoomRegion = class ZoomRegion {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _monitorsChanged() {
 | 
			
		||||
        if (!this.isActive())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._background.set_size(global.screen_width, global.screen_height);
 | 
			
		||||
 | 
			
		||||
        if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
 | 
			
		||||
            this._setViewPort({ x: this._viewPortX,
 | 
			
		||||
                                y: this._viewPortY,
 | 
			
		||||
                                width: this._viewPortWidth,
 | 
			
		||||
                                height: this._viewPortHeight });
 | 
			
		||||
        else
 | 
			
		||||
            this.setScreenPosition(this._screenPosition);
 | 
			
		||||
        this._updateScreenPosition();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,13 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const { Clutter, Gio, GLib, 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 AccessDialog = imports.ui.accessDialog;
 | 
			
		||||
const AudioDeviceSelection = imports.ui.audioDeviceSelection;
 | 
			
		||||
const Components = imports.ui.components;
 | 
			
		||||
const CtrlAltTab = imports.ui.ctrlAltTab;
 | 
			
		||||
const EndSessionDialog = imports.ui.endSessionDialog;
 | 
			
		||||
const Environment = imports.ui.environment;
 | 
			
		||||
const ExtensionSystem = imports.ui.extensionSystem;
 | 
			
		||||
const ExtensionDownloader = imports.ui.extensionDownloader;
 | 
			
		||||
const InputMethod = imports.misc.inputMethod;
 | 
			
		||||
@@ -44,7 +36,6 @@ const ShellMountOperation = imports.ui.shellMountOperation;
 | 
			
		||||
const WindowManager = imports.ui.windowManager;
 | 
			
		||||
const Magnifier = imports.ui.magnifier;
 | 
			
		||||
const XdndHandler = imports.ui.xdndHandler;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
const KbdA11yDialog = imports.ui.kbdA11yDialog;
 | 
			
		||||
 | 
			
		||||
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
 | 
			
		||||
@@ -128,9 +119,8 @@ function start() {
 | 
			
		||||
 | 
			
		||||
    sessionMode = new SessionMode.SessionMode();
 | 
			
		||||
    sessionMode.connect('updated', _sessionUpdated);
 | 
			
		||||
    Gtk.Settings.get_default().connect('notify::gtk-theme-name',
 | 
			
		||||
                                       _loadDefaultStylesheet);
 | 
			
		||||
    Gtk.IconTheme.get_default().add_resource_path('/org/gnome/shell/theme/icons');
 | 
			
		||||
 | 
			
		||||
    St.Settings.get().connect('notify::gtk-theme', _loadDefaultStylesheet);
 | 
			
		||||
    _initializeUI();
 | 
			
		||||
 | 
			
		||||
    shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus();
 | 
			
		||||
@@ -221,13 +211,6 @@ function _initializeUI() {
 | 
			
		||||
 | 
			
		||||
    _startDate = new Date();
 | 
			
		||||
 | 
			
		||||
    let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
 | 
			
		||||
    if (perfModuleName) {
 | 
			
		||||
        let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
 | 
			
		||||
        let module = eval('imports.perf.' + perfModuleName + ';');
 | 
			
		||||
        Scripting.runPerfScript(module, perfOutput);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ExtensionDownloader.init();
 | 
			
		||||
    ExtensionSystem.init();
 | 
			
		||||
 | 
			
		||||
@@ -249,6 +232,13 @@ function _initializeUI() {
 | 
			
		||||
            Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
 | 
			
		||||
                                        ['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
 | 
			
		||||
        if (perfModuleName) {
 | 
			
		||||
            let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
 | 
			
		||||
            let module = eval('imports.perf.' + perfModuleName + ';');
 | 
			
		||||
            Scripting.runPerfScript(module, perfOutput);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -280,7 +270,7 @@ function _getDefaultStylesheet() {
 | 
			
		||||
 | 
			
		||||
    // Look for a high-contrast variant first when using GTK+'s HighContrast
 | 
			
		||||
    // theme
 | 
			
		||||
    if (Gtk.Settings.get_default().gtk_theme_name == 'HighContrast')
 | 
			
		||||
    if (St.Settings.get().gtk_theme == 'HighContrast')
 | 
			
		||||
        stylesheet = _getStylesheet(name.replace('.css', '-high-contrast.css'));
 | 
			
		||||
 | 
			
		||||
    if (stylesheet == null)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,7 @@
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const { Atk, Clutter, Gio, GLib, GObject, Meta, Pango, St } = imports.gi;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -159,7 +152,7 @@ var URLHighlighter = class URLHighlighter {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ScaleLayout = new GObject.registerClass(
 | 
			
		||||
var ScaleLayout = GObject.registerClass(
 | 
			
		||||
class ScaleLayout extends Clutter.BinLayout {
 | 
			
		||||
    _init(params) {
 | 
			
		||||
        this._container = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
@@ -19,7 +10,6 @@ const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
 | 
			
		||||
 | 
			
		||||
@@ -71,6 +61,17 @@ var Urgency = {
 | 
			
		||||
    CRITICAL: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The privacy of the details of a notification. USER is for notifications which
 | 
			
		||||
// contain private information to the originating user account (for example,
 | 
			
		||||
// details of an e-mail they’ve received). SYSTEM is for notifications which
 | 
			
		||||
// contain information private to the physical system (for example, battery
 | 
			
		||||
// status) and hence the same for every user. This affects whether the content
 | 
			
		||||
// of a notification is shown on the lock screen.
 | 
			
		||||
var PrivacyScope = {
 | 
			
		||||
    USER: 0,
 | 
			
		||||
    SYSTEM: 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var FocusGrabber = class FocusGrabber {
 | 
			
		||||
    constructor(actor) {
 | 
			
		||||
        this._actor = actor;
 | 
			
		||||
@@ -87,7 +88,7 @@ var FocusGrabber = class FocusGrabber {
 | 
			
		||||
 | 
			
		||||
        this._focusActorChangedId = global.stage.connect('notify::key-focus', this._focusActorChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        if (!this._actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
        if (!this._actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
            this._actor.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
        this._focused = true;
 | 
			
		||||
@@ -340,6 +341,7 @@ var Notification = class Notification {
 | 
			
		||||
        this.resident = false;
 | 
			
		||||
        // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
 | 
			
		||||
        this.isTransient = false;
 | 
			
		||||
        this.privacyScope = PrivacyScope.USER;
 | 
			
		||||
        this.forFeedback = false;
 | 
			
		||||
        this._acknowledged = false;
 | 
			
		||||
        this.bannerBodyText = null;
 | 
			
		||||
@@ -436,6 +438,10 @@ var Notification = class Notification {
 | 
			
		||||
        this.forFeedback = forFeedback;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setPrivacyScope(privacyScope) {
 | 
			
		||||
        this.privacyScope = privacyScope;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    playSound() {
 | 
			
		||||
        if (this._soundPlayed)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -497,9 +503,12 @@ class NotificationBanner extends Calendar.NotificationMessage {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        super._onDestroy();
 | 
			
		||||
        this.notification.disconnect(this._activatedId);
 | 
			
		||||
    _disconnectNotificationSignals() {
 | 
			
		||||
        super._disconnectNotificationSignals();
 | 
			
		||||
 | 
			
		||||
        if (this._activatedId)
 | 
			
		||||
            this.notification.disconnect(this._activatedId);
 | 
			
		||||
        this._activatedId = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onUpdated(n, clear) {
 | 
			
		||||
@@ -699,6 +708,12 @@ var Source = class Source {
 | 
			
		||||
        return this._policy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set policy(policy) {
 | 
			
		||||
        if (this._policy)
 | 
			
		||||
            this._policy.destroy();
 | 
			
		||||
        this._policy = policy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get count() {
 | 
			
		||||
        return this.notifications.length;
 | 
			
		||||
    }
 | 
			
		||||
@@ -719,6 +734,11 @@ var Source = class Source {
 | 
			
		||||
        return new NotificationPolicy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get narrowestPrivacyScope() {
 | 
			
		||||
        return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) ? PrivacyScope.SYSTEM
 | 
			
		||||
                                                                                    : PrivacyScope.USER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTitle(newTitle) {
 | 
			
		||||
        this.title = newTitle;
 | 
			
		||||
        this.emit('title-changed');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,13 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { Atk, Clutter, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const Dialog = imports.ui.dialog;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
var OPEN_AND_CLOSE_TIME = 0.1;
 | 
			
		||||
@@ -197,7 +188,6 @@ var ModalDialog = class {
 | 
			
		||||
        else
 | 
			
		||||
            this._savedKeyFocus = null;
 | 
			
		||||
        Main.popModal(this._group, timestamp);
 | 
			
		||||
        Gdk.Display.get_default().sync();
 | 
			
		||||
        this._hasModal = false;
 | 
			
		||||
 | 
			
		||||
        if (!this._shellReactive)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const { Gio, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,12 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GdkPixbuf = imports.gi.GdkPixbuf;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 | 
			
		||||
@@ -352,6 +345,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
 | 
			
		||||
        // of the 'transient' hint with hints['transient'] rather than hints.transient
 | 
			
		||||
        notification.setTransient(!!hints['transient']);
 | 
			
		||||
 | 
			
		||||
        let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
 | 
			
		||||
        notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM
 | 
			
		||||
                                                              : MessageTray.PrivacyScope.USER);
 | 
			
		||||
 | 
			
		||||
        let sourceGIcon = source.useNotificationIcon ? gicon : null;
 | 
			
		||||
        source.processNotification(notification, sourceGIcon);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, Gio, Meta, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
 | 
			
		||||
var FADE_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,12 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
 | 
			
		||||
const BarLevel = imports.ui.barLevel;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
 | 
			
		||||
var HIDE_TIMEOUT = 1500;
 | 
			
		||||
var FADE_TIME = 0.1;
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user