Compare commits
	
		
			166 Commits
		
	
	
		
			issue369
			...
			gbsneto/ic
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 87a76a5757 | ||
|   | 717ec0f8a4 | ||
|   | 854922866b | ||
|   | 40ad9ab18c | ||
|   | 55eb949def | ||
|   | 0596848c27 | ||
|   | 0bdcf2958f | ||
|   | ac3bc03f3f | ||
|   | bf322cd51a | ||
|   | 6e3696baad | ||
|   | 4056c56800 | ||
|   | ebf2610140 | ||
|   | a9e7b7853a | ||
|   | 0dd430f2f4 | ||
|   | ca01b0287e | ||
|   | 37aa5d0faf | ||
|   | 2e4fb404a7 | ||
|   | 11ce7829bc | ||
|   | 52257f5137 | ||
|   | 74077b0f6e | ||
|   | 241b4cd1c8 | ||
|   | 79f9391c00 | ||
|   | 6da23c8d4d | ||
|   | bb9f05843f | ||
|   | cc9f949b65 | ||
|   | 23191ec239 | ||
|   | 038917e5f1 | ||
|   | f214c5b572 | ||
|   | 9da49606f7 | ||
|   | c13efe96dc | ||
|   | 47d2f4dbeb | ||
|   | 48a2b6cb0b | ||
|   | ce78e8ae54 | ||
|   | abe9b82c48 | ||
|   | 6c85bd6aeb | ||
|   | 06a7ab871f | ||
|   | 12b8fb15b1 | ||
|   | 5295866eff | ||
|   | 02b47f4640 | ||
|   | 108ac7cf20 | ||
|   | 933c037c6e | ||
|   | 8f3554ff3e | ||
|   | 668128f8c9 | ||
|   | 28ab1f4af4 | ||
|   | d360114226 | ||
|   | 5fc456d9d9 | ||
|   | 007d305736 | ||
|   | ae7ec648b2 | ||
|   | 99a2fad311 | ||
|   | 82d466598c | ||
|   | 3a748fe737 | ||
|   | 89ce53e3ff | ||
|   | 2f29081667 | ||
|   | cb0d28770f | ||
|   | 86c3909908 | ||
|   | b970ee7293 | ||
|   | 5545e84430 | ||
|   | 85d9f39417 | ||
|   | a81450df17 | ||
|   | a7c94b2cd2 | ||
|   | 9d65c8b2ec | ||
|   | 1b7ff76092 | ||
|   | 17e32bf16d | ||
|   | 74905f3edc | ||
|   | 8e1b13ca96 | ||
|   | c0e90807e0 | ||
|   | 3db1058c2c | ||
|   | a57c4c580e | ||
|   | 33bbbdc322 | ||
|   | 5826336a77 | ||
|   | 3b5d13a0b2 | ||
|   | ed37ba1d9b | ||
|   | 8ea6fd1925 | ||
|   | 93a461f3f7 | ||
|   | fda7c9b06e | ||
|   | 1e13f32cea | ||
|   | e357559582 | ||
|   | 71759a0769 | ||
|   | 11b116cb9d | ||
|   | 2f97a1a55d | ||
|   | 79cf3a6dd0 | ||
|   | 0257de1b7e | ||
|   | 466dc8da8f | ||
|   | 2c61badc02 | ||
|   | 3f8d3a7ee2 | ||
|   | a455860978 | ||
|   | 0ecf135a4b | ||
|   | cebb6d40df | ||
|   | 0ee13672ee | ||
|   | 49260a85ad | ||
|   | da9f37e629 | ||
|   | 164f3fa3fd | ||
|   | 8e75d81a44 | ||
|   | 1d60c4d9d4 | ||
|   | eaa32090b9 | ||
|   | 32ddb6f739 | ||
|   | 2653402c5c | ||
|   | 2743f18af4 | ||
|   | dd1fdf88ff | ||
|   | 2a041e9d8d | ||
|   | 1117f4760c | ||
|   | 7dda7abf5e | ||
|   | 7ca3cca306 | ||
|   | d471e3a23b | ||
|   | ce1bee727a | ||
|   | 43cb3754d9 | ||
|   | 1d6ddf060b | ||
|   | 9928125e7d | ||
|   | 1c63893c4b | ||
|   | a7ec7583aa | ||
|   | 4a3476266f | ||
|   | 32e0b895a4 | ||
|   | 58806359ee | ||
|   | 4589da957b | ||
|   | 6a4c55b852 | ||
|   | ea17740719 | ||
|   | d82810240f | ||
|   | 2768b73015 | ||
|   | f9a7718dda | ||
|   | d9d9778a98 | ||
|   | bd5162105e | ||
|   | 208c5e9562 | ||
|   | 305e63750e | ||
|   | ab0f74aa15 | ||
|   | 43443d08ae | ||
|   | b82b553b9e | ||
|   | 08464eadff | ||
|   | 49e56776e8 | ||
|   | 043667dde5 | ||
|   | f583a7c6d8 | ||
|   | 2d908e80fc | ||
|   | 8f0e9abe47 | ||
|   | 1a27ff6130 | ||
|   | 3f2cffc2e6 | ||
|   | a78527050a | ||
|   | a823a213ba | ||
|   | 2c8d380e67 | ||
|   | 3996309f8a | ||
|   | bd18313d12 | ||
|   | 2ff7a78b56 | ||
|   | c765082f72 | ||
|   | 7d2c5c1ac9 | ||
|   | 404bc34089 | ||
|   | 16ca7a21a7 | ||
|   | 1b31fd5afe | ||
|   | e0457b6dc4 | ||
|   | 42b77e7ba5 | ||
|   | f6bed08993 | ||
|   | 5f77cdb0b9 | ||
|   | 109b8e8f38 | ||
|   | 4c0bd88a2c | ||
|   | 3731be9947 | ||
|   | 6cc19ee6f0 | ||
|   | 1570f838f3 | ||
|   | 74feb110b5 | ||
|   | 6ba03ac2a6 | ||
|   | 55c717c2dc | ||
|   | 355b5eebec | ||
|   | 51938c398a | ||
|   | dbb71f0dfc | ||
|   | 1cac7b2218 | ||
|   | ff9bb5399b | ||
|   | 68e45eb051 | ||
|   | d0da96ad29 | ||
|   | 55b036170b | ||
|   | 5473637736 | 
							
								
								
									
										6
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| { | ||||
|     "extends": [ | ||||
|         "./lint/eslintrc-gjs.json", | ||||
|         "./lint/eslintrc-shell.json" | ||||
|     ] | ||||
| } | ||||
| @@ -1,6 +1,5 @@ | ||||
| stages: | ||||
|  - review | ||||
|  - source_check | ||||
|  - build | ||||
|  - test | ||||
|  | ||||
| @@ -26,19 +25,27 @@ check_commit_log: | ||||
|  | ||||
| js_check: | ||||
|     image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1 | ||||
|     stage: source_check | ||||
|     stage: review | ||||
|     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 | ||||
|  | ||||
| eslint: | ||||
|     image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1 | ||||
|     stage: review | ||||
|     script: | ||||
|         - ./.gitlab-ci/run-eslint.sh | ||||
|     <<: *only_default | ||||
|     artifacts: | ||||
|         paths: | ||||
|             - reports | ||||
|         when: always | ||||
|  | ||||
| build: | ||||
|     image: registry.gitlab.gnome.org/gnome/mutter/master:v2 | ||||
|     stage: build | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| FROM registry.fedoraproject.org/fedora:latest | ||||
|  | ||||
| RUN dnf -y update && dnf -y upgrade && \ | ||||
|     dnf install -y 'dnf-command(copr)' && \ | ||||
|     dnf install -y 'dnf-command(copr)' git && \ | ||||
|  | ||||
|     # For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'` | ||||
|     dnf install -y findutils mozjs60-devel && \ | ||||
|   | ||||
							
								
								
									
										97
									
								
								.gitlab-ci/run-eslint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										97
									
								
								.gitlab-ci/run-eslint.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| OUTPUT_REGULAR=reports/lint-regular-report.txt | ||||
| OUTPUT_LEGACY=reports/lint-legacy-report.txt | ||||
| OUTPUT_FINAL=reports/lint-common-report.txt | ||||
|  | ||||
| OUTPUT_MR=reports/lint-mr-report.txt | ||||
|  | ||||
| LINE_CHANGES=changed-lines.txt | ||||
|  | ||||
| is_empty() { | ||||
|   (! grep -q . $1) | ||||
| } | ||||
|  | ||||
| run_eslint() { | ||||
|   ARGS_LEGACY='--config lint/eslintrc-legacy.json' | ||||
|  | ||||
|   local extra_args=ARGS_$1 | ||||
|   local output=OUTPUT_$1 | ||||
|   eslint -f unix ${!extra_args} -o ${!output} js | ||||
| } | ||||
|  | ||||
| list_commit_range_additions() { | ||||
|   # Turn raw context-less git-diff into a list of | ||||
|   # filename:lineno pairs of new (+) lines | ||||
|   git diff -U0 "$@" -- js | | ||||
|   awk ' | ||||
|     BEGIN { file=""; } | ||||
|     /^+++ b/ { file=substr($0,7); } | ||||
|     /^@@ / { | ||||
|         len = split($3,a,",") | ||||
|         start=a[1] | ||||
|         count=(len > 1) ? a[2] : 1 | ||||
|  | ||||
|         for (line=start; line<start+count; line++) | ||||
|             printf "%s/%s:%d:\n",ENVIRON["PWD"],file,line; | ||||
|     }' | ||||
| } | ||||
|  | ||||
| copy_matched_lines() { | ||||
|   local source=$1 | ||||
|   local matches=$2 | ||||
|   local target=$3 | ||||
|  | ||||
|   echo -n > $target | ||||
|   for l in $(<$matches); do | ||||
|     grep $l $source >> $target | ||||
|   done | ||||
| } | ||||
|  | ||||
| create_common() { | ||||
|   # comm requires sorted input; | ||||
|   # we also strip the error message to make the following a "common" error: | ||||
|   # regular: | ||||
|   #  file.js:42:23 Indentation of 55, expected 42 | ||||
|   # legacy: | ||||
|   #  file.js:42:23 Indentation of 55, extected 24 | ||||
|   prepare() { | ||||
|     sed 's: .*::' $1 | sort | ||||
|   } | ||||
|  | ||||
|   comm -12 <(prepare $OUTPUT_REGULAR) <(prepare $OUTPUT_LEGACY) >$OUTPUT_FINAL.tmp | ||||
|  | ||||
|   # Now add back the stripped error messages | ||||
|   copy_matched_lines $OUTPUT_REGULAR $OUTPUT_FINAL.tmp $OUTPUT_FINAL | ||||
|   rm $OUTPUT_FINAL.tmp | ||||
| } | ||||
|  | ||||
| if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then | ||||
|   git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME | ||||
|   branch_point=$(git merge-base HEAD FETCH_HEAD) | ||||
|   commit_range=$branch_point...$CI_COMMIT_SHA | ||||
|  | ||||
|   list_commit_range_additions $commit_range > $LINE_CHANGES | ||||
|  | ||||
|   # Don't bother with running lint when no JS changed | ||||
|   if is_empty $LINE_CHANGES; then | ||||
|     exit 0 | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| echo Generating lint report using regular configuration | ||||
| run_eslint REGULAR | ||||
| echo Generating lint report using legacy configuration | ||||
| run_eslint LEGACY | ||||
| echo Done. | ||||
| create_common | ||||
|  | ||||
| # Just show the report and succeed when not testing a MR | ||||
| if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then | ||||
|   cat $OUTPUT_FINAL | ||||
|   exit 0 | ||||
| fi | ||||
|  | ||||
| copy_matched_lines $OUTPUT_FINAL $LINE_CHANGES $OUTPUT_MR | ||||
| cat $OUTPUT_MR | ||||
| is_empty $OUTPUT_MR | ||||
							
								
								
									
										26
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,3 +1,29 @@ | ||||
| 3.33.4 | ||||
| ====== | ||||
| * Fix unintentional interference between gestures [Jonas; !598] | ||||
| * Fix unintentional loop while polkit dialog is active [Ray; !602] | ||||
| * Fix alt-tab icon size on HiDPI [Jonas; !587] | ||||
| * Style fixes and improvements [Frederik, Jakub; !610, #1446, #1449] | ||||
| * Fix style updates for non-background CSS properties [Florian; #1212] | ||||
| * Fix cursor visibility in screen recordings [Illya; #1208] | ||||
| * Add option for disabling the hot corner [Florian; #688320] | ||||
| * Use more fine-grained levels in battery indicator [Florian; !561, #1442] | ||||
| * Fix the calculation of the maximum number of app search results [Jonas; !110] | ||||
| * Handle horizontal workspace layout with gestures/animations [Florian; !575] | ||||
| * Improve handling of session mode extensions [Florian, Didier; #789852] | ||||
| * Misc. bug fixes and cleanups [Jonas, Florian, Sonny, Carlos, Mario, Benjamin, | ||||
|   Marco, Ting-Wei; !599, !600, !591, !606, !152, !607, !604, !495, !608, !611, | ||||
|   !614, !612, !615, !618, #369, !620, #774, !621, !616, #1065, !609, !626, | ||||
|   !491, !631, !632, !633, #1457] | ||||
|  | ||||
| Contributors: | ||||
|   Benjamin Berg, Jonas Dreßler, Frederik Feichtmeier, Carlos Garnacho, | ||||
|   Illya Klymov, Ting-Wei Lan, Florian Müllner, Sonny Piers, Mario Sanchez Prada, | ||||
|   Didier Roche, Jakub Steiner, Ray Strode, Jor Teron, Marco Trevisan (Treviño) | ||||
|  | ||||
| Translators: | ||||
|   Jordi Mas [ca], Jor Teron [mjw] | ||||
|  | ||||
| 3.33.3 | ||||
| ====== | ||||
| * Prepare for optional X11 [Carlos; !378] | ||||
|   | ||||
| @@ -173,6 +173,30 @@ | ||||
|       <arg type="s" direction="in" name="uuid"/> | ||||
|     </method> | ||||
|  | ||||
|     <!-- | ||||
|         EnableExtension: | ||||
|         @uuid: The UUID of the extension | ||||
|         @success: Whether the operation was successful | ||||
|  | ||||
|         Enable an extension. | ||||
|     --> | ||||
|     <method name="EnableExtension"> \ | ||||
|       <arg type="s" direction="in" name="uuid"/> \ | ||||
|       <arg type="b" direction="out" name="success"/> \ | ||||
|     </method> \ | ||||
|  | ||||
|     <!-- | ||||
|         DisableExtension: | ||||
|         @uuid: The UUID of the extension | ||||
|         @success: Whether the operation was successful | ||||
|  | ||||
|         Disable an extension. | ||||
|     --> | ||||
|     <method name="DisableExtension"> \ | ||||
|       <arg type="s" direction="in" name="uuid"/> \ | ||||
|       <arg type="b" direction="out" name="success"/> \ | ||||
|     </method> \ | ||||
|  | ||||
|     <!-- | ||||
|         LaunchExtensionPrefs: | ||||
|         @uuid: The UUID of the extension | ||||
| @@ -189,6 +213,15 @@ | ||||
|     --> | ||||
|     <method name="CheckForUpdates"/> | ||||
|  | ||||
|     <signal name="ExtensionStateChanged"> | ||||
|       <arg type="s" name="uuid"/> | ||||
|       <arg type="a{sv}" name="state"/> | ||||
|     </signal> | ||||
|  | ||||
|     <!-- | ||||
|         ExtensionStatusChanged: | ||||
|         Deprecated for ExtensionStateChanged | ||||
|     --> | ||||
|     <signal name="ExtensionStatusChanged"> | ||||
|       <arg type="s" name="uuid"/> | ||||
|       <arg type="i" name="state"/> | ||||
|   | ||||
							
								
								
									
										16
									
								
								data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <node> | ||||
|  | ||||
|   <!-- | ||||
|       org.gnome.Shell.WeatherIntegration: | ||||
|       @short_description: Weather integration interface | ||||
|  | ||||
|       The interface used for exporting location settings to GNOME Shell's | ||||
|       weather integration. | ||||
|   --> | ||||
|   <interface name="org.gnome.Shell.WeatherIntegration"> | ||||
|  | ||||
|   <property name="AutomaticLocation" type="b" access="read"/> | ||||
|   <property name="Locations" type="av" access="read"/> | ||||
|  | ||||
|   </interface> | ||||
| </node> | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <method name="ShowOSD"> | ||||
|       <arg type="a{sv}" direction="in" name="params"/> | ||||
|     </method> | ||||
|     <method name="ShowMonitorLabels2"> | ||||
|     <method name="ShowMonitorLabels"> | ||||
|       <arg type="a{sv}" direction="in" name="params"/> | ||||
|     </method> | ||||
|     <method name="HideMonitorLabels"/> | ||||
|   | ||||
| @@ -48,6 +48,7 @@ | ||||
|     <file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.gnome.Shell.WeatherIntegration.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.gnome.Shell.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file> | ||||
|     <file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file> | ||||
|   | ||||
| @@ -21,6 +21,17 @@ | ||||
|         EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. | ||||
|       </description> | ||||
|     </key> | ||||
|     <key name="disabled-extensions" type="as"> | ||||
|       <default>[]</default> | ||||
|       <summary>UUIDs of extensions to force disabling</summary> | ||||
|       <description> | ||||
|         GNOME Shell extensions have a UUID property; this key lists extensions | ||||
|         which should be disabled, even if loaded as part of the current mode. | ||||
|         You can also manipulate this list with the EnableExtension and | ||||
|         DisableExtension D-Bus methods on org.gnome.Shell. | ||||
|         This key takes precedence over the “enabled-extensions” setting. | ||||
|       </description> | ||||
|     </key> | ||||
|     <key name="disable-user-extensions" type="b"> | ||||
|       <default>false</default> | ||||
|       <summary>Disable user extensions</summary> | ||||
| @@ -98,6 +109,10 @@ | ||||
|         the shell. | ||||
|       </description> | ||||
|     </key> | ||||
|     <key name="icons-data" type="a{sv}"> | ||||
|       <default>[]</default> | ||||
|       <summary>Data about the icons in the icon grid</summary> | ||||
|     </key> | ||||
|     <child name="keybindings" schema="org.gnome.shell.keybindings"/> | ||||
|   </schema> | ||||
|  | ||||
| @@ -222,6 +237,25 @@ | ||||
|     </key> | ||||
|   </schema> | ||||
|  | ||||
|   <schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/" | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="automatic-location" type="b"> | ||||
|       <summary>Automatic location</summary> | ||||
|       <description> | ||||
|         Whether to fetch the current location or not | ||||
|       </description> | ||||
|       <default>false</default> | ||||
|     </key> | ||||
|  | ||||
|     <key name="locations" type="av"> | ||||
|       <summary>Location</summary> | ||||
|       <description> | ||||
|         The location for which to show a forecast | ||||
|       </description> | ||||
|       <default>[]</default> | ||||
|     </key> | ||||
|   </schema> | ||||
|  | ||||
|   <!-- unused, change 00_org.gnome.shell.gschema.override instead --> | ||||
|   <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/" | ||||
| 	  gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|   | ||||
| @@ -619,6 +619,18 @@ StScrollBar { | ||||
|   app menu inside the main app window itself rather than the top bar | ||||
| */ | ||||
|  | ||||
| /************* | ||||
|  * App Icons * | ||||
|  *************/ | ||||
| /* Outline for low res icons */ | ||||
| .lowres-icon { | ||||
|     icon-shadow: 0 1px 2px rgba(0,0,0,0.3); | ||||
| } | ||||
|  | ||||
| /* Drapshadow for large icons */ | ||||
| .icon-dropshadow { | ||||
|   icon-shadow: 0 1px 2px rgba(0,0,0,0.4); | ||||
| } | ||||
|  | ||||
| /* OSD */ | ||||
| .osd-window { | ||||
| @@ -728,7 +740,8 @@ StScrollBar { | ||||
|     spacing: 8px; | ||||
|   } | ||||
|  | ||||
|   .ws-switcher-active-up, .ws-switcher-active-down { | ||||
|   .ws-switcher-active-up, .ws-switcher-active-down, | ||||
|   .ws-switcher-active-left, .ws-switcher-active-right { | ||||
|     height: 50px; | ||||
|     background-color: $selected_bg_color; | ||||
|     color: $selected_fg_color; | ||||
| @@ -929,7 +942,7 @@ StScrollBar { | ||||
|     .world-clocks-button, | ||||
|     .weather-button, | ||||
|     .events-section-title { | ||||
|       &:hover, focus { background-color: $_hover_bg_color } | ||||
|       &:hover, &:focus { background-color: $_hover_bg_color } | ||||
|       &:active { background-color: $_active_bg_color } | ||||
|     } | ||||
|  | ||||
| @@ -1000,7 +1013,7 @@ StScrollBar { | ||||
|       background-color: transparent; | ||||
|       width: 32px; | ||||
|       border-radius: 4px; | ||||
|       &:hover, focus { background-color: $_hover_bg_color; } | ||||
|       &:hover, &:focus { background-color: $_hover_bg_color; } | ||||
|       &:active { background-color: transparentize($fg_color, 0.84); } | ||||
|     } | ||||
|  | ||||
| @@ -1016,7 +1029,7 @@ StScrollBar { | ||||
|       margin: 2px; | ||||
|       border-radius: 1.4em; | ||||
|       font-feature-settings: "tnum"; | ||||
|       &:hover, focus { background-color: $_hover_bg_color; } | ||||
|       &:hover, &:focus { background-color: $_hover_bg_color; } | ||||
|       &:active,&:selected { | ||||
|         color: lighten($selected_fg_color,5%); | ||||
|         background-color: $selected_bg_color; | ||||
| @@ -1158,7 +1171,6 @@ StScrollBar { | ||||
|   // a little unstructured mess: | ||||
|  | ||||
|   #appMenu { | ||||
|     spinner-image: url("resource:///org/gnome/shell/theme/process-working.svg"); | ||||
|     spacing: 4px; | ||||
|  | ||||
|     .label-shadow { color: transparent; } | ||||
| @@ -1326,8 +1338,8 @@ StScrollBar { | ||||
|  | ||||
|   .window-clone-border { | ||||
|     $_bg: transparentize(white, 0.65); | ||||
|     border: 5px solid $_bg; | ||||
|     border-radius: 6px; | ||||
|     border: 7px solid $_bg; | ||||
|     border-radius: $modal_radius; | ||||
|     // For window decorations with round corners we can't match | ||||
|     // the exact shape when the window is scaled. So apply a shadow | ||||
|     // to fix that case | ||||
| @@ -1364,11 +1376,8 @@ StScrollBar { | ||||
|  | ||||
|   //search results | ||||
|  | ||||
|   #searchResultsBin { | ||||
|     max-width: 1000px; | ||||
|   } | ||||
|  | ||||
|   #searchResultsContent { | ||||
|     max-width: 1000px; | ||||
|     padding-left: 20px; | ||||
|     padding-right: 20px; | ||||
|     spacing: 16px; | ||||
| @@ -1484,11 +1493,11 @@ StScrollBar { | ||||
|   .search-provider-icon, | ||||
|   .list-search-result { | ||||
|     @extend %icon_tile; | ||||
|     &:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); } | ||||
|     &:focus, &:selected, &:hover { | ||||
|       background-color: transparentize($osd_fg_color,.9); | ||||
|       transition-duration: 200ms; | ||||
|     } | ||||
|     &:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); } | ||||
|   } | ||||
|   .app-well-app, | ||||
|   .app-well-app.app-folder, | ||||
| @@ -1497,10 +1506,6 @@ StScrollBar { | ||||
|     & .overview-icon { | ||||
|       @extend %icon_tile; | ||||
|     } | ||||
|     &:active .overview-icon, | ||||
|     &:checked .overview-icon { | ||||
|       background-color: transparentize(darken($osd_bg_color,10%), 0.5); | ||||
|     } | ||||
|     &:hover .overview-icon, | ||||
|     &:focus .overview-icon, | ||||
|     &:selected .overview-icon { | ||||
| @@ -1509,7 +1514,13 @@ StScrollBar { | ||||
|       border-image: none; | ||||
|       background-image: none; | ||||
|     } | ||||
|  | ||||
|     &:drop .overview-icon { | ||||
|       background-color: transparentize($selected_bg_color,.15); | ||||
|     } | ||||
|     &:active .overview-icon, | ||||
|     &:checked .overview-icon { | ||||
|       background-color: transparentize(darken($osd_bg_color,10%), 0.5); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .app-well-app-running-dot { //running apps indicator | ||||
| @@ -1599,7 +1610,6 @@ StScrollBar { | ||||
|   } | ||||
|  | ||||
|   //Some hacks I don't even | ||||
|   .search-display > StBoxLayout, | ||||
|   .all-apps, | ||||
|   .frequent-apps > StBoxLayout { | ||||
|     // horizontal padding to make sure scrollbars or dash don't overlap content | ||||
|   | ||||
| @@ -28,7 +28,7 @@ foreach iface : ifaces | ||||
|     output: 'doc-gen-' + iface[1], | ||||
|     command: [ | ||||
|       'gdbus-codegen', | ||||
|       '--interface-prefix=@0@.'.format(iface), | ||||
|       '--interface-prefix=@0@.'.format(iface[0]), | ||||
|       '--generate-docbook', 'doc-gen', | ||||
|       '--output-directory', '@OUTDIR@', | ||||
|       '@INPUT@' | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported main */ | ||||
| const Gettext = imports.gettext; | ||||
| const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi; | ||||
| const Format = imports.format; | ||||
| @@ -8,6 +9,8 @@ const Config = imports.misc.config; | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const { loadInterfaceXML } = imports.misc.fileUtils; | ||||
|  | ||||
| const { ExtensionState } = ExtensionUtils; | ||||
|  | ||||
| const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions'); | ||||
| const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); | ||||
|  | ||||
| @@ -17,74 +20,54 @@ function stripPrefix(string, prefix) { | ||||
|     return string; | ||||
| } | ||||
|  | ||||
| var Application = class { | ||||
|     constructor() { | ||||
| var Application = GObject.registerClass({ | ||||
|     GTypeName: 'ExtensionPrefs_Application' | ||||
| }, class Application extends Gtk.Application { | ||||
|     _init() { | ||||
|         GLib.set_prgname('gnome-shell-extension-prefs'); | ||||
|         this.application = new Gtk.Application({ | ||||
|         super._init({ | ||||
|             application_id: 'org.gnome.shell.ExtensionPrefs', | ||||
|             flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE | ||||
|         }); | ||||
|  | ||||
|         this.application.connect('activate', this._onActivate.bind(this)); | ||||
|         this.application.connect('command-line', this._onCommandLine.bind(this)); | ||||
|         this.application.connect('startup', this._onStartup.bind(this)); | ||||
|  | ||||
|         this._extensionPrefsModules = {}; | ||||
|  | ||||
|         this._startupUuid = null; | ||||
|         this._loaded = false; | ||||
|         this._skipMainWindow = false; | ||||
|         this._shellProxy = null; | ||||
|     } | ||||
|  | ||||
|     _extensionAvailable(uuid) { | ||||
|         let extension = ExtensionUtils.extensions[uuid]; | ||||
|     get shellProxy() { | ||||
|         return this._shellProxy; | ||||
|     } | ||||
|  | ||||
|         if (!extension) | ||||
|     _showPrefs(uuid) { | ||||
|         let row = this._extensionSelector.get_children().find(c => { | ||||
|             return c.uuid === uuid && c.hasPrefs; | ||||
|         }); | ||||
|  | ||||
|         if (!row) | ||||
|             return false; | ||||
|  | ||||
|         if (!extension.dir.get_child('prefs.js').query_exists(null)) | ||||
|             return false; | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     _getExtensionPrefsModule(extension) { | ||||
|         let uuid = extension.metadata.uuid; | ||||
|  | ||||
|         if (this._extensionPrefsModules.hasOwnProperty(uuid)) | ||||
|             return this._extensionPrefsModules[uuid]; | ||||
|  | ||||
|         ExtensionUtils.installImporter(extension); | ||||
|  | ||||
|         let prefsModule = extension.imports.prefs; | ||||
|         prefsModule.init(extension.metadata); | ||||
|  | ||||
|         this._extensionPrefsModules[uuid] = prefsModule; | ||||
|         return prefsModule; | ||||
|     } | ||||
|  | ||||
|     _selectExtension(uuid) { | ||||
|         if (!this._extensionAvailable(uuid)) | ||||
|             return; | ||||
|  | ||||
|         let extension = ExtensionUtils.extensions[uuid]; | ||||
|         let widget; | ||||
|  | ||||
|         try { | ||||
|             let prefsModule = this._getExtensionPrefsModule(extension); | ||||
|             widget = prefsModule.buildPrefsWidget(); | ||||
|             widget = row.prefsModule.buildPrefsWidget(); | ||||
|         } catch (e) { | ||||
|             widget = this._buildErrorUI(extension, e); | ||||
|             widget = this._buildErrorUI(row, e); | ||||
|         } | ||||
|  | ||||
|         let dialog = new Gtk.Window({ modal: !this._skipMainWindow, | ||||
|                                       type_hint: Gdk.WindowTypeHint.DIALOG }); | ||||
|         dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true, | ||||
|                                                 title: extension.metadata.name, | ||||
|                                                 visible: true })); | ||||
|         let dialog = new Gtk.Window({ | ||||
|             modal: !this._skipMainWindow, | ||||
|             type_hint: Gdk.WindowTypeHint.DIALOG | ||||
|         }); | ||||
|         dialog.set_titlebar(new Gtk.HeaderBar({ | ||||
|             show_close_button: true, | ||||
|             title: row.name, | ||||
|             visible: true | ||||
|         })); | ||||
|  | ||||
|         if (this._skipMainWindow) { | ||||
|             this.application.add_window(dialog); | ||||
|             this.add_window(dialog); | ||||
|             if (this._window) | ||||
|                 this._window.destroy(); | ||||
|             this._window = dialog; | ||||
| @@ -96,9 +79,11 @@ var Application = class { | ||||
|         dialog.set_default_size(600, 400); | ||||
|         dialog.add(widget); | ||||
|         dialog.show(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     _buildErrorUI(extension, exc) { | ||||
|     _buildErrorUI(row, exc) { | ||||
|         let scroll = new Gtk.ScrolledWindow({ | ||||
|             hscrollbar_policy: Gtk.PolicyType.NEVER, | ||||
|             propagate_natural_height: true | ||||
| @@ -170,7 +155,7 @@ var Application = class { | ||||
|             let clipboard = Gtk.Clipboard.get_default(w.get_display()); | ||||
|             // markdown for pasting in gitlab issues | ||||
|             let lines = [ | ||||
|                 `The settings of extension ${extension.uuid} had an error:`, | ||||
|                 `The settings of extension ${row.uuid} had an error:`, | ||||
|                 '```', | ||||
|                 `${exc}`, | ||||
|                 '```', | ||||
| @@ -192,13 +177,13 @@ var Application = class { | ||||
|             label: _("Homepage"), | ||||
|             tooltip_text: _("Visit extension homepage"), | ||||
|             no_show_all: true, | ||||
|             visible: extension.metadata.url != null | ||||
|             visible: row.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); | ||||
|             Gio.AppInfo.launch_default_for_uri(row.url, context); | ||||
|         }); | ||||
|  | ||||
|         let expandedBox = new Gtk.Box({ | ||||
| @@ -213,8 +198,8 @@ var Application = class { | ||||
|         return scroll; | ||||
|     } | ||||
|  | ||||
|     _buildUI(app) { | ||||
|         this._window = new Gtk.ApplicationWindow({ application: app, | ||||
|     _buildUI() { | ||||
|         this._window = new Gtk.ApplicationWindow({ application: this, | ||||
|                                                    window_position: Gtk.WindowPosition.CENTER }); | ||||
|  | ||||
|         this._window.set_default_size(800, 500); | ||||
| @@ -248,18 +233,14 @@ var Application = class { | ||||
|         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]) => { | ||||
|             if (ExtensionUtils.extensions[uuid] !== undefined) | ||||
|                 this._scanExtensions(); | ||||
|         }); | ||||
|         this._shellProxy.connectSignal('ExtensionStateChanged', | ||||
|             this._onExtensionStateChanged.bind(this)); | ||||
|  | ||||
|         this._window.show_all(); | ||||
|     } | ||||
|  | ||||
|     _sortList(row1, row2) { | ||||
|         let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name; | ||||
|         let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name; | ||||
|         return name1.localeCompare(name2); | ||||
|         return row1.name.localeCompare(row2.name); | ||||
|     } | ||||
|  | ||||
|     _updateHeader(row, before) { | ||||
| @@ -270,19 +251,55 @@ var Application = class { | ||||
|         row.set_header(sep); | ||||
|     } | ||||
|  | ||||
|     _scanExtensions() { | ||||
|         let finder = new ExtensionUtils.ExtensionFinder(); | ||||
|         finder.connect('extension-found', this._extensionFound.bind(this)); | ||||
|         finder.scanExtensions(); | ||||
|         this._extensionsLoaded(); | ||||
|     _findExtensionRow(uuid) { | ||||
|         return this._extensionSelector.get_children().find(c => c.uuid === uuid); | ||||
|     } | ||||
|  | ||||
|     _extensionFound(finder, extension) { | ||||
|         let row = new ExtensionRow(extension.uuid); | ||||
|     _onExtensionStateChanged(proxy, senderName, [uuid, newState]) { | ||||
|         let row = this._findExtensionRow(uuid); | ||||
|         if (row) { | ||||
|             let { state } = ExtensionUtils.deserializeExtension(newState); | ||||
|             if (state == ExtensionState.UNINSTALLED) | ||||
|                 row.destroy(); | ||||
|             return; // we only deal with new and deleted extensions here | ||||
|         } | ||||
|  | ||||
|         this._shellProxy.GetExtensionInfoRemote(uuid, ([serialized]) => { | ||||
|             let extension = ExtensionUtils.deserializeExtension(serialized); | ||||
|             if (!extension) | ||||
|                 return; | ||||
|             // check the extension wasn't added in between | ||||
|             if (this._findExtensionRow(uuid) != null) | ||||
|                 return; | ||||
|             this._addExtensionRow(extension); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _scanExtensions() { | ||||
|         this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => { | ||||
|             if (e) { | ||||
|                 if (e instanceof Gio.DBusError) { | ||||
|                     log(`Failed to connect to shell proxy: ${e}`); | ||||
|                     this._mainStack.add_named(new NoShellPlaceholder(), 'noshell'); | ||||
|                     this._mainStack.visible_child_name = 'noshell'; | ||||
|                 } else | ||||
|                     throw e; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             for (let uuid in extensionsMap) { | ||||
|                 let extension = ExtensionUtils.deserializeExtension(extensionsMap[uuid]); | ||||
|                 this._addExtensionRow(extension); | ||||
|             } | ||||
|             this._extensionsLoaded(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _addExtensionRow(extension) { | ||||
|         let row = new ExtensionRow(extension); | ||||
|  | ||||
|         row.prefsButton.visible = this._extensionAvailable(row.uuid); | ||||
|         row.prefsButton.connect('clicked', () => { | ||||
|             this._selectExtension(row.uuid); | ||||
|             this._showPrefs(row.uuid); | ||||
|         }); | ||||
|  | ||||
|         row.show_all(); | ||||
| @@ -295,24 +312,26 @@ var Application = class { | ||||
|         else | ||||
|             this._mainStack.visible_child_name = 'placeholder'; | ||||
|  | ||||
|         if (this._startupUuid && this._extensionAvailable(this._startupUuid)) | ||||
|             this._selectExtension(this._startupUuid); | ||||
|         if (this._startupUuid) | ||||
|             this._showPrefs(this._startupUuid); | ||||
|         this._startupUuid = null; | ||||
|         this._skipMainWindow = false; | ||||
|         this._loaded = true; | ||||
|     } | ||||
|  | ||||
|     _onActivate() { | ||||
|     vfunc_activate() { | ||||
|         this._window.present(); | ||||
|     } | ||||
|  | ||||
|     _onStartup(app) { | ||||
|         this._buildUI(app); | ||||
|     vfunc_startup() { | ||||
|         super.vfunc_startup(); | ||||
|  | ||||
|         this._buildUI(); | ||||
|         this._scanExtensions(); | ||||
|     } | ||||
|  | ||||
|     _onCommandLine(app, commandLine) { | ||||
|         app.activate(); | ||||
|     vfunc_command_line(commandLine) { | ||||
|         this.activate(); | ||||
|         let args = commandLine.get_arguments(); | ||||
|  | ||||
|         if (args.length) { | ||||
| @@ -323,16 +342,14 @@ var Application = class { | ||||
|             // Strip off "extension:///" prefix which fakes a URI, if it exists | ||||
|             uuid = stripPrefix(uuid, "extension:///"); | ||||
|  | ||||
|             if (this._extensionAvailable(uuid)) | ||||
|                 this._selectExtension(uuid); | ||||
|             else if (!this._loaded) | ||||
|             if (!this._loaded) | ||||
|                 this._startupUuid = uuid; | ||||
|             else | ||||
|             else if (!this._showPrefs(uuid)) | ||||
|                 this._skipMainWindow = false; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var Expander = GObject.registerClass({ | ||||
|     Properties: { | ||||
| @@ -499,6 +516,35 @@ class EmptyPlaceholder extends Gtk.Box { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var NoShellPlaceholder = GObject.registerClass( | ||||
| class NoShellPlaceholder extends Gtk.Box { | ||||
|     _init() { | ||||
|         super._init({ | ||||
|             orientation: Gtk.Orientation.VERTICAL, | ||||
|             spacing: 12, | ||||
|             margin: 100, | ||||
|             margin_bottom: 60 | ||||
|         }); | ||||
|  | ||||
|         let label = new Gtk.Label({ | ||||
|             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); | ||||
|         this.add(label); | ||||
|  | ||||
|         label = new Gtk.Label({ | ||||
|             label: _("We’re very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again."), | ||||
|             justify: Gtk.Justification.CENTER, | ||||
|             wrap: true | ||||
|         }); | ||||
|         this.add(label); | ||||
|  | ||||
|         this.show_all(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var DescriptionLabel = GObject.registerClass( | ||||
| class DescriptionLabel extends Gtk.Label { | ||||
|     vfunc_get_preferred_height_for_width(width) { | ||||
| @@ -511,30 +557,55 @@ class DescriptionLabel extends Gtk.Label { | ||||
|  | ||||
| var ExtensionRow = GObject.registerClass( | ||||
| class ExtensionRow extends Gtk.ListBoxRow { | ||||
|     _init(uuid) { | ||||
|     _init(extension) { | ||||
|         super._init(); | ||||
|  | ||||
|         this.uuid = uuid; | ||||
|         this._app = Gio.Application.get_default(); | ||||
|         this._extension = extension; | ||||
|         this._prefsModule = null; | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); | ||||
|         this._settings.connect('changed::enabled-extensions', () => { | ||||
|             this._switch.state = this._isEnabled(); | ||||
|         }); | ||||
|         this._settings.connect('changed::disable-extension-version-validation', | ||||
|             () => { | ||||
|                 this._switch.sensitive = this._canEnable(); | ||||
|             }); | ||||
|         this._settings.connect('changed::disable-user-extensions', | ||||
|             () => { | ||||
|                 this._switch.sensitive = this._canEnable(); | ||||
|         this._extensionStateChangedId = this._app.shellProxy.connectSignal( | ||||
|             'ExtensionStateChanged', (p, sender, [uuid, newState]) => { | ||||
|                 if (this.uuid !== uuid) | ||||
|                     return; | ||||
|  | ||||
|                 this._extension = ExtensionUtils.deserializeExtension(newState); | ||||
|                 let state = (this._extension.state == ExtensionState.ENABLED); | ||||
|                 this._switch.state = state; | ||||
|                 this._switch.sensitive = this._canToggle(); | ||||
|             }); | ||||
|  | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this._buildUI(); | ||||
|     } | ||||
|  | ||||
|     _buildUI() { | ||||
|         let extension = ExtensionUtils.extensions[this.uuid]; | ||||
|     get uuid() { | ||||
|         return this._extension.uuid; | ||||
|     } | ||||
|  | ||||
|     get name() { | ||||
|         return this._extension.metadata.name; | ||||
|     } | ||||
|  | ||||
|     get hasPrefs() { | ||||
|         return this._extension.hasPrefs; | ||||
|     } | ||||
|  | ||||
|     get url() { | ||||
|         return this._extension.metadata.url; | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         if (!this._app.shellProxy) | ||||
|             return; | ||||
|  | ||||
|         if (this._extensionStateChangedId) | ||||
|             this._app.shellProxy.disconnectSignal(this._extensionStateChangedId); | ||||
|         this._extensionStateChangedId = 0; | ||||
|     } | ||||
|  | ||||
|     _buildUI() { | ||||
|         let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, | ||||
|                                  hexpand: true, margin_end: 24, spacing: 24, | ||||
|                                  margin: 12 }); | ||||
| @@ -544,19 +615,20 @@ class ExtensionRow extends Gtk.ListBoxRow { | ||||
|                                  spacing: 6, hexpand: true }); | ||||
|         hbox.add(vbox); | ||||
|  | ||||
|         let name = GLib.markup_escape_text(extension.metadata.name, -1); | ||||
|         let name = GLib.markup_escape_text(this.name, -1); | ||||
|         let label = new Gtk.Label({ label: '<b>' + name + '</b>', | ||||
|                                     use_markup: true, | ||||
|                                     halign: Gtk.Align.START }); | ||||
|         vbox.add(label); | ||||
|  | ||||
|         let desc = extension.metadata.description.split('\n')[0]; | ||||
|         let desc = this._extension.metadata.description.split('\n')[0]; | ||||
|         label = new DescriptionLabel({ label: desc, wrap: true, lines: 2, | ||||
|                                        ellipsize: Pango.EllipsizeMode.END, | ||||
|                                        xalign: 0, yalign: 0 }); | ||||
|         vbox.add(label); | ||||
|  | ||||
|         let button = new Gtk.Button({ valign: Gtk.Align.CENTER, | ||||
|                                       visible: this.hasPrefs, | ||||
|                                       no_show_all: true }); | ||||
|         button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic', | ||||
|                                          icon_size: Gtk.IconSize.BUTTON, | ||||
| @@ -566,51 +638,37 @@ class ExtensionRow extends Gtk.ListBoxRow { | ||||
|  | ||||
|         this.prefsButton = button; | ||||
|  | ||||
|         this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER, | ||||
|                                         sensitive: this._canEnable(), | ||||
|                                         state: this._isEnabled() }); | ||||
|         this._switch = new Gtk.Switch({ | ||||
|             valign: Gtk.Align.CENTER, | ||||
|             sensitive: this._canToggle(), | ||||
|             state: this._extension.state === ExtensionState.ENABLED | ||||
|         }); | ||||
|         this._switch.connect('notify::active', () => { | ||||
|             if (this._switch.active) | ||||
|                 this._enable(); | ||||
|                 this._app.shellProxy.EnableExtensionRemote(this.uuid); | ||||
|             else | ||||
|                 this._disable(); | ||||
|                 this._app.shellProxy.DisableExtensionRemote(this.uuid); | ||||
|         }); | ||||
|         this._switch.connect('state-set', () => true); | ||||
|         hbox.add(this._switch); | ||||
|     } | ||||
|  | ||||
|     _canEnable() { | ||||
|         let extension = ExtensionUtils.extensions[this.uuid]; | ||||
|         let checkVersion = !this._settings.get_boolean('disable-extension-version-validation'); | ||||
|  | ||||
|         return !this._settings.get_boolean('disable-user-extensions') && | ||||
|                !(checkVersion && ExtensionUtils.isOutOfDate(extension)); | ||||
|     _canToggle() { | ||||
|         return this._extension.canChange; | ||||
|     } | ||||
|  | ||||
|     _isEnabled() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         return extensions.includes(this.uuid); | ||||
|     } | ||||
|     get prefsModule() { | ||||
|         if (!this._prefsModule) { | ||||
|             ExtensionUtils.installImporter(this._extension); | ||||
|  | ||||
|     _enable() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         if (extensions.includes(this.uuid)) | ||||
|             return; | ||||
|             // give extension prefs access to their own extension object | ||||
|             ExtensionUtils.getCurrentExtension = () => this._extension; | ||||
|  | ||||
|         extensions.push(this.uuid); | ||||
|         this._settings.set_strv('enabled-extensions', extensions); | ||||
|     } | ||||
|             this._prefsModule = this._extension.imports.prefs; | ||||
|             this._prefsModule.init(this._extension.metadata); | ||||
|         } | ||||
|  | ||||
|     _disable() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         let pos = extensions.indexOf(this.uuid); | ||||
|         if (pos == -1) | ||||
|             return; | ||||
|         do { | ||||
|             extensions.splice(pos, 1); | ||||
|             pos = extensions.indexOf(this.uuid); | ||||
|         } while (pos != -1); | ||||
|         this._settings.set_strv('enabled-extensions', extensions); | ||||
|         return this._prefsModule; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -638,6 +696,5 @@ function main(argv) { | ||||
|     Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); | ||||
|     Gettext.textdomain(Config.GETTEXT_PACKAGE); | ||||
|  | ||||
|     let app = new Application(); | ||||
|     app.application.run(argv); | ||||
|     new Application().run(argv); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported FprintManager */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported LoginDialog */ | ||||
| /* | ||||
|  * Copyright 2011 Red Hat, Inc | ||||
|  * | ||||
| @@ -372,7 +373,7 @@ var SessionMenuButton = class { | ||||
|         } | ||||
|  | ||||
|         for (let i = 0; i < ids.length; i++) { | ||||
|             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); | ||||
|             let [sessionName, sessionDescription_] = Gdm.get_session_name_and_description(ids[i]); | ||||
|  | ||||
|             let id = ids[i]; | ||||
|             let item = new PopupMenu.PopupMenuItem(sessionName); | ||||
| @@ -518,7 +519,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|     _getBannerAllocation(dialogBox) { | ||||
|         let actorBox = new Clutter.ActorBox(); | ||||
|  | ||||
|         let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size(); | ||||
|         let [, , natWidth, natHeight] = this._bannerView.get_preferred_size(); | ||||
|         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; | ||||
|  | ||||
|         actorBox.x1 = Math.floor(centerX - natWidth / 2); | ||||
| @@ -532,7 +533,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|     _getLogoBinAllocation(dialogBox) { | ||||
|         let actorBox = new Clutter.ActorBox(); | ||||
|  | ||||
|         let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size(); | ||||
|         let [, , natWidth, natHeight] = this._logoBin.get_preferred_size(); | ||||
|         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; | ||||
|  | ||||
|         actorBox.x1 = Math.floor(centerX - natWidth / 2); | ||||
| @@ -546,7 +547,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|     _getCenterActorAllocation(dialogBox, actor) { | ||||
|         let actorBox = new Clutter.ActorBox(); | ||||
|  | ||||
|         let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size(); | ||||
|         let [, , natWidth, natHeight] = actor.get_preferred_size(); | ||||
|         let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; | ||||
|         let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2; | ||||
|  | ||||
| @@ -648,7 +649,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|  | ||||
|                     // figure out how tall it would like to be and try to accommodate | ||||
|                     // but don't let it get too close to the logo | ||||
|                     let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth); | ||||
|                     let [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth); | ||||
|  | ||||
|                     let maxWideHeight = dialogHeight - 3 * logoHeight; | ||||
|                     wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight); | ||||
| @@ -1241,7 +1242,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|         this._authPrompt.cancel(); | ||||
|     } | ||||
|  | ||||
|     addCharacter(unichar) { | ||||
|     addCharacter(_unichar) { | ||||
|         // Don't allow type ahead at the login screen | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getOVirtCredentialsManager */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const Signals = imports.signals; | ||||
|   | ||||
| @@ -15,7 +15,7 @@ const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm"); | ||||
| const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); | ||||
|  | ||||
| var Manager = class { | ||||
|     constructor(parentActor) { | ||||
|     constructor() { | ||||
|         this._aggregateProvider = Provider(Gio.DBus.system, | ||||
|                                            'org.freedesktop.realmd', | ||||
|                                            '/org/freedesktop/realmd', | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY, | ||||
|             DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */ | ||||
|  | ||||
| const { Clutter, Gio, GLib } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -45,7 +47,7 @@ function fadeInActor(actor) { | ||||
|  | ||||
|     let hold = new Batch.Hold(); | ||||
|     actor.show(); | ||||
|     let [minHeight, naturalHeight] = actor.get_preferred_height(-1); | ||||
|     let [, naturalHeight] = actor.get_preferred_height(-1); | ||||
|  | ||||
|     actor.opacity = 0; | ||||
|     actor.set_height(0); | ||||
| @@ -303,7 +305,7 @@ var ShellUserVerifier = class { | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     _oVirtUserAuthenticated(token) { | ||||
|     _oVirtUserAuthenticated(_token) { | ||||
|         this._preemptingService = OVIRT_SERVICE_NAME; | ||||
|         this.emit('ovirt-user-authenticated'); | ||||
|     } | ||||
|   | ||||
| @@ -1,23 +1,37 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported ExtensionState, ExtensionType, getCurrentExtension, | ||||
|    getSettings, initTranslations, isOutOfDate, installImporter, | ||||
|    serializeExtension, deserializeExtension */ | ||||
|  | ||||
| // Common utils for the extension system and the extension | ||||
| // preferences tool | ||||
|  | ||||
| const Gettext = imports.gettext; | ||||
| const Signals = imports.signals; | ||||
| const { Gio, GLib } = imports.gi; | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const Gettext = imports.gettext; | ||||
| const Lang = imports.lang; | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
| const FileUtils = imports.misc.fileUtils; | ||||
|  | ||||
| var ExtensionType = { | ||||
|     SYSTEM: 1, | ||||
|     PER_USER: 2 | ||||
| }; | ||||
|  | ||||
| // Maps uuid -> metadata object | ||||
| var extensions = {}; | ||||
| var ExtensionState = { | ||||
|     ENABLED: 1, | ||||
|     DISABLED: 2, | ||||
|     ERROR: 3, | ||||
|     OUT_OF_DATE: 4, | ||||
|     DOWNLOADING: 5, | ||||
|     INITIALIZED: 6, | ||||
|  | ||||
|     // Used as an error state for operations on unknown extensions, | ||||
|     // should never be in a real extensionMeta object. | ||||
|     UNINSTALLED: 99 | ||||
| }; | ||||
|  | ||||
| const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange']; | ||||
|  | ||||
| /** | ||||
|  * getCurrentExtension: | ||||
| @@ -49,13 +63,17 @@ function getCurrentExtension() { | ||||
|     if (!match) | ||||
|         return null; | ||||
|  | ||||
|     // local import, as the module is used from outside the gnome-shell process | ||||
|     // as well (not this function though) | ||||
|     let extensionManager = imports.ui.main.extensionManager; | ||||
|  | ||||
|     let path = match[1]; | ||||
|     let file = Gio.File.new_for_path(path); | ||||
|  | ||||
|     // Walk up the directory tree, looking for an extension with | ||||
|     // the same UUID as a directory name. | ||||
|     while (file != null) { | ||||
|         let extension = extensions[file.get_basename()]; | ||||
|         let extension = extensionManager.lookup(file.get_basename()); | ||||
|         if (extension !== undefined) | ||||
|             return extension; | ||||
|         file = file.get_parent(); | ||||
| @@ -161,52 +179,50 @@ function isOutOfDate(extension) { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function createExtensionObject(uuid, dir, type) { | ||||
|     let metadataFile = dir.get_child('metadata.json'); | ||||
|     if (!metadataFile.query_exists(null)) { | ||||
|         throw new Error('Missing metadata.json'); | ||||
|     } | ||||
| function serializeExtension(extension) { | ||||
|     let obj = {}; | ||||
|     Lang.copyProperties(extension.metadata, obj); | ||||
|  | ||||
|     let metadataContents, success, tag; | ||||
|     try { | ||||
|         [success, metadataContents, tag] = metadataFile.load_contents(null); | ||||
|         if (metadataContents instanceof Uint8Array) | ||||
|             metadataContents = imports.byteArray.toString(metadataContents); | ||||
|     } catch (e) { | ||||
|         throw new Error(`Failed to load metadata.json: ${e}`); | ||||
|     } | ||||
|     let meta; | ||||
|     try { | ||||
|         meta = JSON.parse(metadataContents); | ||||
|     } catch (e) { | ||||
|         throw new Error(`Failed to parse metadata.json: ${e}`); | ||||
|     } | ||||
|     SERIALIZED_PROPERTIES.forEach(prop => { | ||||
|         obj[prop] = extension[prop]; | ||||
|     }); | ||||
|  | ||||
|     let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; | ||||
|     for (let i = 0; i < requiredProperties.length; i++) { | ||||
|         let prop = requiredProperties[i]; | ||||
|         if (!meta[prop]) { | ||||
|             throw new Error(`missing "${prop}" property in metadata.json`); | ||||
|     let res = {}; | ||||
|     for (let key in obj) { | ||||
|         let val = obj[key]; | ||||
|         let type; | ||||
|         switch (typeof val) { | ||||
|         case 'string': | ||||
|             type = 's'; | ||||
|             break; | ||||
|         case 'number': | ||||
|             type = 'd'; | ||||
|             break; | ||||
|         case 'boolean': | ||||
|             type = 'b'; | ||||
|             break; | ||||
|         default: | ||||
|             continue; | ||||
|         } | ||||
|         res[key] = GLib.Variant.new(type, val); | ||||
|     } | ||||
|  | ||||
|     if (uuid != meta.uuid) { | ||||
|         throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| function deserializeExtension(variant) { | ||||
|     let res = { metadata: {} }; | ||||
|     for (let prop in variant) { | ||||
|         let val = variant[prop].unpack(); | ||||
|         if (SERIALIZED_PROPERTIES.includes(prop)) | ||||
|             res[prop] = val; | ||||
|         else | ||||
|             res.metadata[prop] = val; | ||||
|     } | ||||
|  | ||||
|     let extension = {}; | ||||
|  | ||||
|     extension.metadata = meta; | ||||
|     extension.uuid = meta.uuid; | ||||
|     extension.type = type; | ||||
|     extension.dir = dir; | ||||
|     extension.path = dir.get_path(); | ||||
|     extension.error = ''; | ||||
|     extension.hasPrefs = dir.get_child('prefs.js').query_exists(null); | ||||
|  | ||||
|     extensions[uuid] = extension; | ||||
|  | ||||
|     return extension; | ||||
|     // add the 2 additional properties to create a valid extension object, as createExtensionObject() | ||||
|     res.uuid = res.metadata.uuid; | ||||
|     res.dir = Gio.File.new_for_path(res.path); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| function installImporter(extension) { | ||||
| @@ -217,36 +233,3 @@ function installImporter(extension) { | ||||
|     extension.imports = imports[extension.uuid]; | ||||
|     imports.searchPath = oldSearchPath; | ||||
| } | ||||
|  | ||||
| var ExtensionFinder = class { | ||||
|     _loadExtension(extensionDir, info, perUserDir) { | ||||
|         let fileType = info.get_file_type(); | ||||
|         if (fileType != Gio.FileType.DIRECTORY) | ||||
|             return; | ||||
|         let uuid = info.get_name(); | ||||
|         let existing = extensions[uuid]; | ||||
|         if (existing) { | ||||
|             log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path())); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let extension; | ||||
|         let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER | ||||
|                                                        : ExtensionType.SYSTEM; | ||||
|         try { | ||||
|             extension = createExtensionObject(uuid, extensionDir, type); | ||||
|         } catch (e) { | ||||
|             logError(e, 'Could not load extension %s'.format(uuid)); | ||||
|             return; | ||||
|         } | ||||
|         this.emit('extension-found', extension); | ||||
|     } | ||||
|  | ||||
|     scanExtensions() { | ||||
|         let perUserDir = Gio.File.new_for_path(global.userdatadir); | ||||
|         FileUtils.collectFromDatadirs('extensions', true, (dir, info) => { | ||||
|             this._loadExtension(dir, info, perUserDir); | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ExtensionFinder.prototype); | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported collectFromDatadirs, deleteGFile, recursivelyDeleteDir, | ||||
|             recursivelyMoveDir, loadInterfaceXML */ | ||||
|  | ||||
| const { Gio, GLib } = imports.gi; | ||||
| const Config = imports.misc.config; | ||||
| @@ -84,7 +86,7 @@ function loadInterfaceXML(iface) { | ||||
|     let f = Gio.File.new_for_uri(uri); | ||||
|  | ||||
|     try { | ||||
|         let [ok, bytes] = f.load_contents(null); | ||||
|         let [ok_, bytes] = f.load_contents(null); | ||||
|         if (bytes instanceof Uint8Array) | ||||
|             xml = imports.byteArray.toString(bytes); | ||||
|         else | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported PresenceStatus, Presence, Inhibitor, SessionManager */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getIBusManager */ | ||||
|  | ||||
| const { Gio, GLib, IBus } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported InputMethod */ | ||||
| const { Clutter, GLib, GObject, IBus } = imports.gi; | ||||
|  | ||||
| const Keyboard = imports.ui.status.keyboard; | ||||
| @@ -84,15 +85,15 @@ class InputMethod extends Clutter.InputMethod { | ||||
|             this.emit('request-surrounding'); | ||||
|     } | ||||
|  | ||||
|     _onCommitText(context, text) { | ||||
|     _onCommitText(_context, text) { | ||||
|         this.commit(text.get_text()); | ||||
|     } | ||||
|  | ||||
|     _onDeleteSurroundingText(context) { | ||||
|     _onDeleteSurroundingText() { | ||||
|         this.delete_surrounding(); | ||||
|     } | ||||
|  | ||||
|     _onUpdatePreeditText(context, text, pos, visible) { | ||||
|     _onUpdatePreeditText(_context, text, pos, visible) { | ||||
|         if (text == null) | ||||
|             return; | ||||
|  | ||||
| @@ -108,17 +109,17 @@ class InputMethod extends Clutter.InputMethod { | ||||
|         this._preeditVisible = visible; | ||||
|     } | ||||
|  | ||||
|     _onShowPreeditText(context) { | ||||
|     _onShowPreeditText() { | ||||
|         this._preeditVisible = true; | ||||
|         this.set_preedit_text(this._preeditStr, this._preeditPos); | ||||
|     } | ||||
|  | ||||
|     _onHidePreeditText(context) { | ||||
|     _onHidePreeditText() { | ||||
|         this.set_preedit_text(null, this._preeditPos); | ||||
|         this._preeditVisible = false; | ||||
|     } | ||||
|  | ||||
|     _onForwardKeyEvent(context, keyval, keycode, state) { | ||||
|     _onForwardKeyEvent(_context, keyval, keycode, state) { | ||||
|         let press = (state & IBus.ModifierType.RELEASE_MASK) == 0; | ||||
|         state &= ~(IBus.ModifierType.RELEASE_MASK); | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported IntrospectService */ | ||||
| const { Gio, GLib, Meta, Shell } = imports.gi; | ||||
|  | ||||
| const INTROSPECT_SCHEMA = 'org.gnome.shell'; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
| /* exported getCompletions, getCommonPrefix, getDeclaredConstants */ | ||||
|  | ||||
| // Returns a list of potential completions for text. Completions either | ||||
| // follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo) | ||||
| @@ -8,7 +9,7 @@ | ||||
| // This function is likely the one you want to call from external modules | ||||
| function getCompletions(text, commandHeader, globalCompletionList) { | ||||
|     let methods = []; | ||||
|     let expr, base; | ||||
|     let expr_, base; | ||||
|     let attrHead = ''; | ||||
|     if (globalCompletionList == null) { | ||||
|         globalCompletionList = []; | ||||
| @@ -21,7 +22,7 @@ function getCompletions(text, commandHeader, globalCompletionList) { | ||||
|         // Look for expressions like "Main.panel.foo" and match Main.panel and foo | ||||
|         let matches = text.match(/(.*)\.(.*)/); | ||||
|         if (matches) { | ||||
|             [expr, base, attrHead] = matches; | ||||
|             [expr_, base, attrHead] = matches; | ||||
|  | ||||
|             methods = getPropertyNamesFromExpression(base, commandHeader).filter( | ||||
|                 attr => attr.slice(0, attrHead.length) == attrHead | ||||
| @@ -32,7 +33,7 @@ function getCompletions(text, commandHeader, globalCompletionList) { | ||||
|         // not proceeded by a dot and match them against global constants | ||||
|         matches = text.match(/^(\w*)$/); | ||||
|         if (text == '' || matches) { | ||||
|             [expr, attrHead] = matches; | ||||
|             [expr_, attrHead] = matches; | ||||
|             methods = globalCompletionList.filter( | ||||
|                 attr => attr.slice(0, attrHead.length) == attrHead | ||||
|             ); | ||||
| @@ -151,11 +152,7 @@ function getAllProps(obj) { | ||||
| // e.g., expr="({ foo: null, bar: null, 4: null })" will | ||||
| // return ["foo", "bar", ...] but the list will not include "4", | ||||
| // since methods accessed with '.' notation must star with a letter or _. | ||||
| function getPropertyNamesFromExpression(expr, commandHeader) { | ||||
|     if (commandHeader == null) { | ||||
|         commandHeader = ''; | ||||
|     } | ||||
|  | ||||
| function getPropertyNamesFromExpression(expr, commandHeader = '') { | ||||
|     let obj = {}; | ||||
|     if (!isUnsafeExpression(expr)) { | ||||
|         try { | ||||
| @@ -234,10 +231,10 @@ function isUnsafeExpression(str) { | ||||
| function getDeclaredConstants(str) { | ||||
|     let ret = []; | ||||
|     str.split(';').forEach(s => { | ||||
|         let base, keyword; | ||||
|         let base_, keyword; | ||||
|         let match = s.match(/const\s+(\w+)\s*=/); | ||||
|         if (match) { | ||||
|             [base, keyword] = match; | ||||
|             [base_, keyword] = match; | ||||
|             ret.push(keyword); | ||||
|         } | ||||
|     }); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getKeyboardManager, holdKeyboard, releaseKeyboard */ | ||||
|  | ||||
| const { GLib, GnomeDesktop, Meta } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported canLock, getLoginManager, registerSessionWithGDM */ | ||||
|  | ||||
| const { GLib, Gio } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -109,7 +110,7 @@ var LoginManagerSystemd = class { | ||||
|         let sessionId = GLib.getenv('XDG_SESSION_ID'); | ||||
|         if (!sessionId) { | ||||
|             log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.'); | ||||
|             let [session, objectPath] = this._userProxy.Display; | ||||
|             let [session, objectPath_] = this._userProxy.Display; | ||||
|             if (session) { | ||||
|                 log(`Will monitor session ${session}`); | ||||
|                 sessionId = session; | ||||
| @@ -182,7 +183,7 @@ var LoginManagerSystemd = class { | ||||
|             (proxy, result) => { | ||||
|                 let fd = -1; | ||||
|                 try { | ||||
|                     let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result); | ||||
|                     let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result); | ||||
|                     fd = fdList.steal_fds()[0]; | ||||
|                     callback(new Gio.UnixInputStream({ fd: fd })); | ||||
|                 } catch (e) { | ||||
| @@ -199,7 +200,7 @@ var LoginManagerSystemd = class { | ||||
| Signals.addSignalMethods(LoginManagerSystemd.prototype); | ||||
|  | ||||
| var LoginManagerDummy = class { | ||||
|     getCurrentSessionProxy(callback) { | ||||
|     getCurrentSessionProxy(_callback) { | ||||
|         // we could return a DummySession object that fakes whatever callers | ||||
|         // expect (at the time of writing: connect() and connectSignal() | ||||
|         // methods), but just never calling the callback should be safer | ||||
|   | ||||
| @@ -110,7 +110,7 @@ var ModemGsm = class { | ||||
|             this.signal_quality = quality; | ||||
|             this.emit('notify::signal-quality'); | ||||
|         }); | ||||
|         this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [status, code, name]) => { | ||||
|         this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [_status, code, name]) => { | ||||
|             this.operator_name = _findProviderForMccMnc(name, code); | ||||
|             this.emit('notify::operator-name'); | ||||
|         }); | ||||
| @@ -120,7 +120,7 @@ var ModemGsm = class { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let [status, code, name] = result; | ||||
|             let [status_, code, name] = result; | ||||
|             this.operator_name = _findProviderForMccMnc(name, code); | ||||
|             this.emit('notify::operator-name'); | ||||
|         }); | ||||
| @@ -171,7 +171,7 @@ var ModemCdma = class { | ||||
|                 // it will return an error if the device is not connected | ||||
|                 this.operator_name = null; | ||||
|             } else { | ||||
|                 let [bandClass, band, sid] = result; | ||||
|                 let [bandClass_, band_, sid] = result; | ||||
|  | ||||
|                 this.operator_name = _findProviderForSid(sid); | ||||
|             } | ||||
| @@ -224,7 +224,7 @@ var BroadbandModem = class { | ||||
|     } | ||||
|  | ||||
|     _reloadSignalQuality() { | ||||
|         let [quality, recent] = this._proxy.SignalQuality; | ||||
|         let [quality, recent_] = this._proxy.SignalQuality; | ||||
|         this.signal_quality = quality; | ||||
|         this.emit('notify::signal-quality'); | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Lang = imports.lang; | ||||
| /* exported parse */ | ||||
|  | ||||
| // parse: | ||||
| // @params: caller-provided parameter object, or %null | ||||
| @@ -23,7 +22,6 @@ function parse(params = {}, defaults, allowExtras) { | ||||
|                 throw new Error(`Unrecognized parameter "${prop}"`); | ||||
|     } | ||||
|  | ||||
|     let defaultsCopy = {}; | ||||
|     Lang.copyProperties(defaults, defaultsCopy); | ||||
|     let defaultsCopy = Object.assign({}, defaults); | ||||
|     return Object.assign(defaultsCopy, params); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported PermissionStore */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getSmartcardManager */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const Signals = imports.signals; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported getDefault */ | ||||
| const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi; | ||||
|  | ||||
| const GnomeSession = imports.misc.gnomeSession; | ||||
| @@ -187,30 +188,37 @@ const SystemActions = GObject.registerClass({ | ||||
|         this._sessionUpdated(); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_power_off() { | ||||
|         return this._actions.get(POWER_OFF_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_suspend() { | ||||
|         return this._actions.get(SUSPEND_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_lock_screen() { | ||||
|         return this._actions.get(LOCK_SCREEN_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_switch_user() { | ||||
|         return this._actions.get(SWITCH_USER_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_logout() { | ||||
|         return this._actions.get(LOGOUT_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get can_lock_orientation() { | ||||
|         return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get orientation_lock_icon() { | ||||
|         return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName; | ||||
|     } | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine, | ||||
|             formatTime, formatTimeSpan, createTimeLabel, insertSorted, | ||||
|             makeCloseButton, ensureActorVisibleInScrollView */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi; | ||||
| const Gettext = imports.gettext; | ||||
| @@ -75,7 +78,7 @@ function spawn(argv) { | ||||
| // occur when trying to parse or start the program. | ||||
| function spawnCommandLine(commandLine) { | ||||
|     try { | ||||
|         let [success, argv] = GLib.shell_parse_argv(commandLine); | ||||
|         let [success_, argv] = GLib.shell_parse_argv(commandLine); | ||||
|         trySpawn(argv); | ||||
|     } catch (err) { | ||||
|         _handleSpawnError(commandLine, err); | ||||
| @@ -104,11 +107,11 @@ function spawnApp(argv) { | ||||
| // Runs @argv in the background. If launching @argv fails, | ||||
| // this will throw an error. | ||||
| function trySpawn(argv) { | ||||
|     var success, pid; | ||||
|     var success_, pid; | ||||
|     try { | ||||
|         [success, pid] = GLib.spawn_async(null, argv, null, | ||||
|                                           GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, | ||||
|                                           null); | ||||
|         [success_, pid] = GLib.spawn_async(null, argv, null, | ||||
|                                            GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, | ||||
|                                            null); | ||||
|     } catch (err) { | ||||
|         /* Rewrite the error in case of ENOENT */ | ||||
|         if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) { | ||||
| @@ -139,10 +142,10 @@ function trySpawn(argv) { | ||||
| // Runs @commandLine in the background. If launching @commandLine | ||||
| // fails, this will throw an error. | ||||
| function trySpawnCommandLine(commandLine) { | ||||
|     let success, argv; | ||||
|     let success_, argv; | ||||
|  | ||||
|     try { | ||||
|         [success, argv] = GLib.shell_parse_argv(commandLine); | ||||
|         [success_, argv] = GLib.shell_parse_argv(commandLine); | ||||
|     } catch (err) { | ||||
|         // Replace "Error invoking GLib.shell_parse_argv: " with | ||||
|         // something nicer | ||||
| @@ -395,7 +398,7 @@ function makeCloseButton(boxpointer) { | ||||
|  | ||||
| function ensureActorVisibleInScrollView(scrollView, actor) { | ||||
|     let adjustment = scrollView.vscroll.adjustment; | ||||
|     let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values(); | ||||
|     let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values(); | ||||
|  | ||||
|     let offset = 0; | ||||
|     let vfade = scrollView.get_effect("fade"); | ||||
|   | ||||
| @@ -1,10 +1,19 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const { Geoclue, Gio, GLib, GWeather } = imports.gi; | ||||
| const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const PermissionStore = imports.misc.permissionStore; | ||||
| const Util = imports.misc.util; | ||||
|  | ||||
| const { loadInterfaceXML } = imports.misc.fileUtils; | ||||
|  | ||||
| const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration'); | ||||
|  | ||||
| const WEATHER_BUS_NAME = 'org.gnome.Weather'; | ||||
| const WEATHER_OBJECT_PATH = '/org/gnome/Weather'; | ||||
| const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration'; | ||||
|  | ||||
| const WEATHER_APP_ID = 'org.gnome.Weather.desktop'; | ||||
|  | ||||
| // Minimum time between updates to show loading indication | ||||
| var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE; | ||||
| @@ -66,17 +75,36 @@ var WeatherClient = class { | ||||
|             this.emit('changed'); | ||||
|         }); | ||||
|  | ||||
|         this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop', | ||||
|                                                           'org.gnome.Weather'); | ||||
|         this._weatherAppMon.connect('available-changed', () => this.emit('changed')); | ||||
|         this._weatherAppMon.watchSetting('automatic-location', | ||||
|                                          this._onAutomaticLocationChanged.bind(this)); | ||||
|         this._weatherAppMon.watchSetting('locations', | ||||
|                                          this._onLocationsChanged.bind(this)); | ||||
|         this._weatherApp = null; | ||||
|         this._weatherProxy = null; | ||||
|  | ||||
|         let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface); | ||||
|         Gio.DBusProxy.new( | ||||
|             Gio.DBus.session, | ||||
|             Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES, | ||||
|             nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE), | ||||
|             WEATHER_BUS_NAME, | ||||
|             WEATHER_OBJECT_PATH, | ||||
|             WEATHER_INTEGRATION_IFACE, | ||||
|             null, | ||||
|             this._onWeatherProxyReady.bind(this)); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ | ||||
|             schema_id: 'org.gnome.shell.weather' | ||||
|         }); | ||||
|         this._settings.connect('changed::automatic-location', | ||||
|             this._onAutomaticLocationChanged.bind(this)); | ||||
|         this._settings.connect('changed::locations', | ||||
|             this._onLocationsChanged.bind(this)); | ||||
|  | ||||
|         this._appSystem = Shell.AppSystem.get_default(); | ||||
|         this._appSystem.connect('installed-changed', | ||||
|             this._onInstalledChanged.bind(this)); | ||||
|         this._onInstalledChanged(); | ||||
|     } | ||||
|  | ||||
|     get available() { | ||||
|         return this._weatherAppMon.available; | ||||
|         return this._weatherApp != null; | ||||
|     } | ||||
|  | ||||
|     get loading() { | ||||
| @@ -92,7 +120,8 @@ var WeatherClient = class { | ||||
|     } | ||||
|  | ||||
|     activateApp() { | ||||
|         this._weatherAppMon.activateApp(); | ||||
|         if (this._weatherApp) | ||||
|             this._weatherApp.activate(); | ||||
|     } | ||||
|  | ||||
|     update() { | ||||
| @@ -114,6 +143,37 @@ var WeatherClient = class { | ||||
|                this._weatherAuthorized; | ||||
|     } | ||||
|  | ||||
|     _onWeatherProxyReady(o, res) { | ||||
|         try { | ||||
|             this._weatherProxy = Gio.DBusProxy.new_finish(res); | ||||
|         } catch (e) { | ||||
|             log(`Failed to create GNOME Weather proxy: ${e}`); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._weatherProxy.connect('g-properties-changed', | ||||
|             this._onWeatherPropertiesChanged.bind(this)); | ||||
|  | ||||
|         if (this._weatherProxy.g_name_owner != null) | ||||
|             this._onWeatherPropertiesChanged(); | ||||
|     } | ||||
|  | ||||
|     _onWeatherPropertiesChanged() { | ||||
|         this._settings.set_boolean('automatic-location', | ||||
|             this._weatherProxy.AutomaticLocation); | ||||
|         this._settings.set_value('locations', | ||||
|             new GLib.Variant('av', this._weatherProxy.Locations)); | ||||
|     } | ||||
|  | ||||
|     _onInstalledChanged() { | ||||
|         let hadApp = (this._weatherApp != null); | ||||
|         this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID); | ||||
|         let haveApp = (this._weatherApp != null); | ||||
|  | ||||
|         if (hadApp !== haveApp) | ||||
|             this.emit('changed'); | ||||
|     } | ||||
|  | ||||
|     _loadInfo() { | ||||
|         let id = this._weatherInfo.connect('updated', () => { | ||||
|             this._weatherInfo.disconnect(id); | ||||
| @@ -234,7 +294,7 @@ var WeatherClient = class { | ||||
|     } | ||||
|  | ||||
|     _onPermStoreChanged(proxy, sender, params) { | ||||
|         let [table, id, deleted, data, perms] = params; | ||||
|         let [table, id, deleted_, data_, perms] = params; | ||||
|  | ||||
|         if (table != 'gnome' || id != 'geolocation') | ||||
|             return; | ||||
|   | ||||
| @@ -1,4 +1,9 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported run, script_overviewShowStart, script_overviewShowDone, | ||||
|             script_applicationsShowStart, script_applicationsShowDone, | ||||
|             script_afterShowHide, malloc_usedSize, glx_swapComplete, | ||||
|             clutter_stagePaintDone */ | ||||
| /* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^malloc", "^glx", "^clutter"] }] */ | ||||
|  | ||||
| const System = imports.system; | ||||
|  | ||||
| @@ -121,9 +126,11 @@ function *run() { | ||||
|  | ||||
|     for (let i = 0; i < 2; i++) { | ||||
|         Scripting.scriptEvent('applicationsShowStart'); | ||||
|         // eslint-disable-next-line require-atomic-updates | ||||
|         Main.overview._dash.showAppsButton.checked = true; | ||||
|         yield Scripting.waitLeisure(); | ||||
|         Scripting.scriptEvent('applicationsShowDone'); | ||||
|         // eslint-disable-next-line require-atomic-updates | ||||
|         Main.overview._dash.showAppsButton.checked = false; | ||||
|         yield Scripting.waitLeisure(); | ||||
|     } | ||||
| @@ -147,7 +154,7 @@ function script_overviewShowStart(time) { | ||||
|     overviewFrames = 0; | ||||
| } | ||||
|  | ||||
| function script_overviewShowDone(time) { | ||||
| function script_overviewShowDone(_time) { | ||||
|     // We've set up the state at the end of the zoom out, but we | ||||
|     // need to wait for one more frame to paint before we count | ||||
|     // ourselves as done. | ||||
| @@ -166,7 +173,7 @@ function script_applicationsShowDone(time) { | ||||
|         METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart; | ||||
| } | ||||
|  | ||||
| function script_afterShowHide(time) { | ||||
| function script_afterShowHide(_time) { | ||||
|     if (overviewShowCount == 1) { | ||||
|         METRICS.usedAfterOverview.value = mallocUsedSize; | ||||
|     } else { | ||||
|   | ||||
| @@ -1,3 +1,12 @@ | ||||
| /* exported run, script_desktopShown, script_overviewShowStart, | ||||
|             script_overviewShowDone, script_applicationsShowStart, | ||||
|             script_applicationsShowDone, script_mainViewDrawStart, | ||||
|             script_mainViewDrawDone, script_overviewDrawStart, | ||||
|             script_overviewDrawDone, script_redrawTestStart, | ||||
|             script_redrawTestDone, script_collectTimings, | ||||
|             script_geditLaunch, script_geditFirstFrame, | ||||
|             clutter_stagePaintStart, clutter_paintCompletedTimestamp */ | ||||
| /* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^clutter"] }] */ | ||||
| const { Clutter, Gio, Shell } = imports.gi; | ||||
| const Main = imports.ui.main; | ||||
| const Scripting = imports.ui.scripting; | ||||
| @@ -38,7 +47,7 @@ function waitAndDraw(milliseconds) { | ||||
|     let timeline = new Clutter.Timeline({ duration: milliseconds }); | ||||
|     timeline.start(); | ||||
|  | ||||
|     timeline.connect('new-frame', (timeline, frame) => { | ||||
|     timeline.connect('new-frame', (_timeline, _frame) => { | ||||
|         global.stage.queue_redraw(); | ||||
|     }); | ||||
|  | ||||
| @@ -73,8 +82,8 @@ function extractBootTimestamp() { | ||||
|     let result = null; | ||||
|  | ||||
|     let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe()); | ||||
|     while (true) { | ||||
|         let [line, length] = datastream.read_line_utf8(null); | ||||
|     while (true) { // eslint-disable-line no-constant-condition | ||||
|         let [line, length_] = datastream.read_line_utf8(null); | ||||
|         if (line === null) | ||||
|             break; | ||||
|  | ||||
| @@ -117,6 +126,7 @@ function *run() { | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Scripting.scriptEvent('applicationsShowStart'); | ||||
|     // eslint-disable-next-line require-atomic-updates | ||||
|     Main.overview._dash.showAppsButton.checked = true; | ||||
|  | ||||
|     yield Scripting.waitLeisure(); | ||||
| @@ -234,31 +244,31 @@ function script_applicationsShowDone(time) { | ||||
|     METRICS.applicationsShowTime.value = time - applicationsShowStart; | ||||
| } | ||||
|  | ||||
| function script_mainViewDrawStart(time) { | ||||
| function script_mainViewDrawStart(_time) { | ||||
|     redrawTiming = 'mainView'; | ||||
| } | ||||
|  | ||||
| function script_mainViewDrawDone(time) { | ||||
| function script_mainViewDrawDone(_time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_overviewDrawStart(time) { | ||||
| function script_overviewDrawStart(_time) { | ||||
|     redrawTiming = 'overview'; | ||||
| } | ||||
|  | ||||
| function script_overviewDrawDone(time) { | ||||
| function script_overviewDrawDone(_time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_redrawTestStart(time) { | ||||
| function script_redrawTestStart(_time) { | ||||
|     redrawTiming = 'application'; | ||||
| } | ||||
|  | ||||
| function script_redrawTestDone(time) { | ||||
| function script_redrawTestDone(_time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_collectTimings(time) { | ||||
| function script_collectTimings(_time) { | ||||
|     for (let timing in redrawTimes) { | ||||
|         let times = redrawTimes[timing]; | ||||
|         times.sort((a, b) => a - b); | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported main */ | ||||
| const Format = imports.format; | ||||
| const Gettext = imports.gettext; | ||||
| const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi; | ||||
| @@ -151,7 +152,7 @@ class PortalWindow extends Gtk.ApplicationWindow { | ||||
|         this._webView.load_uri(this._originalUrl); | ||||
|     } | ||||
|  | ||||
|     vfunc_delete_event(event) { | ||||
|     vfunc_delete_event(_event) { | ||||
|         if (this._recheckAtExit) | ||||
|             this._doneCallback(PortalHelperResult.RECHECK); | ||||
|         else | ||||
| @@ -177,7 +178,7 @@ class PortalWindow extends Gtk.ApplicationWindow { | ||||
|         this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); | ||||
|     } | ||||
|  | ||||
|     _onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) { | ||||
|     _onLoadFailedWithTlsErrors(view, failingURI, certificate, _errors) { | ||||
|         this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); | ||||
|         let uri = new Soup.URI(failingURI); | ||||
|         this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host()); | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported AccessDialogDBus */ | ||||
| const { Clutter, Gio, GLib, GObject, Shell } = imports.gi; | ||||
|  | ||||
| const CheckBox = imports.ui.checkBox; | ||||
| @@ -79,7 +80,7 @@ class AccessDialog extends ModalDialog.ModalDialog { | ||||
|         this._requestExported = this._request.export(connection, this._handle); | ||||
|     } | ||||
|  | ||||
|     CloseAsync(invocation, params) { | ||||
|     CloseAsync(invocation, _params) { | ||||
|         if (this._invocation.get_sender() != invocation.get_sender()) { | ||||
|             invocation.return_error_literal(Gio.DBusError, | ||||
|                                             Gio.DBusError.ACCESS_DENIED, | ||||
| @@ -132,7 +133,7 @@ var AccessDialogDBus = class { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let [handle, appId, parentWindow, title, subtitle, body, options] = params; | ||||
|         let [handle, appId, parentWindow_, title, subtitle, body, options] = params; | ||||
|         // We probably want to use parentWindow and global.display.focus_window | ||||
|         // for this check in the future | ||||
|         if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported AppSwitcherPopup, GroupCyclerPopup, WindowSwitcherPopup, | ||||
|             WindowCyclerPopup */ | ||||
|  | ||||
| const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -87,9 +89,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup { | ||||
|             let hPadding = leftPadding + rightPadding; | ||||
|  | ||||
|             let icon = this._items[this._selectedIndex]; | ||||
|             let [posX, posY] = icon.get_transformed_position(); | ||||
|             let [posX] = icon.get_transformed_position(); | ||||
|             let thumbnailCenter = posX + icon.width / 2; | ||||
|             let [childMinWidth, childNaturalWidth] = this._thumbnails.get_preferred_width(-1); | ||||
|             let [, childNaturalWidth] = this._thumbnails.get_preferred_width(-1); | ||||
|             childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2)); | ||||
|             if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) { | ||||
|                 let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding; | ||||
| @@ -103,7 +105,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup { | ||||
|                 childBox.x2 = primary.x + primary.width - rightPadding; | ||||
|             childBox.y1 = this._switcherList.allocation.y2 + spacing; | ||||
|             this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1); | ||||
|             let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1); | ||||
|             let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1); | ||||
|             childBox.y2 = childBox.y1 + childNaturalHeight; | ||||
|             this._thumbnails.allocate(childBox, flags); | ||||
|         } | ||||
| @@ -469,7 +471,7 @@ var CyclerList = GObject.registerClass({ | ||||
|                'item-removed': { param_types: [GObject.TYPE_INT] }, | ||||
|                'item-highlighted': { param_types: [GObject.TYPE_INT] } }, | ||||
| }, class CyclerList extends St.Widget { | ||||
|     highlight(index, justOutline) { | ||||
|     highlight(index, _justOutline) { | ||||
|         this.emit('item-highlighted', index); | ||||
|     } | ||||
| }); | ||||
| @@ -494,7 +496,7 @@ var CyclerPopup = GObject.registerClass({ | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _highlightItem(index, justOutline) { | ||||
|     _highlightItem(index, _justOutline) { | ||||
|         this._highlight.window = this._items[index]; | ||||
|         global.window_group.set_child_above_sibling(this._highlight.actor, null); | ||||
|     } | ||||
| @@ -660,6 +662,7 @@ class AppIcon extends St.BoxLayout { | ||||
|         this.add(this.label, { x_fill: false }); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set_size(size) { | ||||
|         this.icon = this.app.create_icon_texture(size); | ||||
|         this._iconBin.child = this.icon; | ||||
| @@ -801,7 +804,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList { | ||||
|     } | ||||
|  | ||||
|     _enterItem(index) { | ||||
|         let [x, y, mask] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); | ||||
|         if (this._items[index].contains(pickedActor)) | ||||
|             this._itemEntered(index); | ||||
| @@ -908,7 +911,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList { | ||||
|             return; | ||||
|         let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding(); | ||||
|         totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding(); | ||||
|         let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); | ||||
|         let [, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); | ||||
|         let spacing = this._items[0].child.get_theme_node().get_length('spacing'); | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Animation, AnimatedIcon, Spinner */ | ||||
|  | ||||
| const { GLib, Gio, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
|   | ||||
							
								
								
									
										1168
									
								
								js/ui/appDisplay.js
									
									
									
									
									
								
							
							
						
						
									
										1168
									
								
								js/ui/appDisplay.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getAppFavorites */ | ||||
|  | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported AudioDeviceSelectionDBus */ | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| @@ -34,7 +35,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({ | ||||
|             throw new Error('Too few devices for a selection'); | ||||
|     } | ||||
|  | ||||
|     _buildLayout(devices) { | ||||
|     _buildLayout() { | ||||
|         let title = new St.Label({ style_class: 'audio-selection-title', | ||||
|                                    text: _("Select Audio Device"), | ||||
|                                    x_align: Clutter.ActorAlign.CENTER }); | ||||
| @@ -85,6 +86,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({ | ||||
|         box.connect('notify::height', () => { | ||||
|             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
|                 box.width = box.height; | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|   | ||||
| @@ -333,12 +333,12 @@ var Background = class Background { | ||||
|     } | ||||
|  | ||||
|     _loadPattern() { | ||||
|         let colorString, res, color, secondColor; | ||||
|         let colorString, res_, color, secondColor; | ||||
|  | ||||
|         colorString = this._settings.get_string(PRIMARY_COLOR_KEY); | ||||
|         [res, color] = Clutter.Color.from_string(colorString); | ||||
|         [res_, color] = Clutter.Color.from_string(colorString); | ||||
|         colorString = this._settings.get_string(SECONDARY_COLOR_KEY); | ||||
|         [res, secondColor] = Clutter.Color.from_string(colorString); | ||||
|         [res_, secondColor] = Clutter.Color.from_string(colorString); | ||||
|  | ||||
|         let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY); | ||||
|  | ||||
| @@ -633,9 +633,9 @@ var Animation = class Animation { | ||||
|     } | ||||
|  | ||||
|     load(callback) { | ||||
|         this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() }); | ||||
|         this._show = new GnomeDesktop.BGSlideShow({ file: this.file }); | ||||
|  | ||||
|         this._show.load_async(null, (object, result) => { | ||||
|         this._show.load_async(null, () => { | ||||
|             this.loaded = true; | ||||
|             if (callback) | ||||
|                 callback(); | ||||
| @@ -651,7 +651,7 @@ var Animation = class Animation { | ||||
|         if (this._show.get_num_slides() < 1) | ||||
|             return; | ||||
|  | ||||
|         let [progress, duration, isFixed, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height); | ||||
|         let [progress, duration, isFixed_, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height); | ||||
|  | ||||
|         this.transitionDuration = duration; | ||||
|         this.transitionProgress = progress; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported addBackgroundMenu */ | ||||
|  | ||||
| const { Clutter, St } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
| /* exported BarLevel */ | ||||
|  | ||||
| const { Atk, Clutter, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| var BarLevel = class { | ||||
|     constructor(value, params) { | ||||
|     constructor(value, params = {}) { | ||||
|         if (isNaN(value)) | ||||
|             // Avoid spreading NaNs around | ||||
|             throw TypeError('The bar level value must be a number'); | ||||
| @@ -13,9 +14,6 @@ var BarLevel = class { | ||||
|         this._overdriveStart = 1; | ||||
|         this._barLevelWidth = 0; | ||||
|  | ||||
|         if (params == undefined) | ||||
|             params = {}; | ||||
|  | ||||
|         this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel', | ||||
|                                           can_focus: params['canFocus'] || false, | ||||
|                                           reactive: params['reactive'] || false, | ||||
| @@ -36,26 +34,56 @@ var BarLevel = class { | ||||
|         this.connect('value-changed', this._valueChanged.bind(this)); | ||||
|     } | ||||
|  | ||||
|     setValue(value) { | ||||
|     get value() { | ||||
|         return this._value; | ||||
|     } | ||||
|  | ||||
|     set value(value) { | ||||
|         if (isNaN(value)) | ||||
|             throw TypeError('The bar level value must be a number'); | ||||
|  | ||||
|         this._value = Math.max(Math.min(value, this._maxValue), 0); | ||||
|         value = Math.max(Math.min(value, this._maxValue), 0); | ||||
|  | ||||
|         if (this._value == value) | ||||
|             return; | ||||
|  | ||||
|         this._value = value; | ||||
|         this.actor.queue_repaint(); | ||||
|     } | ||||
|  | ||||
|     setMaximumValue(value) { | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get maximum_value() { | ||||
|         return this._maxValue; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set maximum_value(value) { | ||||
|         if (isNaN(value)) | ||||
|             throw TypeError('The bar level max value must be a number'); | ||||
|  | ||||
|         this._maxValue = Math.max(value, 1); | ||||
|         value = Math.max(value, 1); | ||||
|  | ||||
|         if (this._maxValue == value) | ||||
|             return; | ||||
|  | ||||
|         this._maxValue = value; | ||||
|         this._overdriveStart = Math.min(this._overdriveStart, this._maxValue); | ||||
|         this.actor.queue_repaint(); | ||||
|     } | ||||
|  | ||||
|     setOverdriveStart(value) { | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get overdrive_start() { | ||||
|         return this._overdriveStart; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set overdrive_start(value) { | ||||
|         if (isNaN(value)) | ||||
|             throw TypeError('The overdrive limit value must be a number'); | ||||
|  | ||||
|         if (this._overdriveStart == value) | ||||
|             return; | ||||
|  | ||||
|         if (value > this._maxValue) | ||||
|             throw new Error(`Tried to set overdrive value to ${value}, ` + | ||||
|                 `which is a number greater than the maximum allowed value ${this._maxValue}`); | ||||
| @@ -175,32 +203,28 @@ var BarLevel = class { | ||||
|         cr.$dispose(); | ||||
|     } | ||||
|  | ||||
|     _getCurrentValue(actor) { | ||||
|     _getCurrentValue() { | ||||
|         return this._value; | ||||
|     } | ||||
|  | ||||
|     _getOverdriveStart(actor) { | ||||
|     _getOverdriveStart() { | ||||
|         return this._overdriveStart; | ||||
|     } | ||||
|  | ||||
|     _getMinimumValue(actor) { | ||||
|     _getMinimumValue() { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     _getMaximumValue(actor) { | ||||
|     _getMaximumValue() { | ||||
|         return this._maxValue; | ||||
|     } | ||||
|  | ||||
|     _setCurrentValue(actor, value) { | ||||
|     _setCurrentValue(_actor, value) { | ||||
|         this._value = value; | ||||
|     } | ||||
|  | ||||
|     _valueChanged(barLevel, value, property) { | ||||
|     _valueChanged() { | ||||
|         this._customAccessible.notify("accessible-value"); | ||||
|     } | ||||
|  | ||||
|     get value() { | ||||
|         return this._value; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(BarLevel.prototype); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported BoxPointer */ | ||||
|  | ||||
| const { Clutter, GObject, Shell, St } = imports.gi; | ||||
|  | ||||
| @@ -469,7 +470,7 @@ var BoxPointer = GObject.registerClass({ | ||||
|         let sourceAllocation = this._sourceAllocation; | ||||
|         let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment; | ||||
|         let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment; | ||||
|         let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size(); | ||||
|         let [, , natWidth, natHeight] = this.get_preferred_size(); | ||||
|  | ||||
|         // We also want to keep it onscreen, and separated from the | ||||
|         // edge by the same distance as the main part of the box is | ||||
| @@ -594,7 +595,7 @@ var BoxPointer = GObject.registerClass({ | ||||
|  | ||||
|     _calculateArrowSide(arrowSide) { | ||||
|         let sourceAllocation = this._sourceAllocation; | ||||
|         let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size(); | ||||
|         let [, , boxWidth, boxHeight] = this.get_preferred_size(); | ||||
|         let workarea = this._workArea; | ||||
|  | ||||
|         switch (arrowSide) { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Calendar, CalendarMessageList */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -109,15 +110,15 @@ var EmptyEventSource = class EmptyEventSource { | ||||
|     destroy() { | ||||
|     } | ||||
|  | ||||
|     requestRange(begin, end) { | ||||
|     requestRange(_begin, _end) { | ||||
|     } | ||||
|  | ||||
|     getEvents(begin, end) { | ||||
|     getEvents(_begin, _end) { | ||||
|         let result = []; | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     hasEvents(day) { | ||||
|     hasEvents(_day) { | ||||
|         return false; | ||||
|     } | ||||
| }; | ||||
| @@ -220,13 +221,13 @@ var DBusEventSource = class DBusEventSource { | ||||
|         this._lastRequestEnd = null; | ||||
|     } | ||||
|  | ||||
|     _onNameAppeared(owner) { | ||||
|     _onNameAppeared() { | ||||
|         this._initialized = true; | ||||
|         this._resetCache(); | ||||
|         this._loadEvents(true); | ||||
|     } | ||||
|  | ||||
|     _onNameVanished(oldOwner) { | ||||
|     _onNameVanished() { | ||||
|         this._resetCache(); | ||||
|         this.emit('changed'); | ||||
|     } | ||||
| @@ -235,22 +236,20 @@ var DBusEventSource = class DBusEventSource { | ||||
|         this._loadEvents(false); | ||||
|     } | ||||
|  | ||||
|     _onEventsReceived(results, error) { | ||||
|     _onEventsReceived(results, _error) { | ||||
|         let newEvents = []; | ||||
|         let appointments = results ? results[0] : null; | ||||
|         if (appointments != null) { | ||||
|             for (let n = 0; n < appointments.length; n++) { | ||||
|                 let a = appointments[n]; | ||||
|                 let date = new Date(a[4] * 1000); | ||||
|                 let end = new Date(a[5] * 1000); | ||||
|                 let id = a[0]; | ||||
|                 let summary = a[1]; | ||||
|                 let allDay = a[3]; | ||||
|                 let event = new CalendarEvent(id, date, end, summary, allDay); | ||||
|                 newEvents.push(event); | ||||
|             } | ||||
|             newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime()); | ||||
|         let appointments = results[0] || []; | ||||
|         for (let n = 0; n < appointments.length; n++) { | ||||
|             let a = appointments[n]; | ||||
|             let date = new Date(a[4] * 1000); | ||||
|             let end = new Date(a[5] * 1000); | ||||
|             let id = a[0]; | ||||
|             let summary = a[1]; | ||||
|             let allDay = a[3]; | ||||
|             let event = new CalendarEvent(id, date, end, summary, allDay); | ||||
|             newEvents.push(event); | ||||
|         } | ||||
|         newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime()); | ||||
|  | ||||
|         this._events = newEvents; | ||||
|         this.isLoading = false; | ||||
| @@ -736,7 +735,7 @@ class NotificationMessage extends MessageList.Message { | ||||
|             return this.notification.source.createIcon(MESSAGE_ICON_SIZE); | ||||
|     } | ||||
|  | ||||
|     _onUpdated(n, clear) { | ||||
|     _onUpdated(n, _clear) { | ||||
|         this.setIcon(this._getIcon()); | ||||
|         this.setTitle(n.title); | ||||
|         this.setBody(n.bannerBodyText); | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported CheckBox */ | ||||
| const { Clutter, Pango, St } = imports.gi; | ||||
|  | ||||
| var CheckBox = class CheckBox { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported CloseDialog */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported ComponentManager */ | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| var ComponentManager = class { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Gio, GLib } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -55,7 +56,7 @@ var AutomountManager = class { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _InhibitorsChanged(object, senderName, [inhibtor]) { | ||||
|     _InhibitorsChanged(_object, _senderName, [_inhibitor]) { | ||||
|         this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT, | ||||
|             (result, error) => { | ||||
|                 if (!error) { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Gio, St } = imports.gi; | ||||
|  | ||||
| @@ -122,10 +123,7 @@ var ContentTypeDiscoverer = class { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _emitCallback(mount, contentTypes) { | ||||
|         if (!contentTypes) | ||||
|             contentTypes = []; | ||||
|  | ||||
|     _emitCallback(mount, contentTypes = []) { | ||||
|         // we're not interested in win32 software content types here | ||||
|         contentTypes = contentTypes.filter( | ||||
|             type => (type != 'x-content/win32-software') | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi; | ||||
|  | ||||
| @@ -176,21 +177,21 @@ class KeyringDialog extends ModalDialog.ModalDialog { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     _onShowPassword(prompt) { | ||||
|     _onShowPassword() { | ||||
|         this._buildControlTable(); | ||||
|         this._ensureOpen(); | ||||
|         this._updateSensitivity(true); | ||||
|         this._passwordEntry.grab_key_focus(); | ||||
|     } | ||||
|  | ||||
|     _onShowConfirm(prompt) { | ||||
|     _onShowConfirm() { | ||||
|         this._buildControlTable(); | ||||
|         this._ensureOpen(); | ||||
|         this._updateSensitivity(true); | ||||
|         this._continueButton.grab_key_focus(); | ||||
|     } | ||||
|  | ||||
|     _onHidePrompt(prompt) { | ||||
|     _onHidePrompt() { | ||||
|         this.close(); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -199,7 +200,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     _getWirelessSecrets(secrets, wirelessSetting) { | ||||
|     _getWirelessSecrets(secrets, _wirelessSetting) { | ||||
|         let wirelessSecuritySetting = this._connection.get_setting_wireless_security(); | ||||
|  | ||||
|         if (this._settingName == '802-1x') { | ||||
| @@ -385,7 +386,7 @@ var VPNRequestHandler = class { | ||||
|         this._newStylePlugin = authHelper.externalUIMode; | ||||
|  | ||||
|         try { | ||||
|             let [success, pid, stdin, stdout, stderr] = | ||||
|             let [success_, pid, stdin, stdout, stderr] = | ||||
|                 GLib.spawn_async_with_pipes(null, /* pwd */ | ||||
|                                             argv, | ||||
|                                             null, /* envp */ | ||||
| @@ -444,7 +445,7 @@ var VPNRequestHandler = class { | ||||
|         this._destroyed = true; | ||||
|     } | ||||
|  | ||||
|     _vpnChildFinished(pid, status, requestObj) { | ||||
|     _vpnChildFinished(pid, status, _requestObj) { | ||||
|         this._childWatch = 0; | ||||
|         if (this._newStylePlugin) { | ||||
|             // For new style plugin, all work is done in the async reading functions | ||||
| @@ -486,7 +487,7 @@ var VPNRequestHandler = class { | ||||
|  | ||||
|     _readStdoutOldStyle() { | ||||
|         this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => { | ||||
|             let [line, len] = this._dataStdout.read_line_finish_utf8(result); | ||||
|             let [line, len_] = this._dataStdout.read_line_finish_utf8(result); | ||||
|  | ||||
|             if (line == null) { | ||||
|                 // end of file | ||||
| @@ -541,7 +542,7 @@ var VPNRequestHandler = class { | ||||
|                                 message: keyfile.get_string(VPN_UI_GROUP, 'Description'), | ||||
|                                 secrets: [] }; | ||||
|  | ||||
|             let [groups, len] = keyfile.get_groups(); | ||||
|             let [groups, len_] = keyfile.get_groups(); | ||||
|             for (let i = 0; i < groups.length; i++) { | ||||
|                 if (groups[i] == VPN_UI_GROUP) | ||||
|                     continue; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { AccountsService, Clutter, Gio, GLib, | ||||
|         GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi; | ||||
| @@ -383,11 +384,11 @@ var AuthenticationAgent = class { | ||||
|         this._currentDialog.performAuthentication(); | ||||
|     } | ||||
|  | ||||
|     _onCancel(nativeAgent) { | ||||
|     _onCancel(_nativeAgent) { | ||||
|         this._completeRequest(false); | ||||
|     } | ||||
|  | ||||
|     _onDialogDone(dialog, dismissed) { | ||||
|     _onDialogDone(_dialog, dismissed) { | ||||
|         this._completeRequest(dismissed); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, St } = imports.gi; | ||||
| const Lang = imports.lang; | ||||
| @@ -41,7 +42,7 @@ var NotificationDirection = { | ||||
| }; | ||||
|  | ||||
| function makeMessageFromTpMessage(tpMessage, direction) { | ||||
|     let [text, flags] = tpMessage.to_text(); | ||||
|     let [text, flags_] = tpMessage.to_text(); | ||||
|  | ||||
|     let timestamp = tpMessage.get_sent_timestamp(); | ||||
|     if (timestamp == 0) | ||||
| @@ -148,11 +149,11 @@ class TelepathyClient extends Tp.BaseClient { | ||||
|     } | ||||
|  | ||||
|     vfunc_observe_channels(...args) { | ||||
|         let [account, conn, channels, dispatchOp, requests, context] = args; | ||||
|         let [account, conn, channels, dispatchOp_, requests_, context] = args; | ||||
|         let len = channels.length; | ||||
|         for (let i = 0; i < len; i++) { | ||||
|             let channel = channels[i]; | ||||
|             let [targetHandle, targetHandleType] = channel.get_handle(); | ||||
|             let [targetHandle_, targetHandleType] = channel.get_handle(); | ||||
|  | ||||
|             if (channel.get_invalidated()) | ||||
|                 continue; | ||||
| @@ -181,7 +182,7 @@ class TelepathyClient extends Tp.BaseClient { | ||||
|     } | ||||
|  | ||||
|     vfunc_handle_channels(...args) { | ||||
|         let [account, conn, channels, requests, userActionTime, context] = args; | ||||
|         let [account, conn, channels, requests_, userActionTime_, context] = args; | ||||
|         this._handlingChannels(account, conn, channels, true); | ||||
|         context.accept(); | ||||
|     } | ||||
| @@ -239,7 +240,7 @@ class TelepathyClient extends Tp.BaseClient { | ||||
|     } | ||||
|  | ||||
|     _approveTextChannel(account, conn, channel, dispatchOp, context) { | ||||
|         let [targetHandle, targetHandleType] = channel.get_handle(); | ||||
|         let [targetHandle_, targetHandleType] = channel.get_handle(); | ||||
|  | ||||
|         if (targetHandleType != Tp.HandleType.CONTACT) { | ||||
|             context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT, | ||||
| @@ -260,7 +261,7 @@ class TelepathyClient extends Tp.BaseClient { | ||||
|         context.accept(); | ||||
|     } | ||||
|  | ||||
|     _delegatedChannelsCb(client, channels) { | ||||
|     _delegatedChannelsCb(_client, _channels) { | ||||
|         // Nothing to do as we don't make a distinction between observed and | ||||
|         // handled channels. | ||||
|     } | ||||
| @@ -427,7 +428,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|     } | ||||
|  | ||||
|     _displayPendingMessages(logManager, result) { | ||||
|         let [success, events] = logManager.get_filtered_events_finish(result); | ||||
|         let [success_, events] = logManager.get_filtered_events_finish(result); | ||||
|  | ||||
|         let logMessages = events.map(makeMessageFromTplEvent); | ||||
|         this._ensureNotification(); | ||||
| @@ -562,7 +563,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|  | ||||
|     // This is called for both messages we send from | ||||
|     // our client and other clients as well. | ||||
|     _messageSent(channel, message, flags, token) { | ||||
|     _messageSent(channel, message, _flags, _token) { | ||||
|         this._ensureNotification(); | ||||
|         message = makeMessageFromTpMessage(message, NotificationDirection.SENT); | ||||
|         this._notification.appendMessage(message); | ||||
| @@ -600,7 +601,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _presenceChanged(contact, presence, status, message) { | ||||
|     _presenceChanged(_contact, _presence, _status, _message) { | ||||
|         if (this._notification) | ||||
|             this._notification.update(this._notification.title, | ||||
|                                       this._notification.bannerBodyText, | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported CtrlAltTabManager */ | ||||
|  | ||||
| const { Clutter, GObject, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| @@ -63,9 +64,8 @@ var CtrlAltTabManager = class CtrlAltTabManager { | ||||
|         if (a.sortGroup != b.sortGroup) | ||||
|             return a.sortGroup - b.sortGroup; | ||||
|  | ||||
|         let ax, bx, y; | ||||
|         [ax, y] = a.proxy.get_transformed_position(); | ||||
|         [bx, y] = b.proxy.get_transformed_position(); | ||||
|         let [ax] = a.proxy.get_transformed_position(); | ||||
|         let [bx] = b.proxy.get_transformed_position(); | ||||
|  | ||||
|         return ax - bx; | ||||
|     } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Dash */ | ||||
|  | ||||
| const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -24,6 +25,32 @@ function getAppFromSource(source) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| var DashIcon = class DashIcon extends AppDisplay.AppIcon { | ||||
|     constructor(app) { | ||||
|         super(app, null, { | ||||
|             setSizeManually: true, | ||||
|             showLabel: false | ||||
|         }); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     // Disable all DnD methods | ||||
|     _onDragBegin() { | ||||
|     } | ||||
|  | ||||
|     _onDragEnd() { | ||||
|     } | ||||
|  | ||||
|     handleDragOver() { | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
|     } | ||||
|  | ||||
|     acceptDrop() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // A container like StBin, but taking the child's scale into account | ||||
| // when requesting a size | ||||
| var DashItemContainer = GObject.registerClass( | ||||
| @@ -241,14 +268,14 @@ class ShowAppsIcon extends DashItemContainer { | ||||
|             this.setLabelText(_("Show Applications")); | ||||
|     } | ||||
|  | ||||
|     handleDragOver(source, actor, x, y, time) { | ||||
|     handleDragOver(source, _actor, _x, _y, _time) { | ||||
|         if (!this._canRemoveApp(getAppFromSource(source))) | ||||
|             return DND.DragMotionResult.NO_DROP; | ||||
|  | ||||
|         return DND.DragMotionResult.MOVE_DROP; | ||||
|     } | ||||
|  | ||||
|     acceptDrop(source, actor, x, y, time) { | ||||
|     acceptDrop(source, _actor, _x, _y, _time) { | ||||
|         let app = getAppFromSource(source); | ||||
|         if (!this._canRemoveApp(app)) | ||||
|             return false; | ||||
| @@ -296,7 +323,7 @@ class DashActor extends St.Widget { | ||||
|         this.set_allocation(box, flags); | ||||
|  | ||||
|         let [appIcons, showAppsButton] = this.get_children(); | ||||
|         let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth); | ||||
|         let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth); | ||||
|  | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
|         childBox.x1 = contentBox.x1; | ||||
| @@ -474,19 +501,7 @@ var Dash = class Dash { | ||||
|     } | ||||
|  | ||||
|     _createAppItem(app) { | ||||
|         let appIcon = new AppDisplay.AppIcon(app, | ||||
|                                              { setSizeManually: true, | ||||
|                                                showLabel: false }); | ||||
|         if (appIcon._draggable) { | ||||
|             appIcon._draggable.connect('drag-begin', | ||||
|                                        () => { | ||||
|                                            appIcon.actor.opacity = 50; | ||||
|                                        }); | ||||
|             appIcon._draggable.connect('drag-end', | ||||
|                                        () => { | ||||
|                                            appIcon.actor.opacity = 255; | ||||
|                                        }); | ||||
|         } | ||||
|         let appIcon = new DashIcon(app); | ||||
|  | ||||
|         appIcon.connect('menu-state-changed', | ||||
|                         (appIcon, opened) => { | ||||
| @@ -790,7 +805,7 @@ var Dash = class Dash { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     handleDragOver(source, actor, x, y, time) { | ||||
|     handleDragOver(source, actor, x, y, _time) { | ||||
|         let app = getAppFromSource(source); | ||||
|  | ||||
|         // Don't allow favoriting of transient apps | ||||
| @@ -868,7 +883,7 @@ var Dash = class Dash { | ||||
|     } | ||||
|  | ||||
|     // Draggable target interface | ||||
|     acceptDrop(source, actor, x, y, time) { | ||||
|     acceptDrop(source, _actor, _x, _y, _time) { | ||||
|         let app = getAppFromSource(source); | ||||
|  | ||||
|         // Don't allow favoriting of transient apps | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported DateMenuButton */ | ||||
|  | ||||
| const { Clutter, GLib, GnomeDesktop, | ||||
|         GObject, GWeather, Shell, St } = imports.gi; | ||||
| @@ -249,12 +250,12 @@ var WeatherSection = class WeatherSection { | ||||
|         let current = info; | ||||
|         let infos = [info]; | ||||
|         for (let i = 0; i < forecasts.length; i++) { | ||||
|             let [ok, timestamp] = forecasts[i].get_value_update(); | ||||
|             let [ok_, timestamp] = forecasts[i].get_value_update(); | ||||
|             let datetime = new Date(timestamp * 1000); | ||||
|             if (!_isToday(datetime)) | ||||
|                 continue; // Ignore forecasts from other days | ||||
|  | ||||
|             [ok, timestamp] = current.get_value_update(); | ||||
|             [ok_, timestamp] = current.get_value_update(); | ||||
|             let currenttime = new Date(timestamp * 1000); | ||||
|             if (currenttime.getHours() == datetime.getHours()) | ||||
|                 continue; // Enforce a minimum interval of 1h | ||||
| @@ -275,7 +276,7 @@ var WeatherSection = class WeatherSection { | ||||
|  | ||||
|         let col = 0; | ||||
|         infos.forEach(fc => { | ||||
|             let [ok, timestamp] = fc.get_value_update(); | ||||
|             let [ok_, timestamp] = fc.get_value_update(); | ||||
|             let timeStr = Util.formatTime(new Date(timestamp * 1000), { | ||||
|                 timeOnly: true | ||||
|             }); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Dialog, MessageDialogContent */ | ||||
|  | ||||
| const { Clutter, Gio, GObject, Pango, St } = imports.gi; | ||||
|  | ||||
| @@ -180,10 +181,8 @@ var MessageDialogContent = GObject.registerClass({ | ||||
|         this._subtitle.clutter_text.set(textProps); | ||||
|         this._body.clutter_text.set(textProps); | ||||
|  | ||||
|         if (!params.hasOwnProperty('style_class')) | ||||
|             params.style_class = 'message-dialog-main-layout'; | ||||
|  | ||||
|         super._init(params); | ||||
|         let defaultParams = { style_class: 'message-dialog-main-layout' }; | ||||
|         super._init(Object.assign(defaultParams, params)); | ||||
|  | ||||
|         this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content', | ||||
|                                              x_expand: true, | ||||
|   | ||||
							
								
								
									
										11
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported addDragMonitor, removeDragMonitor, makeDraggable */ | ||||
|  | ||||
| const { Clutter, GLib, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -503,7 +504,7 @@ var _Draggable = class _Draggable { | ||||
|  | ||||
|         while (target) { | ||||
|             if (target._delegate && target._delegate.handleDragOver) { | ||||
|                 let [r, targX, targY] = target.transform_stage_point(this._dragX, this._dragY); | ||||
|                 let [r_, targX, targY] = target.transform_stage_point(this._dragX, this._dragY); | ||||
|                 // We currently loop through all parents on drag-over even if one of the children has handled it. | ||||
|                 // We can check the return value of the function and break the loop if it's true if we don't want | ||||
|                 // to continue checking the parents. | ||||
| @@ -575,7 +576,7 @@ var _Draggable = class _Draggable { | ||||
|  | ||||
|         while (target) { | ||||
|             if (target._delegate && target._delegate.acceptDrop) { | ||||
|                 let [r, targX, targY] = target.transform_stage_point(dropX, dropY); | ||||
|                 let [r_, targX, targY] = target.transform_stage_point(dropX, dropY); | ||||
|                 if (target._delegate.acceptDrop(this.actor._delegate, | ||||
|                                                 this._dragActor, | ||||
|                                                 targX, | ||||
| @@ -613,15 +614,15 @@ var _Draggable = class _Draggable { | ||||
|         if (this._dragActorSource && this._dragActorSource.visible) { | ||||
|             // Snap the clone back to its source | ||||
|             [x, y] = this._dragActorSource.get_transformed_position(); | ||||
|             let [sourceScaledWidth, sourceScaledHeight] = this._dragActorSource.get_transformed_size(); | ||||
|             let [sourceScaledWidth] = this._dragActorSource.get_transformed_size(); | ||||
|             scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0; | ||||
|         } else if (this._dragOrigParent) { | ||||
|             // Snap the actor back to its original position within | ||||
|             // its parent, adjusting for the fact that the parent | ||||
|             // may have been moved or scaled | ||||
|             let [parentX, parentY] = this._dragOrigParent.get_transformed_position(); | ||||
|             let [parentWidth, parentHeight] = this._dragOrigParent.get_size(); | ||||
|             let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size(); | ||||
|             let [parentWidth] = this._dragOrigParent.get_size(); | ||||
|             let [parentScaledWidth] = this._dragOrigParent.get_transformed_size(); | ||||
|             let parentScale = 1.0; | ||||
|             if (parentWidth != 0) | ||||
|                 parentScale = parentScaledWidth / parentWidth; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported EdgeDragAction */ | ||||
|  | ||||
| const { Clutter, GObject, Meta, St } = imports.gi; | ||||
|  | ||||
| @@ -26,7 +27,7 @@ var EdgeDragAction = GObject.registerClass({ | ||||
|         return global.display.get_monitor_geometry(monitorIndex); | ||||
|     } | ||||
|  | ||||
|     vfunc_gesture_prepare(actor) { | ||||
|     vfunc_gesture_prepare(_actor) { | ||||
|         if (this.get_n_current_points() == 0) | ||||
|             return false; | ||||
|  | ||||
| @@ -42,7 +43,7 @@ var EdgeDragAction = GObject.registerClass({ | ||||
|                 (this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD)); | ||||
|     } | ||||
|  | ||||
|     vfunc_gesture_progress(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); | ||||
| @@ -62,7 +63,7 @@ var EdgeDragAction = GObject.registerClass({ | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     vfunc_gesture_end(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); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported init, EndSessionDialog */ | ||||
| /* | ||||
|  * Copyright 2010-2016 Red Hat, Inc | ||||
|  * | ||||
| @@ -353,8 +354,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|         // It only makes sense to check for this permission if PackageKit is available. | ||||
|         try { | ||||
|             this._updatesPermission = Polkit.Permission.new_sync( | ||||
|                 "org.freedesktop.packagekit.trigger-offline-update", null, null); | ||||
|         } catch(e) { | ||||
|                 'org.freedesktop.packagekit.trigger-offline-update', null, null); | ||||
|         } catch (e) { | ||||
|             log('No permission to trigger offline updates: %s'.format(e.toString())); | ||||
|         } | ||||
|     } | ||||
| @@ -668,7 +669,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|         this._loginManager.listSessions(result => { | ||||
|             let n = 0; | ||||
|             for (let i = 0; i < result.length; i++) { | ||||
|                 let [id, uid, userName, seat, sessionPath] = result[i]; | ||||
|                 let [id_, uid_, userName, seat_, sessionPath] = result[i]; | ||||
|                 let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath); | ||||
|  | ||||
|                 if (proxy.Class != 'user') | ||||
| @@ -734,7 +735,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|         let dialogContent = DialogContent[this._type]; | ||||
|  | ||||
|         for (let i = 0; i < inhibitorObjectPaths.length; i++) { | ||||
|             let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], (proxy, error) => { | ||||
|             let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => { | ||||
|                 this._onInhibitorLoaded(proxy); | ||||
|             }); | ||||
|  | ||||
| @@ -778,7 +779,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     Close(parameters, invocation) { | ||||
|     Close(_parameters, _invocation) { | ||||
|         this.close(); | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported init */ | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
|  | ||||
| @@ -106,6 +107,12 @@ function init() { | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     St.set_slow_down_factor = function(factor) { | ||||
|         let { stack } = new Error(); | ||||
|         log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`); | ||||
|         St.Settings.get().slow_down_factor = factor; | ||||
|     }; | ||||
|  | ||||
|     let origToString = Object.prototype.toString; | ||||
|     Object.prototype.toString = function() { | ||||
|         let base = origToString.call(this); | ||||
| @@ -128,7 +135,7 @@ function init() { | ||||
|     if (slowdownEnv) { | ||||
|         let factor = parseFloat(slowdownEnv); | ||||
|         if (!isNaN(factor) && factor > 0.0) | ||||
|             St.set_slow_down_factor(factor); | ||||
|             St.Settings.get().slow_down_factor = factor; | ||||
|     } | ||||
|  | ||||
|     // OK, now things are initialized enough that we can import shell JS | ||||
|   | ||||
| @@ -1,12 +1,14 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported init, installExtension, uninstallExtension, | ||||
|             checkForUpdates, updateExtension */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Soup } = imports.gi; | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
| const Dialog = imports.ui.dialog; | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const ExtensionSystem = imports.ui.extensionSystem; | ||||
| const FileUtils = imports.misc.fileUtils; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
|  | ||||
| var REPOSITORY_URL_BASE = 'https://extensions.gnome.org'; | ||||
| @@ -24,7 +26,7 @@ function installExtension(uuid, invocation) { | ||||
|  | ||||
|     _httpSession.queue_message(message, (session, message) => { | ||||
|         if (message.status_code != Soup.KnownStatusCode.OK) { | ||||
|             ExtensionSystem.logExtensionError(uuid, `downloading info: ${message.status_code}`); | ||||
|             Main.extensionManager.logExtensionError(uuid, `downloading info: ${message.status_code}`); | ||||
|             invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString()); | ||||
|             return; | ||||
|         } | ||||
| @@ -33,7 +35,7 @@ function installExtension(uuid, invocation) { | ||||
|         try { | ||||
|             info = JSON.parse(message.response_body.data); | ||||
|         } catch (e) { | ||||
|             ExtensionSystem.logExtensionError(uuid, `parsing info: ${e}`); | ||||
|             Main.extensionManager.logExtensionError(uuid, `parsing info: ${e}`); | ||||
|             invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString()); | ||||
|             return; | ||||
|         } | ||||
| @@ -44,7 +46,7 @@ function installExtension(uuid, invocation) { | ||||
| } | ||||
|  | ||||
| function uninstallExtension(uuid) { | ||||
|     let extension = ExtensionUtils.extensions[uuid]; | ||||
|     let extension = Main.extensionManager.lookup(uuid); | ||||
|     if (!extension) | ||||
|         return false; | ||||
|  | ||||
| @@ -52,7 +54,7 @@ function uninstallExtension(uuid) { | ||||
|     if (extension.type != ExtensionUtils.ExtensionType.PER_USER) | ||||
|         return false; | ||||
|  | ||||
|     if (!ExtensionSystem.unloadExtension(extension)) | ||||
|     if (!Main.extensionManager.unloadExtension(extension)) | ||||
|         return false; | ||||
|  | ||||
|     FileUtils.recursivelyDeleteDir(extension.dir, true); | ||||
| @@ -113,10 +115,10 @@ function updateExtension(uuid) { | ||||
|  | ||||
|     _httpSession.queue_message(message, (session, message) => { | ||||
|         gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => { | ||||
|             let oldExtension = ExtensionUtils.extensions[uuid]; | ||||
|             let oldExtension = Main.extensionManager.lookup(uuid); | ||||
|             let extensionDir = oldExtension.dir; | ||||
|  | ||||
|             if (!ExtensionSystem.unloadExtension(oldExtension)) | ||||
|             if (!Main.extensionManager.unloadExtension(oldExtension)) | ||||
|                 return; | ||||
|  | ||||
|             FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir); | ||||
| @@ -125,11 +127,11 @@ function updateExtension(uuid) { | ||||
|             let extension = null; | ||||
|  | ||||
|             try { | ||||
|                 extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); | ||||
|                 ExtensionSystem.loadExtension(extension); | ||||
|                 extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); | ||||
|                 Main.extensionManager.loadExtension(extension); | ||||
|             } catch (e) { | ||||
|                 if (extension) | ||||
|                     ExtensionSystem.unloadExtension(extension); | ||||
|                     Main.extensionManager.unloadExtension(extension); | ||||
|  | ||||
|                 logError(e, 'Error loading extension %s'.format(uuid)); | ||||
|  | ||||
| @@ -138,7 +140,7 @@ function updateExtension(uuid) { | ||||
|  | ||||
|                 // Restore what was there before. We can't do much if we | ||||
|                 // fail here. | ||||
|                 ExtensionSystem.loadExtension(oldExtension); | ||||
|                 Main.extensionManager.loadExtension(oldExtension); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -151,9 +153,9 @@ function updateExtension(uuid) { | ||||
|  | ||||
| function checkForUpdates() { | ||||
|     let metadatas = {}; | ||||
|     for (let uuid in ExtensionUtils.extensions) { | ||||
|         metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata; | ||||
|     } | ||||
|     Main.extensionManager.getUuids().forEach(uuid => { | ||||
|         metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata; | ||||
|     }); | ||||
|  | ||||
|     let params = { shell_version: Config.PACKAGE_VERSION, | ||||
|                    installed: JSON.stringify(metadatas) }; | ||||
| @@ -203,12 +205,12 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog { | ||||
|         this.contentLayout.add(content); | ||||
|     } | ||||
|  | ||||
|     _onCancelButtonPressed(button, event) { | ||||
|     _onCancelButtonPressed() { | ||||
|         this.close(); | ||||
|         this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled'])); | ||||
|     } | ||||
|  | ||||
|     _onInstallButtonPressed(button, event) { | ||||
|     _onInstallButtonPressed() { | ||||
|         let params = { shell_version: Config.PACKAGE_VERSION }; | ||||
|  | ||||
|         let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid); | ||||
| @@ -224,16 +226,11 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog { | ||||
|         } | ||||
|  | ||||
|         function callback() { | ||||
|             // Add extension to 'enabled-extensions' for the user, always... | ||||
|             let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY); | ||||
|             if (!enabledExtensions.includes(uuid)) { | ||||
|                 enabledExtensions.push(uuid); | ||||
|                 global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions); | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); | ||||
|                 ExtensionSystem.loadExtension(extension); | ||||
|                 let extension = Main.extensionManager.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); | ||||
|                 Main.extensionManager.loadExtension(extension); | ||||
|                 if (!Main.extensionManager.enableExtension(uuid)) | ||||
|                     throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`); | ||||
|             } catch (e) { | ||||
|                 uninstallExtension(uuid); | ||||
|                 errback('LoadExtensionError', e); | ||||
|   | ||||
| @@ -1,374 +1,523 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported init connect disconnect */ | ||||
|  | ||||
| const { Gio, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const FileUtils = imports.misc.fileUtils; | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| var ExtensionState = { | ||||
|     ENABLED: 1, | ||||
|     DISABLED: 2, | ||||
|     ERROR: 3, | ||||
|     OUT_OF_DATE: 4, | ||||
|     DOWNLOADING: 5, | ||||
|     INITIALIZED: 6, | ||||
|  | ||||
|     // Used as an error state for operations on unknown extensions, | ||||
|     // should never be in a real extensionMeta object. | ||||
|     UNINSTALLED: 99 | ||||
| }; | ||||
|  | ||||
| // Arrays of uuids | ||||
| var enabledExtensions; | ||||
| // Contains the order that extensions were enabled in. | ||||
| var extensionOrder = []; | ||||
|  | ||||
| // We don't really have a class to add signals on. So, create | ||||
| // a simple dummy object, add the signal methods, and export those | ||||
| // publically. | ||||
| var _signals = {}; | ||||
| Signals.addSignalMethods(_signals); | ||||
|  | ||||
| var connect = _signals.connect.bind(_signals); | ||||
| var disconnect = _signals.disconnect.bind(_signals); | ||||
| const { ExtensionState, ExtensionType } = ExtensionUtils; | ||||
|  | ||||
| const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; | ||||
| const DISABLED_EXTENSIONS_KEY = 'disabled-extensions'; | ||||
| const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; | ||||
| const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; | ||||
|  | ||||
| var initted = false; | ||||
| var enabled; | ||||
| var ExtensionManager = class { | ||||
|     constructor() { | ||||
|         this._initted = false; | ||||
|         this._enabled = false; | ||||
|  | ||||
| function disableExtension(uuid) { | ||||
|     let extension = ExtensionUtils.extensions[uuid]; | ||||
|     if (!extension) | ||||
|         return; | ||||
|         this._extensions = new Map(); | ||||
|         this._enabledExtensions = []; | ||||
|         this._extensionOrder = []; | ||||
|  | ||||
|     if (extension.state != ExtensionState.ENABLED) | ||||
|         return; | ||||
|         Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); | ||||
|     } | ||||
|  | ||||
|     // "Rebase" the extension order by disabling and then enabling extensions | ||||
|     // in order to help prevent conflicts. | ||||
|     init() { | ||||
|         this._sessionUpdated(); | ||||
|     } | ||||
|  | ||||
|     // Example: | ||||
|     //   order = [A, B, C, D, E] | ||||
|     //   user disables C | ||||
|     //   this should: disable E, disable D, disable C, enable D, enable E | ||||
|     lookup(uuid) { | ||||
|         return this._extensions.get(uuid); | ||||
|     } | ||||
|  | ||||
|     let orderIdx = extensionOrder.indexOf(uuid); | ||||
|     let order = extensionOrder.slice(orderIdx + 1); | ||||
|     let orderReversed = order.slice().reverse(); | ||||
|     getUuids() { | ||||
|         return [...this._extensions.keys()]; | ||||
|     } | ||||
|  | ||||
|     _callExtensionDisable(uuid) { | ||||
|         let extension = this.lookup(uuid); | ||||
|         if (!extension) | ||||
|             return; | ||||
|  | ||||
|         if (extension.state != ExtensionState.ENABLED) | ||||
|             return; | ||||
|  | ||||
|         // "Rebase" the extension order by disabling and then enabling extensions | ||||
|         // in order to help prevent conflicts. | ||||
|  | ||||
|         // Example: | ||||
|         //   order = [A, B, C, D, E] | ||||
|         //   user disables C | ||||
|         //   this should: disable E, disable D, disable C, enable D, enable E | ||||
|  | ||||
|         let orderIdx = this._extensionOrder.indexOf(uuid); | ||||
|         let order = this._extensionOrder.slice(orderIdx + 1); | ||||
|         let orderReversed = order.slice().reverse(); | ||||
|  | ||||
|         for (let i = 0; i < orderReversed.length; i++) { | ||||
|             let uuid = orderReversed[i]; | ||||
|             try { | ||||
|                 this.lookup(uuid).stateObj.disable(); | ||||
|             } catch (e) { | ||||
|                 this.logExtensionError(uuid, e); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (extension.stylesheet) { | ||||
|             let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); | ||||
|             theme.unload_stylesheet(extension.stylesheet); | ||||
|             delete extension.stylesheet; | ||||
|         } | ||||
|  | ||||
|     for (let i = 0; i < orderReversed.length; i++) { | ||||
|         let uuid = orderReversed[i]; | ||||
|         try { | ||||
|             ExtensionUtils.extensions[uuid].stateObj.disable(); | ||||
|             extension.stateObj.disable(); | ||||
|         } catch (e) { | ||||
|             logExtensionError(uuid, e); | ||||
|             this.logExtensionError(uuid, e); | ||||
|         } | ||||
|  | ||||
|         for (let i = 0; i < order.length; i++) { | ||||
|             let uuid = order[i]; | ||||
|             try { | ||||
|                 this.lookup(uuid).stateObj.enable(); | ||||
|             } catch (e) { | ||||
|                 this.logExtensionError(uuid, e); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._extensionOrder.splice(orderIdx, 1); | ||||
|  | ||||
|         if (extension.state != ExtensionState.ERROR) { | ||||
|             extension.state = ExtensionState.DISABLED; | ||||
|             this.emit('extension-state-changed', extension); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (extension.stylesheet) { | ||||
|     _callExtensionEnable(uuid) { | ||||
|         let extension = this.lookup(uuid); | ||||
|         if (!extension) | ||||
|             return; | ||||
|  | ||||
|         if (extension.state == ExtensionState.INITIALIZED) | ||||
|             this._callExtensionInit(uuid); | ||||
|  | ||||
|         if (extension.state != ExtensionState.DISABLED) | ||||
|             return; | ||||
|  | ||||
|         this._extensionOrder.push(uuid); | ||||
|  | ||||
|         let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css']; | ||||
|         let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); | ||||
|         theme.unload_stylesheet(extension.stylesheet); | ||||
|         delete extension.stylesheet; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         extension.stateObj.disable(); | ||||
|     } catch (e) { | ||||
|         logExtensionError(uuid, e); | ||||
|     } | ||||
|  | ||||
|     for (let i = 0; i < order.length; i++) { | ||||
|         let uuid = order[i]; | ||||
|         try { | ||||
|             ExtensionUtils.extensions[uuid].stateObj.enable(); | ||||
|         } catch (e) { | ||||
|             logExtensionError(uuid, e); | ||||
|         for (let i = 0; i < stylesheetNames.length; i++) { | ||||
|             try { | ||||
|                 let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); | ||||
|                 theme.load_stylesheet(stylesheetFile); | ||||
|                 extension.stylesheet = stylesheetFile; | ||||
|                 break; | ||||
|             } catch (e) { | ||||
|                 if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) | ||||
|                     continue; // not an error | ||||
|                 log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     extensionOrder.splice(orderIdx, 1); | ||||
|  | ||||
|     if ( extension.state != ExtensionState.ERROR ) { | ||||
|         extension.state = ExtensionState.DISABLED; | ||||
|         _signals.emit('extension-state-changed', extension); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function enableExtension(uuid) { | ||||
|     let extension = ExtensionUtils.extensions[uuid]; | ||||
|     if (!extension) | ||||
|         return; | ||||
|  | ||||
|     if (extension.state == ExtensionState.INITIALIZED) | ||||
|         initExtension(uuid); | ||||
|  | ||||
|     if (extension.state != ExtensionState.DISABLED) | ||||
|         return; | ||||
|  | ||||
|     extensionOrder.push(uuid); | ||||
|  | ||||
|     let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css']; | ||||
|     let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); | ||||
|     for (let i = 0; i < stylesheetNames.length; i++) { | ||||
|         try { | ||||
|             let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); | ||||
|             theme.load_stylesheet(stylesheetFile); | ||||
|             extension.stylesheet = stylesheetFile; | ||||
|             break; | ||||
|             extension.stateObj.enable(); | ||||
|             extension.state = ExtensionState.ENABLED; | ||||
|             this.emit('extension-state-changed', extension); | ||||
|             return; | ||||
|         } catch (e) { | ||||
|             if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) | ||||
|                 continue; // not an error | ||||
|             log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`); | ||||
|             if (extension.stylesheet) { | ||||
|                 theme.unload_stylesheet(extension.stylesheet); | ||||
|                 delete extension.stylesheet; | ||||
|             } | ||||
|             this.logExtensionError(uuid, e); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         extension.stateObj.enable(); | ||||
|         extension.state = ExtensionState.ENABLED; | ||||
|         _signals.emit('extension-state-changed', extension); | ||||
|         return; | ||||
|     } catch (e) { | ||||
|         if (extension.stylesheet) { | ||||
|             theme.unload_stylesheet(extension.stylesheet); | ||||
|             delete extension.stylesheet; | ||||
|     enableExtension(uuid) { | ||||
|         if (!this._extensions.has(uuid)) | ||||
|             return false; | ||||
|  | ||||
|         let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); | ||||
|         let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY); | ||||
|  | ||||
|         if (disabledExtensions.includes(uuid)) { | ||||
|             disabledExtensions = disabledExtensions.filter(item => item !== uuid); | ||||
|             global.settings.set_strv(DISABLED_EXTENSIONS_KEY, disabledExtensions); | ||||
|         } | ||||
|         logExtensionError(uuid, e); | ||||
|         return; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function logExtensionError(uuid, error) { | ||||
|     let extension = ExtensionUtils.extensions[uuid]; | ||||
|     if (!extension) | ||||
|         return; | ||||
|  | ||||
|     let message = `${error}`; | ||||
|  | ||||
|     extension.state = ExtensionState.ERROR; | ||||
|     if (!extension.errors) | ||||
|         extension.errors = []; | ||||
|     extension.errors.push(message); | ||||
|  | ||||
|     log('Extension "%s" had error: %s'.format(uuid, message)); | ||||
|     _signals.emit('extension-state-changed', { uuid: uuid, | ||||
|                                                error: message, | ||||
|                                                state: extension.state }); | ||||
| } | ||||
|  | ||||
| function loadExtension(extension) { | ||||
|     // Default to error, we set success as the last step | ||||
|     extension.state = ExtensionState.ERROR; | ||||
|  | ||||
|     let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); | ||||
|  | ||||
|     if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { | ||||
|         extension.state = ExtensionState.OUT_OF_DATE; | ||||
|     } else { | ||||
|         let enabled = enabledExtensions.includes(extension.uuid); | ||||
|         if (enabled) { | ||||
|             if (!initExtension(extension.uuid)) | ||||
|                 return; | ||||
|             if (extension.state == ExtensionState.DISABLED) | ||||
|                 enableExtension(extension.uuid); | ||||
|         } else { | ||||
|             extension.state = ExtensionState.INITIALIZED; | ||||
|         if (!enabledExtensions.includes(uuid)) { | ||||
|             enabledExtensions.push(uuid); | ||||
|             global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     _signals.emit('extension-state-changed', extension); | ||||
| } | ||||
|     disableExtension(uuid) { | ||||
|         if (!this._extensions.has(uuid)) | ||||
|             return false; | ||||
|  | ||||
| function unloadExtension(extension) { | ||||
|     // Try to disable it -- if it's ERROR'd, we can't guarantee that, | ||||
|     // but it will be removed on next reboot, and hopefully nothing | ||||
|     // broke too much. | ||||
|     disableExtension(extension.uuid); | ||||
|         let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY); | ||||
|         let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY); | ||||
|  | ||||
|     extension.state = ExtensionState.UNINSTALLED; | ||||
|     _signals.emit('extension-state-changed', extension); | ||||
|         if (enabledExtensions.includes(uuid)) { | ||||
|             enabledExtensions = enabledExtensions.filter(item => item !== uuid); | ||||
|             global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions); | ||||
|         } | ||||
|  | ||||
|     delete ExtensionUtils.extensions[extension.uuid]; | ||||
|     return true; | ||||
| } | ||||
|         if (!disabledExtensions.includes(uuid)) { | ||||
|             disabledExtensions.push(uuid); | ||||
|             global.settings.set_strv(DISABLED_EXTENSIONS_KEY, disabledExtensions); | ||||
|         } | ||||
|  | ||||
| function reloadExtension(oldExtension) { | ||||
|     // Grab the things we'll need to pass to createExtensionObject | ||||
|     // to reload it. | ||||
|     let { uuid: uuid, dir: dir, type: type } = oldExtension; | ||||
|  | ||||
|     // Then unload the old extension. | ||||
|     unloadExtension(oldExtension); | ||||
|  | ||||
|     // Now, recreate the extension and load it. | ||||
|     let newExtension; | ||||
|     try { | ||||
|         newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type); | ||||
|     } catch (e) { | ||||
|         logExtensionError(uuid, e); | ||||
|         return; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     loadExtension(newExtension); | ||||
| } | ||||
|     logExtensionError(uuid, error) { | ||||
|         let extension = this.lookup(uuid); | ||||
|         if (!extension) | ||||
|             return; | ||||
|  | ||||
| function initExtension(uuid) { | ||||
|     let extension = ExtensionUtils.extensions[uuid]; | ||||
|     let dir = extension.dir; | ||||
|         let message = `${error}`; | ||||
|  | ||||
|     if (!extension) | ||||
|         throw new Error("Extension was not properly created. Call loadExtension first"); | ||||
|         extension.error = message; | ||||
|         extension.state = ExtensionState.ERROR; | ||||
|         if (!extension.errors) | ||||
|             extension.errors = []; | ||||
|         extension.errors.push(message); | ||||
|  | ||||
|     let extensionJs = dir.get_child('extension.js'); | ||||
|     if (!extensionJs.query_exists(null)) { | ||||
|         logExtensionError(uuid, new Error('Missing extension.js')); | ||||
|         return false; | ||||
|         log('Extension "%s" had error: %s'.format(uuid, message)); | ||||
|         this.emit('extension-state-changed', extension); | ||||
|     } | ||||
|  | ||||
|     let extensionModule; | ||||
|     let extensionState = null; | ||||
|     createExtensionObject(uuid, dir, type) { | ||||
|         let metadataFile = dir.get_child('metadata.json'); | ||||
|         if (!metadataFile.query_exists(null)) { | ||||
|             throw new Error('Missing metadata.json'); | ||||
|         } | ||||
|  | ||||
|     ExtensionUtils.installImporter(extension); | ||||
|     try { | ||||
|         extensionModule = extension.imports.extension; | ||||
|     } catch (e) { | ||||
|         logExtensionError(uuid, e); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (extensionModule.init) { | ||||
|         let metadataContents, success_; | ||||
|         try { | ||||
|             extensionState = extensionModule.init(extension); | ||||
|             [success_, metadataContents] = metadataFile.load_contents(null); | ||||
|             if (metadataContents instanceof Uint8Array) | ||||
|                 metadataContents = imports.byteArray.toString(metadataContents); | ||||
|         } catch (e) { | ||||
|             logExtensionError(uuid, e); | ||||
|             throw new Error(`Failed to load metadata.json: ${e}`); | ||||
|         } | ||||
|         let meta; | ||||
|         try { | ||||
|             meta = JSON.parse(metadataContents); | ||||
|         } catch (e) { | ||||
|             throw new Error(`Failed to parse metadata.json: ${e}`); | ||||
|         } | ||||
|  | ||||
|         let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; | ||||
|         for (let i = 0; i < requiredProperties.length; i++) { | ||||
|             let prop = requiredProperties[i]; | ||||
|             if (!meta[prop]) { | ||||
|                 throw new Error(`missing "${prop}" property in metadata.json`); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (uuid != meta.uuid) { | ||||
|             throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); | ||||
|         } | ||||
|  | ||||
|         let extension = { | ||||
|             metadata: meta, | ||||
|             uuid: meta.uuid, | ||||
|             type, | ||||
|             dir, | ||||
|             path: dir.get_path(), | ||||
|             error: '', | ||||
|             hasPrefs: dir.get_child('prefs.js').query_exists(null), | ||||
|             canChange: false | ||||
|         }; | ||||
|         this._extensions.set(uuid, extension); | ||||
|  | ||||
|         return extension; | ||||
|     } | ||||
|  | ||||
|     loadExtension(extension) { | ||||
|         // Default to error, we set success as the last step | ||||
|         extension.state = ExtensionState.ERROR; | ||||
|  | ||||
|         let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); | ||||
|  | ||||
|         if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { | ||||
|             extension.state = ExtensionState.OUT_OF_DATE; | ||||
|         } else { | ||||
|             let enabled = this._enabledExtensions.includes(extension.uuid); | ||||
|             if (enabled) { | ||||
|                 if (!this._callExtensionInit(extension.uuid)) | ||||
|                     return; | ||||
|                 if (extension.state == ExtensionState.DISABLED) | ||||
|                     this._callExtensionEnable(extension.uuid); | ||||
|             } else { | ||||
|                 extension.state = ExtensionState.INITIALIZED; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._updateCanChange(extension); | ||||
|         this.emit('extension-state-changed', extension); | ||||
|     } | ||||
|  | ||||
|     unloadExtension(extension) { | ||||
|         // Try to disable it -- if it's ERROR'd, we can't guarantee that, | ||||
|         // but it will be removed on next reboot, and hopefully nothing | ||||
|         // broke too much. | ||||
|         this._callExtensionDisable(extension.uuid); | ||||
|  | ||||
|         extension.state = ExtensionState.UNINSTALLED; | ||||
|         this.emit('extension-state-changed', extension); | ||||
|  | ||||
|         this._extensions.delete(extension.uuid); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     reloadExtension(oldExtension) { | ||||
|         // Grab the things we'll need to pass to createExtensionObject | ||||
|         // to reload it. | ||||
|         let { uuid: uuid, dir: dir, type: type } = oldExtension; | ||||
|  | ||||
|         // Then unload the old extension. | ||||
|         this.unloadExtension(oldExtension); | ||||
|  | ||||
|         // Now, recreate the extension and load it. | ||||
|         let newExtension; | ||||
|         try { | ||||
|             newExtension = this.createExtensionObject(uuid, dir, type); | ||||
|         } catch (e) { | ||||
|             this.logExtensionError(uuid, e); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.loadExtension(newExtension); | ||||
|     } | ||||
|  | ||||
|     _callExtensionInit(uuid) { | ||||
|         let extension = this.lookup(uuid); | ||||
|         let dir = extension.dir; | ||||
|  | ||||
|         if (!extension) | ||||
|             throw new Error("Extension was not properly created. Call loadExtension first"); | ||||
|  | ||||
|         let extensionJs = dir.get_child('extension.js'); | ||||
|         if (!extensionJs.query_exists(null)) { | ||||
|             this.logExtensionError(uuid, new Error('Missing extension.js')); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         let extensionModule; | ||||
|         let extensionState = null; | ||||
|  | ||||
|         ExtensionUtils.installImporter(extension); | ||||
|         try { | ||||
|             extensionModule = extension.imports.extension; | ||||
|         } catch (e) { | ||||
|             this.logExtensionError(uuid, e); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (extensionModule.init) { | ||||
|             try { | ||||
|                 extensionState = extensionModule.init(extension); | ||||
|             } catch (e) { | ||||
|                 this.logExtensionError(uuid, e); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!extensionState) | ||||
|             extensionState = extensionModule; | ||||
|         extension.stateObj = extensionState; | ||||
|  | ||||
|         extension.state = ExtensionState.DISABLED; | ||||
|         this.emit('extension-loaded', uuid); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     if (!extensionState) | ||||
|         extensionState = extensionModule; | ||||
|     extension.stateObj = extensionState; | ||||
|     _getModeExtensions() { | ||||
|         if (Array.isArray(Main.sessionMode.enabledExtensions)) | ||||
|             return Main.sessionMode.enabledExtensions; | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     extension.state = ExtensionState.DISABLED; | ||||
|     _signals.emit('extension-loaded', uuid); | ||||
|     return true; | ||||
| } | ||||
|     _updateCanChange(extension) { | ||||
|         let hasError = | ||||
|             extension.state == ExtensionState.ERROR || | ||||
|             extension.state == ExtensionState.OUT_OF_DATE; | ||||
|  | ||||
| function getEnabledExtensions() { | ||||
|     let extensions; | ||||
|     if (Array.isArray(Main.sessionMode.enabledExtensions)) | ||||
|         extensions = Main.sessionMode.enabledExtensions; | ||||
|     else | ||||
|         extensions = []; | ||||
|         let isMode = this._getModeExtensions().includes(extension.uuid); | ||||
|         let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY); | ||||
|  | ||||
|     if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) | ||||
|         return extensions; | ||||
|         let changeKey = isMode | ||||
|             ? DISABLE_USER_EXTENSIONS_KEY | ||||
|             : ENABLED_EXTENSIONS_KEY; | ||||
|  | ||||
|     return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); | ||||
| } | ||||
|         extension.canChange = | ||||
|             !hasError && | ||||
|             global.settings.is_writable(changeKey) && | ||||
|             (isMode || !modeOnly); | ||||
|     } | ||||
|  | ||||
| function onEnabledExtensionsChanged() { | ||||
|     let newEnabledExtensions = getEnabledExtensions(); | ||||
|     _getEnabledExtensions() { | ||||
|         let extensions = this._getModeExtensions(); | ||||
|  | ||||
|     if (!enabled) | ||||
|         return; | ||||
|         if (!global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) | ||||
|             extensions = extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); | ||||
|  | ||||
|     // Find and enable all the newly enabled extensions: UUIDs found in the | ||||
|     // new setting, but not in the old one. | ||||
|     newEnabledExtensions.filter( | ||||
|         uuid => !enabledExtensions.includes(uuid) | ||||
|     ).forEach(uuid => { | ||||
|         enableExtension(uuid); | ||||
|     }); | ||||
|         // filter out 'disabled-extensions' which takes precedence | ||||
|         let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY); | ||||
|         return extensions.filter(item => !disabledExtensions.includes(item)); | ||||
|     } | ||||
|  | ||||
|     // Find and disable all the newly disabled extensions: UUIDs found in the | ||||
|     // old setting, but not in the new one. | ||||
|     enabledExtensions.filter( | ||||
|         item => !newEnabledExtensions.includes(item) | ||||
|     ).forEach(uuid => { | ||||
|         disableExtension(uuid); | ||||
|     }); | ||||
|     _onUserExtensionsEnabledChanged() { | ||||
|         this._onEnabledExtensionsChanged(); | ||||
|         this._onSettingsWritableChanged(); | ||||
|     } | ||||
|  | ||||
|     enabledExtensions = newEnabledExtensions; | ||||
| } | ||||
|     _onEnabledExtensionsChanged() { | ||||
|         let newEnabledExtensions = this._getEnabledExtensions(); | ||||
|  | ||||
| function _onVersionValidationChanged() { | ||||
|     // we want to reload all extensions, but only enable | ||||
|     // extensions when allowed by the sessionMode, so | ||||
|     // temporarily disable them all | ||||
|     enabledExtensions = []; | ||||
|     for (let uuid in ExtensionUtils.extensions) | ||||
|         reloadExtension(ExtensionUtils.extensions[uuid]); | ||||
|     enabledExtensions = getEnabledExtensions(); | ||||
|         if (!this._enabled) | ||||
|             return; | ||||
|  | ||||
|     if (Main.sessionMode.allowExtensions) { | ||||
|         enabledExtensions.forEach(uuid => { | ||||
|             enableExtension(uuid); | ||||
|         // Find and enable all the newly enabled extensions: UUIDs found in the | ||||
|         // new setting, but not in the old one. | ||||
|         newEnabledExtensions.filter( | ||||
|             uuid => !this._enabledExtensions.includes(uuid) | ||||
|         ).forEach(uuid => { | ||||
|             this._callExtensionEnable(uuid); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function _loadExtensions() { | ||||
|     global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, onEnabledExtensionsChanged); | ||||
|     global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, onEnabledExtensionsChanged); | ||||
|     global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, _onVersionValidationChanged); | ||||
|  | ||||
|     enabledExtensions = getEnabledExtensions(); | ||||
|  | ||||
|     let finder = new ExtensionUtils.ExtensionFinder(); | ||||
|     finder.connect('extension-found', (finder, extension) => { | ||||
|         loadExtension(extension); | ||||
|     }); | ||||
|     finder.scanExtensions(); | ||||
| } | ||||
|  | ||||
| function enableAllExtensions() { | ||||
|     if (enabled) | ||||
|         return; | ||||
|  | ||||
|     if (!initted) { | ||||
|         _loadExtensions(); | ||||
|         initted = true; | ||||
|     } else { | ||||
|         enabledExtensions.forEach(uuid => { | ||||
|             enableExtension(uuid); | ||||
|         // Find and disable all the newly disabled extensions: UUIDs found in the | ||||
|         // old setting, but not in the new one. | ||||
|         this._enabledExtensions.filter( | ||||
|             item => !newEnabledExtensions.includes(item) | ||||
|         ).forEach(uuid => { | ||||
|             this._callExtensionDisable(uuid); | ||||
|         }); | ||||
|  | ||||
|         this._enabledExtensions = newEnabledExtensions; | ||||
|     } | ||||
|     enabled = true; | ||||
| } | ||||
|  | ||||
| function disableAllExtensions() { | ||||
|     if (!enabled) | ||||
|         return; | ||||
|     _onSettingsWritableChanged() { | ||||
|         for (let extension of this._extensions.values()) { | ||||
|             this._updateCanChange(extension); | ||||
|             this.emit('extension-state-changed', extension); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (initted) { | ||||
|         extensionOrder.slice().reverse().forEach(uuid => { | ||||
|             disableExtension(uuid); | ||||
|     _onVersionValidationChanged() { | ||||
|         // we want to reload all extensions, but only enable | ||||
|         // extensions when allowed by the sessionMode, so | ||||
|         // temporarily disable them all | ||||
|         this._enabledExtensions = []; | ||||
|  | ||||
|         // The loop modifies the extensions map, so iterate over a copy | ||||
|         let extensions = [...this._extensions.values()]; | ||||
|         for (let extension of extensions) | ||||
|             this.reloadExtension(extension); | ||||
|         this._enabledExtensions = this._getEnabledExtensions(); | ||||
|  | ||||
|         if (Main.sessionMode.allowExtensions) { | ||||
|             this._enabledExtensions.forEach(uuid => { | ||||
|                 this._callExtensionEnable(uuid); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _loadExtensions() { | ||||
|         global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, | ||||
|             this._onEnabledExtensionsChanged.bind(this)); | ||||
|         global.settings.connect(`changed::${DISABLED_EXTENSIONS_KEY}`, | ||||
|             this._onEnabledExtensionsChanged.bind(this)); | ||||
|         global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, | ||||
|             this._onUserExtensionsEnabledChanged.bind(this)); | ||||
|         global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, | ||||
|             this._onVersionValidationChanged.bind(this)); | ||||
|         global.settings.connect(`writable-changed::${ENABLED_EXTENSIONS_KEY}`, | ||||
|             this._onSettingsWritableChanged.bind(this)); | ||||
|         global.settings.connect(`writable-changed::${DISABLED_EXTENSIONS_KEY}`, | ||||
|             this._onSettingsWritableChanged.bind(this)); | ||||
|  | ||||
|         this._enabledExtensions = this._getEnabledExtensions(); | ||||
|  | ||||
|         let perUserDir = Gio.File.new_for_path(global.userdatadir); | ||||
|         FileUtils.collectFromDatadirs('extensions', true, (dir, info) => { | ||||
|             let fileType = info.get_file_type(); | ||||
|             if (fileType != Gio.FileType.DIRECTORY) | ||||
|                 return; | ||||
|             let uuid = info.get_name(); | ||||
|             let existing = this.lookup(uuid); | ||||
|             if (existing) { | ||||
|                 log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let extension; | ||||
|             let type = dir.has_prefix(perUserDir) | ||||
|                 ? ExtensionType.PER_USER | ||||
|                 : ExtensionType.SYSTEM; | ||||
|             try { | ||||
|                 extension = this.createExtensionObject(uuid, dir, type); | ||||
|             } catch (e) { | ||||
|                 logError(e, `Could not load extension ${uuid}`); | ||||
|                 return; | ||||
|             } | ||||
|             this.loadExtension(extension); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     enabled = false; | ||||
| } | ||||
|     _enableAllExtensions() { | ||||
|         if (this._enabled) | ||||
|             return; | ||||
|  | ||||
| function _sessionUpdated() { | ||||
|     // For now sessionMode.allowExtensions controls extensions from both the | ||||
|     // 'enabled-extensions' preference and the sessionMode.enabledExtensions | ||||
|     // property; it might make sense to make enabledExtensions independent | ||||
|     // from allowExtensions in the future | ||||
|     if (Main.sessionMode.allowExtensions) { | ||||
|         if (initted) | ||||
|             enabledExtensions = getEnabledExtensions(); | ||||
|         enableAllExtensions(); | ||||
|     } else { | ||||
|         disableAllExtensions(); | ||||
|         if (!this._initted) { | ||||
|             this._loadExtensions(); | ||||
|             this._initted = true; | ||||
|         } else { | ||||
|             this._enabledExtensions.forEach(uuid => { | ||||
|                 this._callExtensionEnable(uuid); | ||||
|             }); | ||||
|         } | ||||
|         this._enabled = true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function init() { | ||||
|     Main.sessionMode.connect('updated', _sessionUpdated); | ||||
|     _sessionUpdated(); | ||||
| } | ||||
|     _disableAllExtensions() { | ||||
|         if (!this._enabled) | ||||
|             return; | ||||
|  | ||||
|         if (this._initted) { | ||||
|             this._extensionOrder.slice().reverse().forEach(uuid => { | ||||
|                 this._callExtensionDisable(uuid); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         this._enabled = false; | ||||
|     } | ||||
|  | ||||
|     _sessionUpdated() { | ||||
|         // For now sessionMode.allowExtensions controls extensions from both the | ||||
|         // 'enabled-extensions' preference and the sessionMode.enabledExtensions | ||||
|         // property; it might make sense to make enabledExtensions independent | ||||
|         // from allowExtensions in the future | ||||
|         if (Main.sessionMode.allowExtensions) { | ||||
|             if (this._initted) | ||||
|                 this._enabledExtensions = this._getEnabledExtensions(); | ||||
|             this._enableAllExtensions(); | ||||
|         } else { | ||||
|             this._disableAllExtensions(); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ExtensionManager.prototype); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported GrabHelper */ | ||||
|  | ||||
| const { Clutter, St } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported CandidatePopup */ | ||||
|  | ||||
| const { Clutter, IBus, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -198,29 +199,29 @@ var CandidatePopup = class CandidatePopup { | ||||
|                 this._setTextAttributes(this._preeditText.clutter_text, | ||||
|                                         attrs); | ||||
|         }); | ||||
|         panelService.connect('show-preedit-text', ps => { | ||||
|         panelService.connect('show-preedit-text', () => { | ||||
|             this._preeditText.show(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('hide-preedit-text', ps => { | ||||
|         panelService.connect('hide-preedit-text', () => { | ||||
|             this._preeditText.hide(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('update-auxiliary-text', (ps, text, visible) => { | ||||
|         panelService.connect('update-auxiliary-text', (_ps, text, visible) => { | ||||
|             this._auxText.visible = visible; | ||||
|             this._updateVisibility(); | ||||
|  | ||||
|             this._auxText.text = text.get_text(); | ||||
|         }); | ||||
|         panelService.connect('show-auxiliary-text', ps => { | ||||
|         panelService.connect('show-auxiliary-text', () => { | ||||
|             this._auxText.show(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('hide-auxiliary-text', ps => { | ||||
|         panelService.connect('hide-auxiliary-text', () => { | ||||
|             this._auxText.hide(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('update-lookup-table', (ps, lookupTable, visible) => { | ||||
|         panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => { | ||||
|             this._candidateArea.actor.visible = visible; | ||||
|             this._updateVisibility(); | ||||
|  | ||||
| @@ -256,15 +257,15 @@ var CandidatePopup = class CandidatePopup { | ||||
|             this._candidateArea.setOrientation(lookupTable.get_orientation()); | ||||
|             this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages); | ||||
|         }); | ||||
|         panelService.connect('show-lookup-table', ps => { | ||||
|         panelService.connect('show-lookup-table', () => { | ||||
|             this._candidateArea.actor.show(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('hide-lookup-table', ps => { | ||||
|         panelService.connect('hide-lookup-table', () => { | ||||
|             this._candidateArea.actor.hide(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('focus-out', ps => { | ||||
|         panelService.connect('focus-out', () => { | ||||
|             this._boxPointer.close(BoxPointer.PopupAnimation.NONE); | ||||
|             Main.keyboard.resetSuggestions(); | ||||
|         }); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported BaseIcon, IconGrid, PaginatedIconGrid */ | ||||
|  | ||||
| const { Clutter, GObject, Meta, St } = imports.gi; | ||||
| const { Clutter, GLib, GObject, Meta, St } = imports.gi; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| @@ -28,6 +29,27 @@ var AnimationDirection = { | ||||
| var APPICON_ANIMATION_OUT_SCALE = 3; | ||||
| var APPICON_ANIMATION_OUT_TIME = 0.25; | ||||
|  | ||||
| const LEFT_DIVIDER_LEEWAY = 30; | ||||
| const RIGHT_DIVIDER_LEEWAY = 30; | ||||
|  | ||||
| const NUDGE_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_ELASTIC; | ||||
| const NUDGE_DURATION = 800; | ||||
|  | ||||
| const NUDGE_RETURN_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_QUINT; | ||||
| const NUDGE_RETURN_DURATION = 300; | ||||
|  | ||||
| const NUDGE_FACTOR = 0.33; | ||||
|  | ||||
| const ICON_POSITION_DELAY = 25; | ||||
|  | ||||
| var DragLocation = { | ||||
|     DEFAULT: 0, | ||||
|     ON_ICON: 1, | ||||
|     START_EDGE: 2, | ||||
|     END_EDGE: 3, | ||||
|     EMPTY_AREA: 4, | ||||
| } | ||||
|  | ||||
| var BaseIcon = GObject.registerClass( | ||||
| class BaseIcon extends St.Bin { | ||||
|     _init(label, params) { | ||||
| @@ -56,6 +78,10 @@ class BaseIcon extends St.Bin { | ||||
|  | ||||
|         if (params.showLabel) { | ||||
|             this.label = new St.Label({ text: label }); | ||||
|             this.label.clutter_text.set({ | ||||
|                 x_align: Clutter.ActorAlign.CENTER, | ||||
|                 y_align: Clutter.ActorAlign.CENTER | ||||
|             }); | ||||
|             this._box.add_actor(this.label); | ||||
|         } else { | ||||
|             this.label = null; | ||||
| @@ -71,14 +97,14 @@ class BaseIcon extends St.Bin { | ||||
|         this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this)); | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_width(forHeight) { | ||||
|     vfunc_get_preferred_width(_forHeight) { | ||||
|         // Return the actual height to keep the squared aspect | ||||
|         return this.get_preferred_height(-1); | ||||
|     } | ||||
|  | ||||
|     // This can be overridden by a subclass, or by the createIcon | ||||
|     // parameter to _init() | ||||
|     createIcon(size) { | ||||
|     createIcon(_size) { | ||||
|         throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`); | ||||
|     } | ||||
|  | ||||
| @@ -137,6 +163,10 @@ class BaseIcon extends St.Bin { | ||||
|         // animating. | ||||
|         zoomOutActor(this.child); | ||||
|     } | ||||
|  | ||||
|     update() { | ||||
|         this._createIconTexture(this.iconSize); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function clamp(value, min, max) { | ||||
| @@ -206,6 +236,8 @@ var IconGrid = GObject.registerClass({ | ||||
|         this.rightPadding = 0; | ||||
|         this.leftPadding = 0; | ||||
|  | ||||
|         this._updateIconSizesLaterId = 0; | ||||
|  | ||||
|         this._items = []; | ||||
|         this._clonesAnimating = []; | ||||
|         // Pulled from CSS, but hardcode some defaults here | ||||
| @@ -223,6 +255,14 @@ var IconGrid = GObject.registerClass({ | ||||
|  | ||||
|         this.connect('actor-added', this._childAdded.bind(this)); | ||||
|         this.connect('actor-removed', this._childRemoved.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         if (this._updateIconSizesLaterId) { | ||||
|             Meta.later_remove (this._updateIconSizesLaterId); | ||||
|             this._updateIconSizesLaterId = 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _keyFocusIn(actor) { | ||||
| @@ -237,7 +277,7 @@ var IconGrid = GObject.registerClass({ | ||||
|         child.disconnect(child._iconGridKeyFocusInId); | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_width(forHeight) { | ||||
|     vfunc_get_preferred_width(_forHeight) { | ||||
|         if (this._fillParent) | ||||
|             // Ignore all size requests of children and request a size of 0; | ||||
|             // later we'll allocate as many children as fit the parent | ||||
| @@ -327,6 +367,7 @@ var IconGrid = GObject.registerClass({ | ||||
|         let y = box.y1 + this.topPadding; | ||||
|         let columnIndex = 0; | ||||
|         let rowIndex = 0; | ||||
|         let nChanged = 0; | ||||
|         for (let i = 0; i < children.length; i++) { | ||||
|             let childBox = this._calculateChildBox(children[i], x, y, box); | ||||
|  | ||||
| @@ -336,7 +377,16 @@ var IconGrid = GObject.registerClass({ | ||||
|             } else { | ||||
|                 if (!animating) | ||||
|                     children[i].opacity = 255; | ||||
|  | ||||
|                 // Figure out how much delay to apply | ||||
|                 if (!childBox.equal(children[i].get_allocation_box())) | ||||
|                     nChanged++; | ||||
|  | ||||
|                 children[i].save_easing_state(); | ||||
|                 children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD); | ||||
|                 children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged); | ||||
|                 children[i].allocate(childBox, flags); | ||||
|                 children[i].restore_easing_state(); | ||||
|             } | ||||
|  | ||||
|             columnIndex++; | ||||
| @@ -602,6 +652,8 @@ var IconGrid = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _computeLayout(forWidth) { | ||||
|         this.ensure_style(); | ||||
|  | ||||
|         let nColumns = 0; | ||||
|         let usedWidth = this.leftPadding + this.rightPadding; | ||||
|         let spacing = this._getSpacing(); | ||||
| @@ -674,6 +726,22 @@ var IconGrid = GObject.registerClass({ | ||||
|             this.add_actor(item.actor); | ||||
|     } | ||||
|  | ||||
|     moveItem(item, newPosition) { | ||||
|         if (!this.contains(item.actor)) { | ||||
|             log('Cannot move item not contained by the IconGrid'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let children = this.get_children(); | ||||
|         let visibleChildren = children.filter(c => c.is_visible()); | ||||
|         let visibleChildAtPosition = visibleChildren[newPosition]; | ||||
|         let realPosition = children.indexOf(visibleChildAtPosition); | ||||
|  | ||||
|         this.set_child_at_index(item.actor, realPosition); | ||||
|  | ||||
|         return realPosition; | ||||
|     } | ||||
|  | ||||
|     removeItem(item) { | ||||
|         this.remove_child(item.actor); | ||||
|     } | ||||
| @@ -755,17 +823,237 @@ var IconGrid = GObject.registerClass({ | ||||
|  | ||||
|             this._updateSpacingForSize(availWidth, availHeight); | ||||
|         } | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                        this._updateIconSizes.bind(this)); | ||||
|         if (!this._updateIconSizesLaterId) | ||||
|             this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                                                           this._updateIconSizes.bind(this)); | ||||
|     } | ||||
|  | ||||
|     // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up | ||||
|     _updateIconSizes() { | ||||
|         this._updateIconSizesLaterId = 0; | ||||
|         let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize); | ||||
|         let newIconSize = Math.floor(ICON_SIZE * scale); | ||||
|         for (let i in this._items) { | ||||
|             this._items[i].icon.setIconSize(newIconSize); | ||||
|         } | ||||
|         return GLib.SOURCE_REMOVE; | ||||
|     } | ||||
|  | ||||
|     // Drag n' Drop methods | ||||
|  | ||||
|     nudgeItemsAtIndex(index, dragLocation) { | ||||
|         // No nudging when the cursor is in an empty area | ||||
|         if (dragLocation == DragLocation.EMPTY_AREA || dragLocation == DragLocation.ON_ICON) | ||||
|             return; | ||||
|  | ||||
|         let children = this.get_children().filter(c => c.is_visible()); | ||||
|         let nudgeIndex = index; | ||||
|         let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); | ||||
|  | ||||
|         if (dragLocation != DragLocation.START_EDGE) { | ||||
|             let leftItem = children[nudgeIndex - 1]; | ||||
|             let offset = rtl ? Math.floor(this._hItemSize * NUDGE_FACTOR) : Math.floor(-this._hItemSize * NUDGE_FACTOR); | ||||
|             this._animateNudge(leftItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset); | ||||
|         } | ||||
|  | ||||
|         // Nudge the icon to the right if we are the first item or not at the | ||||
|         // end of row | ||||
|         if (dragLocation != DragLocation.END_EDGE) { | ||||
|             let rightItem = children[nudgeIndex]; | ||||
|             let offset = rtl ? Math.floor(-this._hItemSize * NUDGE_FACTOR) : Math.floor(this._hItemSize * NUDGE_FACTOR); | ||||
|             this._animateNudge(rightItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     removeNudges() { | ||||
|         let children = this.get_children().filter(c => c.is_visible()); | ||||
|         for (let index = 0; index < children.length; index++) { | ||||
|             this._animateNudge(children[index], | ||||
|                                NUDGE_RETURN_ANIMATION_TYPE, | ||||
|                                NUDGE_RETURN_DURATION, | ||||
|                                0); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _animateNudge(item, animationType, duration, offset) { | ||||
|         if (!item) | ||||
|             return; | ||||
|  | ||||
|         item.save_easing_state(); | ||||
|         item.set_easing_mode(animationType); | ||||
|         item.set_easing_duration(duration); | ||||
|         item.translation_x = offset; | ||||
|         item.restore_easing_state(); | ||||
|     } | ||||
|  | ||||
|     // This function is overriden by the PaginatedIconGrid subclass so we can | ||||
|     // take into account the extra space when dragging from a folder | ||||
|     _calculateDndRow(y) { | ||||
|         let rowHeight = this._getVItemSize() + this._getSpacing(); | ||||
|         return Math.floor(y / rowHeight); | ||||
|     } | ||||
|  | ||||
|     // Returns the drop point index or -1 if we can't drop there | ||||
|     canDropAt(x, y) { | ||||
|         // This is an complex calculation, but in essence, we divide the grid | ||||
|         // as: | ||||
|         // | ||||
|         //  left empty space | ||||
|         //      |   left padding                          right padding | ||||
|         //      |     |        width without padding               | | ||||
|         // +--------+---+---------------------------------------+-----+ | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |--------+-----------+----------+-------|     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |--------+-----------+----------+-------|     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |--------+-----------+----------+-------|     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // |        |   |        |           |          |       |     | | ||||
|         // +--------+---+---------------------------------------+-----+ | ||||
|         // | ||||
|         // The left empty space is immediately discarded, and ignored in all | ||||
|         // calculations. | ||||
|         // | ||||
|         // The width (with paddings) is used to determine if we're dragging | ||||
|         // over the left or right padding, and which column is being dragged | ||||
|         // on. | ||||
|         // | ||||
|         // Finally, the width without padding is used to figure out where in | ||||
|         // the icon (start edge, end edge, on it, etc) the cursor is. | ||||
|  | ||||
|         let [nColumns, usedWidth] = this._computeLayout(this.width); | ||||
|  | ||||
|         let leftEmptySpace; | ||||
|         switch (this._xAlign) { | ||||
|         case St.Align.START: | ||||
|             leftEmptySpace = 0; | ||||
|             break; | ||||
|         case St.Align.MIDDLE: | ||||
|             leftEmptySpace = Math.floor((this.width - usedWidth) / 2); | ||||
|             break; | ||||
|         case St.Align.END: | ||||
|             leftEmptySpace = availWidth - usedWidth; | ||||
|         } | ||||
|  | ||||
|         x -= leftEmptySpace; | ||||
|         y -= this.topPadding; | ||||
|  | ||||
|         let row = this._calculateDndRow(y); | ||||
|  | ||||
|         // Correct sx to handle the left padding to correctly calculate | ||||
|         // the column | ||||
|         let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); | ||||
|         let gridX = x - this.leftPadding; | ||||
|  | ||||
|         let widthWithoutPadding = usedWidth - this.leftPadding - this.rightPadding; | ||||
|         let columnWidth = widthWithoutPadding / nColumns; | ||||
|  | ||||
|         let column; | ||||
|         if (x < this.leftPadding) | ||||
|             column = 0; | ||||
|         else if (x > usedWidth - this.rightPadding) | ||||
|             column = nColumns - 1; | ||||
|         else | ||||
|             column = Math.floor(gridX / columnWidth); | ||||
|  | ||||
|         let isFirstIcon = column == 0; | ||||
|         let isLastIcon = column == nColumns - 1; | ||||
|  | ||||
|         // If we're outside of the grid, we are in an invalid drop location | ||||
|         if (x < 0 || x > usedWidth) | ||||
|             return [-1, DragLocation.DEFAULT]; | ||||
|  | ||||
|         let children = this.get_children().filter(c => c.is_visible()); | ||||
|         let childIndex = Math.min((row * nColumns) + column, children.length); | ||||
|  | ||||
|         // If we're above the grid vertically, we are in an invalid | ||||
|         // drop location | ||||
|         if (childIndex < 0) | ||||
|             return [-1, DragLocation.DEFAULT]; | ||||
|  | ||||
|         // If we're past the last visible element in the grid, | ||||
|         // we might be allowed to drop there. | ||||
|         if (childIndex >= children.length) | ||||
|             return [children.length, DragLocation.EMPTY_AREA]; | ||||
|  | ||||
|         let child = children[childIndex]; | ||||
|         let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] = child.get_preferred_size(); | ||||
|  | ||||
|         // This is the width of the cell that contains the icon | ||||
|         // (excluding spacing between cells) | ||||
|         let childIconWidth = Math.max(this._getHItemSize(), childNaturalWidth); | ||||
|  | ||||
|         // Calculate the original position of the child icon (prior to nudging) | ||||
|         let childX; | ||||
|         if (rtl) | ||||
|             childX = widthWithoutPadding - (column * columnWidth) - childIconWidth; | ||||
|         else | ||||
|             childX = column * columnWidth; | ||||
|  | ||||
|         let iconLeftX = childX + LEFT_DIVIDER_LEEWAY; | ||||
|         let iconRightX = childX + childIconWidth - RIGHT_DIVIDER_LEEWAY | ||||
|  | ||||
|         let dropIndex; | ||||
|         let dragLocation; | ||||
|  | ||||
|         x -= this.leftPadding; | ||||
|  | ||||
|         if (x < iconLeftX) { | ||||
|             // We are to the left of the icon target | ||||
|             if (isFirstIcon || x < 0) { | ||||
|                 // We are before the leftmost icon on the grid | ||||
|                 if (rtl) { | ||||
|                     dropIndex = childIndex + 1; | ||||
|                     dragLocation = DragLocation.END_EDGE; | ||||
|                 } else { | ||||
|                     dropIndex = childIndex; | ||||
|                     dragLocation = DragLocation.START_EDGE; | ||||
|                 } | ||||
|             } else { | ||||
|                 // We are between the previous icon (next in RTL) and this one | ||||
|                 if (rtl) | ||||
|                     dropIndex = childIndex + 1; | ||||
|                 else | ||||
|                     dropIndex = childIndex; | ||||
|  | ||||
|                 dragLocation = DragLocation.DEFAULT; | ||||
|             } | ||||
|         } else if (x >= iconRightX) { | ||||
|             // We are to the right of the icon target | ||||
|             if (childIndex >= children.length) { | ||||
|                 // We are beyond the last valid icon | ||||
|                 // (to the right of the app store / trash can, if present) | ||||
|                 dropIndex = -1; | ||||
|                 dragLocation = DragLocation.DEFAULT; | ||||
|             } else if (isLastIcon || x >= widthWithoutPadding) { | ||||
|                 // We are beyond the rightmost icon on the grid | ||||
|                 if (rtl) { | ||||
|                     dropIndex = childIndex; | ||||
|                     dragLocation = DragLocation.START_EDGE; | ||||
|                 } else { | ||||
|                     dropIndex = childIndex + 1; | ||||
|                     dragLocation = DragLocation.END_EDGE; | ||||
|                 } | ||||
|             } else { | ||||
|                 // We are between this icon and the next one (previous in RTL) | ||||
|                 if (rtl) | ||||
|                     dropIndex = childIndex; | ||||
|                 else | ||||
|                     dropIndex = childIndex + 1; | ||||
|  | ||||
|                 dragLocation = DragLocation.DEFAULT; | ||||
|             } | ||||
|         } else { | ||||
|             // We are over the icon target area | ||||
|             dropIndex = childIndex; | ||||
|             dragLocation = DragLocation.ON_ICON; | ||||
|         } | ||||
|  | ||||
|         return [dropIndex, dragLocation]; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -782,7 +1070,7 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|         this._childrenPerPage = 0; | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_height(forWidth) { | ||||
|     vfunc_get_preferred_height(_forWidth) { | ||||
|         let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages; | ||||
|         return [height, height]; | ||||
|     } | ||||
| @@ -819,10 +1107,21 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|         let x = box.x1 + leftEmptySpace + this.leftPadding; | ||||
|         let y = box.y1 + this.topPadding; | ||||
|         let columnIndex = 0; | ||||
|         let nChanged = 0; | ||||
|  | ||||
|         for (let i = 0; i < children.length; i++) { | ||||
|             let childBox = this._calculateChildBox(children[i], x, y, box); | ||||
|  | ||||
|             // Figure out how much delay to apply | ||||
|             if (!childBox.equal(children[i].get_allocation_box())) | ||||
|                 nChanged++; | ||||
|  | ||||
|             children[i].save_easing_state(); | ||||
|             children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD); | ||||
|             children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged); | ||||
|             children[i].allocate(childBox, flags); | ||||
|             children[i].restore_easing_state(); | ||||
|  | ||||
|             children[i].show(); | ||||
|  | ||||
|             columnIndex++; | ||||
| @@ -841,6 +1140,23 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     // Overridden from IconGrid | ||||
|     _calculateDndRow(y) { | ||||
|         let row = super._calculateDndRow(y); | ||||
|  | ||||
|         // If there's no extra space, just return the current value and maintain | ||||
|         // the same behavior when without a folder opened. | ||||
|         if (!this._extraSpaceData) | ||||
|             return row; | ||||
|  | ||||
|         let [ baseRow, nRowsUp, nRowsDown ] = this._extraSpaceData; | ||||
|         let newRow = row + nRowsUp; | ||||
|  | ||||
|         if (row > baseRow) | ||||
|             newRow -= nRowsDown; | ||||
|  | ||||
|         return newRow; | ||||
|     } | ||||
|  | ||||
|     _getChildrenToAnimate() { | ||||
|         let children = this._getVisibleChildren(); | ||||
|         let firstIndex = this._childrenPerPage * this.currentPage; | ||||
| @@ -850,7 +1166,7 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _computePages(availWidthPerPage, availHeightPerPage) { | ||||
|         let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage); | ||||
|         let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage); | ||||
|         let nRows; | ||||
|         let children = this._getVisibleChildren(); | ||||
|         if (nColumns > 0) | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported InhibitShortcutsDialog */ | ||||
| const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi; | ||||
|  | ||||
| const Dialog = imports.ui.dialog; | ||||
| @@ -139,7 +140,7 @@ var InhibitShortcutsDialog = GObject.registerClass({ | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     let [permissions, data] = res; | ||||
|                     let [permissions] = res; | ||||
|                     if (permissions[appId] === undefined) // Not found | ||||
|                         this._dialog.open(); | ||||
|                     else if (permissions[appId] == GRANTED) | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported KbdA11yDialog */ | ||||
| const { Clutter, Gio, GObject } = imports.gi; | ||||
|  | ||||
| const Dialog = imports.ui.dialog; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Keyboard */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -100,7 +101,7 @@ class KeyContainer extends St.Widget { | ||||
|         this._rows = []; | ||||
|     } | ||||
|  | ||||
|     appendRow(length) { | ||||
|     appendRow() { | ||||
|         this._currentRow++; | ||||
|         this._currentCol = 0; | ||||
|  | ||||
| @@ -474,7 +475,7 @@ var KeyboardModel = class { | ||||
|  | ||||
|     _loadModel(groupName) { | ||||
|         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName)); | ||||
|         let [success, contents] = file.load_contents(null); | ||||
|         let [success_, contents] = file.load_contents(null); | ||||
|         if (contents instanceof Uint8Array) | ||||
|             contents = imports.byteArray.toString(contents); | ||||
|  | ||||
| @@ -662,7 +663,7 @@ var EmojiPager = class EmojiPager { | ||||
|     } | ||||
|  | ||||
|     _onPan(action) { | ||||
|         let [dist, dx, dy] = action.get_motion_delta(0); | ||||
|         let [dist_, dx, dy_] = action.get_motion_delta(0); | ||||
|         this.delta = this.delta + dx; | ||||
|  | ||||
|         if (this._currentKey != null) { | ||||
| @@ -904,7 +905,7 @@ var EmojiSelection = class EmojiSelection { | ||||
|  | ||||
|     _populateSections() { | ||||
|         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json'); | ||||
|         let [success, contents] = file.load_contents(null); | ||||
|         let [success_, contents] = file.load_contents(null); | ||||
|  | ||||
|         if (contents instanceof Uint8Array) | ||||
|             contents = imports.byteArray.toString(contents); | ||||
| @@ -1171,7 +1172,7 @@ var Keyboard = class Keyboard { | ||||
|  | ||||
|         this._emojiSelection = new EmojiSelection(); | ||||
|         this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this)); | ||||
|         this._emojiSelection.connect('hide', (selection) => this.hide()); | ||||
|         this._emojiSelection.connect('hide', () => this.hide()); | ||||
|         this._emojiSelection.connect('emoji-selected', (selection, emoji) => { | ||||
|             this._keyboardController.commitString(emoji); | ||||
|         }); | ||||
| @@ -1282,7 +1283,7 @@ var Keyboard = class Keyboard { | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             button.connect('released', (actor, keyval, str) => { | ||||
|             button.connect('released', (actor, keyval, _str) => { | ||||
|                 if (keyval != 0) { | ||||
|                     if (button._keyvalPress) | ||||
|                         this._keyboardController.keyvalRelease(keyval); | ||||
| @@ -1467,7 +1468,7 @@ var Keyboard = class Keyboard { | ||||
|         this._setActiveLayer(0); | ||||
|     } | ||||
|  | ||||
|     _onKeyboardGroupsChanged(keyboard) { | ||||
|     _onKeyboardGroupsChanged() { | ||||
|         let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor]; | ||||
|         this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => { | ||||
|             c.destroy(); | ||||
| @@ -1729,7 +1730,7 @@ var KeyboardController = class { | ||||
|         this.emit('groups-changed'); | ||||
|     } | ||||
|  | ||||
|     _onSourceChanged(inputSourceManager, oldSource) { | ||||
|     _onSourceChanged(inputSourceManager, _oldSource) { | ||||
|         let source = inputSourceManager.currentSource; | ||||
|         this._currentSource = source; | ||||
|         this.emit('active-group', source.id); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported MonitorConstraint, LayoutManager */ | ||||
|  | ||||
| const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Background = imports.ui.background; | ||||
| @@ -80,10 +81,12 @@ var MonitorConstraint = GObject.registerClass({ | ||||
|         this.notify('index'); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get work_area() { | ||||
|         return this._workArea; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set work_area(v) { | ||||
|         if (v == this._workArea) | ||||
|             return; | ||||
| @@ -165,12 +168,12 @@ var Monitor = class Monitor { | ||||
|  | ||||
| const UiActor = GObject.registerClass( | ||||
| class UiActor extends St.Widget { | ||||
|     vfunc_get_preferred_width (forHeight) { | ||||
|     vfunc_get_preferred_width (_forHeight) { | ||||
|         let width = global.stage.width; | ||||
|         return [width, width]; | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_height (forWidth) { | ||||
|     vfunc_get_preferred_height (_forWidth) { | ||||
|         let height = global.stage.height; | ||||
|         return [height, height]; | ||||
|     } | ||||
| @@ -274,6 +277,13 @@ var LayoutManager = GObject.registerClass({ | ||||
|         this._backgroundGroup.lower_bottom(); | ||||
|         this._bgManagers = []; | ||||
|  | ||||
|         this._interfaceSettings = new Gio.Settings({ | ||||
|             schema_id: 'org.gnome.desktop.interface' | ||||
|         }); | ||||
|  | ||||
|         this._interfaceSettings.connect('changed::enable-hot-corners', | ||||
|                                         this._updateHotCorners.bind(this)); | ||||
|  | ||||
|         // Need to update struts on new workspaces when they are added | ||||
|         let workspaceManager = global.workspace_manager; | ||||
|         workspaceManager.connect('notify::n-workspaces', | ||||
| @@ -377,6 +387,11 @@ var LayoutManager = GObject.registerClass({ | ||||
|         }); | ||||
|         this.hotCorners = []; | ||||
|  | ||||
|         if (!this._interfaceSettings.get_boolean('enable-hot-corners')) { | ||||
|             this.emit('hot-corners-changed'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let size = this.panelBox.height; | ||||
|  | ||||
|         // build new hot corners | ||||
| @@ -829,7 +844,7 @@ var LayoutManager = GObject.registerClass({ | ||||
|     // @params can have any of the same values as in addChrome(), | ||||
|     // though some possibilities don't make sense. By default, @actor has | ||||
|     // the same params as its chrome ancestor. | ||||
|     trackChrome(actor, params) { | ||||
|     trackChrome(actor, params = {}) { | ||||
|         let ancestor = actor.get_parent(); | ||||
|         let index = this._findActor(ancestor); | ||||
|         while (ancestor && index == -1) { | ||||
| @@ -839,8 +854,6 @@ var LayoutManager = GObject.registerClass({ | ||||
|  | ||||
|         let ancestorData = ancestor ? this._trackedActors[index] | ||||
|                                     : defaultParams; | ||||
|         if (!params) | ||||
|             params = {}; | ||||
|         // We can't use Params.parse here because we want to drop | ||||
|         // the extra values like ancestorData.actor | ||||
|         for (let prop in defaultParams) { | ||||
| @@ -1220,7 +1233,7 @@ var HotCorner = class HotCorner { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     handleDragOver(source, actor, x, y, time) { | ||||
|     handleDragOver(source, _actor, _x, _y, _time) { | ||||
|         if (source != Main.xdndHandler) | ||||
|             return DND.DragMotionResult.CONTINUE; | ||||
|  | ||||
| @@ -1321,7 +1334,7 @@ var PressureBarrier = class PressureBarrier { | ||||
|         let threshold = this._lastTime - this._timeout; | ||||
|  | ||||
|         while (i < this._barrierEvents.length) { | ||||
|             let [time, distance] = this._barrierEvents[i]; | ||||
|             let [time, distance_] = this._barrierEvents[i]; | ||||
|             if (time >= threshold) | ||||
|                 break; | ||||
|             i++; | ||||
| @@ -1330,14 +1343,14 @@ var PressureBarrier = class PressureBarrier { | ||||
|         let firstNewEvent = i; | ||||
|  | ||||
|         for (i = 0; i < firstNewEvent; i++) { | ||||
|             let [time, distance] = this._barrierEvents[i]; | ||||
|             let [time_, distance] = this._barrierEvents[i]; | ||||
|             this._currentPressure -= distance; | ||||
|         } | ||||
|  | ||||
|         this._barrierEvents = this._barrierEvents.slice(firstNewEvent); | ||||
|     } | ||||
|  | ||||
|     _onBarrierLeft(barrier, event) { | ||||
|     _onBarrierLeft(barrier, _event) { | ||||
|         barrier._isHit = false; | ||||
|         if (this._barriers.every(b => !b._isHit)) { | ||||
|             this._reset(); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Lightbox */ | ||||
|  | ||||
| const { Clutter, GObject, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -23,8 +24,8 @@ t = clamp(t, 0.0, 1.0);\n\ | ||||
| float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\ | ||||
| cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);'; | ||||
|  | ||||
| var RadialShaderQuad = GObject.registerClass( | ||||
| class RadialShaderQuad extends Shell.GLSLQuad { | ||||
| var RadialShaderEffect = GObject.registerClass( | ||||
| class RadialShaderEffect extends Shell.GLSLEffect { | ||||
|     _init(params) { | ||||
|         super._init(params); | ||||
|  | ||||
| @@ -98,16 +99,13 @@ var Lightbox = class Lightbox { | ||||
|         this._children = container.get_children(); | ||||
|         this._fadeFactor = params.fadeFactor; | ||||
|         this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect; | ||||
|  | ||||
|         this.actor = new St.Bin({ reactive: params.inhibitEvents }); | ||||
|  | ||||
|         if (this._radialEffect) | ||||
|             this.actor = new RadialShaderQuad({ x: 0, | ||||
|                                                 y: 0, | ||||
|                                                 reactive: params.inhibitEvents }); | ||||
|             this.actor.add_effect(new RadialShaderEffect({ name: 'radial' })); | ||||
|         else | ||||
|             this.actor = new St.Bin({ x: 0, | ||||
|                                       y: 0, | ||||
|                                       opacity: 0, | ||||
|                                       style_class: 'lightbox', | ||||
|                                       reactive: params.inhibitEvents }); | ||||
|             this.actor.set({ opacity: 0, style_class: 'lightbox' }); | ||||
|  | ||||
|         container.add_actor(this.actor); | ||||
|         this.actor.raise_top(); | ||||
| @@ -156,9 +154,10 @@ var Lightbox = class Lightbox { | ||||
|     show(fadeInTime) { | ||||
|         fadeInTime = fadeInTime || 0; | ||||
|  | ||||
|         Tweener.removeTweens(this.actor); | ||||
|         if (this._radialEffect) { | ||||
|             Tweener.addTween(this.actor, | ||||
|             let effect = this.actor.get_effect('radial'); | ||||
|             Tweener.removeTweens(effect); | ||||
|             Tweener.addTween(effect, | ||||
|                              { brightness: VIGNETTE_BRIGHTNESS, | ||||
|                                vignetteSharpness: VIGNETTE_SHARPNESS, | ||||
|                                time: fadeInTime, | ||||
| @@ -169,6 +168,7 @@ var Lightbox = class Lightbox { | ||||
|                                } | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.removeTweens(this.actor); | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { opacity: 255 * this._fadeFactor, | ||||
|                                time: fadeInTime, | ||||
| @@ -187,9 +187,11 @@ var Lightbox = class Lightbox { | ||||
|         fadeOutTime = fadeOutTime || 0; | ||||
|  | ||||
|         this.shown = false; | ||||
|         Tweener.removeTweens(this.actor); | ||||
|  | ||||
|         if (this._radialEffect) { | ||||
|             Tweener.addTween(this.actor, | ||||
|             let effect = this.actor.get_effect('radial'); | ||||
|             Tweener.removeTweens(effect); | ||||
|             Tweener.addTween(effect, | ||||
|                              { brightness: 1.0, | ||||
|                                vignetteSharpness: 0.0, | ||||
|                                opacity: 0, | ||||
| @@ -200,6 +202,7 @@ var Lightbox = class Lightbox { | ||||
|                                } | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.removeTweens(this.actor); | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: fadeOutTime, | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported LocatePointer */ | ||||
|  | ||||
| const { Gio } = imports.gi; | ||||
| const Ripples = imports.ui.ripples; | ||||
| @@ -18,7 +19,7 @@ var LocatePointer = class { | ||||
|         if (!this._settings.get_boolean(LOCATE_POINTER_KEY)) | ||||
|             return; | ||||
|  | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         this._ripples.playAnimation(x, y); | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported LookingGlass */ | ||||
|  | ||||
| const { Clutter, Cogl, Gio, GLib, | ||||
|         GObject, Meta, Pango, Shell, St } = imports.gi; | ||||
| @@ -7,13 +8,14 @@ const Signals = imports.signals; | ||||
| const System = imports.system; | ||||
|  | ||||
| const History = imports.misc.history; | ||||
| const ExtensionSystem = imports.ui.extensionSystem; | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Main = imports.ui.main; | ||||
| const JsParse = imports.misc.jsParse; | ||||
|  | ||||
| const { ExtensionState } = ExtensionUtils; | ||||
|  | ||||
| const CHEVRON = '>>> '; | ||||
|  | ||||
| /* Imports...feel free to add here as needed */ | ||||
| @@ -266,7 +268,7 @@ var ObjLink = class ObjLink { | ||||
|         this._lookingGlass = lookingGlass; | ||||
|     } | ||||
|  | ||||
|     _onClicked(link) { | ||||
|     _onClicked() { | ||||
|         this._lookingGlass.inspectObject(this._obj, this.actor); | ||||
|     } | ||||
| }; | ||||
| @@ -518,7 +520,7 @@ var Inspector = GObject.registerClass({ | ||||
|  | ||||
|         let primary = Main.layoutManager.primaryMonitor; | ||||
|  | ||||
|         let [minWidth, minHeight, natWidth, natHeight] = | ||||
|         let [, , natWidth, natHeight] = | ||||
|             this._eventHandler.get_preferred_size(); | ||||
|  | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
| @@ -623,15 +625,16 @@ var Extensions = class Extensions { | ||||
|         this._extensionsList.add(this._noExtensions); | ||||
|         this.actor.add(this._extensionsList); | ||||
|  | ||||
|         for (let uuid in ExtensionUtils.extensions) | ||||
|         Main.extensionManager.getUuids().forEach(uuid => { | ||||
|             this._loadExtension(null, uuid); | ||||
|         }); | ||||
|  | ||||
|         ExtensionSystem.connect('extension-loaded', | ||||
|                                 this._loadExtension.bind(this)); | ||||
|         Main.extensionManager.connect('extension-loaded', | ||||
|                                       this._loadExtension.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _loadExtension(o, uuid) { | ||||
|         let extension = ExtensionUtils.extensions[uuid]; | ||||
|         let extension = Main.extensionManager.lookup(uuid); | ||||
|         // There can be cases where we create dummy extension metadata | ||||
|         // that's not really a proper extension. Don't bother with these. | ||||
|         if (!extension.metadata.name) | ||||
| @@ -688,16 +691,16 @@ var Extensions = class Extensions { | ||||
|  | ||||
|     _stateToString(extensionState) { | ||||
|         switch (extensionState) { | ||||
|         case ExtensionSystem.ExtensionState.ENABLED: | ||||
|         case ExtensionState.ENABLED: | ||||
|             return _("Enabled"); | ||||
|         case ExtensionSystem.ExtensionState.DISABLED: | ||||
|         case ExtensionSystem.ExtensionState.INITIALIZED: | ||||
|         case ExtensionState.DISABLED: | ||||
|         case ExtensionState.INITIALIZED: | ||||
|             return _("Disabled"); | ||||
|         case ExtensionSystem.ExtensionState.ERROR: | ||||
|         case ExtensionState.ERROR: | ||||
|             return _("Error"); | ||||
|         case ExtensionSystem.ExtensionState.OUT_OF_DATE: | ||||
|         case ExtensionState.OUT_OF_DATE: | ||||
|             return _("Out of date"); | ||||
|         case ExtensionSystem.ExtensionState.DOWNLOADING: | ||||
|         case ExtensionState.DOWNLOADING: | ||||
|             return _("Downloading"); | ||||
|         } | ||||
|         return 'Unknown'; // Not translated, shouldn't appear | ||||
| @@ -854,7 +857,7 @@ var LookingGlass = class LookingGlass { | ||||
|         this._extensions = new Extensions(this); | ||||
|         notebook.appendPage('Extensions', this._extensions.actor); | ||||
|  | ||||
|         this._entry.clutter_text.connect('activate', (o, e) => { | ||||
|         this._entry.clutter_text.connect('activate', (o, _e) => { | ||||
|             // Hide any completions we are currently showing | ||||
|             this._hideCompletions(); | ||||
|  | ||||
| @@ -940,15 +943,16 @@ var LookingGlass = class LookingGlass { | ||||
|         // Setting the height to -1 allows us to get its actual preferred height rather than | ||||
|         // whatever was last given in set_height by Tweener. | ||||
|         this._completionActor.set_height(-1); | ||||
|         let [minHeight, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width()); | ||||
|         let [, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width()); | ||||
|  | ||||
|         // Don't reanimate if we are already visible | ||||
|         if (this._completionActor.visible) { | ||||
|             this._completionActor.height = naturalHeight; | ||||
|         } else { | ||||
|             let settings = St.Settings.get(); | ||||
|             this._completionActor.show(); | ||||
|             Tweener.removeTweens(this._completionActor); | ||||
|             Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(), | ||||
|             Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor, | ||||
|                                                       transition: 'easeOutQuad', | ||||
|                                                       height: naturalHeight, | ||||
|                                                       opacity: 255 | ||||
| @@ -958,8 +962,9 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|     _hideCompletions() { | ||||
|         if (this._completionActor) { | ||||
|             let settings = St.Settings.get(); | ||||
|             Tweener.removeTweens(this._completionActor); | ||||
|             Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(), | ||||
|             Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor, | ||||
|                                                       transition: 'easeOutQuad', | ||||
|                                                       height: 0, | ||||
|                                                       opacity: 0, | ||||
| @@ -1009,7 +1014,10 @@ var LookingGlass = class LookingGlass { | ||||
|     } | ||||
|  | ||||
|     _queueResize() { | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => this._resize()); | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
|             this._resize(); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _resize() { | ||||
| @@ -1076,7 +1084,8 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|         // We inverse compensate for the slow-down so you can change the factor | ||||
|         // through LookingGlass without long waits. | ||||
|         Tweener.addTween(this.actor, { time: 0.5 / St.get_slow_down_factor(), | ||||
|         let settings = St.Settings.get(); | ||||
|         Tweener.addTween(this.actor, { time: 0.5 / settings.slow_down_factor, | ||||
|                                        transition: 'easeOutQuad', | ||||
|                                        y: this._targetY | ||||
|                                      }); | ||||
| @@ -1095,7 +1104,8 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|         Main.popModal(this._entry); | ||||
|  | ||||
|         Tweener.addTween(this.actor, { time: Math.min(0.5 / St.get_slow_down_factor(), 0.5), | ||||
|         let settings = St.Settings.get(); | ||||
|         Tweener.addTween(this.actor, { time: Math.min(0.5 / settings.slow_down_factor, 0.5), | ||||
|                                        transition: 'easeOutQuad', | ||||
|                                        y: this._hiddenY, | ||||
|                                        onComplete: () => { | ||||
|   | ||||
| @@ -107,8 +107,7 @@ var Magnifier = class Magnifier { | ||||
|         // Create the first ZoomRegion and initialize it according to the | ||||
|         // magnification settings. | ||||
|  | ||||
|         let mask; | ||||
|         [this.xMouse, this.yMouse, mask] = global.get_pointer(); | ||||
|         [this.xMouse, this.yMouse] = global.get_pointer(); | ||||
|  | ||||
|         let aZoomRegion = new ZoomRegion(this, this._cursorRoot); | ||||
|         this._zoomRegions.push(aZoomRegion); | ||||
| @@ -148,7 +147,7 @@ var Magnifier = class Magnifier { | ||||
|     setActive(activate) { | ||||
|         let isActive = this.isActive(); | ||||
|  | ||||
|         this._zoomRegions.forEach((zoomRegion, index, array) => { | ||||
|         this._zoomRegions.forEach(zoomRegion => { | ||||
|             zoomRegion.setActive(activate); | ||||
|         }); | ||||
|  | ||||
| @@ -227,14 +226,14 @@ var Magnifier = class Magnifier { | ||||
|      * @return      true. | ||||
|      */ | ||||
|     scrollToMousePos() { | ||||
|         let [xMouse, yMouse, mask] = global.get_pointer(); | ||||
|         let [xMouse, yMouse] = global.get_pointer(); | ||||
|  | ||||
|         if (xMouse != this.xMouse || yMouse != this.yMouse) { | ||||
|             this.xMouse = xMouse; | ||||
|             this.yMouse = yMouse; | ||||
|  | ||||
|             let sysMouseOverAny = false; | ||||
|             this._zoomRegions.forEach((zoomRegion, index, array) => { | ||||
|             this._zoomRegions.forEach(zoomRegion => { | ||||
|                 if (zoomRegion.scrollToMousePos()) | ||||
|                     sysMouseOverAny = true; | ||||
|             }); | ||||
| @@ -332,7 +331,7 @@ var Magnifier = class Magnifier { | ||||
|         this.setCrosshairsClip(clip); | ||||
|  | ||||
|         let theCrossHairs = this._crossHairs; | ||||
|         this._zoomRegions.forEach ((zoomRegion, index, array) => { | ||||
|         this._zoomRegions.forEach (zoomRegion => { | ||||
|             zoomRegion.addCrosshairs(theCrossHairs); | ||||
|         }); | ||||
|     } | ||||
| @@ -360,7 +359,7 @@ var Magnifier = class Magnifier { | ||||
|      */ | ||||
|     setCrosshairsColor(color) { | ||||
|         if (this._crossHairs) { | ||||
|             let [res, clutterColor] = Clutter.Color.from_string(color); | ||||
|             let [res_, clutterColor] = Clutter.Color.from_string(color); | ||||
|             this._crossHairs.setColor(clutterColor); | ||||
|         } | ||||
|     } | ||||
| @@ -1515,7 +1514,7 @@ var ZoomRegion = class ZoomRegion { | ||||
|     } | ||||
|  | ||||
|     _centerFromPointProportional(xPoint, yPoint) { | ||||
|         let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI(); | ||||
|         let [xRoi_, yRoi_, widthRoi, heightRoi] = this.getROI(); | ||||
|         let halfScreenWidth = global.screen_width / 2; | ||||
|         let halfScreenHeight = global.screen_height / 2; | ||||
|         // We want to pad with a constant distance after zooming, so divide | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported ShellMagnifier */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const Main = imports.ui.main; | ||||
| @@ -124,7 +125,7 @@ var ShellMagnifier = class ShellMagnifier { | ||||
|         let zoomRegions = Main.magnifier.getZoomRegions(); | ||||
|         let objectPaths = []; | ||||
|         let thoseZoomers = this._zoomers; | ||||
|         zoomRegions.forEach ((aZoomRegion, index, array) => { | ||||
|         zoomRegions.forEach (aZoomRegion => { | ||||
|             let found = false; | ||||
|             for (let objectPath in thoseZoomers) { | ||||
|                 let proxyAndZoomRegion = thoseZoomers[objectPath]; | ||||
|   | ||||
| @@ -1,4 +1,12 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported componentManager, notificationDaemon, windowAttentionHandler, | ||||
|             ctrlAltTabManager, padOsdService, osdWindowManager, | ||||
|             osdMonitorLabeler, shellMountOpDBusService, shellDBusService, | ||||
|             shellAccessDialogDBusService, shellAudioSelectionDBusService, | ||||
|             screenSaverDBus, screencastService, uiGroup, magnifier, | ||||
|             xdndHandler, keyboard, kbdA11yDialog, introspectService, | ||||
|             start, pushModal, popModal, activateWindow, createLookingGlass, | ||||
|             initializeDeferredWork, getThemeStylesheet, setThemeStylesheet */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -46,6 +54,7 @@ const LOG_DOMAIN = 'GNOME Shell'; | ||||
| const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a'; | ||||
|  | ||||
| var componentManager = null; | ||||
| var extensionManager = null; | ||||
| var panel = null; | ||||
| var overview = null; | ||||
| var runDialog = null; | ||||
| @@ -226,7 +235,8 @@ function _initializeUI() { | ||||
|     _startDate = new Date(); | ||||
|  | ||||
|     ExtensionDownloader.init(); | ||||
|     ExtensionSystem.init(); | ||||
|     extensionManager = new ExtensionSystem.ExtensionManager(); | ||||
|     extensionManager.init(); | ||||
|  | ||||
|     if (sessionMode.isGreeter && screenShield) { | ||||
|         layoutManager.connect('startup-prepared', () => { | ||||
| @@ -656,7 +666,7 @@ function _queueBeforeRedraw(workId) { | ||||
|  * | ||||
|  * Returns: A string work identifier | ||||
|  */ | ||||
| function initializeDeferredWork(actor, callback, props) { | ||||
| function initializeDeferredWork(actor, callback) { | ||||
|     // Turn into a string so we can use as an object property | ||||
|     let workId = `${(++_deferredWorkSequence)}`; | ||||
|     _deferredWorkData[workId] = { 'actor': actor, | ||||
|   | ||||
| @@ -33,9 +33,7 @@ function _fixMarkup(text, allowMarkup) { | ||||
| } | ||||
|  | ||||
| var URLHighlighter = class URLHighlighter { | ||||
|     constructor(text, lineWrap, allowMarkup) { | ||||
|         if (!text) | ||||
|             text = ''; | ||||
|     constructor(text = '', lineWrap, allowMarkup) { | ||||
|         this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter', | ||||
|                                     x_expand: true, x_align: Clutter.ActorAlign.START }); | ||||
|         this._linkColor = '#ccccff'; | ||||
| @@ -132,12 +130,12 @@ var URLHighlighter = class URLHighlighter { | ||||
|     } | ||||
|  | ||||
|     _findUrlAtPos(event) { | ||||
|         let success; | ||||
|         let success_; | ||||
|         let [x, y] = event.get_coords(); | ||||
|         [success, x, y] = this.actor.transform_stage_point(x, y); | ||||
|         [success_, x, y] = this.actor.transform_stage_point(x, y); | ||||
|         let findPos = -1; | ||||
|         for (let i = 0; i < this.actor.clutter_text.text.length; i++) { | ||||
|             let [success, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i); | ||||
|             let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i); | ||||
|             if (py > y || py + lineHeight < y || x < px) | ||||
|                 continue; | ||||
|             findPos = i; | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported NotificationPolicy, NotificationGenericPolicy, | ||||
|    NotificationApplicationPolicy, Source, SourceActor, SourceActorWithLabel, | ||||
|    SystemNotificationSource, MessageTray */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -473,9 +476,7 @@ var Notification = class Notification { | ||||
|             this.destroy(); | ||||
|     } | ||||
|  | ||||
|     destroy(reason) { | ||||
|         if (!reason) | ||||
|             reason = NotificationDestroyedReason.DISMISSED; | ||||
|     destroy(reason = NotificationDestroyedReason.DISMISSED) { | ||||
|         this.emit('destroy', reason); | ||||
|     } | ||||
| }; | ||||
| @@ -652,7 +653,7 @@ class SourceActorWithLabel extends SourceActor { | ||||
|  | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
|  | ||||
|         let [minWidth, minHeight, naturalWidth, naturalHeight] = this._counterBin.get_preferred_size(); | ||||
|         let [, , naturalWidth, naturalHeight] = this._counterBin.get_preferred_size(); | ||||
|         let direction = this.get_text_direction(); | ||||
|  | ||||
|         if (direction == Clutter.TextDirection.LTR) { | ||||
| @@ -829,7 +830,7 @@ Signals.addSignalMethods(Source.prototype); | ||||
|  | ||||
| var MessageTray = class MessageTray { | ||||
|     constructor() { | ||||
|         this._presence = new GnomeSession.Presence((proxy, error) => { | ||||
|         this._presence = new GnomeSession.Presence((proxy, _error) => { | ||||
|             this._onStatusChanged(proxy.status); | ||||
|         }); | ||||
|         this._busy = false; | ||||
| @@ -1129,7 +1130,7 @@ var MessageTray = class MessageTray { | ||||
|             // this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us | ||||
|             // to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still | ||||
|             // close to its previous position, we extend the timeout once. | ||||
|             let [x, y, mods] = global.get_pointer(); | ||||
|             let [x, y] = global.get_pointer(); | ||||
|             this._notificationLeftMouseX = x; | ||||
|             this._notificationLeftMouseY = y; | ||||
|  | ||||
| @@ -1158,7 +1159,7 @@ var MessageTray = class MessageTray { | ||||
|     } | ||||
|  | ||||
|     _onNotificationLeftTimeout() { | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         // We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side. | ||||
|         if (this._notificationLeftMouseX > -1 && | ||||
|             y < this._notificationLeftMouseY + MOUSE_LEFT_ACTOR_THRESHOLD && | ||||
| @@ -1310,7 +1311,7 @@ var MessageTray = class MessageTray { | ||||
|         Meta.disable_unredirect_for_display(global.display); | ||||
|         this._updateShowingNotification(); | ||||
|  | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         // We save the position of the mouse at the time when we started showing the notification | ||||
|         // in order to determine if the notification popped up under it. We make that check if | ||||
|         // the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't | ||||
| @@ -1380,7 +1381,7 @@ var MessageTray = class MessageTray { | ||||
|     } | ||||
|  | ||||
|     _notificationTimeout() { | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         if (y < this._lastSeenMouseY - 10 && !this._notificationHovered) { | ||||
|             // The mouse is moving towards the notification, so don't | ||||
|             // hide it yet. (We just create a new timeout (and destroy | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported ModalDialog */ | ||||
|  | ||||
| const { Atk, Clutter, GObject, Shell, St } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported MediaSection */ | ||||
| const { Gio, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported NotificationDaemon */ | ||||
|  | ||||
| const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -64,7 +65,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { | ||||
|     _imageForNotificationData(hints) { | ||||
|         if (hints['image-data']) { | ||||
|             let [width, height, rowStride, hasAlpha, | ||||
|                  bitsPerSample, nChannels, data] = hints['image-data']; | ||||
|                  bitsPerSample, nChannels_, data] = hints['image-data']; | ||||
|             return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha, | ||||
|                                                       bitsPerSample, width, height, rowStride); | ||||
|         } else if (hints['image-path']) { | ||||
| @@ -259,7 +260,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { | ||||
|     } | ||||
|  | ||||
|     _notifyForSource(source, ndata) { | ||||
|         let [id, icon, summary, body, actions, hints, notification] = | ||||
|         let [id_, icon, summary, body, actions, hints, notification] = | ||||
|             [ndata.id, ndata.icon, ndata.summary, ndata.body, | ||||
|              ndata.actions, ndata.hints, ndata.notification]; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported OsdMonitorLabeler */ | ||||
|  | ||||
| const { Clutter, Gio, Meta, St } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported OsdWindowManager */ | ||||
|  | ||||
| const { Clutter, GLib, GObject, Meta, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -12,39 +13,6 @@ var HIDE_TIMEOUT = 1500; | ||||
| var FADE_TIME = 0.1; | ||||
| var LEVEL_ANIMATION_TIME = 0.1; | ||||
|  | ||||
| var LevelBar = class extends BarLevel.BarLevel { | ||||
|     constructor() { | ||||
|         super(0, { styleClass: 'level' }); | ||||
|  | ||||
|         this._level = 0; | ||||
|         this._maxLevel = 100; | ||||
|  | ||||
|         this.actor.accessible_name = _("Volume"); | ||||
|  | ||||
|         this.actor.connect('notify::width', () => this.level = this.level); | ||||
|     } | ||||
|  | ||||
|     get level() { | ||||
|         return this._level; | ||||
|     } | ||||
|  | ||||
|     set level(value) { | ||||
|         this._level = Math.max(0, Math.min(value, this._maxLevel)); | ||||
|  | ||||
|         this.setValue(this._level / 100); | ||||
|     } | ||||
|  | ||||
|     get maxLevel() { | ||||
|         return this._maxLevel; | ||||
|     } | ||||
|  | ||||
|     set maxLevel(value) { | ||||
|         this._maxLevel = Math.max(100, value); | ||||
|  | ||||
|         this.setMaximumValue(this._maxLevel / 100); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var OsdWindowConstraint = GObject.registerClass( | ||||
| class OsdWindowConstraint extends Clutter.Constraint { | ||||
|     _init(props) { | ||||
| @@ -98,7 +66,7 @@ var OsdWindow = class { | ||||
|         this._label = new St.Label(); | ||||
|         this._box.add(this._label); | ||||
|  | ||||
|         this._level = new LevelBar(); | ||||
|         this._level = new BarLevel.BarLevel(0, { styleClass: 'level' }); | ||||
|         this._box.add(this._level.actor); | ||||
|  | ||||
|         this._hideTimeoutId = 0; | ||||
| @@ -138,23 +106,21 @@ var OsdWindow = class { | ||||
|             this._label.text = label; | ||||
|     } | ||||
|  | ||||
|     setLevel(level) { | ||||
|         this._level.actor.visible = (level != undefined); | ||||
|         if (level != undefined) { | ||||
|     setLevel(value) { | ||||
|         this._level.actor.visible = (value != undefined); | ||||
|         if (value != undefined) { | ||||
|             if (this.actor.visible) | ||||
|                 Tweener.addTween(this._level, | ||||
|                                  { level: level, | ||||
|                                  { value: value, | ||||
|                                    time: LEVEL_ANIMATION_TIME, | ||||
|                                    transition: 'easeOutQuad' }); | ||||
|             else | ||||
|                 this._level.level = level; | ||||
|                 this._level.value = value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     setMaxLevel(maxLevel) { | ||||
|         if (maxLevel === undefined) | ||||
|             maxLevel = 100; | ||||
|         this._level.maxLevel = maxLevel; | ||||
|     setMaxLevel(maxLevel = 1) { | ||||
|         this._level.maximum_value = maxLevel; | ||||
|     } | ||||
|  | ||||
|     show() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Overview */ | ||||
|  | ||||
| const { Clutter, GLib, Meta, Shell, St } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -386,16 +387,16 @@ var Overview = class { | ||||
|         this.emit('windows-restacked', stackIndices); | ||||
|     } | ||||
|  | ||||
|     beginItemDrag(source) { | ||||
|     beginItemDrag(_source) { | ||||
|         this.emit('item-drag-begin'); | ||||
|         this._inItemDrag = true; | ||||
|     } | ||||
|  | ||||
|     cancelledItemDrag(source) { | ||||
|     cancelledItemDrag(_source) { | ||||
|         this.emit('item-drag-cancelled'); | ||||
|     } | ||||
|  | ||||
|     endItemDrag(source) { | ||||
|     endItemDrag(_source) { | ||||
|         if (!this._inItemDrag) | ||||
|             return; | ||||
|         this.emit('item-drag-end'); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported ControlsManager */ | ||||
|  | ||||
| const { Clutter, GObject, Meta, St } = imports.gi; | ||||
|  | ||||
| @@ -423,17 +424,6 @@ var ControlsManager = class { | ||||
|         layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this)); | ||||
|  | ||||
|         Main.overview.connect('showing', this._updateSpacerVisibility.bind(this)); | ||||
|         Main.overview.connect('item-drag-begin', () => { | ||||
|             let activePage = this.viewSelector.getActivePage(); | ||||
|             if (activePage != ViewSelector.ViewPage.WINDOWS) | ||||
|                 this.viewSelector.fadeHalf(); | ||||
|         }); | ||||
|         Main.overview.connect('item-drag-end', () => { | ||||
|             this.viewSelector.fadeIn(); | ||||
|         }); | ||||
|         Main.overview.connect('item-drag-cancelled', () => { | ||||
|             this.viewSelector.fadeIn(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _updateWorkspacesGeometry() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported PadOsdService */ | ||||
|  | ||||
| const { Atk, Clutter, GDesktopEnums, Gio, | ||||
|         GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi; | ||||
| @@ -295,7 +296,7 @@ var PadDiagram = GObject.registerClass({ | ||||
| }, class PadDiagram extends St.DrawingArea { | ||||
|     _init(params) { | ||||
|         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css'); | ||||
|         let [success, css, etag] = file.load_contents(null); | ||||
|         let [success_, css] = file.load_contents(null); | ||||
|         if (css instanceof Uint8Array) | ||||
|             css = imports.byteArray.toString(css); | ||||
|         this._curEdited = null; | ||||
| @@ -306,10 +307,12 @@ var PadDiagram = GObject.registerClass({ | ||||
|         super._init(params); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get left_handed() { | ||||
|         return this._leftHanded; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set left_handed(leftHanded) { | ||||
|         this._leftHanded = leftHanded; | ||||
|     } | ||||
| @@ -328,10 +331,12 @@ var PadDiagram = GObject.registerClass({ | ||||
|         this._handle = this._composeStyledDiagram(); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     get editor_actor() { | ||||
|         return this._editorActor; | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line camelcase | ||||
|     set editor_actor(actor) { | ||||
|         actor.hide(); | ||||
|         this._editorActor = actor; | ||||
| @@ -396,8 +401,8 @@ var PadDiagram = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _allocateChild(child, x, y, direction) { | ||||
|         let [prefHeight, natHeight] = child.get_preferred_height(-1); | ||||
|         let [prefWidth, natWidth] = child.get_preferred_width(natHeight); | ||||
|         let [, natHeight] = child.get_preferred_height(-1); | ||||
|         let [, natWidth] = child.get_preferred_width(natHeight); | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
|  | ||||
|         if (direction == LTR) { | ||||
| @@ -419,13 +424,13 @@ var PadDiagram = GObject.registerClass({ | ||||
|  | ||||
|         for (let i = 0; i < this._labels.length; i++) { | ||||
|             let [label, action, idx, dir] = this._labels[i]; | ||||
|             let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             this._allocateChild(label, x, y, arrangement); | ||||
|         } | ||||
|  | ||||
|         if (this._editorActor && this._curEdited) { | ||||
|             let [label, action, idx, dir] = this._curEdited; | ||||
|             let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             let [label_, action, idx, dir] = this._curEdited; | ||||
|             let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             this._allocateChild(this._editorActor, x, y, arrangement); | ||||
|         } | ||||
|     } | ||||
| @@ -561,7 +566,7 @@ var PadDiagram = GObject.registerClass({ | ||||
|         if (str != null) { | ||||
|             label.set_text(str); | ||||
|  | ||||
|             let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir); | ||||
|             this._allocateChild(label, x, y, arrangement); | ||||
|         } | ||||
|         label.show(); | ||||
| @@ -789,13 +794,13 @@ var PadOsd = class { | ||||
|         } else if (event.get_source_device() == this.padDevice && | ||||
|                    event.type() == Clutter.EventType.PAD_STRIP) { | ||||
|             if (this._editionMode) { | ||||
|                 let [retval, number, mode] = event.get_pad_event_details(); | ||||
|                 let [retval_, number, mode] = event.get_pad_event_details(); | ||||
|                 this._startStripActionEdition(number, UP, mode); | ||||
|             } | ||||
|         } else if (event.get_source_device() == this.padDevice && | ||||
|                    event.type() == Clutter.EventType.PAD_RING) { | ||||
|             if (this._editionMode) { | ||||
|                 let [retval, number, mode] = event.get_pad_event_details(); | ||||
|                 let [retval_, number, mode] = event.get_pad_event_details(); | ||||
|                 this._startRingActionEdition(number, CCW, mode); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported PageIndicators, AnimatedPageIndicators */ | ||||
|  | ||||
| const { Clutter, GObject, St } = imports.gi; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Panel */ | ||||
|  | ||||
| const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Cairo = imports.cairo; | ||||
| @@ -19,8 +20,6 @@ var APP_MENU_ICON_MARGIN = 0; | ||||
|  | ||||
| var BUTTON_DND_ACTIVATION_TIMEOUT = 250; | ||||
|  | ||||
| var SPINNER_ANIMATION_TIME = 1.0; | ||||
|  | ||||
| // To make sure the panel corners blend nicely with the panel, | ||||
| // we draw background and borders the same way, e.g. drawing | ||||
| // them as filled shapes from the outside inwards instead of | ||||
| @@ -203,7 +202,6 @@ var AppMenuButton = GObject.registerClass({ | ||||
|         this._busyNotifyId = 0; | ||||
|  | ||||
|         let bin = new St.Bin({ name: 'appMenu' }); | ||||
|         bin.connect('style-changed', this._onStyleChanged.bind(this)); | ||||
|         this.add_actor(bin); | ||||
|  | ||||
|         this.bind_property("reactive", this, "can-focus", 0); | ||||
| @@ -238,9 +236,8 @@ var AppMenuButton = GObject.registerClass({ | ||||
|         this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this)); | ||||
|         this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this)); | ||||
|  | ||||
|         this._stop = true; | ||||
|  | ||||
|         this._spinner = null; | ||||
|         this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true); | ||||
|         this._container.add_actor(this._spinner.actor); | ||||
|  | ||||
|         let menu = new AppMenu(this); | ||||
|         this.setMenu(menu); | ||||
| @@ -288,17 +285,6 @@ var AppMenuButton = GObject.registerClass({ | ||||
|                            } }); | ||||
|     } | ||||
|  | ||||
|     _onStyleChanged(actor) { | ||||
|         let node = actor.get_theme_node(); | ||||
|         let [success, icon] = node.lookup_url('spinner-image', false); | ||||
|         if (!success || (this._spinnerIcon && this._spinnerIcon.equal(icon))) | ||||
|             return; | ||||
|         this._spinnerIcon = icon; | ||||
|         this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE); | ||||
|         this._container.add_actor(this._spinner.actor); | ||||
|         this._spinner.actor.hide(); | ||||
|     } | ||||
|  | ||||
|     _syncIcon() { | ||||
|         if (!this._targetApp) | ||||
|             return; | ||||
| @@ -315,34 +301,11 @@ var AppMenuButton = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     stopAnimation() { | ||||
|         if (this._stop) | ||||
|             return; | ||||
|  | ||||
|         this._stop = true; | ||||
|  | ||||
|         if (this._spinner == null) | ||||
|             return; | ||||
|  | ||||
|         Tweener.addTween(this._spinner.actor, | ||||
|                          { opacity: 0, | ||||
|                            time: SPINNER_ANIMATION_TIME, | ||||
|                            transition: "easeOutQuad", | ||||
|                            onComplete: () => { | ||||
|                                this._spinner.stop(); | ||||
|                                this._spinner.actor.opacity = 255; | ||||
|                                this._spinner.actor.hide(); | ||||
|                            } | ||||
|                          }); | ||||
|         this._spinner.stop(); | ||||
|     } | ||||
|  | ||||
|     startAnimation() { | ||||
|         this._stop = false; | ||||
|  | ||||
|         if (this._spinner == null) | ||||
|             return; | ||||
|  | ||||
|         this._spinner.play(); | ||||
|         this._spinner.actor.show(); | ||||
|     } | ||||
|  | ||||
|     _onAppStateChanged(appSys, app) { | ||||
| @@ -484,14 +447,14 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|         this._xdndTimeOut = 0; | ||||
|     } | ||||
|  | ||||
|     handleDragOver(source, actor, x, y, time) { | ||||
|     handleDragOver(source, _actor, _x, _y, _time) { | ||||
|         if (source != Main.xdndHandler) | ||||
|             return DND.DragMotionResult.CONTINUE; | ||||
|  | ||||
|         if (this._xdndTimeOut != 0) | ||||
|             Mainloop.source_remove(this._xdndTimeOut); | ||||
|         this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, () => { | ||||
|             this._xdndToggleOverview(actor); | ||||
|             this._xdndToggleOverview(); | ||||
|         }); | ||||
|         GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview'); | ||||
|  | ||||
| @@ -527,8 +490,8 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _xdndToggleOverview(actor) { | ||||
|         let [x, y, mask] = global.get_pointer(); | ||||
|     _xdndToggleOverview() { | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); | ||||
|  | ||||
|         if (pickedActor == this && Main.overview.shouldToggleByCornerOrButton()) | ||||
| @@ -634,7 +597,7 @@ var PanelCorner = class { | ||||
|  | ||||
|             // Synchronize the locate button's pseudo classes with this corner | ||||
|             this._buttonStyleChangedSignalId = button.connect('style-changed', | ||||
|                 actor => { | ||||
|                 () => { | ||||
|                     let pseudoClass = button.get_style_pseudo_class(); | ||||
|                     this.actor.set_style_pseudo_class(pseudoClass); | ||||
|                 }); | ||||
| @@ -706,9 +669,7 @@ var PanelCorner = class { | ||||
|  | ||||
| var AggregateLayout = GObject.registerClass( | ||||
| class AggregateLayout extends Clutter.BoxLayout { | ||||
|     _init(params) { | ||||
|         if (!params) | ||||
|             params = {}; | ||||
|     _init(params = {}) { | ||||
|         params['orientation'] = Clutter.Orientation.VERTICAL; | ||||
|         super._init(params); | ||||
|  | ||||
| @@ -866,7 +827,7 @@ class Panel extends St.Widget { | ||||
|         this._updatePanel(); | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_width(forHeight) { | ||||
|     vfunc_get_preferred_width(_forHeight) { | ||||
|         let primaryMonitor = Main.layoutManager.primaryMonitor; | ||||
|  | ||||
|         if (primaryMonitor) | ||||
| @@ -881,9 +842,9 @@ class Panel extends St.Widget { | ||||
|         let allocWidth = box.x2 - box.x1; | ||||
|         let allocHeight = box.y2 - box.y1; | ||||
|  | ||||
|         let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1); | ||||
|         let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1); | ||||
|         let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1); | ||||
|         let [, leftNaturalWidth] = this._leftBox.get_preferred_width(-1); | ||||
|         let [, centerNaturalWidth] = this._centerBox.get_preferred_width(-1); | ||||
|         let [, rightNaturalWidth] = this._rightBox.get_preferred_width(-1); | ||||
|  | ||||
|         let sideWidth, centerWidth; | ||||
|         centerWidth = centerNaturalWidth; | ||||
| @@ -934,19 +895,18 @@ class Panel extends St.Widget { | ||||
|         } | ||||
|         this._rightBox.allocate(childBox, flags); | ||||
|  | ||||
|         let cornerMinWidth, cornerMinHeight; | ||||
|         let cornerWidth, cornerHeight; | ||||
|  | ||||
|         [cornerMinWidth, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1); | ||||
|         [cornerMinHeight, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1); | ||||
|         [, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1); | ||||
|         childBox.x1 = 0; | ||||
|         childBox.x2 = cornerWidth; | ||||
|         childBox.y1 = allocHeight; | ||||
|         childBox.y2 = allocHeight + cornerHeight; | ||||
|         this._leftCorner.actor.allocate(childBox, flags); | ||||
|  | ||||
|         [cornerMinWidth, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1); | ||||
|         [cornerMinHeight, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1); | ||||
|         [, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1); | ||||
|         childBox.x1 = allocWidth - cornerWidth; | ||||
|         childBox.x2 = allocWidth; | ||||
|         childBox.y1 = allocHeight; | ||||
| @@ -1167,7 +1127,7 @@ class Panel extends St.Widget { | ||||
|     } | ||||
|  | ||||
|     _onMenuSet(indicator) { | ||||
|         if (!indicator.menu || indicator.menu.hasOwnProperty('_openChangedId')) | ||||
|         if (!indicator.menu || indicator.menu._openChangedId) | ||||
|             return; | ||||
|  | ||||
|         indicator.menu._openChangedId = indicator.menu.connect('open-state-changed', | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Button, SystemIndicator */ | ||||
|  | ||||
| const { Atk, Clutter, GObject, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -33,7 +34,7 @@ class ButtonBox extends St.Widget { | ||||
|         this._natHPadding = themeNode.get_length('-natural-hpadding'); | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_width(forHeight) { | ||||
|     vfunc_get_preferred_width(_forHeight) { | ||||
|         let child = this.get_first_child(); | ||||
|         let minimumSize, naturalSize; | ||||
|  | ||||
| @@ -48,7 +49,7 @@ class ButtonBox extends St.Widget { | ||||
|         return [minimumSize, naturalSize]; | ||||
|     } | ||||
|  | ||||
|     vfunc_get_preferred_height(forWidth) { | ||||
|     vfunc_get_preferred_height(_forWidth) { | ||||
|         let child = this.get_first_child(); | ||||
|  | ||||
|         if (child) | ||||
| @@ -64,7 +65,7 @@ class ButtonBox extends St.Widget { | ||||
|         if (!child) | ||||
|             return; | ||||
|  | ||||
|         let [minWidth, natWidth] = child.get_preferred_width(-1); | ||||
|         let [, natWidth] = child.get_preferred_width(-1); | ||||
|  | ||||
|         let availWidth = box.x2 - box.x1; | ||||
|         let availHeight = box.y2 - box.y1; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* exported PointerA11yTimeout */ | ||||
| const { Clutter, GLib, GObject, Meta, St } = imports.gi; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Main = imports.ui.main; | ||||
| @@ -85,7 +86,7 @@ var PointerA11yTimeout = class PointerA11yTimeout { | ||||
|         Main.uiGroup.add_actor(pieTimer); | ||||
|  | ||||
|         manager.connect('ptr-a11y-timeout-started', (manager, device, type, timeout) => { | ||||
|             let [x, y, mods] = global.get_pointer(); | ||||
|             let [x, y] = global.get_pointer(); | ||||
|             pieTimer.start(x, y, timeout); | ||||
|             if (type == Clutter.PointerA11yTimeoutType.GESTURE) | ||||
|                 global.display.set_cursor(Meta.Cursor.CROSSHAIR); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported getPointerWatcher */ | ||||
|  | ||||
| const { GLib, Meta } = imports.gi; | ||||
| const Mainloop = imports.mainloop; | ||||
| @@ -72,13 +73,13 @@ var PointerWatcher = class { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _onIdleMonitorBecameActive(monitor) { | ||||
|     _onIdleMonitorBecameActive() { | ||||
|         this._idle = false; | ||||
|         this._updatePointer(); | ||||
|         this._updateTimeout(); | ||||
|     } | ||||
|  | ||||
|     _onIdleMonitorBecameIdle(monitor) { | ||||
|     _onIdleMonitorBecameIdle() { | ||||
|         this._idle = true; | ||||
|         this._idleMonitor.add_user_active_watch(this._onIdleMonitorBecameActive.bind(this)); | ||||
|         this._updateTimeout(); | ||||
| @@ -108,7 +109,7 @@ var PointerWatcher = class { | ||||
|     } | ||||
|  | ||||
|     _updatePointer() { | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         if (this.pointerX == x && this.pointerY == y) | ||||
|             return; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported PopupMenuItem, PopupSeparatorMenuItem, Switch, PopupSwitchMenuItem, | ||||
|             PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu, | ||||
|             PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */ | ||||
|  | ||||
| const { Atk, Clutter, Gio, GObject, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -122,7 +125,7 @@ var PopupBaseMenuItem = GObject.registerClass({ | ||||
|         this._parent = parent; | ||||
|     } | ||||
|  | ||||
|     _onButtonPressEvent(actor, event) { | ||||
|     _onButtonPressEvent() { | ||||
|         // This is the CSS active state | ||||
|         this.add_style_pseudo_class('active'); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
| @@ -571,7 +574,7 @@ var PopupMenuBase = class { | ||||
|                     menuItem.actor.grab_key_focus(); | ||||
|             } | ||||
|         }); | ||||
|         menuItem._activateId = menuItem.connect_after('activate', (menuItem, event) => { | ||||
|         menuItem._activateId = menuItem.connect_after('activate', (menuItem, _event) => { | ||||
|             this.emit('activate', menuItem); | ||||
|             this.itemActivated(BoxPointer.PopupAnimation.FULL); | ||||
|         }); | ||||
| @@ -958,7 +961,7 @@ var PopupSubMenu = class extends PopupMenuBase { | ||||
|  | ||||
|     _needsScrollbar() { | ||||
|         let topMenu = this._getTopMenu(); | ||||
|         let [topMinHeight, topNaturalHeight] = topMenu.actor.get_preferred_height(-1); | ||||
|         let [, topNaturalHeight] = topMenu.actor.get_preferred_height(-1); | ||||
|         let topThemeNode = topMenu.actor.get_theme_node(); | ||||
|  | ||||
|         let topMaxHeight = topThemeNode.get_max_height(); | ||||
| @@ -1008,7 +1011,7 @@ var PopupSubMenu = class extends PopupMenuBase { | ||||
|         let targetAngle = this.actor.text_direction == Clutter.TextDirection.RTL ? -90 : 90; | ||||
|  | ||||
|         if (animate) { | ||||
|             let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1); | ||||
|             let [, naturalHeight] = this.actor.get_preferred_height(-1); | ||||
|             this.actor.height = 0; | ||||
|             this.actor._arrowRotation = this._arrow.rotation_angle_z; | ||||
|             Tweener.addTween(this.actor, | ||||
| @@ -1193,11 +1196,11 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem { | ||||
|         return super._onKeyPressEvent(actor, event); | ||||
|     } | ||||
|  | ||||
|     activate(event) { | ||||
|     activate(_event) { | ||||
|         this._setOpenState(true); | ||||
|     } | ||||
|  | ||||
|     _onButtonReleaseEvent(actor) { | ||||
|     _onButtonReleaseEvent() { | ||||
|         // Since we override the parent, we need to manage what the parent does | ||||
|         // with the active style class | ||||
|         this.remove_style_pseudo_class('active'); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported loadRemoteSearchProviders */ | ||||
|  | ||||
| const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi; | ||||
|  | ||||
| @@ -221,7 +222,7 @@ var RemoteSearchProvider = class { | ||||
|             gicon = Gio.icon_new_for_string(meta['gicon']); | ||||
|         } else if (meta['icon-data']) { | ||||
|             let [width, height, rowStride, hasAlpha, | ||||
|                  bitsPerSample, nChannels, data] = meta['icon-data']; | ||||
|                  bitsPerSample, nChannels_, data] = meta['icon-data']; | ||||
|             gicon = Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha, | ||||
|                                                        bitsPerSample, width, height, rowStride); | ||||
|         } | ||||
| @@ -310,7 +311,7 @@ var RemoteSearchProvider = class { | ||||
|         this.proxy.ActivateResultRemote(id); | ||||
|     } | ||||
|  | ||||
|     launchSearch(terms) { | ||||
|     launchSearch(_terms) { | ||||
|         // the provider is not compatible with the new version of the interface, launch | ||||
|         // the app itself but warn so we can catch the error in logs | ||||
|         log(`Search provider ${this.appInfo.get_id()} does not implement LaunchSearch`); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Ripples */ | ||||
|  | ||||
| const { St } = imports.gi; | ||||
| const Tweener = imports.ui.tweener; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported RunDialog */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| @@ -239,7 +240,7 @@ class RunDialog extends ModalDialog.ModalDialog { | ||||
|         this._errorMessage.set_text(message); | ||||
|  | ||||
|         if (!this._errorBox.visible) { | ||||
|             let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1); | ||||
|             let [, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1); | ||||
|  | ||||
|             let parentActor = this._errorBox.get_parent(); | ||||
|             Tweener.addTween(parentActor, | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user