Compare commits

..

1 Commits

269 changed files with 23107 additions and 42579 deletions

View File

@ -1,5 +1,6 @@
stages: stages:
- review - review
- source_check
- build - build
- test - test
@ -25,27 +26,19 @@ check_commit_log:
js_check: js_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1 image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review stage: source_check
script: script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG - find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG) - (! grep -q . $JS_LOG)
<<: *only_default <<: *only_default
only:
changes:
- js/**/*
artifacts: artifacts:
paths: paths:
- ${JS_LOG} - ${JS_LOG}
when: on_failure 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: build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2 image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: build stage: build
@ -54,7 +47,7 @@ build:
- meson mutter mutter/build --prefix=/usr -Dtests=false - meson mutter mutter/build --prefix=/usr -Dtests=false
- ninja -C mutter/build install - ninja -C mutter/build install
script: script:
- meson . build -Dbuiltype=debugoptimized -Dman=false --werror - meson . build -Dbuiltype=debugoptimized
- ninja -C build - ninja -C build
- ninja -C build install - ninja -C build install
<<: *only_default <<: *only_default
@ -67,8 +60,6 @@ build:
test: test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2 image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: test stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
before_script: before_script:
- ninja -C mutter/build install - ninja -C mutter/build install
script: script:

View File

@ -1,7 +1,7 @@
FROM registry.fedoraproject.org/fedora:latest FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf -y upgrade && \ RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' git && \ dnf install -y 'dnf-command(copr)' && \
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'` # For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
dnf install -y findutils mozjs60-devel && \ dnf install -y findutils mozjs60-devel && \

View File

@ -1,105 +0,0 @@
#!/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
}
# Disable MR handling for now. We aren't ready to enforce
# non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
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
if ! is_empty $OUTPUT_FINAL; then
cat $OUTPUT_FINAL
exit 1
fi
# Just show the report and succeed when not testing a MR
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
exit 0
fi
copy_matched_lines $OUTPUT_REGULAR $LINE_CHANGES $OUTPUT_MR
cat $OUTPUT_MR
is_empty $OUTPUT_MR

View File

@ -84,6 +84,7 @@ don't use.
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util; const Util = imports.misc.util;
``` ```
The alphabetical ordering should be done independently of the location of the The alphabetical ordering should be done independently of the location of the
@ -276,49 +277,34 @@ If your usage of an object is like a hash table (and thus conceptually the keys
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42 can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
}`, `foo['bar']`. }`, `foo['bar']`.
## Animations ## Getters, setters, and Tweener
Most objects that are animated are actors, and most properties used in animations
are animatable, which means they can use implicit animations:
Getters and setters should be used when you are dealing with an API that is
designed around setting properties, like Tweener. If you want to animate an
arbitrary property, create a getter and setter, and use Tweener to animate the
property.
```javascript ```javascript
moveActor(actor, x, y) { var ANIMATION_TIME = 2000;
actor.ease({
x, var MyClass = class {
y, constructor() {
duration: 500, // ms this.actor = new St.BoxLayout();
mode: Clutter.AnimationMode.EASE_OUT_QUAD this._position = 0;
}); }
}
``` get position() {
return this._position;
The above is a convenience wrapper around the actual Clutter API, and should generally }
be preferred over the more verbose:
set position(value) {
```javascript this._position = value;
moveActor(actor, x, y) { this.actor.set_position(value, value);
actor.save_easing_state(); }
};
actor.set_easing_duration(500);
actor.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD); let myThing = new MyClass();
actor.set({ Tweener.addTween(myThing,
x, { position: 100,
y time: ANIMATION_TIME,
}); transition: 'easeOutQuad' });
actor.restore_easing_state();
}
```
There is a similar convenience API around Clutter.PropertyTransition to animate
actor (or actor meta) properties that cannot use implicit animations:
```javascript
desaturateActor(actor, desaturate) {
let factor = desaturate ? 1.0 : 0.0;
actor.ease_property('@effects.desaturate.factor', factor, {
duration: 500, // ms
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
``` ```

151
NEWS
View File

@ -1,154 +1,3 @@
3.35.1
======
* Misc. bug fixes and cleanups [Marco; Matthias; !758, #701212]
Contributors:
Marco Trevisan (Treviño)
3.34.1
======
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
* Allow editing app folder names [Georges, Marco; !675, !720]
* Skip property transitions while hidden [Florian; !708]
* Make menu animations more consistent [Florian, GB_2; #1595, !717]
* Improve performance when enabling/disabling all extensions [Jonas D.; !96]
* Fix extra icons appearing in "Frequent" view animation [Georges; !696]
* Fix fading out desktop icons [Harshula; #1616]
* Fix box-shadow glitch with prerendered resources [Daniel; #1186]
* Fix accidentally skipped animations [Florian; #1572]
* Fix screenshots and window animations when scaled [Robert; !728]
* Don't leak NOTIFY_SOCKET environment variable to applications [Benjamin; !741]
* Fix lock-up on X11 when ibus is already running on startup [Marco; #1712]
* Fix screen dimming on idle [Marco; #1683]
* Do not notify systemd before initialization is complete [Iain; !750]
* Support SAE secrets in network agent [Lubomir; !751]
* Fix various regressions with dynamic workspaces [Florian; #1497]
* Fixed crashes [Florian, Marco; #1678, !746]
* Misc. bug fixes and cleanups [Marco, Jonas D., Florian, Iain, Georges,
Jonas Å., Martin, Takao, Carlos; !700, !705, !709, !711, !707, #1538, !710,
!713, !699, !715, !718, !716, !719, !721, #1243, !725, !731, #1614, !683,
!732, !121, !735, !736, !740, #573, #1641, #1571]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Jonas Dreßler, Takao Fujiwara, GB_2,
Carlos Garnacho, Harshula Jayasuriya, Iain Lane, Robert Mader,
Daniel García Moreno, Florian Müllner, Georges Basile Stavracas Neto,
Lubomir Rintel, Martin Zurowietz, Jonas Ådahl
Translators:
Rafael Fontenelle [pt_BR], Fran Dieguez [gl], Balázs Úr [hu],
Milo Casagrande [it], Daniel Șerbănescu [ro], Kukuh Syafaat [id],
Jiri Grönroos [fi], Daniel Mustieles [es], Piotr Drąg [pl],
Anders Jonsson [sv], Marek Černocký [cs], Jordi Mas [ca],
Aurimas Černius [lt], Christian Kirbach [de], Emin Tufan Çetin [tr],
Enrico Nicoletto [pt_BR], Danial Behzadi [fa], Марко Костић [sr],
Alexandre Franke [fr], Charles Monzat [fr], Kjartan Maraas [nb],
Ryuta Fujii [ja], Nathan Follens [nl], Dušan Kazik [sk], Fabio Tomat [fur],
Matej Urbančič [sl], Ask Hjorth Larsen [da], Alan Mortensen [da]
3.34.0
======
* Handle startup/shutdown of misc X11 services [Carlos; !680]
* Fix sound volume mute/unmute [Iain; #1557]
* Correctly terminate pasted text [Carlos; #1570]
Contributors:
Carlos Garnacho, Iain Lane
Translators:
Tom Tryfonidis [el], Milo Casagrande [it], Ryuta Fujii [ja],
Efstathios Iosifidis [el], Carmen Bianca BAKKER [eo], Sabri Ünal [tr],
Dušan Kazik [sk], Balázs Meskó [hu], Claude Paroz [fr]
3.33.92
=======
* Animate pointer a11y pie timer [Jonas D.; !688]
* Fix restarting shell in systemd user session [Benjamin; !690]
* Misc. bug fixes and cleanups [Florian, Jonas D., Jonas Å., Will;
!691, !689, !692, #1552, !698]
Contributors:
Jonas Ådahl, Benjamin Berg, Piotr Drąg, Jonas Dreßler, Florian Müllner,
Will Thompson
Translators:
Daniel Șerbănescu [ro], Danial Behzadi [fa], Daniel Mustieles [es],
Jiri Grönroos [fi], Asier Sarasua Garmendia [eu], Piotr Drąg [pl],
Rūdolfs Mazurs [lv], Anders Jonsson [sv], Fran Dieguez [gl], Jordi Mas [ca],
Matej Urbančič [sl], Zander Brown [en_GB], Ryuta Fujii [ja], Tim Sabsch [de],
Fabio Tomat [fur], Pawan Chitrakar [ne], A S Alam [pa], Changwoo Ryu [ko],
Aurimas Černius [lt], Daniel Rusek [cs], Marek Černocký [cs],
Kukuh Syafaat [id], Goran Vidović [hr], Rafael Fontenelle [pt_BR]
3.33.91
=======
* Fix regression when adjusting brightness [Florian; #1500]
* Fix pointer a11y timeout animation [Jonas D.; #1533]
* Add new extensions CLI tool [Florian; #1234]
* Only track top-level windows [Carlos; #556]
* Misc. bug fixes and cleanups [Jonas D., Jonas Å., Piotr, Florian;
!678, !682, !686]
Contributors:
Jonas Ådahl, Jonas Dreßler, Carlos Garnacho, Florian Müllner
Translators:
Asier Sarasua Garmendia [eu], Sveinn í Felli [is], Anders Jonsson [sv],
Jordi Mas [ca], Kukuh Syafaat [id], Florentina Mușat [ro], Jiri Grönroos [fi],
Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl],
Danial Behzadi [fa]
3.33.90
=======
* Implement DND app picker folder management [Georges; !643, !645, !664, !671]
* Make Clocks/Weather integration work with sandboxed apps [Florian; #1158]
* Support startup via systemd user instance [Benjamin; !507]
* Replace Tweener with Clutter animations [Florian; !663, !22, !666, !668, !669]
* Minimize travel distance in overview animation [Sergey; !267]
* Rescan icon theme when installed apps changed [Georges; !661]
* Consistently animate new window actions [Jonas; !662, !673]
* Misc. bug fixes and cleanups [Florian, Daniel, Ray, Bastien, Jonas, Niels,
Marco, Georges; !635, !636, !637, #1462, !628, !640, !641, !627, !644, !647,
!385, #1474, !651, #1144, !646, !653, !652, !655, #1482, !656, $654, !665,
!667, !670, #1357, !672, !657, #1507, !674, !677]
Contributors:
Benjamin Berg, Sergey Bugaev, Jonas Dreßler, Niels De Graef, Florian Müllner,
Georges Basile Stavracas Neto, Bastien Nocera, Ray Strode,
Marco Trevisan (Treviño), verdre, Daniel van Vugt
Translators:
Asier Sarasua Garmendia [eu], Rafael Fontenelle [pt_BR],
Kristjan SCHMIDT [eo], Jor Teron [mjw], Daniel Mustieles [es],
Kukuh Syafaat [id], Jordi Mas [ca], Fabio Tomat [fur], Daniel Șerbănescu [ro],
Anders Jonsson [sv]
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 3.33.3
====== ======
* Prepare for optional X11 [Carlos; !378] * Prepare for optional X11 [Carlos; !378]

View File

@ -1,15 +0,0 @@
<node>
<!--
org.gnome.Shell.ClocksIntegration:
@short_description: Clocks integration interface
The interface used for exporting location settings to GNOME Shell's
world clocks integration.
-->
<interface name="org.gnome.Shell.ClocksIntegration">
<property name="Locations" type="av" access="read"/>
</interface>
</node>

View File

@ -173,30 +173,6 @@
<arg type="s" direction="in" name="uuid"/> <arg type="s" direction="in" name="uuid"/>
</method> </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: LaunchExtensionPrefs:
@uuid: The UUID of the extension @uuid: The UUID of the extension
@ -213,15 +189,6 @@
--> -->
<method name="CheckForUpdates"/> <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"> <signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/> <arg type="s" name="uuid"/>
<arg type="i" name="state"/> <arg type="i" name="state"/>

View File

@ -1,16 +0,0 @@
<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>

View File

@ -40,7 +40,6 @@
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file> <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.ClocksIntegration.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>
@ -49,7 +48,6 @@
<file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file> <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.Screenshot.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.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.gnome.Shell.xml</file>
<file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file> <file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file>
<file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file> <file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file>

View File

@ -1,14 +0,0 @@
[Unit]
Description=Disable GNOME Shell extensions after failure
DefaultDependencies=no
# Only disable extensions for a short period of time after login.
# This means we err on the side of failing the first login after a broken
# extension was installed.
Requisite=gnome-session-stable.timer
[Service]
Type=simple
# Disable extensions
ExecStart=gsettings set org.gnome.shell disable-user-extensions true
Restart=no

View File

@ -1,27 +0,0 @@
[Unit]
Description=GNOME Shell on Wayland
# On wayland, force a session shutdown
OnFailure=gnome-shell-disable-extensions.service gnome-session-shutdown.target
OnFailureJobMode=replace-irreversibly
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-x11.service
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On wayland we cannot restart
Restart=no
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@ -1,10 +1,5 @@
[Unit] [Unit]
Description=GNOME Shell on Wayland Description=GNOME Shell (wayland sync point)
DefaultDependencies=no After=gnome-shell.service
BindsTo=gnome-shell.service
Requisite=gnome-session-initialized.target Conflicts=gnome-shell-x11.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-wayland.service
After=gnome-shell-wayland.service

View File

@ -1,33 +0,0 @@
[Unit]
Description=GNOME Shell on X11
# On X11, try to show the GNOME Session Failed screen
OnFailure=gnome-shell-disable-extensions.service gnome-session-failed.target
OnFailureJobMode=replace
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-wayland.service
# Limit startup frequency more than the default
StartLimitIntervalSec=15s
StartLimitBurst=3
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On X11 we want to restart on-success (Alt+F2 + r) and on-failure.
Restart=always
# Do not wait before restarting the shell
RestartSec=0ms
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@ -1,10 +1,5 @@
[Unit] [Unit]
Description=GNOME Shell on X11 Description=GNOME Shell (x11 sync point)
DefaultDependencies=no After=gnome-shell.service
BindsTo=gnome-shell.service
Requisite=gnome-session-initialized.target Conflicts=gnome-shell-wayland.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-x11.service
After=gnome-shell-x11.service

View File

@ -0,0 +1,11 @@
[Unit]
Description=GNOME Shell
Wants=gnome-session.service
After=graphical-session-pre.target gnome-session-bus.target
PartOf=graphical-session.target
[Service]
Type=dbus
ExecStart=@bindir@/gnome-shell
Restart=on-failure
BusName=org.gnome.Shell

View File

@ -14,8 +14,6 @@ desktopconf = configuration_data()
# file when built in a non-system prefix # file when built in a non-system prefix
desktopconf.set('bindir', bindir) desktopconf.set('bindir', bindir)
desktopconf.set('VERSION', meson.project_version()) desktopconf.set('VERSION', meson.project_version())
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files foreach desktop_file : desktop_files
i18n.merge_file('desktop', i18n.merge_file('desktop',
input: configure_file( input: configure_file(
@ -24,7 +22,7 @@ foreach desktop_file : desktop_files
configuration: desktopconf configuration: desktopconf
), ),
output: desktop_file, output: desktop_file,
po_dir: po_dir, po_dir: '../po',
install: true, install: true,
install_dir: desktopdir, install_dir: desktopdir,
type: 'desktop' type: 'desktop'
@ -100,23 +98,15 @@ if have_systemd
unitconf = configuration_data() unitconf = configuration_data()
unitconf.set('bindir', bindir) unitconf.set('bindir', bindir)
configure_file( unit = configure_file(
input: 'gnome-shell-x11.service.in', input: 'gnome-shell.service.in',
output: 'gnome-shell-x11.service', output: 'gnome-shell.service',
configuration: unitconf, configuration: unitconf,
install_dir: systemduserunitdir install_dir: systemduserunitdir
) )
configure_file( units = files('gnome-shell-wayland.target',
input: 'gnome-shell-wayland.service.in', 'gnome-shell-x11.target')
output: 'gnome-shell-wayland.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-x11.target',
'gnome-shell-wayland.target',
'gnome-shell-disable-extensions.service')
install_data(units, install_dir: systemduserunitdir) install_data(units, install_dir: systemduserunitdir)
endif endif

View File

@ -14,4 +14,3 @@ X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Provides=panel;windowmanager; X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false X-GNOME-AutoRestart=false
X-GNOME-HiddenUnderSystemd=@systemd_hidden@

View File

@ -21,17 +21,6 @@
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
</description> </description>
</key> </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"> <key name="disable-user-extensions" type="b">
<default>false</default> <default>false</default>
<summary>Disable user extensions</summary> <summary>Disable user extensions</summary>
@ -150,6 +139,11 @@
Keybinding to focus the active notification. Keybinding to focus the active notification.
</description> </description>
</key> </key>
<key name="pause-resume-tweens" type="as">
<default>[]</default>
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<description></description>
</key>
<key name="switch-to-application-1" type="as"> <key name="switch-to-application-1" type="as">
<default>["&lt;Super&gt;1"]</default> <default>["&lt;Super&gt;1"]</default>
<summary>Switch to application 1</summary> <summary>Switch to application 1</summary>
@ -228,36 +222,6 @@
</key> </key>
</schema> </schema>
<schema id="org.gnome.shell.world-clocks" path="/org/gnome/shell/world-clocks/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="locations" type="av">
<summary>Locations</summary>
<description>
The locations to show in world clocks
</description>
<default>[]</default>
</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 --> <!-- unused, change 00_org.gnome.shell.gschema.override instead -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/" <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">

View File

@ -610,13 +610,6 @@ StScrollBar {
border-bottom-style: solid; border-bottom-style: solid;
} }
// Rename popup
.rename-folder-popup {
.rename-folder-popup-item {
spacing: 6px;
&:ltr, &:rtl { padding: 0, 12px; }
}
}
// Background menu // Background menu
.background-menu { -boxpointer-gap: 4px; -arrow-rise: 0px; } .background-menu { -boxpointer-gap: 4px; -arrow-rise: 0px; }
@ -631,12 +624,16 @@ StScrollBar {
*************/ *************/
/* Outline for low res icons */ /* Outline for low res icons */
.lowres-icon { .lowres-icon {
icon-shadow: 0 1px 2px rgba(0,0,0,0.3); icon-shadow: 0 -1px rgba(0,0,0,0.05),
1px 0 rgba(0,0,0,0.1),
0 1px rgba(0,0,0,0.3),
-1px 0 rgba(0,0,0,0.1);
} }
/* Drapshadow for large icons */ /* Drapshadow for large icons */
.icon-dropshadow { .icon-dropshadow {
icon-shadow: 0 1px 2px rgba(0,0,0,0.4); icon-shadow: 0 2px 12px rgba(0,0,0,0.1),
0 1px 2px rgba(0,0,0,0.5);
} }
/* OSD */ /* OSD */
@ -747,9 +744,8 @@ StScrollBar {
spacing: 8px; 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;
height: 52px;
background-color: $selected_bg_color; background-color: $selected_bg_color;
color: $selected_fg_color; color: $selected_fg_color;
background-size: 32px; background-size: 32px;
@ -949,7 +945,7 @@ StScrollBar {
.world-clocks-button, .world-clocks-button,
.weather-button, .weather-button,
.events-section-title { .events-section-title {
&:hover, &:focus { background-color: $_hover_bg_color } &:hover, focus { background-color: $_hover_bg_color }
&:active { background-color: $_active_bg_color } &:active { background-color: $_active_bg_color }
} }
@ -1020,7 +1016,7 @@ StScrollBar {
background-color: transparent; background-color: transparent;
width: 32px; width: 32px;
border-radius: 4px; 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); } &:active { background-color: transparentize($fg_color, 0.84); }
} }
@ -1036,7 +1032,7 @@ StScrollBar {
margin: 2px; margin: 2px;
border-radius: 1.4em; border-radius: 1.4em;
font-feature-settings: "tnum"; font-feature-settings: "tnum";
&:hover, &:focus { background-color: $_hover_bg_color; } &:hover, focus { background-color: $_hover_bg_color; }
&:active,&:selected { &:active,&:selected {
color: lighten($selected_fg_color,5%); color: lighten($selected_fg_color,5%);
background-color: $selected_bg_color; background-color: $selected_bg_color;
@ -1178,6 +1174,7 @@ StScrollBar {
// a little unstructured mess: // a little unstructured mess:
#appMenu { #appMenu {
spinner-image: url("resource:///org/gnome/shell/theme/process-working.svg");
spacing: 4px; spacing: 4px;
.label-shadow { color: transparent; } .label-shadow { color: transparent; }
@ -1521,9 +1518,6 @@ StScrollBar {
border-image: none; border-image: none;
background-image: none; background-image: none;
} }
&:drop .overview-icon {
background-color: transparentize($selected_bg_color,.15);
}
&:active .overview-icon, &:active .overview-icon,
&:checked .overview-icon { &:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5); background-color: transparentize(darken($osd_bg_color,10%), 0.5);

View File

@ -28,7 +28,7 @@ foreach iface : ifaces
output: 'doc-gen-' + iface[1], output: 'doc-gen-' + iface[1],
command: [ command: [
'gdbus-codegen', 'gdbus-codegen',
'--interface-prefix=@0@.'.format(iface[0]), '--interface-prefix=@0@.'.format(iface),
'--generate-docbook', 'doc-gen', '--generate-docbook', 'doc-gen',
'--output-directory', '@OUTDIR@', '--output-directory', '@OUTDIR@',
'@INPUT@' '@INPUT@'

View File

@ -1,7 +1,3 @@
/* exported main */
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext; const Gettext = imports.gettext;
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi; const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
const Format = imports.format; const Format = imports.format;
@ -12,8 +8,6 @@ const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions'); const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -23,54 +17,74 @@ function stripPrefix(string, prefix) {
return string; return string;
} }
var Application = GObject.registerClass({ var Application = class {
GTypeName: 'ExtensionPrefs_Application' constructor() {
}, class Application extends Gtk.Application {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs'); GLib.set_prgname('gnome-shell-extension-prefs');
super._init({ this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs', application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE 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._startupUuid = null;
this._loaded = false; this._loaded = false;
this._skipMainWindow = false; this._skipMainWindow = false;
this._shellProxy = null;
} }
get shellProxy() { _extensionAvailable(uuid) {
return this._shellProxy; let extension = ExtensionUtils.extensions[uuid];
}
_showPrefs(uuid) { if (!extension)
let row = this._extensionSelector.get_children().find(c => {
return c.uuid === uuid && c.hasPrefs;
});
if (!row)
return false; 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; let widget;
try { try {
widget = row.prefsModule.buildPrefsWidget(); let prefsModule = this._getExtensionPrefsModule(extension);
widget = prefsModule.buildPrefsWidget();
} catch (e) { } catch (e) {
widget = this._buildErrorUI(row, e); widget = this._buildErrorUI(extension, e);
} }
let dialog = new Gtk.Window({ let dialog = new Gtk.Window({ modal: !this._skipMainWindow,
modal: !this._skipMainWindow, type_hint: Gdk.WindowTypeHint.DIALOG });
type_hint: Gdk.WindowTypeHint.DIALOG dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true,
}); title: extension.metadata.name,
dialog.set_titlebar(new Gtk.HeaderBar({ visible: true }));
show_close_button: true,
title: row.name,
visible: true
}));
if (this._skipMainWindow) { if (this._skipMainWindow) {
this.add_window(dialog); this.application.add_window(dialog);
if (this._window) if (this._window)
this._window.destroy(); this._window.destroy();
this._window = dialog; this._window = dialog;
@ -82,11 +96,9 @@ var Application = GObject.registerClass({
dialog.set_default_size(600, 400); dialog.set_default_size(600, 400);
dialog.add(widget); dialog.add(widget);
dialog.show(); dialog.show();
return true;
} }
_buildErrorUI(row, exc) { _buildErrorUI(extension, exc) {
let scroll = new Gtk.ScrolledWindow({ let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER, hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true propagate_natural_height: true
@ -158,7 +170,7 @@ var Application = GObject.registerClass({
let clipboard = Gtk.Clipboard.get_default(w.get_display()); let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues // markdown for pasting in gitlab issues
let lines = [ let lines = [
`The settings of extension ${row.uuid} had an error:`, `The settings of extension ${extension.uuid} had an error:`,
'```', '```',
`${exc}`, `${exc}`,
'```', '```',
@ -180,13 +192,13 @@ var Application = GObject.registerClass({
label: _("Homepage"), label: _("Homepage"),
tooltip_text: _("Visit extension homepage"), tooltip_text: _("Visit extension homepage"),
no_show_all: true, no_show_all: true,
visible: row.url != null visible: extension.metadata.url != null
}); });
toolbar.add(urlButton); toolbar.add(urlButton);
urlButton.connect('clicked', w => { urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context(); let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(row.url, context); Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context);
}); });
let expandedBox = new Gtk.Box({ let expandedBox = new Gtk.Box({
@ -201,8 +213,8 @@ var Application = GObject.registerClass({
return scroll; return scroll;
} }
_buildUI() { _buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: this, this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER }); window_position: Gtk.WindowPosition.CENTER });
this._window.set_default_size(800, 500); this._window.set_default_size(800, 500);
@ -236,14 +248,18 @@ var Application = GObject.registerClass({
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder'); this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStateChanged', this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
this._onExtensionStateChanged.bind(this)); if (ExtensionUtils.extensions[uuid] !== undefined)
this._scanExtensions();
});
this._window.show_all(); this._window.show_all();
} }
_sortList(row1, row2) { _sortList(row1, row2) {
return row1.name.localeCompare(row2.name); let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
} }
_updateHeader(row, before) { _updateHeader(row, before) {
@ -254,56 +270,19 @@ var Application = GObject.registerClass({
row.set_header(sep); row.set_header(sep);
} }
_findExtensionRow(uuid) {
return this._extensionSelector.get_children().find(c => c.uuid === 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() { _scanExtensions() {
this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => { let finder = new ExtensionUtils.ExtensionFinder();
if (e) { finder.connect('extension-found', this._extensionFound.bind(this));
if (e instanceof Gio.DBusError) { finder.scanExtensions();
log(`Failed to connect to shell proxy: ${e}`); this._extensionsLoaded();
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) { _extensionFound(finder, extension) {
let row = new ExtensionRow(extension); let row = new ExtensionRow(extension.uuid);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', () => { row.prefsButton.connect('clicked', () => {
this._showPrefs(row.uuid); this._selectExtension(row.uuid);
}); });
row.show_all(); row.show_all();
@ -316,26 +295,24 @@ var Application = GObject.registerClass({
else else
this._mainStack.visible_child_name = 'placeholder'; this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid) if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._showPrefs(this._startupUuid); this._selectExtension(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false; this._skipMainWindow = false;
this._loaded = true; this._loaded = true;
} }
vfunc_activate() { _onActivate() {
this._window.present(); this._window.present();
} }
vfunc_startup() { _onStartup(app) {
super.vfunc_startup(); this._buildUI(app);
this._buildUI();
this._scanExtensions(); this._scanExtensions();
} }
vfunc_command_line(commandLine) { _onCommandLine(app, commandLine) {
this.activate(); app.activate();
let args = commandLine.get_arguments(); let args = commandLine.get_arguments();
if (args.length) { if (args.length) {
@ -346,14 +323,16 @@ var Application = GObject.registerClass({
// Strip off "extension:///" prefix which fakes a URI, if it exists // Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///"); uuid = stripPrefix(uuid, "extension:///");
if (!this._loaded) if (this._extensionAvailable(uuid))
this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid; this._startupUuid = uuid;
else if (!this._showPrefs(uuid)) else
this._skipMainWindow = false; this._skipMainWindow = false;
} }
return 0; return 0;
} }
}); };
var Expander = GObject.registerClass({ var Expander = GObject.registerClass({
Properties: { Properties: {
@ -520,35 +499,6 @@ 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(
_("Somethings gone wrong")),
use_markup: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again."),
justify: Gtk.Justification.CENTER,
wrap: true
});
this.add(label);
this.show_all();
}
});
var DescriptionLabel = GObject.registerClass( var DescriptionLabel = GObject.registerClass(
class DescriptionLabel extends Gtk.Label { class DescriptionLabel extends Gtk.Label {
vfunc_get_preferred_height_for_width(width) { vfunc_get_preferred_height_for_width(width) {
@ -561,59 +511,30 @@ class DescriptionLabel extends Gtk.Label {
var ExtensionRow = GObject.registerClass( var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow { class ExtensionRow extends Gtk.ListBoxRow {
_init(extension) { _init(uuid) {
super._init(); super._init();
this._app = Gio.Application.get_default(); this.uuid = uuid;
this._extension = extension;
this._prefsModule = null;
this.connect('destroy', this._onDestroy.bind(this)); 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._buildUI(); this._buildUI();
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);
GObject.signal_handler_block(this._switch, this._notifyActiveId);
this._switch.state = state;
GObject.signal_handler_unblock(this._switch, this._notifyActiveId);
this._switch.sensitive = this._canToggle();
});
}
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() { _buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin_end: 24, spacing: 24, hexpand: true, margin_end: 24, spacing: 24,
margin: 12 }); margin: 12 });
@ -623,20 +544,19 @@ class ExtensionRow extends Gtk.ListBoxRow {
spacing: 6, hexpand: true }); spacing: 6, hexpand: true });
hbox.add(vbox); hbox.add(vbox);
let name = GLib.markup_escape_text(this.name, -1); let name = GLib.markup_escape_text(extension.metadata.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>', let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true, use_markup: true,
halign: Gtk.Align.START }); halign: Gtk.Align.START });
vbox.add(label); vbox.add(label);
let desc = this._extension.metadata.description.split('\n')[0]; let desc = extension.metadata.description.split('\n')[0];
label = new DescriptionLabel({ label: desc, wrap: true, lines: 2, label = new DescriptionLabel({ label: desc, wrap: true, lines: 2,
ellipsize: Pango.EllipsizeMode.END, ellipsize: Pango.EllipsizeMode.END,
xalign: 0, yalign: 0 }); xalign: 0, yalign: 0 });
vbox.add(label); vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER, let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
visible: this.hasPrefs,
no_show_all: true }); no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic', button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON, icon_size: Gtk.IconSize.BUTTON,
@ -646,37 +566,51 @@ class ExtensionRow extends Gtk.ListBoxRow {
this.prefsButton = button; this.prefsButton = button;
this._switch = new Gtk.Switch({ this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER, sensitive: this._canEnable(),
sensitive: this._canToggle(), state: this._isEnabled() });
state: this._extension.state === ExtensionState.ENABLED this._switch.connect('notify::active', () => {
});
this._notifyActiveId = this._switch.connect('notify::active', () => {
if (this._switch.active) if (this._switch.active)
this._app.shellProxy.EnableExtensionRemote(this.uuid); this._enable();
else else
this._app.shellProxy.DisableExtensionRemote(this.uuid); this._disable();
}); });
this._switch.connect('state-set', () => true); this._switch.connect('state-set', () => true);
hbox.add(this._switch); hbox.add(this._switch);
} }
_canToggle() { _canEnable() {
return this._extension.canChange; 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));
} }
get prefsModule() { _isEnabled() {
if (!this._prefsModule) { let extensions = this._settings.get_strv('enabled-extensions');
ExtensionUtils.installImporter(this._extension); return extensions.includes(this.uuid);
}
// give extension prefs access to their own extension object _enable() {
ExtensionUtils.getCurrentExtension = () => this._extension; let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.includes(this.uuid))
return;
this._prefsModule = this._extension.imports.prefs; extensions.push(this.uuid);
this._prefsModule.init(this._extension.metadata); this._settings.set_strv('enabled-extensions', extensions);
} }
return this._prefsModule; _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);
} }
}); });
@ -704,5 +638,6 @@ function main(argv) {
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Gettext.textdomain(Config.GETTEXT_PACKAGE); Gettext.textdomain(Config.GETTEXT_PACKAGE);
new Application().run(argv); let app = new Application();
app.application.run(argv);
} }

View File

@ -8,13 +8,14 @@ const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
var DEFAULT_BUTTON_WELL_ICON_SIZE = 16; var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000; var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300; var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500; var MESSAGE_FADE_OUT_ANIMATION_TIME = 0.5;
var AuthPromptMode = { var AuthPromptMode = {
UNLOCK_ONLY: 0, UNLOCK_ONLY: 0,
@ -266,7 +267,7 @@ var AuthPrompt = class {
let oldActor = this._defaultButtonWellActor; let oldActor = this._defaultButtonWellActor;
if (oldActor) if (oldActor)
oldActor.remove_all_transitions(); Tweener.removeTweens(oldActor);
let wasSpinner; let wasSpinner;
if (oldActor == this._spinner.actor) if (oldActor == this._spinner.actor)
@ -289,18 +290,18 @@ var AuthPrompt = class {
this._spinner.stop(); this._spinner.stop();
} }
} else { } else {
oldActor.ease({ Tweener.addTween(oldActor,
opacity: 0, { opacity: 0,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
onComplete: () => { onComplete: () => {
if (wasSpinner) { if (wasSpinner) {
if (this._spinner) if (this._spinner)
this._spinner.stop(); this._spinner.stop();
} }
} }
}); });
} }
} }
@ -311,12 +312,11 @@ var AuthPrompt = class {
if (!animate) if (!animate)
actor.opacity = 255; actor.opacity = 255;
else else
actor.ease({ Tweener.addTween(actor,
opacity: 255, { opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR transition: 'linear' });
});
} }
this._defaultButtonWellActor = actor; this._defaultButtonWellActor = actor;
@ -365,12 +365,12 @@ var AuthPrompt = class {
_fadeOutMessage() { _fadeOutMessage() {
if (this._message.opacity == 0) if (this._message.opacity == 0)
return; return;
this._message.remove_all_transitions(); Tweener.removeTweens(this._message);
this._message.ease({ Tweener.addTween(this._message,
opacity: 0, { opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME, time: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad'
}); });
} }
setMessage(message, type) { setMessage(message, type) {
@ -385,7 +385,7 @@ var AuthPrompt = class {
this._message.remove_style_class_name('login-dialog-message-hint'); this._message.remove_style_class_name('login-dialog-message-hint');
if (message) { if (message) {
this._message.remove_all_transitions(); Tweener.removeTweens(this._message);
this._message.text = message; this._message.text = message;
this._message.opacity = 255; this._message.opacity = 255;
} else { } else {

View File

@ -20,7 +20,7 @@
* In order for transformation animations to look good, they need to be * In order for transformation animations to look good, they need to be
* incremental and have some order to them (e.g., fade out hidden items, * incremental and have some order to them (e.g., fade out hidden items,
* then shrink to close the void left over). Chaining animations in this way can * then shrink to close the void left over). Chaining animations in this way can
* be error-prone and wordy using just ease() callbacks. * be error-prone and wordy using just Tweener callbacks.
* *
* The classes in this file help with this: * The classes in this file help with this:
* *
@ -202,6 +202,7 @@ var ConsecutiveBatch = class extends Batch {
hold.disconnect(signalId); hold.disconnect(signalId);
this.nextTask(); this.nextTask();
}); });
return;
} else { } else {
// This task finished, process the next one // This task finished, process the next one
this.nextTask(); this.nextTask();

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported FprintManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LoginDialog */
/* /*
* Copyright 2011 Red Hat, Inc * Copyright 2011 Red Hat, Inc
* *
@ -31,10 +30,11 @@ const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Realmd = imports.gdm.realmd; const Realmd = imports.gdm.realmd;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250; const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 500; const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48; const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5; const _MAX_BOTTOM_MENU_ITEMS = 5;
@ -204,10 +204,11 @@ var UserList = class {
let adjustment = this.actor.get_vscroll_bar().get_adjustment(); let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.ease(value, { Tweener.removeTweens(adjustment);
mode: Clutter.AnimationMode.EASE_OUT_QUAD, Tweener.addTween (adjustment,
duration: _SCROLL_ANIMATION_TIME { value: value,
}); time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' });
} }
jumpToItem(item) { jumpToItem(item) {
@ -371,7 +372,7 @@ var SessionMenuButton = class {
} }
for (let i = 0; i < ids.length; i++) { 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 id = ids[i];
let item = new PopupMenu.PopupMenuItem(sessionName); let item = new PopupMenu.PopupMenuItem(sessionName);
@ -517,7 +518,7 @@ var LoginDialog = GObject.registerClass({
_getBannerAllocation(dialogBox) { _getBannerAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = this._bannerView.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2); actorBox.x1 = Math.floor(centerX - natWidth / 2);
@ -531,7 +532,7 @@ var LoginDialog = GObject.registerClass({
_getLogoBinAllocation(dialogBox) { _getLogoBinAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = this._logoBin.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2); actorBox.x1 = Math.floor(centerX - natWidth / 2);
@ -545,7 +546,7 @@ var LoginDialog = GObject.registerClass({
_getCenterActorAllocation(dialogBox, actor) { _getCenterActorAllocation(dialogBox, actor) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = actor.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2; let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
@ -647,7 +648,7 @@ var LoginDialog = GObject.registerClass({
// figure out how tall it would like to be and try to accommodate // figure out how tall it would like to be and try to accommodate
// but don't let it get too close to the logo // but don't let it get too close to the logo
let [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth); let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight; let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight); wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
@ -757,15 +758,14 @@ var LoginDialog = GObject.registerClass({
_fadeInBannerView() { _fadeInBannerView() {
this._bannerView.show(); this._bannerView.show();
this._bannerView.ease({ Tweener.addTween(this._bannerView,
opacity: 255, { opacity: 255,
duration: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad' });
});
} }
_hideBannerView() { _hideBannerView() {
this._bannerView.remove_all_transitions(); Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0; this._bannerView.opacity = 0;
this._bannerView.hide(); this._bannerView.hide();
} }
@ -858,11 +858,10 @@ var LoginDialog = GObject.registerClass({
return; return;
this._authPrompt.actor.opacity = 0; this._authPrompt.actor.opacity = 0;
this._authPrompt.actor.show(); this._authPrompt.actor.show();
this._authPrompt.actor.ease({ Tweener.addTween(this._authPrompt.actor,
opacity: 255, { opacity: 255,
duration: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad' });
});
this._fadeInBannerView(); this._fadeInBannerView();
} }
@ -906,31 +905,26 @@ var LoginDialog = GObject.registerClass({
this._showPrompt(); this._showPrompt();
} }
_bindOpacity() {
this._bindings = Main.layoutManager.uiGroup.get_children()
.filter(c => c != Main.layoutManager.screenShieldGroup)
.map(c => this.bind_property('opacity', c, 'opacity', 0));
}
_unbindOpacity() {
this._bindings.forEach(b => b.unbind());
}
_loginScreenSessionActivated() { _loginScreenSessionActivated() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
return; return;
this._bindOpacity(); Tweener.addTween(this,
this.ease({ { opacity: 255,
opacity: 255, time: _FADE_ANIMATION_TIME,
duration: _FADE_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onUpdate: () => {
onComplete: () => { let children = Main.layoutManager.uiGroup.get_children();
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset(); for (let i = 0; i < children.length; i++) {
this._unbindOpacity(); if (children[i] != Main.layoutManager.screenShieldGroup)
} children[i].opacity = this.opacity;
}); }
},
onComplete: () => {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
} });
} }
_gotGreeterSessionProxy(proxy) { _gotGreeterSessionProxy(proxy) {
@ -943,16 +937,21 @@ var LoginDialog = GObject.registerClass({
} }
_startSession(serviceName) { _startSession(serviceName) {
this._bindOpacity(); Tweener.addTween(this,
this.ease({ { opacity: 0,
opacity: 0, time: _FADE_ANIMATION_TIME,
duration: _FADE_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onUpdate: () => {
onComplete: () => { let children = Main.layoutManager.uiGroup.get_children();
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
this._unbindOpacity(); for (let i = 0; i < children.length; i++) {
} if (children[i] != Main.layoutManager.screenShieldGroup)
}); children[i].opacity = this.opacity;
}
},
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
} });
} }
_onSessionOpened(client, serviceName) { _onSessionOpened(client, serviceName) {
@ -1225,11 +1224,10 @@ var LoginDialog = GObject.registerClass({
Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN }); Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
this.ease({ Tweener.addTween(this,
opacity: 255, { opacity: 255,
duration: 1000, time: 1,
mode: Clutter.AnimationMode.EASE_IN_QUAD transition: 'easeInQuad' });
});
return true; return true;
} }
@ -1243,7 +1241,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.cancel(); this._authPrompt.cancel();
} }
addCharacter(_unichar) { addCharacter(unichar) {
// Don't allow type ahead at the login screen // Don't allow type ahead at the login screen
} }

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getOVirtCredentialsManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Signals = imports.signals; const Signals = imports.signals;

View File

@ -15,13 +15,12 @@ const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = class { var Manager = class {
constructor() { constructor(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system, this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd', 'org.freedesktop.realmd',
'/org/freedesktop/realmd', '/org/freedesktop/realmd',
this._reloadRealms.bind(this)); this._reloadRealms.bind(this));
this._realms = {}; this._realms = {};
this._loginFormat = null;
this._signalId = this._aggregateProvider.connect('g-properties-changed', this._signalId = this._aggregateProvider.connect('g-properties-changed',
(proxy, properties) => { (proxy, properties) => {
@ -87,7 +86,7 @@ var Manager = class {
} }
get loginFormat() { get loginFormat() {
if (this._loginFormat) if (this._loginFormat !== undefined)
return this._loginFormat; return this._loginFormat;
this._updateLoginFormat(); this._updateLoginFormat();

View File

@ -1,6 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -11,13 +9,14 @@ const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager; const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
var PASSWORD_SERVICE_NAME = 'gdm-password'; var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
var OVIRT_SERVICE_NAME = 'gdm-ovirtcred'; var OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
var FADE_ANIMATION_TIME = 160; var FADE_ANIMATION_TIME = 0.16;
var CLONE_FADE_ANIMATION_TIME = 250; var CLONE_FADE_ANIMATION_TIME = 0.25;
var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication'; var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
@ -46,20 +45,20 @@ function fadeInActor(actor) {
let hold = new Batch.Hold(); let hold = new Batch.Hold();
actor.show(); actor.show();
let [, naturalHeight] = actor.get_preferred_height(-1); let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
actor.opacity = 0; actor.opacity = 0;
actor.set_height(0); actor.set_height(0);
actor.ease({ Tweener.addTween(actor,
opacity: 255, { opacity: 255,
height: naturalHeight, height: naturalHeight,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
this.set_height(-1); this.set_height(-1);
hold.release(); hold.release();
} },
}); });
return hold; return hold;
} }
@ -72,17 +71,17 @@ function fadeOutActor(actor) {
} }
let hold = new Batch.Hold(); let hold = new Batch.Hold();
actor.ease({ Tweener.addTween(actor,
opacity: 0, { opacity: 0,
height: 0, height: 0,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
this.hide(); this.hide();
this.set_height(-1); this.set_height(-1);
hold.release(); hold.release();
} },
}); });
return hold; return hold;
} }
@ -102,15 +101,15 @@ function cloneAndFadeOutActor(actor) {
clone.set_position(x, y); clone.set_position(x, y);
let hold = new Batch.Hold(); let hold = new Batch.Hold();
clone.ease({ Tweener.addTween(clone,
opacity: 0, { opacity: 0,
duration: CLONE_FADE_ANIMATION_TIME, time: CLONE_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
clone.destroy(); clone.destroy();
hold.release(); hold.release();
} }
}); });
return hold; return hold;
} }
@ -304,7 +303,7 @@ var ShellUserVerifier = class {
}); });
} }
_oVirtUserAuthenticated(_token) { _oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME; this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated'); this.emit('ovirt-user-authenticated');
} }

View File

@ -1,37 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 // Common utils for the extension system and the extension
// preferences tool // preferences tool
const { Gio, GLib } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const Lang = imports.lang; const Signals = imports.signals;
const Gio = imports.gi.Gio;
const Config = imports.misc.config; const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
var ExtensionType = { var ExtensionType = {
SYSTEM: 1, SYSTEM: 1,
PER_USER: 2 PER_USER: 2
}; };
var ExtensionState = { // Maps uuid -> metadata object
ENABLED: 1, var extensions = {};
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: * getCurrentExtension:
@ -63,17 +49,13 @@ function getCurrentExtension() {
if (!match) if (!match)
return null; 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 path = match[1];
let file = Gio.File.new_for_path(path); let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with // Walk up the directory tree, looking for an extension with
// the same UUID as a directory name. // the same UUID as a directory name.
while (file != null) { while (file != null) {
let extension = extensionManager.lookup(file.get_basename()); let extension = extensions[file.get_basename()];
if (extension !== undefined) if (extension !== undefined)
return extension; return extension;
file = file.get_parent(); file = file.get_parent();
@ -165,8 +147,8 @@ function versionCheck(required, current) {
let requiredArray = required[i].split('.'); let requiredArray = required[i].split('.');
if (requiredArray[0] == major && if (requiredArray[0] == major &&
requiredArray[1] == minor && requiredArray[1] == minor &&
((requiredArray[2] === undefined && parseInt(minor) % 2 == 0) || (requiredArray[2] == point ||
requiredArray[2] == point)) (requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
return true; return true;
} }
return false; return false;
@ -179,50 +161,52 @@ function isOutOfDate(extension) {
return false; return false;
} }
function serializeExtension(extension) { function createExtensionObject(uuid, dir, type) {
let obj = {}; let metadataFile = dir.get_child('metadata.json');
Lang.copyProperties(extension.metadata, obj); if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
SERIALIZED_PROPERTIES.forEach(prop => { let metadataContents, success, tag;
obj[prop] = extension[prop]; 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}`);
}
let res = {}; let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let key in obj) { for (let i = 0; i < requiredProperties.length; i++) {
let val = obj[key]; let prop = requiredProperties[i];
let type; if (!meta[prop]) {
switch (typeof val) { throw new Error(`missing "${prop}" property in metadata.json`);
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
case 'boolean':
type = 'b';
break;
default:
continue;
} }
res[key] = GLib.Variant.new(type, val);
} }
return res; if (uuid != meta.uuid) {
} throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
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;
} }
// add the 2 additional properties to create a valid extension object, as createExtensionObject()
res.uuid = res.metadata.uuid; let extension = {};
res.dir = Gio.File.new_for_path(res.path);
return res; 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;
} }
function installImporter(extension) { function installImporter(extension) {
@ -233,3 +217,36 @@ function installImporter(extension) {
extension.imports = imports[extension.uuid]; extension.imports = imports[extension.uuid];
imports.searchPath = oldSearchPath; 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);

View File

@ -1,6 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported collectFromDatadirs, deleteGFile, recursivelyDeleteDir,
recursivelyMoveDir, loadInterfaceXML */
const { Gio, GLib } = imports.gi; const { Gio, GLib } = imports.gi;
const Config = imports.misc.config; const Config = imports.misc.config;
@ -86,7 +84,7 @@ function loadInterfaceXML(iface) {
let f = Gio.File.new_for_uri(uri); let f = Gio.File.new_for_uri(uri);
try { try {
let [ok_, bytes] = f.load_contents(null); let [ok, bytes] = f.load_contents(null);
if (bytes instanceof Uint8Array) if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes); xml = imports.byteArray.toString(bytes);
else else

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PresenceStatus, Presence, Inhibitor, SessionManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;

View File

@ -28,7 +28,7 @@ var HistoryManager = class {
this._entry = params.entry; this._entry = params.entry;
if (this._entry) { if (this._entry) {
this._entry.connect('key-press-event', this._entry.connect('key-press-event',
this._onEntryKeyPress.bind(this)); this._onEntryKeyPress.bind(this));
} }
} }

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi; const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup; const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@ -18,9 +18,9 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
IBus.MICRO_VERSION >= requiredMicro)) IBus.MICRO_VERSION >= requiredMicro))
return; return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d" throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
.format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION, format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro); requiredMajor, requiredMinor, requiredMicro);
} }
function getIBusManager() { function getIBusManager() {
@ -58,30 +58,16 @@ var IBusManager = class {
this._spawn(); this._spawn();
} }
_spawn(extraArgs = []) { _spawn() {
try { try {
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs]; Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE); Gio.SubprocessFlags.NONE);
} catch (e) { } catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`); log(`Failed to launch ibus-daemon: ${e.message}`);
} }
} }
restartDaemon(extraArgs = []) {
this._spawn(['-r', ...extraArgs]);
}
_clear() { _clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
if (this._preloadEnginesId) {
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
if (this._panelService) if (this._panelService)
this._panelService.destroy(); this._panelService.destroy();
@ -93,44 +79,33 @@ var IBusManager = class {
this._currentEngineName = null; this._currentEngineName = null;
this.emit('ready', false); this.emit('ready', false);
this._spawn();
} }
_onConnected() { _onConnected() {
this._cancellable = new Gio.Cancellable(); this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL, this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable, IBus.BusNameFlag.REPLACE_EXISTING,
this._initPanelService.bind(this)); -1, null,
this._initPanelService.bind(this));
} }
_initEngines(ibus, result) { _initEngines(ibus, result) {
try { let enginesList = this._ibus.list_engines_async_finish(result);
let enginesList = this._ibus.list_engines_async_finish(result); if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) { for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name(); let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]); this._engines.set(name, enginesList[i]);
} }
this._updateReadiness(); this._updateReadiness();
} catch (e) { } else {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
this._clear(); this._clear();
} }
} }
_initPanelService(ibus, result) { _initPanelService(ibus, result) {
let success = false; let success = this._ibus.request_name_async_finish(result);
try {
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) { if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(), this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL }); object_path: IBus.PATH_PANEL });
@ -157,7 +132,7 @@ var IBusManager = class {
} catch (e) { } catch (e) {
} }
// If an engine is already active we need to get its properties // If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => { this._ibus.get_global_engine_async(-1, null, (i, result) => {
let engine; let engine;
try { try {
engine = this._ibus.get_global_engine_async_finish(result); engine = this._ibus.get_global_engine_async_finish(result);
@ -229,18 +204,8 @@ var IBusManager = class {
return; return;
} }
this._ibus.set_global_engine_async(id, this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME, null, callback || null);
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
} }
preloadEngines(ids) { preloadEngines(ids) {
@ -248,23 +213,21 @@ var IBusManager = class {
return; return;
if (this._preloadEnginesId != 0) { if (this._preloadEnginesId != 0) {
GLib.source_remove(this._preloadEnginesId); Mainloop.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0; this._preloadEnginesId = 0;
} }
this._preloadEnginesId = this._preloadEnginesId =
GLib.timeout_add_seconds( Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
GLib.PRIORITY_DEFAULT, () => {
this._PRELOAD_ENGINES_DELAY_TIME, this._ibus.preload_engines_async(
() => { ids,
this._ibus.preload_engines_async( -1,
ids, null,
-1, null);
this._cancellable, this._preloadEnginesId = 0;
null); return GLib.SOURCE_REMOVE;
this._preloadEnginesId = 0; });
return GLib.SOURCE_REMOVE;
});
} }
}; };
Signals.addSignalMethods(IBusManager.prototype); Signals.addSignalMethods(IBusManager.prototype);

View File

@ -1,6 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */ const { Clutter, GLib, GObject, IBus } = imports.gi;
const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard; const Keyboard = imports.ui.status.keyboard;
@ -36,7 +35,15 @@ class InputMethod extends Clutter.InputMethod {
} }
_updateCapabilities() { _updateCapabilities() {
let caps = IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT; let caps = 0;
if (this.can_show_preedit)
caps |= IBus.Capabilite.PREEDIT_TEXT;
if (this._currentFocus)
caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
else
caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT | IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY;
if (this._context) if (this._context)
this._context.set_capabilities(caps); this._context.set_capabilities(caps);
@ -47,22 +54,12 @@ class InputMethod extends Clutter.InputMethod {
} }
_onConnected() { _onConnected() {
this._cancellable = new Gio.Cancellable(); this._ibus.create_input_context_async ('gnome-shell', -1, null,
this._ibus.create_input_context_async ('gnome-shell', -1, this._setContext.bind(this));
this._cancellable, this._setContext.bind(this));
} }
_setContext(bus, res) { _setContext(bus, res) {
try { this._context = this._ibus.create_input_context_async_finish(res);
this._context = this._ibus.create_input_context_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
this._clear();
}
return;
}
this._context.connect('commit-text', this._onCommitText.bind(this)); this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this)); this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this)); this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
@ -74,11 +71,6 @@ class InputMethod extends Clutter.InputMethod {
} }
_clear() { _clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
this._context = null; this._context = null;
this._hints = 0; this._hints = 0;
this._purpose = 0; this._purpose = 0;
@ -92,15 +84,15 @@ class InputMethod extends Clutter.InputMethod {
this.emit('request-surrounding'); this.emit('request-surrounding');
} }
_onCommitText(_context, text) { _onCommitText(context, text) {
this.commit(text.get_text()); this.commit(text.get_text());
} }
_onDeleteSurroundingText() { _onDeleteSurroundingText(context) {
this.delete_surrounding(); this.delete_surrounding();
} }
_onUpdatePreeditText(_context, text, pos, visible) { _onUpdatePreeditText(context, text, pos, visible) {
if (text == null) if (text == null)
return; return;
@ -116,17 +108,17 @@ class InputMethod extends Clutter.InputMethod {
this._preeditVisible = visible; this._preeditVisible = visible;
} }
_onShowPreeditText() { _onShowPreeditText(context) {
this._preeditVisible = true; this._preeditVisible = true;
this.set_preedit_text(this._preeditStr, this._preeditPos); this.set_preedit_text(this._preeditStr, this._preeditPos);
} }
_onHidePreeditText() { _onHidePreeditText(context) {
this.set_preedit_text(null, this._preeditPos); this.set_preedit_text(null, this._preeditPos);
this._preeditVisible = false; this._preeditVisible = false;
} }
_onForwardKeyEvent(_context, keyval, keycode, state) { _onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0; let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~(IBus.ModifierType.RELEASE_MASK); state &= ~(IBus.ModifierType.RELEASE_MASK);
@ -144,6 +136,7 @@ class InputMethod extends Clutter.InputMethod {
this._currentFocus = focus; this._currentFocus = focus;
if (this._context) { if (this._context) {
this._context.focus_in(); this._context.focus_in();
this._updateCapabilities();
this._emitRequestSurrounding(); this._emitRequestSurrounding();
} }
@ -155,8 +148,10 @@ class InputMethod extends Clutter.InputMethod {
vfunc_focus_out() { vfunc_focus_out() {
this._currentFocus = null; this._currentFocus = null;
if (this._context) if (this._context) {
this._context.focus_out(); this._context.focus_out();
this._updateCapabilities();
}
if (this._preeditStr) { if (this._preeditStr) {
// Unset any preedit text // Unset any preedit text
@ -259,19 +254,17 @@ class InputMethod extends Clutter.InputMethod {
if (event.type() == Clutter.EventType.KEY_RELEASE) if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK; state |= IBus.ModifierType.RELEASE_MASK;
this._context.process_key_event_async( this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_symbol(), event.get_key_code() - 8, // Convert XKB keycodes to evcodes
event.get_key_code() - 8, // Convert XKB keycodes to evcodes state, -1, null,
state, -1, this._cancellable, (context, res) => {
(context, res) => { try {
try { let retval = context.process_key_event_async_finish(res);
let retval = context.process_key_event_async_finish(res); this.notify_key_event(event, retval);
this.notify_key_event(event, retval); } catch (e) {
} catch (e) { log(`Error processing key on IM: ${e.message}`);
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) }
log(`Error processing key on IM: ${e.message}`); });
}
});
return true; return true;
} }
}); });

View File

@ -1,4 +1,3 @@
/* exported IntrospectService */
const { Gio, GLib, Meta, Shell } = imports.gi; const { Gio, GLib, Meta, Shell } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell'; const INTROSPECT_SCHEMA = 'org.gnome.shell';
@ -127,8 +126,7 @@ var IntrospectService = class {
let apps = this._appSystem.get_running(); let apps = this._appSystem.get_running();
let windowsList = {}; let windowsList = {};
if (!this._isIntrospectEnabled() && if (!this._isIntrospectEnabled()) {
!this._isSenderWhitelisted(invocation.get_sender())) {
invocation.return_error_literal(Gio.DBusError, invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED, Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed'); 'App introspection not allowed');

View File

@ -1,5 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
// Returns a list of potential completions for text. Completions either // 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) // follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
@ -9,7 +8,7 @@
// This function is likely the one you want to call from external modules // This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) { function getCompletions(text, commandHeader, globalCompletionList) {
let methods = []; let methods = [];
let expr_, base; let expr, base;
let attrHead = ''; let attrHead = '';
if (globalCompletionList == null) { if (globalCompletionList == null) {
globalCompletionList = []; globalCompletionList = [];
@ -22,7 +21,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// Look for expressions like "Main.panel.foo" and match Main.panel and foo // Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/); let matches = text.match(/(.*)\.(.*)/);
if (matches) { if (matches) {
[expr_, base, attrHead] = matches; [expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter( methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead attr => attr.slice(0, attrHead.length) == attrHead
@ -33,7 +32,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// not proceeded by a dot and match them against global constants // not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/); matches = text.match(/^(\w*)$/);
if (text == '' || matches) { if (text == '' || matches) {
[expr_, attrHead] = matches; [expr, attrHead] = matches;
methods = globalCompletionList.filter( methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead attr => attr.slice(0, attrHead.length) == attrHead
); );
@ -172,7 +171,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
// Make sure propsUnique contains one key for every // Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties // property so we end up with a unique list of properties
allProps.map(p => (propsUnique[p] = null)); allProps.map(p => propsUnique[p] = null);
} }
return Object.keys(propsUnique).sort(); return Object.keys(propsUnique).sort();
} }
@ -217,7 +216,7 @@ function isUnsafeExpression(str) {
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/[=]/)) { if (prunedStr.match(/=/)) {
return true; return true;
} else if (prunedStr.match(/;/)) { } else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well // If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
@ -231,10 +230,10 @@ function isUnsafeExpression(str) {
function getDeclaredConstants(str) { function getDeclaredConstants(str) {
let ret = []; let ret = [];
str.split(';').forEach(s => { str.split(';').forEach(s => {
let base_, keyword; let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/); let match = s.match(/const\s+(\w+)\s*=/);
if (match) { if (match) {
[base_, keyword] = match; [base, keyword] = match;
ret.push(keyword); ret.push(keyword);
} }
}); });

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop, Meta } = imports.gi; const { GLib, GnomeDesktop, Meta } = imports.gi;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported canLock, getLoginManager, registerSessionWithGDM */
const { GLib, Gio } = imports.gi; const { GLib, Gio } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -110,7 +109,7 @@ var LoginManagerSystemd = class {
let sessionId = GLib.getenv('XDG_SESSION_ID'); let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) { if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.'); 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) { if (session) {
log(`Will monitor session ${session}`); log(`Will monitor session ${session}`);
sessionId = session; sessionId = session;
@ -183,7 +182,7 @@ var LoginManagerSystemd = class {
(proxy, result) => { (proxy, result) => {
let fd = -1; let fd = -1;
try { 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]; fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd: fd })); callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) { } catch (e) {
@ -200,7 +199,7 @@ var LoginManagerSystemd = class {
Signals.addSignalMethods(LoginManagerSystemd.prototype); Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = class { var LoginManagerDummy = class {
getCurrentSessionProxy(_callback) { getCurrentSessionProxy(callback) {
// we could return a DummySession object that fakes whatever callers // we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal() // expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer // methods), but just never calling the callback should be safer

View File

@ -84,9 +84,9 @@ function _findProviderForSid(sid) {
} }
// ----------------------------------------------------- // //------------------------------------------------------------------------------
// Support for the old ModemManager interface (MM < 0.7) // // Support for the old ModemManager interface (MM < 0.7)
// ----------------------------------------------------- // //------------------------------------------------------------------------------
// The following are not the complete interfaces, just the methods we need // The following are not the complete interfaces, just the methods we need
@ -110,7 +110,7 @@ var ModemGsm = class {
this.signal_quality = quality; this.signal_quality = quality;
this.emit('notify::signal-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.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name'); this.emit('notify::operator-name');
}); });
@ -120,7 +120,7 @@ var ModemGsm = class {
return; return;
} }
let [status_, code, name] = result; let [status, code, name] = result;
this.operator_name = _findProviderForMccMnc(name, code); this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name'); this.emit('notify::operator-name');
}); });
@ -171,7 +171,7 @@ var ModemCdma = class {
// it will return an error if the device is not connected // it will return an error if the device is not connected
this.operator_name = null; this.operator_name = null;
} else { } else {
let [bandClass_, band_, sid] = result; let [bandClass, band, sid] = result;
this.operator_name = _findProviderForSid(sid); this.operator_name = _findProviderForSid(sid);
} }
@ -182,9 +182,9 @@ var ModemCdma = class {
Signals.addSignalMethods(ModemCdma.prototype); Signals.addSignalMethods(ModemCdma.prototype);
// ------------------------------------------------------- // //------------------------------------------------------------------------------
// Support for the new ModemManager1 interface (MM >= 0.7) // // Support for the new ModemManager1 interface (MM >= 0.7)
// ------------------------------------------------------- // //------------------------------------------------------------------------------
const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem'); const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem');
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface); const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
@ -224,7 +224,7 @@ var BroadbandModem = class {
} }
_reloadSignalQuality() { _reloadSignalQuality() {
let [quality, recent_] = this._proxy.SignalQuality; let [quality, recent] = this._proxy.SignalQuality;
this.signal_quality = quality; this.signal_quality = quality;
this.emit('notify::signal-quality'); this.emit('notify::signal-quality');
} }

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported parse */
// parse: // parse:
// @params: caller-provided parameter object, or %null // @params: caller-provided parameter object, or %null

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PermissionStore */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getSmartcardManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Signals = imports.signals; const Signals = imports.signals;

View File

@ -1,4 +1,3 @@
/* exported getDefault */
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi; const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
@ -174,21 +173,13 @@ const SystemActions = GObject.registerClass({
}); });
Main.layoutManager.connect('monitors-changed', Main.layoutManager.connect('monitors-changed',
() => this._updateOrientationLock()); () => this._updateOrientationLock());
this._sensorProxy = new SensorProxy(Gio.DBus.system, Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
SENSOR_BUS_NAME, Gio.BusNameWatcherFlags.NONE,
SENSOR_OBJECT_PATH, () => this._sensorProxyAppeared(),
(proxy, error) => { () => {
if (error) this._sensorProxy = null;
log(error.message); this._updateOrientationLock();
}, });
null,
Gio.DBusProxyFlags.DO_NOT_AUTO_START);
this._sensorProxy.connect('g-properties-changed', () => {
this._updateOrientationLock();
});
this._sensorProxy.connect('notify::g-name-owner', () => {
this._updateOrientationLock();
});
this._updateOrientationLock(); this._updateOrientationLock();
this._updateOrientationLockIcon(); this._updateOrientationLockIcon();
@ -196,44 +187,50 @@ const SystemActions = GObject.registerClass({
this._sessionUpdated(); this._sessionUpdated();
} }
// eslint-disable-next-line camelcase
get can_power_off() { get can_power_off() {
return this._actions.get(POWER_OFF_ACTION_ID).available; return this._actions.get(POWER_OFF_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_suspend() { get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available; return this._actions.get(SUSPEND_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_lock_screen() { get can_lock_screen() {
return this._actions.get(LOCK_SCREEN_ACTION_ID).available; return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_switch_user() { get can_switch_user() {
return this._actions.get(SWITCH_USER_ACTION_ID).available; return this._actions.get(SWITCH_USER_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_logout() { get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available; return this._actions.get(LOGOUT_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_lock_orientation() { get can_lock_orientation() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available; return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get orientation_lock_icon() { get orientation_lock_icon() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName; return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
} }
_sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._sensorProxy.connect('g-properties-changed',
() => this._updateOrientationLock());
this._updateOrientationLock();
});
}
_updateOrientationLock() { _updateOrientationLock() {
let available = false; let available = false;
if (this._sensorProxy.g_name_owner) if (this._sensorProxy)
available = this._sensorProxy.HasAccelerometer && available = this._sensorProxy.HasAccelerometer &&
this._monitorManager.get_is_builtin_display_on(); this._monitorManager.get_is_builtin_display_on();
@ -244,9 +241,8 @@ const SystemActions = GObject.registerClass({
_updateOrientationLockIcon() { _updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock'); let locked = this._orientationSettings.get_boolean('orientation-lock');
let iconName = locked let iconName = locked ? 'rotation-locked-symbolic'
? 'rotation-locked-symbolic' : 'rotation-allowed-symbolic';
: 'rotation-allowed-symbolic';
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName; this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
this.notify('orientation-lock-icon'); this.notify('orientation-lock-icon');
@ -269,7 +265,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) { getMatchingActions(terms) {
// terms is a list of strings // terms is a list of strings
terms = terms.map(term => term.toLowerCase()); terms = terms.map((term) => term.toLowerCase());
let results = []; let results = [];

View File

@ -1,20 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Params = imports.misc.params; const Params = imports.misc.params;
var SCROLL_TIME = 100; var SCROLL_TIME = 0.1;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls // http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)'; const _balancedParens = '\\([^\\s()<>]+\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]'; const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]'; const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _urlRegexp = new RegExp( const _urlRegexp = new RegExp(
`(^|${_leadingJunk})` + `(^|${_leadingJunk})` +
@ -75,7 +75,7 @@ function spawn(argv) {
// occur when trying to parse or start the program. // occur when trying to parse or start the program.
function spawnCommandLine(commandLine) { function spawnCommandLine(commandLine) {
try { try {
let [success_, argv] = GLib.shell_parse_argv(commandLine); let [success, argv] = GLib.shell_parse_argv(commandLine);
trySpawn(argv); trySpawn(argv);
} catch (err) { } catch (err) {
_handleSpawnError(commandLine, err); _handleSpawnError(commandLine, err);
@ -104,11 +104,11 @@ function spawnApp(argv) {
// Runs @argv in the background. If launching @argv fails, // Runs @argv in the background. If launching @argv fails,
// this will throw an error. // this will throw an error.
function trySpawn(argv) { function trySpawn(argv) {
var success_, pid; var success, pid;
try { try {
[success_, pid] = GLib.spawn_async(null, argv, null, [success, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null); null);
} catch (err) { } catch (err) {
/* Rewrite the error in case of ENOENT */ /* Rewrite the error in case of ENOENT */
if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) { if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) {
@ -139,10 +139,10 @@ function trySpawn(argv) {
// Runs @commandLine in the background. If launching @commandLine // Runs @commandLine in the background. If launching @commandLine
// fails, this will throw an error. // fails, this will throw an error.
function trySpawnCommandLine(commandLine) { function trySpawnCommandLine(commandLine) {
let success_, argv; let success, argv;
try { try {
[success_, argv] = GLib.shell_parse_argv(commandLine); [success, argv] = GLib.shell_parse_argv(commandLine);
} catch (err) { } catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with // Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer // something nicer
@ -313,8 +313,7 @@ function lowerBound(array, val, cmp) {
if (array.length == 0) if (array.length == 0)
return 0; return 0;
min = 0; min = 0; max = array.length;
max = array.length;
while (min < (max - 1)) { while (min < (max - 1)) {
mid = Math.floor((min + max) / 2); mid = Math.floor((min + max) / 2);
v = cmp(array[mid], val); v = cmp(array[mid], val);
@ -396,7 +395,7 @@ function makeCloseButton(boxpointer) {
function ensureActorVisibleInScrollView(scrollView, actor) { function ensureActorVisibleInScrollView(scrollView, actor) {
let adjustment = scrollView.vscroll.adjustment; 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 offset = 0;
let vfade = scrollView.get_effect("fade"); let vfade = scrollView.get_effect("fade");
@ -424,8 +423,97 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
else else
return; return;
adjustment.ease(value, { Tweener.addTween(adjustment,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, { value: value,
duration: SCROLL_TIME time: SCROLL_TIME,
}); transition: 'easeOutQuad' });
} }
var AppSettingsMonitor = class {
constructor(appId, schemaId) {
this._appId = appId;
this._schemaId = schemaId;
this._app = null;
this._settings = null;
this._handlers = [];
this._schemaSource = Gio.SettingsSchemaSource.get_default();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
}
get available() {
return this._app != null && this._settings != null;
}
activateApp() {
if (this._app)
this._app.activate();
}
watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler);
this._connectHandler(handler);
}
_connectHandler(handler) {
if (!this._settings || handler.id > 0)
return;
handler.id = this._settings.connect(`changed::${handler.key}`,
handler.callback);
handler.callback(this._settings, handler.key);
}
_disconnectHandler(handler) {
if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id);
handler.id = 0;
}
_onInstalledChanged() {
let hadApp = (this._app != null);
this._app = this._appSystem.lookup_app(this._appId);
let haveApp = (this._app != null);
if (hadApp == haveApp)
return;
if (haveApp)
this._checkSettings();
else
this._setSettings(null);
}
_setSettings(settings) {
this._handlers.forEach((handler) => this._disconnectHandler(handler));
let hadSettings = (this._settings != null);
this._settings = settings;
let haveSettings = (this._settings != null);
this._handlers.forEach((handler) => this._connectHandler(handler));
if (hadSettings != haveSettings)
this.emit('available-changed');
}
_checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true);
if (schema) {
this._setSettings(new Gio.Settings({ settings_schema: schema }));
} else if (this._app) {
Mainloop.timeout_add_seconds(1, () => {
this._checkSettings();
return GLib.SOURCE_REMOVE;
});
}
}
};
Signals.addSignalMethods(AppSettingsMonitor.prototype);

View File

@ -1,19 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi; const { Geoclue, Gio, GLib, GWeather } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore; 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 // Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE; var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@ -75,38 +66,17 @@ var WeatherClient = class {
this.emit('changed'); this.emit('changed');
}); });
this._weatherApp = null; this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
this._weatherProxy = null; 'org.gnome.Weather');
this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface); this._weatherAppMon.watchSetting('automatic-location',
Gio.DBusProxy.new( this._onAutomaticLocationChanged.bind(this));
Gio.DBus.session, this._weatherAppMon.watchSetting('locations',
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES, this._onLocationsChanged.bind(this));
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._onAutomaticLocationChanged();
this._settings.connect('changed::locations',
this._onLocationsChanged.bind(this));
this._onLocationsChanged();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
} }
get available() { get available() {
return this._weatherApp != null; return this._weatherAppMon.available;
} }
get loading() { get loading() {
@ -122,8 +92,7 @@ var WeatherClient = class {
} }
activateApp() { activateApp() {
if (this._weatherApp) this._weatherAppMon.activateApp();
this._weatherApp.activate();
} }
update() { update() {
@ -145,38 +114,6 @@ var WeatherClient = class {
this._weatherAuthorized; 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));
this._onWeatherPropertiesChanged();
}
_onWeatherPropertiesChanged() {
if (this._weatherProxy.g_name_owner == null)
return;
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() { _loadInfo() {
let id = this._weatherInfo.connect('updated', () => { let id = this._weatherInfo.connect('updated', () => {
this._weatherInfo.disconnect(id); this._weatherInfo.disconnect(id);
@ -261,8 +198,8 @@ var WeatherClient = class {
this._setLocation(location); this._setLocation(location);
} }
_onAutomaticLocationChanged() { _onAutomaticLocationChanged(settings, key) {
let useAutoLocation = this._settings.get_boolean('automatic-location'); let useAutoLocation = settings.get_boolean(key);
if (this._autoLocationRequested == useAutoLocation) if (this._autoLocationRequested == useAutoLocation)
return; return;
@ -280,9 +217,8 @@ var WeatherClient = class {
this._setLocation(this._mostRecentLocation); this._setLocation(this._mostRecentLocation);
} }
_onLocationsChanged() { _onLocationsChanged(settings, key) {
let locations = this._settings.get_value('locations').deep_unpack(); let serialized = settings.get_value(key).deep_unpack().shift();
let serialized = locations.shift();
let mostRecentLocation = null; let mostRecentLocation = null;
if (serialized) if (serialized)
@ -298,7 +234,7 @@ var WeatherClient = class {
} }
_onPermStoreChanged(proxy, sender, params) { _onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted_, data_, perms] = params; let [table, id, deleted, data, perms] = params;
if (table != 'gnome' || id != 'geolocation') if (table != 'gnome' || id != 'geolocation')
return; return;

View File

@ -1,9 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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; const System = imports.system;
@ -126,11 +121,9 @@ function *run() {
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true; Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = false; Main.overview._dash.showAppsButton.checked = false;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
} }
@ -154,7 +147,7 @@ function script_overviewShowStart(time) {
overviewFrames = 0; 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 // 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 // need to wait for one more frame to paint before we count
// ourselves as done. // ourselves as done.
@ -173,7 +166,7 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart; METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
} }
function script_afterShowHide(_time) { function script_afterShowHide(time) {
if (overviewShowCount == 1) { if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize; METRICS.usedAfterOverview.value = mallocUsedSize;
} else { } else {

View File

@ -1,12 +1,3 @@
/* 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 { Clutter, Gio, Shell } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const Scripting = imports.ui.scripting; const Scripting = imports.ui.scripting;
@ -47,7 +38,7 @@ function waitAndDraw(milliseconds) {
let timeline = new Clutter.Timeline({ duration: milliseconds }); let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start(); timeline.start();
timeline.connect('new-frame', (_timeline, _frame) => { timeline.connect('new-frame', (timeline, frame) => {
global.stage.queue_redraw(); global.stage.queue_redraw();
}); });
@ -57,7 +48,7 @@ function waitAndDraw(milliseconds) {
cb(); cb();
}); });
return callback => (cb = callback); return callback => cb = callback;
} }
function waitSignal(object, signal) { function waitSignal(object, signal) {
@ -69,7 +60,7 @@ function waitSignal(object, signal) {
cb(); cb();
}); });
return callback => (cb = callback); return callback => cb = callback;
} }
function extractBootTimestamp() { function extractBootTimestamp() {
@ -82,8 +73,8 @@ function extractBootTimestamp() {
let result = null; let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe()); let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) { // eslint-disable-line no-constant-condition while (true) {
let [line, length_] = datastream.read_line_utf8(null); let [line, length] = datastream.read_line_utf8(null);
if (line === null) if (line === null)
break; break;
@ -126,7 +117,6 @@ function *run() {
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true; Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
@ -137,9 +127,9 @@ function *run() {
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
// --------------------- // ////////////////////////////////////////
// Tests of redraw speed // // Tests of redraw speed
// --------------------- // ////////////////////////////////////////
global.frame_timestamps = true; global.frame_timestamps = true;
global.frame_finish_timestamp = true; global.frame_finish_timestamp = true;
@ -186,6 +176,8 @@ function *run() {
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default(); let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop'); let app = appSys.lookup_app('org.gnome.gedit.desktop');
@ -242,31 +234,31 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart; METRICS.applicationsShowTime.value = time - applicationsShowStart;
} }
function script_mainViewDrawStart(_time) { function script_mainViewDrawStart(time) {
redrawTiming = 'mainView'; redrawTiming = 'mainView';
} }
function script_mainViewDrawDone(_time) { function script_mainViewDrawDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_overviewDrawStart(_time) { function script_overviewDrawStart(time) {
redrawTiming = 'overview'; redrawTiming = 'overview';
} }
function script_overviewDrawDone(_time) { function script_overviewDrawDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_redrawTestStart(_time) { function script_redrawTestStart(time) {
redrawTiming = 'application'; redrawTiming = 'application';
} }
function script_redrawTestDone(_time) { function script_redrawTestDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_collectTimings(_time) { function script_collectTimings(time) {
for (let timing in redrawTimes) { for (let timing in redrawTimes) {
let times = redrawTimes[timing]; let times = redrawTimes[timing];
times.sort((a, b) => a - b); times.sort((a, b) => a - b);

View File

@ -1,4 +1,3 @@
/* exported main */
const Format = imports.format; const Format = imports.format;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi; const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi;
@ -152,7 +151,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._webView.load_uri(this._originalUrl); this._webView.load_uri(this._originalUrl);
} }
vfunc_delete_event(_event) { vfunc_delete_event(event) {
if (this._recheckAtExit) if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK); this._doneCallback(PortalHelperResult.RECHECK);
else else
@ -178,7 +177,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
} }
_onLoadFailedWithTlsErrors(view, failingURI, certificate, _errors) { _onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
let uri = new Soup.URI(failingURI); let uri = new Soup.URI(failingURI);
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host()); this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());

View File

@ -1,4 +1,3 @@
/* exported AccessDialogDBus */
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi; const { Clutter, Gio, GLib, GObject, Shell } = imports.gi;
const CheckBox = imports.ui.checkBox; const CheckBox = imports.ui.checkBox;
@ -80,7 +79,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this._requestExported = this._request.export(connection, this._handle); this._requestExported = this._request.export(connection, this._handle);
} }
CloseAsync(invocation, _params) { CloseAsync(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) { if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError, invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED, Gio.DBusError.ACCESS_DENIED,
@ -133,7 +132,7 @@ var AccessDialogDBus = class {
return; 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 // We probably want to use parentWindow and global.display.focus_window
// for this check in the future // for this check in the future
if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) { if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) {
@ -147,7 +146,7 @@ var AccessDialogDBus = class {
subtitle, body, options); subtitle, body, options);
dialog.open(); dialog.open();
dialog.connect('closed', () => (this._accessDialog = null)); dialog.connect('closed', () => this._accessDialog = null);
this._accessDialog = dialog; this._accessDialog = dialog;
} }

View File

@ -1,17 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main; const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup; const SwitcherPopup = imports.ui.switcherPopup;
const Tweener = imports.ui.tweener;
var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
var THUMBNAIL_DEFAULT_SIZE = 256; var THUMBNAIL_DEFAULT_SIZE = 256;
var THUMBNAIL_POPUP_TIME = 500; // milliseconds var THUMBNAIL_POPUP_TIME = 500; // milliseconds
var THUMBNAIL_FADE_TIME = 100; // milliseconds var THUMBNAIL_FADE_TIME = 0.1; // seconds
var WINDOW_PREVIEW_SIZE = 128; var WINDOW_PREVIEW_SIZE = 128;
var APP_ICON_SIZE = 96; var APP_ICON_SIZE = 96;
@ -87,9 +87,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let hPadding = leftPadding + rightPadding; let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex]; let icon = this._items[this._selectedIndex];
let [posX] = icon.get_transformed_position(); let [posX, posY] = icon.get_transformed_position();
let thumbnailCenter = posX + icon.width / 2; let thumbnailCenter = posX + icon.width / 2;
let [, childNaturalWidth] = this._thumbnails.get_preferred_width(-1); let [childMinWidth, childNaturalWidth] = this._thumbnails.get_preferred_width(-1);
childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2)); childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2));
if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) { if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) {
let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding; let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding;
@ -103,7 +103,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
childBox.x2 = primary.x + primary.width - rightPadding; childBox.x2 = primary.x + primary.width - rightPadding;
childBox.y1 = this._switcherList.allocation.y2 + spacing; childBox.y1 = this._switcherList.allocation.y2 + spacing;
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1); this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1); let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight; childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags); this._thumbnails.allocate(childBox, flags);
} }
@ -291,7 +291,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
if (this._thumbnails) if (this._thumbnails)
this._destroyThumbnails(); this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0) if (this._thumbnailTimeoutId != 0)
GLib.source_remove(this._thumbnailTimeoutId); Mainloop.source_remove(this._thumbnailTimeoutId);
} }
/** /**
@ -326,7 +326,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
if (this._thumbnailTimeoutId != 0) { if (this._thumbnailTimeoutId != 0) {
GLib.source_remove(this._thumbnailTimeoutId); Mainloop.source_remove(this._thumbnailTimeoutId);
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
} }
@ -343,8 +343,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.highlight(window, forceAppFocus); this._thumbnails.highlight(window, forceAppFocus);
} else if (this._items[this._selectedIndex].cachedWindows.length > 1 && } else if (this._items[this._selectedIndex].cachedWindows.length > 1 &&
!forceAppFocus) { !forceAppFocus) {
this._thumbnailTimeoutId = GLib.timeout_add( this._thumbnailTimeoutId = Mainloop.timeout_add (
GLib.PRIORITY_DEFAULT,
THUMBNAIL_POPUP_TIME, THUMBNAIL_POPUP_TIME,
this._timeoutPopupThumbnails.bind(this)); this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails'); GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
@ -361,15 +360,15 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_destroyThumbnails() { _destroyThumbnails() {
let thumbnailsActor = this._thumbnails; let thumbnailsActor = this._thumbnails;
this._thumbnails.ease({ Tweener.addTween(thumbnailsActor,
opacity: 0, { opacity: 0,
duration: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => {
thumbnailsActor.destroy(); thumbnailsActor.destroy();
this.thumbnailsVisible = false; this.thumbnailsVisible = false;
} }
}); });
this._thumbnails = null; this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex]) if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED); this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
@ -392,14 +391,12 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.get_allocation_box(); this._thumbnails.get_allocation_box();
this._thumbnails.opacity = 0; this._thumbnails.opacity = 0;
this._thumbnails.ease({ Tweener.addTween(this._thumbnails,
opacity: 255, { opacity: 255,
duration: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => this.thumbnailsVisible = true
this.thumbnailsVisible = true; });
}
});
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED); this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
} }
@ -437,8 +434,8 @@ class CyclerHighlight {
if (this._clone.source) if (this._clone.source)
this._clone.source.sync_visibility(); this._clone.source.sync_visibility();
let windowActor = this._window let windowActor = this._window ? this._window.get_compositor_private()
? this._window.get_compositor_private() : null; : null;
if (windowActor) if (windowActor)
windowActor.hide(); windowActor.hide();
@ -472,7 +469,7 @@ var CyclerList = GObject.registerClass({
'item-removed': { param_types: [GObject.TYPE_INT] }, 'item-removed': { param_types: [GObject.TYPE_INT] },
'item-highlighted': { param_types: [GObject.TYPE_INT] } }, 'item-highlighted': { param_types: [GObject.TYPE_INT] } },
}, class CyclerList extends St.Widget { }, class CyclerList extends St.Widget {
highlight(index, _justOutline) { highlight(index, justOutline) {
this.emit('item-highlighted', index); this.emit('item-highlighted', index);
} }
}); });
@ -497,7 +494,7 @@ var CyclerPopup = GObject.registerClass({
}); });
} }
_highlightItem(index, _justOutline) { _highlightItem(index, justOutline) {
this._highlight.window = this._items[index]; this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null); global.window_group.set_child_above_sibling(this._highlight.actor, null);
} }
@ -648,9 +645,8 @@ class WindowCyclerPopup extends CyclerPopup {
} }
}); });
var AppIcon = GObject.registerClass({ var AppIcon = GObject.registerClass(
GTypeName: 'AltTab_AppIcon' class AppIcon extends St.BoxLayout {
}, class AppIcon extends St.BoxLayout {
_init(app) { _init(app) {
super._init({ style_class: 'alt-tab-app', super._init({ style_class: 'alt-tab-app',
vertical: true }); vertical: true });
@ -664,7 +660,6 @@ var AppIcon = GObject.registerClass({
this.add(this.label, { x_fill: false }); this.add(this.label, { x_fill: false });
} }
// eslint-disable-next-line camelcase
set_size(size) { set_size(size) {
this.icon = this.app.create_icon_texture(size); this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon; this._iconBin.child = this.icon;
@ -712,7 +707,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_onDestroy() { _onDestroy() {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
GLib.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => { this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId); icon.app.disconnect(icon._stateChangedId);
@ -791,16 +786,14 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// activation when the thumbnail list is open // activation when the thumbnail list is open
_onItemEnter(index) { _onItemEnter(index) {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
GLib.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) { if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = GLib.timeout_add( this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
GLib.PRIORITY_DEFAULT, () => {
APP_ICON_HOVER_TIMEOUT, this._enterItem(index);
() => { this._mouseTimeOutId = 0;
this._enterItem(index); return GLib.SOURCE_REMOVE;
this._mouseTimeOutId = 0; });
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem'); GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else { } else {
this._itemEntered(index); this._itemEntered(index);
@ -808,7 +801,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
} }
_enterItem(index) { _enterItem(index) {
let [x, y] = global.get_pointer(); let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor)) if (this._items[index].contains(pickedActor))
this._itemEntered(index); this._itemEntered(index);
@ -877,9 +870,9 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
_init(windows) { _init(windows) {
super._init(false); super._init(false);
this._labels = []; this._labels = new Array();
this._thumbnailBins = []; this._thumbnailBins = new Array();
this._clones = []; this._clones = new Array();
this._windows = windows; this._windows = windows;
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
@ -915,7 +908,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
return; return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding(); 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(); totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding();
let [, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let spacing = this._items[0].child.get_theme_node().get_length('spacing'); let spacing = this._items[0].child.get_theme_node().get_length('spacing');
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor; let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;
@ -940,7 +933,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
} }
// Make sure we only do this once // Make sure we only do this once
this._thumbnailBins = []; this._thumbnailBins = new Array();
} }
_removeThumbnail(source, clone) { _removeThumbnail(source, clone) {
@ -1014,9 +1007,9 @@ class WindowIcon extends St.BoxLayout {
} }
_createAppIcon(app, size) { _createAppIcon(app, size) {
let appIcon = app let appIcon = app ? app.create_icon_texture(size)
? app.create_icon_texture(size) : new St.Icon({ icon_name: 'icon-missing',
: new St.Icon({ icon_name: 'icon-missing', icon_size: size }); icon_size: size });
appIcon.x_expand = appIcon.y_expand = true; appIcon.x_expand = appIcon.y_expand = true;
appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END; appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END;
@ -1043,7 +1036,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.addItem(icon, icon.label); this.addItem(icon, icon.label);
this.icons.push(icon); this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', window => { icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
this._removeWindow(window); this._removeWindow(window);
}); });
} }

View File

@ -1,11 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
const { Clutter, GLib, Gio, St } = imports.gi; const { GLib, Gio, St } = imports.gi;
const Mainloop = imports.mainloop;
const Tweener = imports.ui.tweener;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16; var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300; var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1000; var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = class { var Animation = class {
constructor(file, width, height, speed) { constructor(file, width, height, speed) {
@ -44,7 +46,7 @@ var Animation = class {
stop() { stop() {
if (this._timeoutId > 0) { if (this._timeoutId > 0) {
GLib.source_remove(this._timeoutId); Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0; this._timeoutId = 0;
} }
@ -53,19 +55,12 @@ var Animation = class {
_loadFile(file, width, height) { _loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale(); let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false; this._isLoaded = false;
this.actor.destroy_all_children(); this.actor.destroy_all_children();
if (!validResourceScale) { if (!validResourceScale)
if (wasPlaying)
this.play();
return; return;
}
let textureCache = St.TextureCache.get_default(); let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
@ -73,9 +68,6 @@ var Animation = class {
scaleFactor, resourceScale, scaleFactor, resourceScale,
this._animationsLoaded.bind(this)); this._animationsLoaded.bind(this));
this.actor.set_child(this._animations); this.actor.set_child(this._animations);
if (wasPlaying)
this.play();
} }
_showFrame(frame) { _showFrame(frame) {
@ -145,15 +137,15 @@ var Spinner = class extends AnimatedIcon {
} }
play() { play() {
this.actor.remove_all_transitions(); Tweener.removeTweens(this.actor);
if (this._animate) { if (this._animate) {
super.play(); super.play();
this.actor.ease({ Tweener.addTween(this.actor, {
opacity: 255, opacity: 255,
delay: SPINNER_ANIMATION_DELAY, delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME, time: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR transition: 'linear'
}); });
} else { } else {
this.actor.opacity = 255; this.actor.opacity = 255;
@ -162,14 +154,16 @@ var Spinner = class extends AnimatedIcon {
} }
stop() { stop() {
this.actor.remove_all_transitions(); Tweener.removeTweens(this.actor);
if (this._animate) { if (this._animate) {
this.actor.ease({ Tweener.addTween(this.actor, {
opacity: 0, opacity: 0,
duration: SPINNER_ANIMATION_TIME, time: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
onComplete: () => super.stop() onComplete: () => {
super.stop();
}
}); });
} else { } else {
this.actor.opacity = 0; this.actor.opacity = 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getAppFavorites */
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
@ -147,11 +146,12 @@ class AppFavorites {
let app = Shell.AppSystem.get_default().lookup_app(appId); let app = Shell.AppSystem.get_default().lookup_app(appId);
let msg = _("%s has been added to your favorites.").format(app.get_name()); Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
Main.overview.setMessage(msg, { { forFeedback: true,
forFeedback: true, undoCallback: () => {
undoCallback: () => this._removeFavorite(appId), this._removeFavorite(appId);
}); }
});
} }
addFavorite(appId) { addFavorite(appId) {
@ -180,11 +180,12 @@ class AppFavorites {
if (!this._removeFavorite(appId)) if (!this._removeFavorite(appId))
return; return;
let msg = _("%s has been removed from your favorites.").format(app.get_name()); Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
Main.overview.setMessage(msg, { { forFeedback: true,
forFeedback: true, undoCallback: () => {
undoCallback: () => this._addFavorite(appId, pos), this._addFavorite(appId, pos);
}); }
});
} }
} }
Signals.addSignalMethods(AppFavorites.prototype); Signals.addSignalMethods(AppFavorites.prototype);

View File

@ -1,4 +1,3 @@
/* exported AudioDeviceSelectionDBus */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -35,7 +34,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
throw new Error('Too few devices for a selection'); throw new Error('Too few devices for a selection');
} }
_buildLayout() { _buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title', let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"), text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.CENTER });
@ -86,7 +85,6 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
box.connect('notify::height', () => { box.connect('notify::height', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
box.width = box.height; box.width = box.height;
return GLib.SOURCE_REMOVE;
}); });
}); });
@ -161,7 +159,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params; let [deviceNames] = params;
let devices = 0; let devices = 0;
deviceNames.forEach(n => (devices |= AudioDevice[n.toUpperCase()])); deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
let dialog; let dialog;
try { try {

View File

@ -99,6 +99,7 @@ const Signals = imports.signals;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff); var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
@ -109,7 +110,7 @@ const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options'; const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_URI_KEY = 'picture-uri'; const PICTURE_URI_KEY = 'picture-uri';
var FADE_ANIMATION_TIME = 1000; var FADE_ANIMATION_TIME = 1.0;
// These parameters affect how often we redraw. // These parameters affect how often we redraw.
// The first is how different (percent crossfaded) the slide show // The first is how different (percent crossfaded) the slide show
@ -332,12 +333,12 @@ var Background = class Background {
} }
_loadPattern() { _loadPattern() {
let colorString, res_, color, secondColor; let colorString, res, color, secondColor;
colorString = this._settings.get_string(PRIMARY_COLOR_KEY); 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); 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); let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
@ -441,21 +442,20 @@ var Background = class Background {
} }
_loadAnimation(file) { _loadAnimation(file) {
this._cache.getAnimation({ this._cache.getAnimation({ file: file,
file: file, settingsSchema: this._settings.schema_id,
settingsSchema: this._settings.schema_id, onLoaded: animation => {
onLoaded: animation => { this._animation = animation;
this._animation = animation;
if (!this._animation || this._cancellable.is_cancelled()) { if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded(); this._setLoaded();
return; return;
} }
this._updateAnimation(); this._updateAnimation();
this._watchFile(file); this._watchFile(file);
} }
}); });
} }
_loadImage(file) { _loadImage(file) {
@ -633,9 +633,9 @@ var Animation = class Animation {
} }
load(callback) { load(callback) {
this._show = new GnomeDesktop.BGSlideShow({ file: this.file }); this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
this._show.load_async(null, () => { this._show.load_async(null, (object, result) => {
this.loaded = true; this.loaded = true;
if (callback) if (callback)
callback(); callback();
@ -651,7 +651,7 @@ var Animation = class Animation {
if (this._show.get_num_slides() < 1) if (this._show.get_num_slides() < 1)
return; 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.transitionDuration = duration;
this.transitionProgress = progress; this.transitionProgress = progress;
@ -710,12 +710,14 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = null; this._newBackgroundActor = null;
this.emit('changed'); this.emit('changed');
oldBackgroundActor.ease({ Tweener.addTween(oldBackgroundActor,
opacity: 0, { opacity: 0,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => oldBackgroundActor.destroy() onComplete() {
}); oldBackgroundActor.destroy();
}
});
} }
_updateBackgroundActor() { _updateBackgroundActor() {
@ -749,14 +751,13 @@ var BackgroundManager = class BackgroundManager {
_createBackgroundActor() { _createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex); let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
meta_display: global.display, monitor: this._monitorIndex,
monitor: this._monitorIndex, background: background.background,
background: background.background, vignette: this._vignette,
vignette: this._vignette, vignette_sharpness: 0.5,
vignette_sharpness: 0.5, brightness: 0.5,
brightness: 0.5, });
});
this._container.add_child(backgroundActor); this._container.add_child(backgroundActor);

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addBackgroundMenu */
const { Clutter, St } = imports.gi; const { Clutter, St } = imports.gi;
@ -31,7 +30,7 @@ function addBackgroundMenu(actor, layoutManager) {
function openMenu(x, y) { function openMenu(x, y) {
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.FULL); actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
} }
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();

View File

@ -1,106 +1,71 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported BarLevel */
const { Atk, Clutter, GObject, St } = imports.gi; const { Atk, Clutter, St } = imports.gi;
const Signals = imports.signals;
var BarLevel = GObject.registerClass({ var BarLevel = class {
Properties: { constructor(value, params = {}) {
'value': GObject.ParamSpec.double( if (isNaN(value))
'value', 'value', 'value', // Avoid spreading NaNs around
GObject.ParamFlags.READWRITE, throw TypeError('The bar level value must be a number');
0, 2, 0),
'maximum-value': GObject.ParamSpec.double(
'maximum-value', 'maximum-value', 'maximum-value',
GObject.ParamFlags.READWRITE,
1, 2, 1),
'overdrive-start': GObject.ParamSpec.double(
'overdrive-start', 'overdrive-start', 'overdrive-start',
GObject.ParamFlags.READWRITE,
1, 2, 1)
}
}, class BarLevel extends St.DrawingArea {
_init(params) {
this._maxValue = 1; this._maxValue = 1;
this._value = 0; this._value = Math.max(Math.min(value, this._maxValue), 0);
this._overdriveStart = 1; this._overdriveStart = 1;
this._barLevelWidth = 0; this._barLevelWidth = 0;
let defaultParams = { this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
style_class: 'barlevel', can_focus: params['canFocus'] || false,
accessible_role: Atk.Role.LEVEL_BAR reactive: params['reactive'] || false,
}; accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
super._init(Object.assign(defaultParams, params)); this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.connect('allocation-changed', (actor, box) => { this.actor.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width(); this._barLevelWidth = box.get_width();
}); });
this._customAccessible = St.GenericAccessible.new_for_actor(this); this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.set_accessible(this._customAccessible); this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this)); this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this)); this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this)); this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this)); this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('notify::value', this._valueChanged.bind(this)); this.connect('value-changed', this._valueChanged.bind(this));
} }
get value() { setValue(value) {
return this._value; if (isNaN(value))
throw TypeError('The bar level value must be a number');
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
} }
set value(value) { setMaximumValue(value) {
value = Math.max(Math.min(value, this._maxValue), 0); if (isNaN(value))
throw TypeError('The bar level max value must be a number');
if (this._value == value) this._maxValue = Math.max(value, 1);
return;
this._value = value;
this.notify('value');
this.queue_repaint();
}
// eslint-disable-next-line camelcase
get maximum_value() {
return this._maxValue;
}
// eslint-disable-next-line camelcase
set maximum_value(value) {
value = Math.max(value, 1);
if (this._maxValue == value)
return;
this._maxValue = value;
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue); this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.notify('maximum-value'); this.actor.queue_repaint();
this.queue_repaint();
} }
// eslint-disable-next-line camelcase setOverdriveStart(value) {
get overdrive_start() { if (isNaN(value))
return this._overdriveStart; throw TypeError('The overdrive limit value must be a number');
}
// eslint-disable-next-line camelcase
set overdrive_start(value) {
if (this._overdriveStart == value)
return;
if (value > this._maxValue) if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` + throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`); `which is a number greater than the maximum allowed value ${this._maxValue}`);
this._overdriveStart = value; this._overdriveStart = value;
this.notify('overdrive-start'); this._value = Math.max(Math.min(value, this._maxValue), 0);
this.queue_repaint(); this.actor.queue_repaint();
} }
vfunc_repaint() { _barLevelRepaint(area) {
let cr = this.get_context(); let cr = area.get_context();
let themeNode = this.get_theme_node(); let themeNode = area.get_theme_node();
let [width, height] = this.get_surface_size(); let [width, height] = area.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height'); let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2; let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
@ -207,27 +172,32 @@ var BarLevel = GObject.registerClass({
cr.$dispose(); cr.$dispose();
} }
_getCurrentValue() { _getCurrentValue(actor) {
return this._value; return this._value;
} }
_getOverdriveStart() { _getOverdriveStart(actor) {
return this._overdriveStart; return this._overdriveStart;
} }
_getMinimumValue() { _getMinimumValue(actor) {
return 0; return 0;
} }
_getMaximumValue() { _getMaximumValue(actor) {
return this._maxValue; return this._maxValue;
} }
_setCurrentValue(_actor, value) { _setCurrentValue(actor, value) {
this._value = value; this._value = value;
} }
_valueChanged() { _valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value"); this._customAccessible.notify("accessible-value");
} }
});
get value() {
return this._value;
}
};
Signals.addSignalMethods(BarLevel.prototype);

View File

@ -1,9 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BoxPointer */
const { Clutter, GObject, Shell, St } = imports.gi; const { Clutter, GObject, Shell, St } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var PopupAnimation = { var PopupAnimation = {
NONE: 0, NONE: 0,
@ -12,7 +12,7 @@ var PopupAnimation = {
FULL: ~0, FULL: ~0,
}; };
var POPUP_ANIMATION_TIME = 150; var POPUP_ANIMATION_TIME = 0.15;
/** /**
* BoxPointer: * BoxPointer:
@ -105,18 +105,16 @@ var BoxPointer = GObject.registerClass({
} }
} }
this.ease({ Tweener.addTween(this, { opacity: 255,
opacity: 255, translation_x: 0,
translation_x: 0, translation_y: 0,
translation_y: 0, transition: 'linear',
duration: animationTime, onComplete: () => {
mode: Clutter.AnimationMode.LINEAR, this._unmuteInput();
onComplete: () => { if (onComplete)
this._unmuteInput(); onComplete();
if (onComplete) },
onComplete(); time: animationTime });
}
});
} }
close(animate, onComplete) { close(animate, onComplete) {
@ -149,22 +147,21 @@ var BoxPointer = GObject.registerClass({
this._muteInput(); this._muteInput();
this.remove_all_transitions(); Tweener.removeTweens(this);
this.ease({ Tweener.addTween(this, { opacity: fade ? 0 : 255,
opacity: fade ? 0 : 255, translation_x: translationX,
translation_x: translationX, translation_y: translationY,
translation_y: translationY, transition: 'linear',
duration: animationTime, time: animationTime,
mode: Clutter.AnimationMode.LINEAR, onComplete: () => {
onComplete: () => { this.hide();
this.hide(); this.opacity = 0;
this.opacity = 0; this.translation_x = 0;
this.translation_x = 0; this.translation_y = 0;
this.translation_y = 0; if (onComplete)
if (onComplete) onComplete();
onComplete(); }
} });
});
} }
_adjustAllocationForArrow(isWidth, minSize, natSize) { _adjustAllocationForArrow(isWidth, minSize, natSize) {
@ -172,8 +169,8 @@ var BoxPointer = GObject.registerClass({
let borderWidth = themeNode.get_length('-arrow-border-width'); let borderWidth = themeNode.get_length('-arrow-border-width');
minSize += borderWidth * 2; minSize += borderWidth * 2;
natSize += borderWidth * 2; natSize += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) || if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
(isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) { || (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
minSize += rise; minSize += rise;
natSize += rise; natSize += rise;
@ -472,7 +469,7 @@ var BoxPointer = GObject.registerClass({
let sourceAllocation = this._sourceAllocation; let sourceAllocation = this._sourceAllocation;
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment; 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 sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [, , natWidth, natHeight] = this.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
// We also want to keep it onscreen, and separated from the // We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is // edge by the same distance as the main part of the box is
@ -597,7 +594,7 @@ var BoxPointer = GObject.registerClass({
_calculateArrowSide(arrowSide) { _calculateArrowSide(arrowSide) {
let sourceAllocation = this._sourceAllocation; let sourceAllocation = this._sourceAllocation;
let [, , boxWidth, boxHeight] = this.get_preferred_size(); let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let workarea = this._workArea; let workarea = this._workArea;
switch (arrowSide) { switch (arrowSide) {

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi; const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -110,15 +109,15 @@ var EmptyEventSource = class EmptyEventSource {
destroy() { destroy() {
} }
requestRange(_begin, _end) { requestRange(begin, end) {
} }
getEvents(_begin, _end) { getEvents(begin, end) {
let result = []; let result = [];
return result; return result;
} }
hasEvents(_day) { hasEvents(day) {
return false; return false;
} }
}; };
@ -221,13 +220,13 @@ var DBusEventSource = class DBusEventSource {
this._lastRequestEnd = null; this._lastRequestEnd = null;
} }
_onNameAppeared() { _onNameAppeared(owner) {
this._initialized = true; this._initialized = true;
this._resetCache(); this._resetCache();
this._loadEvents(true); this._loadEvents(true);
} }
_onNameVanished() { _onNameVanished(oldOwner) {
this._resetCache(); this._resetCache();
this.emit('changed'); this.emit('changed');
} }
@ -236,7 +235,7 @@ var DBusEventSource = class DBusEventSource {
this._loadEvents(false); this._loadEvents(false);
} }
_onEventsReceived(results, _error) { _onEventsReceived(results, error) {
let newEvents = []; let newEvents = [];
let appointments = results[0] || []; let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) { for (let n = 0; n < appointments.length; n++) {
@ -581,9 +580,8 @@ var Calendar = class Calendar {
if (row == 2) if (row == 2)
styleClass = `calendar-day-top ${styleClass}`; styleClass = `calendar-day-top ${styleClass}`;
let leftMost = rtl let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
? iter.getDay() == (this._weekStart + 6) % 7 : iter.getDay() == this._weekStart;
: iter.getDay() == this._weekStart;
if (leftMost) if (leftMost)
styleClass = `calendar-day-left ${styleClass}`; styleClass = `calendar-day-left ${styleClass}`;
@ -681,24 +679,23 @@ var EventMessage = class EventMessage extends MessageList.Message {
*/ */
title = C_("event list time", "All Day"); title = C_("event list time", "All Day");
} else { } else {
let date = this._event.date >= periodBegin let date = this._event.date >= periodBegin ? this._event.date
? this._event.date : this._event.end;
: this._event.end;
title = Util.formatTime(date, { timeOnly: true }); title = Util.formatTime(date, { timeOnly: true });
} }
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
if (this._event.date < periodBegin && !this._event.allDay) { if (this._event.date < periodBegin && !this._event.allDay) {
if (rtl) if (rtl)
title = `${title}${ELLIPSIS_CHAR}`; title = title + ELLIPSIS_CHAR;
else else
title = `${ELLIPSIS_CHAR}${title}`; title = ELLIPSIS_CHAR + title;
} }
if (this._event.end > periodEnd && !this._event.allDay) { if (this._event.end > periodEnd && !this._event.allDay) {
if (rtl) if (rtl)
title = `${ELLIPSIS_CHAR}${title}`; title = ELLIPSIS_CHAR + title;
else else
title = `${title}${ELLIPSIS_CHAR}`; title = title + ELLIPSIS_CHAR;
} }
return title; return title;
} }
@ -737,7 +734,7 @@ class NotificationMessage extends MessageList.Message {
return this.notification.source.createIcon(MESSAGE_ICON_SIZE); return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
} }
_onUpdated(n, _clear) { _onUpdated(n, clear) {
this.setIcon(this._getIcon()); this.setIcon(this._getIcon());
this.setTitle(n.title); this.setTitle(n.title);
this.setBody(n.bannerBodyText); this.setBody(n.bannerBodyText);
@ -1073,14 +1070,10 @@ var CalendarMessageList = class CalendarMessageList {
this._clearButton.set_x_align(Clutter.ActorAlign.END); this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => { this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()]; let sections = [...this._sections.keys()];
sections.forEach(s => s.clear()); sections.forEach((s) => s.clear());
}); });
box.add_actor(this._clearButton); box.add_actor(this._clearButton);
this._placeholder.actor.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections', this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true, vertical: true,
y_expand: true, y_expand: true,
@ -1151,6 +1144,7 @@ var CalendarMessageList = class CalendarMessageList {
let empty = sections.every(s => s.empty || !s.actor.visible); let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty; this._placeholder.actor.visible = empty;
this._clearButton.visible = !empty;
let canClear = sections.some(s => s.canClear && s.actor.visible); let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear; this._clearButton.reactive = canClear;

View File

@ -1,4 +1,3 @@
/* exported CheckBox */
const { Clutter, Pango, St } = imports.gi; const { Clutter, Pango, St } = imports.gi;
var CheckBox = class CheckBox { var CheckBox = class CheckBox {

View File

@ -1,13 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var FROZEN_WINDOW_BRIGHTNESS = -0.3; var FROZEN_WINDOW_BRIGHTNESS = -0.3;
var DIALOG_TRANSITION_TIME = 150; var DIALOG_TRANSITION_TIME = 0.15;
var ALIVE_TIMEOUT = 5000; var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({ var CloseDialog = GObject.registerClass({
@ -148,12 +148,12 @@ var CloseDialog = GObject.registerClass({
this._dialog.scale_y = 0; this._dialog.scale_y = 0;
this._dialog.set_pivot_point(0.5, 0.5); this._dialog.set_pivot_point(0.5, 0.5);
this._dialog.ease({ Tweener.addTween(this._dialog,
scale_y: 1, { scale_y: 1,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
duration: DIALOG_TRANSITION_TIME, time: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this) onComplete: this._onFocusChanged.bind(this)
}); });
} }
vfunc_hide() { vfunc_hide() {
@ -175,12 +175,14 @@ var CloseDialog = GObject.registerClass({
this._dialog = null; this._dialog = null;
this._removeWindowEffect(); this._removeWindowEffect();
dialog.ease({ Tweener.addTween(dialog,
scale_y: 0, { scale_y: 0,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
duration: DIALOG_TRANSITION_TIME, time: DIALOG_TRANSITION_TIME,
onComplete: () => dialog.destroy() onComplete: () => {
}); dialog.destroy();
}
});
} }
vfunc_focus() { vfunc_focus() {

View File

@ -1,4 +1,3 @@
/* exported ComponentManager */
const Main = imports.ui.main; const Main = imports.ui.main;
var ComponentManager = class { var ComponentManager = class {

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, GLib } = imports.gi; const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
const Params = imports.misc.params; const Params = imports.misc.params;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
@ -38,7 +38,7 @@ var AutomountManager = class {
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', this._onDriveDisconnected.bind(this)); this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', this._onDriveDisconnected.bind(this));
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', this._onDriveEjectButton.bind(this)); this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', this._onDriveEjectButton.bind(this));
this._mountAllId = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._startupMountAll.bind(this)); this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll'); GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
} }
@ -50,12 +50,12 @@ var AutomountManager = class {
this._volumeMonitor.disconnect(this._driveEjectButtonId); this._volumeMonitor.disconnect(this._driveEjectButtonId);
if (this._mountAllId > 0) { if (this._mountAllId > 0) {
GLib.source_remove(this._mountAllId); Mainloop.source_remove(this._mountAllId);
this._mountAllId = 0; this._mountAllId = 0;
} }
} }
_InhibitorsChanged(_object, _senderName, [_inhibitor]) { _InhibitorsChanged(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT, this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
(result, error) => { (result, error) => {
if (!error) { if (!error) {
@ -156,7 +156,7 @@ var AutomountManager = class {
!volume.should_automount() || !volume.should_automount() ||
!volume.can_mount()) { !volume.can_mount()) {
// allow the autorun to run anyway; this can happen if the // allow the autorun to run anyway; this can happen if the
// mount gets added programmatically later, even if // mount gets added programmatically later, even if
// should_automount() or can_mount() are false, like for // should_automount() or can_mount() are false, like for
// blank optical media. // blank optical media.
this._allowAutorun(volume); this._allowAutorun(volume);
@ -219,17 +219,17 @@ var AutomountManager = class {
_onVolumeRemoved(monitor, volume) { _onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) { if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
GLib.source_remove(volume._allowAutorunExpireId); Mainloop.source_remove(volume._allowAutorunExpireId);
delete volume._allowAutorunExpireId; delete volume._allowAutorunExpireId;
} }
this._volumeQueue = this._volumeQueue =
this._volumeQueue.filter(element => (element != volume)); this._volumeQueue.filter(element => (element != volume));
} }
_reaskPassword(volume) { _reaskPassword(volume) {
let prevOperation = this._activeOperations.get(volume); let prevOperation = this._activeOperations.get(volume);
let existingDialog = prevOperation ? prevOperation.borrowDialog() : null; let existingDialog = prevOperation ? prevOperation.borrowDialog() : null;
let operation = let operation =
new ShellMountOperation.ShellMountOperation(volume, new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog: existingDialog }); { existingDialog: existingDialog });
this._mountVolume(volume, operation); this._mountVolume(volume, operation);
@ -248,7 +248,7 @@ var AutomountManager = class {
} }
_allowAutorunExpire(volume) { _allowAutorunExpire(volume) {
let id = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, AUTORUN_EXPIRE_TIMEOUT_SECS, () => { let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false; volume.allowAutorun = false;
delete volume._allowAutorunExpireId; delete volume._allowAutorunExpireId;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, St } = imports.gi; const { Gio, St } = imports.gi;
@ -63,7 +62,7 @@ function startAppForMount(app, mount) {
files.push(root); files.push(root);
try { try {
retval = app.launch(files, retval = app.launch(files,
global.create_app_launch_context(0, -1)); global.create_app_launch_context(0, -1));
} catch (e) { } catch (e) {
log(`Unable to launch the application ${app.get_name()}: ${e}`); log(`Unable to launch the application ${app.get_name()}: ${e}`);
@ -72,6 +71,8 @@ function startAppForMount(app, mount) {
return retval; return retval;
} }
/******************************************/
const HotplugSnifferIface = loadInterfaceXML('org.gnome.Shell.HotplugSniffer'); const HotplugSnifferIface = loadInterfaceXML('org.gnome.Shell.HotplugSniffer');
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface); const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() { function HotplugSniffer() {
@ -115,9 +116,9 @@ var ContentTypeDiscoverer = class {
let hotplugSniffer = new HotplugSniffer(); let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(), hotplugSniffer.SniffURIRemote(root.get_uri(),
([contentTypes]) => { ([contentTypes]) => {
this._emitCallback(mount, contentTypes); this._emitCallback(mount, contentTypes);
}); });
} }
} }
@ -213,11 +214,11 @@ var AutorunDispatcher = class {
} }
_addSource(mount, apps) { _addSource(mount, apps) {
// if we already have a source showing for this // if we already have a source showing for this
// mount, return // mount, return
if (this._getSourceForMount(mount)) if (this._getSourceForMount(mount))
return; return;
// add a new source // add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps)); this._sources.push(new AutorunSource(this._manager, mount, apps));
} }
@ -262,7 +263,7 @@ var AutorunDispatcher = class {
removeMount(mount) { removeMount(mount) {
let source = this._getSourceForMount(mount); let source = this._getSourceForMount(mount);
// if we aren't tracking this mount, don't do anything // if we aren't tracking this mount, don't do anything
if (!source) if (!source)
return; return;
@ -323,10 +324,10 @@ var AutorunNotification = class extends MessageTray.Notification {
style_class: 'hotplug-notification-item-icon' }); style_class: 'hotplug-notification-item-icon' });
box.add(icon); box.add(icon);
let label = new St.Bin({ let label = new St.Bin({ y_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE, child: new St.Label
child: new St.Label({ text: _("Open with %s").format(app.get_name()) }), ({ text: _("Open with %s").format(app.get_name()) })
}); });
box.add(label); box.add(label);
let button = new St.Button({ child: box, let button = new St.Button({ child: box,

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi; const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
@ -177,21 +176,21 @@ class KeyringDialog extends ModalDialog.ModalDialog {
return false; return false;
} }
_onShowPassword() { _onShowPassword(prompt) {
this._buildControlTable(); this._buildControlTable();
this._ensureOpen(); this._ensureOpen();
this._updateSensitivity(true); this._updateSensitivity(true);
this._passwordEntry.grab_key_focus(); this._passwordEntry.grab_key_focus();
} }
_onShowConfirm() { _onShowConfirm(prompt) {
this._buildControlTable(); this._buildControlTable();
this._ensureOpen(); this._ensureOpen();
this._updateSensitivity(true); this._updateSensitivity(true);
this._continueButton.grab_key_focus(); this._continueButton.grab_key_focus();
} }
_onHidePrompt() { _onHidePrompt(prompt) {
this.close(); this.close();
} }
@ -232,9 +231,8 @@ var KeyringPrompter = class {
constructor() { constructor() {
this._prompter = new Gcr.SystemPrompter(); this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => { this._prompter.connect('new-prompt', () => {
let dialog = this._enabled let dialog = this._enabled ? new KeyringDialog()
? new KeyringDialog() : new KeyringDummyDialog();
: new KeyringDummyDialog();
this._currentPrompt = dialog.prompt; this._currentPrompt = dialog.prompt;
return this._currentPrompt; return this._currentPrompt;
}); });

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -112,17 +111,16 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
expand: true }); expand: true });
} }
this._okButton = { this._okButton = { label: _("Connect"),
label: _("Connect"), action: this._onOk.bind(this),
action: this._onOk.bind(this), default: true
default: true, };
};
this.setButtons([{ this.setButtons([{ label: _("Cancel"),
label: _("Cancel"), action: this.cancel.bind(this),
action: this.cancel.bind(this), key: Clutter.KEY_Escape,
key: Clutter.KEY_Escape, },
}, this._okButton]); this._okButton]);
this._updateOkButton(); this._updateOkButton();
} }
@ -164,9 +162,9 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (value.length == 64) { if (value.length == 64) {
// must be composed of hexadecimal digits only // must be composed of hexadecimal digits only
for (let i = 0; i < 64; i++) { for (let i = 0; i < 64; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f') || if (!((value[i] >= 'a' && value[i] <= 'f')
(value[i] >= 'A' && value[i] <= 'F') || || (value[i] >= 'A' && value[i] <= 'F')
(value[i] >= '0' && value[i] <= '9'))) || (value[i] >= '0' && value[i] <= '9')))
return false; return false;
} }
return true; return true;
@ -180,15 +178,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (secret.wep_key_type == NM.WepKeyType.KEY) { if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) { if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f') || if (!((value[i] >= 'a' && value[i] <= 'f')
(value[i] >= 'A' && value[i] <= 'F') || || (value[i] >= 'A' && value[i] <= 'F')
(value[i] >= '0' && value[i] <= '9'))) || (value[i] >= '0' && value[i] <= '9')))
return false; return false;
} }
} else if (value.length == 5 || value.length == 13) { } else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'z') || if (!((value[i] >= 'a' && value[i] <= 'z')
(value[i] >= 'A' && value[i] <= 'Z'))) || (value[i] >= 'A' && value[i] <= 'Z')))
return false; return false;
} }
} else { } else {
@ -201,7 +199,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
return true; return true;
} }
_getWirelessSecrets(secrets, _wirelessSetting) { _getWirelessSecrets(secrets, wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security(); let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
if (this._settingName == '802-1x') { if (this._settingName == '802-1x') {
@ -213,7 +211,6 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
// First the easy ones // First the easy ones
case 'wpa-none': case 'wpa-none':
case 'wpa-psk': case 'wpa-psk':
case 'sae':
secrets.push({ label: _("Password: "), key: 'psk', secrets.push({ label: _("Password: "), key: 'psk',
value: wirelessSecuritySetting.psk || '', value: wirelessSecuritySetting.psk || '',
validate: this._validateWpaPsk, password: true }); validate: this._validateWpaPsk, password: true });
@ -388,7 +385,7 @@ var VPNRequestHandler = class {
this._newStylePlugin = authHelper.externalUIMode; this._newStylePlugin = authHelper.externalUIMode;
try { try {
let [success_, pid, stdin, stdout, stderr] = let [success, pid, stdin, stdout, stderr] =
GLib.spawn_async_with_pipes(null, /* pwd */ GLib.spawn_async_with_pipes(null, /* pwd */
argv, argv,
null, /* envp */ null, /* envp */
@ -447,7 +444,7 @@ var VPNRequestHandler = class {
this._destroyed = true; this._destroyed = true;
} }
_vpnChildFinished(pid, status, _requestObj) { _vpnChildFinished(pid, status, requestObj) {
this._childWatch = 0; this._childWatch = 0;
if (this._newStylePlugin) { if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions // For new style plugin, all work is done in the async reading functions
@ -489,7 +486,7 @@ var VPNRequestHandler = class {
_readStdoutOldStyle() { _readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => { 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) { if (line == null) {
// end of file // end of file
@ -544,7 +541,7 @@ var VPNRequestHandler = class {
message: keyfile.get_string(VPN_UI_GROUP, 'Description'), message: keyfile.get_string(VPN_UI_GROUP, 'Description'),
secrets: [] }; secrets: [] };
let [groups, len_] = keyfile.get_groups(); let [groups, len] = keyfile.get_groups();
for (let i = 0; i < groups.length; i++) { for (let i = 0; i < groups.length; i++) {
if (groups[i] == VPN_UI_GROUP) if (groups[i] == VPN_UI_GROUP)
continue; continue;
@ -553,12 +550,11 @@ var VPNRequestHandler = class {
let shouldAsk = keyfile.get_boolean(groups[i], 'ShouldAsk'); let shouldAsk = keyfile.get_boolean(groups[i], 'ShouldAsk');
if (shouldAsk) { if (shouldAsk) {
contentOverride.secrets.push({ contentOverride.secrets.push({ label: keyfile.get_string(groups[i], 'Label'),
label: keyfile.get_string(groups[i], 'Label'), key: groups[i],
key: groups[i], value: value,
value: value, password: keyfile.get_boolean(groups[i], 'IsSecret')
password: keyfile.get_boolean(groups[i], 'IsSecret'), });
});
} else { } else {
if (!value.length) // Ignore empty secrets if (!value.length) // Ignore empty secrets
continue; continue;
@ -612,11 +608,10 @@ Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = class { var NetworkAgent = class {
constructor() { constructor() {
this._native = new Shell.NetworkAgent({ this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
identifier: 'org.gnome.Shell.NetworkAgent', capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
capabilities: NM.SecretAgentCapabilities.VPN_HINTS, auto_register: false
auto_register: false, });
});
this._dialogs = { }; this._dialogs = { };
this._vpnRequests = { }; this._vpnRequests = { };
@ -625,7 +620,7 @@ var NetworkAgent = class {
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR); this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try { try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null); let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => (this._vpnCacheBuilt = false)); monitor.connect('changed', () => this._vpnCacheBuilt = false);
} catch (e) { } catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`); log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
} }

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { AccountsService, Clutter, Gio, GLib, const { AccountsService, Clutter, Gio, GLib,
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi; GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
@ -384,11 +383,11 @@ var AuthenticationAgent = class {
this._currentDialog.performAuthentication(); this._currentDialog.performAuthentication();
} }
_onCancel(_nativeAgent) { _onCancel(nativeAgent) {
this._completeRequest(false); this._completeRequest(false);
} }
_onDialogDone(_dialog, dismissed) { _onDialogDone(dialog, dismissed) {
this._completeRequest(dismissed); this._completeRequest(dismissed);
} }

View File

@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, St } = imports.gi; const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop;
var Tpl = null; var Tpl = null;
var Tp = null; var Tp = null;
@ -41,7 +41,7 @@ var NotificationDirection = {
}; };
function makeMessageFromTpMessage(tpMessage, direction) { function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags_] = tpMessage.to_text(); let [text, flags] = tpMessage.to_text();
let timestamp = tpMessage.get_sent_timestamp(); let timestamp = tpMessage.get_sent_timestamp();
if (timestamp == 0) if (timestamp == 0)
@ -148,11 +148,11 @@ class TelepathyClient extends Tp.BaseClient {
} }
vfunc_observe_channels(...args) { vfunc_observe_channels(...args) {
let [account, conn, channels, dispatchOp_, requests_, context] = args; let [account, conn, channels, dispatchOp, requests, context] = args;
let len = channels.length; let len = channels.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
let channel = channels[i]; let channel = channels[i];
let [targetHandle_, targetHandleType] = channel.get_handle(); let [targetHandle, targetHandleType] = channel.get_handle();
if (channel.get_invalidated()) if (channel.get_invalidated())
continue; continue;
@ -181,7 +181,7 @@ class TelepathyClient extends Tp.BaseClient {
} }
vfunc_handle_channels(...args) { 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); this._handlingChannels(account, conn, channels, true);
context.accept(); context.accept();
} }
@ -239,7 +239,7 @@ class TelepathyClient extends Tp.BaseClient {
} }
_approveTextChannel(account, conn, channel, dispatchOp, context) { _approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle_, targetHandleType] = channel.get_handle(); let [targetHandle, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) { if (targetHandleType != Tp.HandleType.CONTACT) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT, context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
@ -260,7 +260,7 @@ class TelepathyClient extends Tp.BaseClient {
context.accept(); context.accept();
} }
_delegatedChannelsCb(_client, _channels) { _delegatedChannelsCb(client, channels) {
// Nothing to do as we don't make a distinction between observed and // Nothing to do as we don't make a distinction between observed and
// handled channels. // handled channels.
} }
@ -427,7 +427,7 @@ var ChatSource = class extends MessageTray.Source {
} }
_displayPendingMessages(logManager, result) { _displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result); let [success, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(makeMessageFromTplEvent); let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification(); this._ensureNotification();
@ -545,8 +545,8 @@ var ChatSource = class extends MessageTray.Source {
// Wait a bit before notifying for the received message, a handler // Wait a bit before notifying for the received message, a handler
// could ack it in the meantime. // could ack it in the meantime.
if (this._notifyTimeoutId != 0) if (this._notifyTimeoutId != 0)
GLib.source_remove(this._notifyTimeoutId); Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, this._notifyTimeoutId = Mainloop.timeout_add(500,
this._notifyTimeout.bind(this)); this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout'); GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
} }
@ -562,7 +562,7 @@ var ChatSource = class extends MessageTray.Source {
// This is called for both messages we send from // This is called for both messages we send from
// our client and other clients as well. // our client and other clients as well.
_messageSent(channel, message, _flags, _token) { _messageSent(channel, message, flags, token) {
this._ensureNotification(); this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT); message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message); this._notification.appendMessage(message);
@ -583,7 +583,7 @@ var ChatSource = class extends MessageTray.Source {
let msg = Tp.ClientMessage.new_text(type, text); let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0, (src, result) => { this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result); this._channel.send_message_finish(result);
}); });
} }
@ -600,7 +600,7 @@ var ChatSource = class extends MessageTray.Source {
} }
} }
_presenceChanged(_contact, _presence, _status, _message) { _presenceChanged(contact, presence, status, message) {
if (this._notification) if (this._notification)
this._notification.update(this._notification.title, this._notification.update(this._notification.title,
this._notification.bannerBodyText, this._notification.bannerBodyText,
@ -640,7 +640,7 @@ var ChatNotification = class extends MessageTray.Notification {
destroy(reason) { destroy(reason) {
if (this._timestampTimeoutId) if (this._timestampTimeoutId)
GLib.source_remove(this._timestampTimeoutId); Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
super.destroy(reason); super.destroy(reason);
} }
@ -653,7 +653,7 @@ var ChatNotification = class extends MessageTray.Notification {
* sender: the name of the sender, * sender: the name of the sender,
* timestamp: the time the message was sent * timestamp: the time the message was sent
* direction: a #NotificationDirection * direction: a #NotificationDirection
* *
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp * @noTimestamp: Whether to add a timestamp. If %true, no timestamp
* will be added, regardless of the difference since the * will be added, regardless of the difference since the
* last timestamp * last timestamp
@ -673,8 +673,8 @@ var ChatNotification = class extends MessageTray.Notification {
{ datetime: GLib.DateTime.new_from_unix_local (message.timestamp), { datetime: GLib.DateTime.new_from_unix_local (message.timestamp),
bannerMarkup: true }); bannerMarkup: true });
let group = (message.direction == NotificationDirection.RECEIVED let group = (message.direction == NotificationDirection.RECEIVED ?
? 'received' : 'sent'); 'received' : 'sent');
this._append({ body: messageBody, this._append({ body: messageBody,
group: group, group: group,
@ -696,8 +696,8 @@ var ChatNotification = class extends MessageTray.Notification {
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise // SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
// we'll keep SCROLLBACK_IDLE_LENGTH messages. // we'll keep SCROLLBACK_IDLE_LENGTH messages.
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ?
? SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH; SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(item => item.realMessage); let filteredHistory = this.messages.filter(item => item.realMessage);
if (filteredHistory.length > maxLength) { if (filteredHistory.length > maxLength) {
@ -728,7 +728,7 @@ var ChatNotification = class extends MessageTray.Notification {
// Reset the old message timeout // Reset the old message timeout
if (this._timestampTimeoutId) if (this._timestampTimeoutId)
GLib.source_remove(this._timestampTimeoutId); Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
let message = { realMessage: props.group != 'meta', let message = { realMessage: props.group != 'meta',
@ -746,8 +746,7 @@ var ChatNotification = class extends MessageTray.Notification {
} else { } else {
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME // Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
// from the timestamp of the message. // from the timestamp of the message.
this._timestampTimeoutId = GLib.timeout_add_seconds( this._timestampTimeoutId = Mainloop.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp), SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
this.appendTimestamp.bind(this)); this.appendTimestamp.bind(this));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp'); GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
@ -952,15 +951,14 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
// Remove composing timeout. // Remove composing timeout.
if (this._composingTimeoutId > 0) { if (this._composingTimeoutId > 0) {
GLib.source_remove(this._composingTimeoutId); Mainloop.source_remove(this._composingTimeoutId);
this._composingTimeoutId = 0; this._composingTimeoutId = 0;
} }
if (text != '') { if (text != '') {
this.notification.source.setChatState(Tp.ChannelChatState.COMPOSING); this.notification.source.setChatState(Tp.ChannelChatState.COMPOSING);
this._composingTimeoutId = GLib.timeout_add_seconds( this._composingTimeoutId = Mainloop.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
COMPOSING_STOP_TIMEOUT, COMPOSING_STOP_TIMEOUT,
this._composingStopTimeout.bind(this)); this._composingStopTimeout.bind(this));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout'); GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CtrlAltTabManager */
const { Clutter, GObject, Meta, Shell, St } = imports.gi; const { Clutter, GObject, Meta, Shell, St } = imports.gi;
@ -64,8 +63,9 @@ var CtrlAltTabManager = class CtrlAltTabManager {
if (a.sortGroup != b.sortGroup) if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup; return a.sortGroup - b.sortGroup;
let [ax] = a.proxy.get_transformed_position(); let ax, bx, y;
let [bx] = b.proxy.get_transformed_position(); [ax, y] = a.proxy.get_transformed_position();
[bx, y] = b.proxy.get_transformed_position();
return ax - bx; return ax - bx;
} }

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
@ -9,10 +9,11 @@ const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var DASH_ANIMATION_TIME = 200; var DASH_ANIMATION_TIME = 0.2;
var DASH_ITEM_LABEL_SHOW_TIME = 150; var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
var DASH_ITEM_LABEL_HIDE_TIME = 100; var DASH_ITEM_LABEL_HIDE_TIME = 0.1;
var DASH_ITEM_HOVER_TIMEOUT = 300; var DASH_ITEM_HOVER_TIMEOUT = 300;
function getAppFromSource(source) { function getAppFromSource(source) {
@ -23,30 +24,6 @@ function getAppFromSource(source) {
} }
} }
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
constructor(app) {
super(app, {
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 // A container like StBin, but taking the child's scale into account
// when requesting a size // when requesting a size
var DashItemContainer = GObject.registerClass( var DashItemContainer = GObject.registerClass(
@ -54,9 +31,6 @@ class DashItemContainer extends St.Widget {
_init() { _init() {
super._init({ style_class: 'dash-item-container', super._init({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }), pivot_point: new Clutter.Point({ x: .5, y: .5 }),
scale_x: 0,
scale_y: 0,
opacity: 0,
x_expand: true, x_expand: true,
x_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.CENTER });
@ -67,11 +41,10 @@ class DashItemContainer extends St.Widget {
this.label_actor = this.label; this.label_actor = this.label;
this.child = null; this.child = null;
this._childScale = 0;
this._childOpacity = 0;
this.animatingOut = false; this.animatingOut = false;
this.connect('notify::scale-x', () => this.queue_relayout());
this.connect('notify::scale-y', () => this.queue_relayout());
this.connect('destroy', () => { this.connect('destroy', () => {
if (this.child != null) if (this.child != null)
this.child.destroy(); this.child.destroy();
@ -122,11 +95,11 @@ class DashItemContainer extends St.Widget {
x = stageX + this.get_width() + xOffset; x = stageX + this.get_width() + xOffset;
this.label.set_position(x, y); this.label.set_position(x, y);
this.label.ease({ Tweener.addTween(this.label,
opacity: 255, { opacity: 255,
duration: DASH_ITEM_LABEL_SHOW_TIME, time: DASH_ITEM_LABEL_SHOW_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad',
}); });
} }
setLabelText(text) { setLabelText(text) {
@ -135,12 +108,14 @@ class DashItemContainer extends St.Widget {
} }
hideLabel() { hideLabel() {
this.label.ease({ Tweener.addTween(this.label,
opacity: 0, { opacity: 0,
duration: DASH_ITEM_LABEL_HIDE_TIME, time: DASH_ITEM_LABEL_HIDE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => this.label.hide() onComplete: () => {
}); this.label.hide();
}
});
} }
setChild(actor) { setChild(actor) {
@ -151,6 +126,9 @@ class DashItemContainer extends St.Widget {
this.child = actor; this.child = actor;
this.add_actor(this.child); this.add_actor(this.child);
this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity);
} }
show(animate) { show(animate) {
@ -158,13 +136,12 @@ class DashItemContainer extends St.Widget {
return; return;
let time = animate ? DASH_ANIMATION_TIME : 0; let time = animate ? DASH_ANIMATION_TIME : 0;
this.ease({ Tweener.addTween(this,
scale_x: 1, { childScale: 1.0,
scale_y: 1, childOpacity: 255,
opacity: 255, time: time,
duration: time, transition: 'easeOutQuad'
mode: Clutter.AnimationMode.EASE_OUT_QUAD });
});
} }
animateOutAndDestroy() { animateOutAndDestroy() {
@ -176,14 +153,37 @@ class DashItemContainer extends St.Widget {
} }
this.animatingOut = true; this.animatingOut = true;
this.ease({ Tweener.addTween(this,
scale_x: 0, { childScale: 0.0,
scale_y: 0, childOpacity: 0,
opacity: 0, time: DASH_ANIMATION_TIME,
duration: DASH_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => {
onComplete: () => this.destroy() this.destroy();
}); }
});
}
set childScale(scale) {
this._childScale = scale;
this.set_scale(scale, scale);
this.queue_relayout();
}
get childScale() {
return this._childScale;
}
set childOpacity(opacity) {
this._childOpacity = opacity;
this.set_opacity(opacity);
this.queue_redraw();
}
get childOpacity() {
return this._childOpacity;
} }
}); });
@ -241,14 +241,14 @@ class ShowAppsIcon extends DashItemContainer {
this.setLabelText(_("Show Applications")); this.setLabelText(_("Show Applications"));
} }
handleDragOver(source, _actor, _x, _y, _time) { handleDragOver(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source))) if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
} }
acceptDrop(source, _actor, _x, _y, _time) { acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
if (!this._canRemoveApp(app)) if (!this._canRemoveApp(app))
return false; return false;
@ -296,7 +296,7 @@ class DashActor extends St.Widget {
this.set_allocation(box, flags); this.set_allocation(box, flags);
let [appIcons, showAppsButton] = this.get_children(); let [appIcons, showAppsButton] = this.get_children();
let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth); let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1; childBox.x1 = contentBox.x1;
@ -351,7 +351,8 @@ var Dash = class Dash {
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._showAppsIcon = new ShowAppsIcon(); this._showAppsIcon = new ShowAppsIcon();
this._showAppsIcon.show(false); this._showAppsIcon.childScale = 1;
this._showAppsIcon.childOpacity = 255;
this._showAppsIcon.icon.setIconSize(this.iconSize); this._showAppsIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(this._showAppsIcon); this._hookUpLabel(this._showAppsIcon);
@ -473,7 +474,19 @@ var Dash = class Dash {
} }
_createAppItem(app) { _createAppItem(app) {
let appIcon = new DashIcon(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;
});
}
appIcon.connect('menu-state-changed', appIcon.connect('menu-state-changed',
(appIcon, opened) => { (appIcon, opened) => {
@ -499,7 +512,7 @@ var Dash = class Dash {
// that the notify::hover handler does everything we need to. // that the notify::hover handler does everything we need to.
if (opened) { if (opened) {
if (this._showLabelTimeoutId > 0) { if (this._showLabelTimeoutId > 0) {
GLib.source_remove(this._showLabelTimeoutId); Mainloop.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0; this._showLabelTimeoutId = 0;
} }
@ -513,7 +526,7 @@ var Dash = class Dash {
if (shouldShow) { if (shouldShow) {
if (this._showLabelTimeoutId == 0) { if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT; let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
() => { () => {
this._labelShowing = true; this._labelShowing = true;
item.showLabel(); item.showLabel();
@ -522,17 +535,17 @@ var Dash = class Dash {
}); });
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel'); GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) { if (this._resetHoverTimeoutId > 0) {
GLib.source_remove(this._resetHoverTimeoutId); Mainloop.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
} }
} }
} else { } else {
if (this._showLabelTimeoutId > 0) if (this._showLabelTimeoutId > 0)
GLib.source_remove(this._showLabelTimeoutId); Mainloop.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0; this._showLabelTimeoutId = 0;
item.hideLabel(); item.hideLabel();
if (this._labelShowing) { if (this._labelShowing) {
this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DASH_ITEM_HOVER_TIMEOUT, this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
() => { () => {
this._labelShowing = false; this._labelShowing = false;
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
@ -620,12 +633,12 @@ var Dash = class Dash {
icon.icon.set_size(icon.icon.width * scale, icon.icon.set_size(icon.icon.width * scale,
icon.icon.height * scale); icon.icon.height * scale);
icon.icon.ease({ Tweener.addTween(icon.icon,
width: targetWidth, { width: targetWidth,
height: targetHeight, height: targetHeight,
duration: DASH_ANIMATION_TIME, time: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad',
}); });
} }
} }
@ -703,8 +716,8 @@ var Dash = class Dash {
} }
// App moved // App moved
let nextApp = newApps.length > newIndex + 1 let nextApp = newApps.length > newIndex + 1 ? newApps[newIndex + 1]
? newApps[newIndex + 1] : null; : null;
let insertHere = nextApp && nextApp == oldApp; let insertHere = nextApp && nextApp == oldApp;
let alreadyRemoved = removedActors.reduce((result, actor) => { let alreadyRemoved = removedActors.reduce((result, actor) => {
let removedApp = actor.child._delegate.app; let removedApp = actor.child._delegate.app;
@ -777,7 +790,7 @@ var Dash = class Dash {
} }
} }
handleDragOver(source, actor, x, y, _time) { handleDragOver(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
// Don't allow favoriting of transient apps // Don't allow favoriting of transient apps
@ -855,7 +868,7 @@ var Dash = class Dash {
} }
// Draggable target interface // Draggable target interface
acceptDrop(source, _actor, _x, _y, _time) { acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
// Don't allow favoriting of transient apps // Don't allow favoriting of transient apps

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported DateMenuButton */
const { Clutter, Gio, GLib, GnomeDesktop, const { Clutter, GLib, GnomeDesktop,
GObject, GWeather, Shell, St } = imports.gi; GObject, GWeather, Shell, St } = imports.gi;
const Util = imports.misc.util; const Util = imports.misc.util;
@ -11,13 +10,8 @@ const Calendar = imports.ui.calendar;
const Weather = imports.misc.weather; const Weather = imports.misc.weather;
const System = imports.system; const System = imports.system;
const { loadInterfaceXML } = imports.misc.fileUtils;
const MAX_FORECASTS = 5; const MAX_FORECASTS = 5;
const ClocksIntegrationIface = loadInterfaceXML('org.gnome.Shell.ClocksIntegration');
const ClocksProxy = Gio.DBusProxy.makeProxyWrapper(ClocksIntegrationIface);
function _isToday(date) { function _isToday(date) {
let now = new Date(); let now = new Date();
return now.getYear() == date.getYear() && return now.getYear() == date.getYear() &&
@ -30,13 +24,11 @@ var TodayButton = class TodayButton {
// Having the ability to go to the current date if the user is already // Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive // on the current date can be confusing. So don't make the button reactive
// until the selected date changes. // until the selected date changes.
this.actor = new St.Button({ this.actor = new St.Button({ style_class: 'datemenu-today-button',
style_class: 'datemenu-today-button', x_expand: true, x_align: St.Align.START,
x_align: St.Align.START, can_focus: true,
x_expand: true, reactive: false
can_focus: true, });
reactive: false,
});
this.actor.connect('clicked', () => { this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false); this._calendar.setDate(new Date(), false);
}); });
@ -90,8 +82,7 @@ var WorldClocksSection = class WorldClocksSection {
x_fill: true, x_fill: true,
can_focus: true }); can_focus: true });
this.actor.connect('clicked', () => { this.actor.connect('clicked', () => {
if (this._clocksApp) this._clockAppMon.activateApp();
this._clocksApp.activate();
Main.overview.hide(); Main.overview.hide();
Main.panel.closeCalendar(); Main.panel.closeCalendar();
@ -104,40 +95,29 @@ var WorldClocksSection = class WorldClocksSection {
this.actor.child = this._grid; this.actor.child = this._grid;
this._clocksApp = null; this._clockAppMon = new Util.AppSettingsMonitor('org.gnome.clocks.desktop',
this._clocksProxy = new ClocksProxy( 'org.gnome.clocks');
Gio.DBus.session, this._clockAppMon.connect('available-changed',
'org.gnome.clocks', this._sync.bind(this));
'/org/gnome/clocks', this._clockAppMon.watchSetting('world-clocks',
this._onProxyReady.bind(this), this._clocksChanged.bind(this));
null /* cancellable */,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES);
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.world-clocks'
});
this._settings.connect('changed', this._clocksChanged.bind(this));
this._clocksChanged();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._sync.bind(this));
this._sync(); this._sync();
} }
_sync() { _sync() {
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop'); this.actor.visible = this._clockAppMon.available;
this.actor.visible = this._clocksApp != null;
} }
_clocksChanged() { _clocksChanged(settings) {
this._grid.destroy_all_children(); this._grid.destroy_all_children();
this._locations = []; this._locations = [];
let world = GWeather.Location.get_world(); let world = GWeather.Location.get_world();
let clocks = this._settings.get_value('locations').deep_unpack(); let clocks = settings.get_value('world-clocks').deep_unpack();
for (let i = 0; i < clocks.length; i++) { for (let i = 0; i < clocks.length; i++) {
let l = world.deserialize(clocks[i]); if (!clocks[i].location)
continue;
let l = world.deserialize(clocks[i].location);
if (l && l.get_timezone() != null) if (l && l.get_timezone() != null)
this._locations.push({ location: l }); this._locations.push({ location: l });
} }
@ -148,9 +128,8 @@ var WorldClocksSection = class WorldClocksSection {
}); });
let layout = this._grid.layout_manager; let layout = this._grid.layout_manager;
let title = (this._locations.length == 0) let title = (this._locations.length == 0) ? _("Add world clocks…")
? _("Add world clocks") : _("World Clocks");
: _("World Clocks");
let header = new St.Label({ style_class: 'world-clocks-header', let header = new St.Label({ style_class: 'world-clocks-header',
x_align: Clutter.ActorAlign.START, x_align: Clutter.ActorAlign.START,
text: title }); text: title });
@ -217,25 +196,6 @@ var WorldClocksSection = class WorldClocksSection {
l.actor.text = Util.formatTime(now, { timeOnly: true }); l.actor.text = Util.formatTime(now, { timeOnly: true });
} }
} }
_onProxyReady(proxy, error) {
if (error) {
log(`Failed to create GNOME Clocks proxy: ${error}`);
return;
}
this._clocksProxy.connect('g-properties-changed',
this._onClocksPropertiesChanged.bind(this));
this._onClocksPropertiesChanged();
}
_onClocksPropertiesChanged() {
if (this._clocksProxy.g_name_owner == null)
return;
this._settings.set_value('locations',
new GLib.Variant('av', this._clocksProxy.Locations));
}
}; };
var WeatherSection = class WeatherSection { var WeatherSection = class WeatherSection {
@ -289,12 +249,12 @@ var WeatherSection = class WeatherSection {
let current = info; let current = info;
let infos = [info]; let infos = [info];
for (let i = 0; i < forecasts.length; i++) { 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); let datetime = new Date(timestamp * 1000);
if (!_isToday(datetime)) if (!_isToday(datetime))
continue; // Ignore forecasts from other days continue; // Ignore forecasts from other days
[ok_, timestamp] = current.get_value_update(); [ok, timestamp] = current.get_value_update();
let currenttime = new Date(timestamp * 1000); let currenttime = new Date(timestamp * 1000);
if (currenttime.getHours() == datetime.getHours()) if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h continue; // Enforce a minimum interval of 1h
@ -315,7 +275,7 @@ var WeatherSection = class WeatherSection {
let col = 0; let col = 0;
infos.forEach(fc => { 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), { let timeStr = Util.formatTime(new Date(timestamp * 1000), {
timeOnly: true timeOnly: true
}); });
@ -413,7 +373,7 @@ var MessagesIndicator = class MessagesIndicator {
_updateCount() { _updateCount() {
let count = 0; let count = 0;
this._sources.forEach(source => (count += source.unseenCount)); this._sources.forEach(source => count += source.unseenCount);
count -= Main.messageTray.queueCount; count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0); this.actor.visible = (count > 0);

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent */
const { Clutter, Gio, GObject, Pango, St } = imports.gi; const { Clutter, Gio, GObject, Pango, St } = imports.gi;

View File

@ -1,18 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addDragMonitor, removeDragMonitor, makeDraggable */
const { Clutter, GLib, Meta, Shell, St } = imports.gi; const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
// Time to scale down to maxDragActorSize // Time to scale down to maxDragActorSize
var SCALE_ANIMATION_TIME = 250; var SCALE_ANIMATION_TIME = 0.25;
// Time to animate to original position on cancel // Time to animate to original position on cancel
var SNAP_BACK_ANIMATION_TIME = 250; var SNAP_BACK_ANIMATION_TIME = 0.25;
// Time to animate to original position on success // Time to animate to original position on success
var REVERT_ANIMATION_TIME = 750; var REVERT_ANIMATION_TIME = 0.75;
var DragMotionResult = { var DragMotionResult = {
NO_DROP: 0, NO_DROP: 0,
@ -111,6 +111,9 @@ var _Draggable = class _Draggable {
if (event.get_button() != 1) if (event.get_button() != 1)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true; this._buttonDown = true;
this._grabActor(event.get_device()); this._grabActor(event.get_device());
@ -136,6 +139,9 @@ var _Draggable = class _Draggable {
!global.display.is_pointer_emulating_sequence(event.get_event_sequence())) !global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true; this._buttonDown = true;
this._grabActor(event.get_device(), event.get_event_sequence()); this._grabActor(event.get_device(), event.get_event_sequence());
@ -422,22 +428,19 @@ var _Draggable = class _Draggable {
// to the final position because that tween would // to the final position because that tween would
// fight with updates as the user continues dragging // fight with updates as the user continues dragging
// the mouse; instead we do the position computations in // the mouse; instead we do the position computations in
// a ::new-frame handler. // an onUpdate() function.
this._dragActor.ease({ Tweener.addTween(this._dragActor,
scale_x: scale * origScale, { scale_x: scale * origScale,
scale_y: scale * origScale, scale_y: scale * origScale,
duration: SCALE_ANIMATION_TIME, time: SCALE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad',
}); onUpdate: () => {
let currentScale = this._dragActor.scale_x / origScale;
this._dragActor.get_transition('scale-x').connect('new-frame', () => { this._dragOffsetX = currentScale * origDragOffsetX;
let currentScale = this._dragActor.scale_x / origScale; this._dragOffsetY = currentScale * origDragOffsetY;
this._dragOffsetX = currentScale * origDragOffsetX; this._dragActor.set_position(this._dragX + this._dragOffsetX,
this._dragOffsetY = currentScale * origDragOffsetY; this._dragY + this._dragOffsetY);
this._dragActor.set_position( } });
this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
});
} }
} }
} }
@ -500,7 +503,7 @@ var _Draggable = class _Draggable {
while (target) { while (target) {
if (target._delegate && target._delegate.handleDragOver) { 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 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 // 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. // to continue checking the parents.
@ -572,7 +575,7 @@ var _Draggable = class _Draggable {
while (target) { while (target) {
if (target._delegate && target._delegate.acceptDrop) { 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, if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor, this._dragActor,
targX, targX,
@ -610,15 +613,15 @@ var _Draggable = class _Draggable {
if (this._dragActorSource && this._dragActorSource.visible) { if (this._dragActorSource && this._dragActorSource.visible) {
// Snap the clone back to its source // Snap the clone back to its source
[x, y] = this._dragActorSource.get_transformed_position(); [x, y] = this._dragActorSource.get_transformed_position();
let [sourceScaledWidth] = this._dragActorSource.get_transformed_size(); let [sourceScaledWidth, sourceScaledHeight] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? sourceScaledWidth / this._dragActor.width : 0; scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0;
} else if (this._dragOrigParent) { } else if (this._dragOrigParent) {
// Snap the actor back to its original position within // Snap the actor back to its original position within
// its parent, adjusting for the fact that the parent // its parent, adjusting for the fact that the parent
// may have been moved or scaled // may have been moved or scaled
let [parentX, parentY] = this._dragOrigParent.get_transformed_position(); let [parentX, parentY] = this._dragOrigParent.get_transformed_position();
let [parentWidth] = this._dragOrigParent.get_size(); let [parentWidth, parentHeight] = this._dragOrigParent.get_size();
let [parentScaledWidth] = this._dragOrigParent.get_transformed_size(); let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size();
let parentScale = 1.0; let parentScale = 1.0;
if (parentWidth != 0) if (parentWidth != 0)
parentScale = parentScaledWidth / parentWidth; parentScale = parentScaledWidth / parentWidth;
@ -654,13 +657,13 @@ var _Draggable = class _Draggable {
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation(); let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
this._animateDragEnd(eventTime, { this._animateDragEnd(eventTime,
x: snapBackX, { x: snapBackX,
y: snapBackY, y: snapBackY,
scale_x: snapBackScale, scale_x: snapBackScale,
scale_y: snapBackScale, scale_y: snapBackScale,
duration: SNAP_BACK_ANIMATION_TIME time: SNAP_BACK_ANIMATION_TIME,
}); });
} }
_restoreDragActor(eventTime) { _restoreDragActor(eventTime) {
@ -672,22 +675,21 @@ var _Draggable = class _Draggable {
this._dragActor.set_scale(restoreScale, restoreScale); this._dragActor.set_scale(restoreScale, restoreScale);
this._dragActor.opacity = 0; this._dragActor.opacity = 0;
this._animateDragEnd(eventTime, { this._animateDragEnd(eventTime,
duration: REVERT_ANIMATION_TIME { time: REVERT_ANIMATION_TIME });
});
} }
_animateDragEnd(eventTime, params) { _animateDragEnd(eventTime, params) {
this._animationInProgress = true; this._animationInProgress = true;
params['opacity'] = this._dragOrigOpacity;
params['transition'] = 'easeOutQuad';
params['onComplete'] = this._onAnimationComplete;
params['onCompleteScope'] = this;
params['onCompleteParams'] = [this._dragActor, eventTime];
// start the animation // start the animation
this._dragActor.ease(Object.assign(params, { Tweener.addTween(this._dragActor, params);
opacity: this._dragOrigOpacity,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._onAnimationComplete(this._dragActor, eventTime);
}
}));
} }
_finishAnimation() { _finishAnimation() {

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported EdgeDragAction */
const { Clutter, GObject, Meta, St } = imports.gi; const { Clutter, GObject, Meta, St } = imports.gi;
@ -27,7 +26,7 @@ var EdgeDragAction = GObject.registerClass({
return global.display.get_monitor_geometry(monitorIndex); return global.display.get_monitor_geometry(monitorIndex);
} }
vfunc_gesture_prepare(_actor) { vfunc_gesture_prepare(actor) {
if (this.get_n_current_points() == 0) if (this.get_n_current_points() == 0)
return false; return false;
@ -43,7 +42,7 @@ var EdgeDragAction = GObject.registerClass({
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD)); (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 [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0); let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX); let offsetX = Math.abs (x - startX);
@ -63,7 +62,7 @@ var EdgeDragAction = GObject.registerClass({
return true; return true;
} }
vfunc_gesture_end(_actor) { vfunc_gesture_end(actor) {
let [startX, startY] = this.get_press_coords(0); let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0); let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY); let monitorRect = this._getMonitorRect(startX, startY);

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, EndSessionDialog */
/* /*
* Copyright 2010-2016 Red Hat, Inc * Copyright 2010-2016 Red Hat, Inc
* *
@ -17,6 +16,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
const Mainloop = imports.mainloop;
const { AccountsService, Clutter, Gio, const { AccountsService, Clutter, Gio,
GLib, GObject, Pango, Polkit, Shell, St } = imports.gi; GLib, GObject, Pango, Polkit, Shell, St } = imports.gi;
@ -350,15 +351,12 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
} }
// It only makes sense to check for this permission if PackageKit is available. // It only makes sense to check for this permission if PackageKit is available.
Polkit.Permission.new( try {
'org.freedesktop.packagekit.trigger-offline-update', null, null, this._updatesPermission = Polkit.Permission.new_sync(
(source, res) => { 'org.freedesktop.packagekit.trigger-offline-update', null, null);
try { } catch (e) {
this._updatesPermission = Polkit.Permission.new_finish(res); log('No permission to trigger offline updates: %s'.format(e.toString()));
} catch (e) { }
log(`No permission to trigger offline updates: ${e}`);
}
});
} }
_onDestroy() { _onDestroy() {
@ -449,16 +447,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
for (let i = 0; i < dialogContent.confirmButtons.length; i++) { for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
let signal = dialogContent.confirmButtons[i].signal; let signal = dialogContent.confirmButtons[i].signal;
let label = dialogContent.confirmButtons[i].label; let label = dialogContent.confirmButtons[i].label;
buttons.push({ buttons.push({ action: () => {
action: () => { this.close(true);
this.close(true); let signalId = this.connect('closed', () => {
let signalId = this.connect('closed', () => { this.disconnect(signalId);
this.disconnect(signalId); this._confirm(signal);
this._confirm(signal); });
}); },
}, label: label });
label: label,
});
} }
this.setButtons(buttons); this.setButtons(buttons);
@ -565,7 +561,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let startTime = GLib.get_monotonic_time(); let startTime = GLib.get_monotonic_time();
this._secondsLeft = this._totalSecondsToStayOpen; this._secondsLeft = this._totalSecondsToStayOpen;
this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { this._timerId = Mainloop.timeout_add_seconds(1, () => {
let currentTime = GLib.get_monotonic_time(); let currentTime = GLib.get_monotonic_time();
let secondsElapsed = ((currentTime - startTime) / 1000000); let secondsElapsed = ((currentTime - startTime) / 1000000);
@ -587,7 +583,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
_stopTimer() { _stopTimer() {
if (this._timerId > 0) { if (this._timerId > 0) {
GLib.source_remove(this._timerId); Mainloop.source_remove(this._timerId);
this._timerId = 0; this._timerId = 0;
} }
@ -672,7 +668,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._loginManager.listSessions(result => { this._loginManager.listSessions(result => {
let n = 0; let n = 0;
for (let i = 0; i < result.length; i++) { 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); let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user') if (proxy.Class != 'user')
@ -738,7 +734,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let dialogContent = DialogContent[this._type]; let dialogContent = DialogContent[this._type];
for (let i = 0; i < inhibitorObjectPaths.length; i++) { for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => { let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], (proxy, error) => {
this._onInhibitorLoaded(proxy); this._onInhibitorLoaded(proxy);
}); });
@ -782,7 +778,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}); });
} }
Close(_parameters, _invocation) { Close(parameters, invocation) {
this.close(); this.close();
} }
}); });

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init */
const Config = imports.misc.config; const Config = imports.misc.config;
@ -10,7 +9,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12'; imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2'; imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, Meta, Shell, St } = imports.gi; const { Clutter, GLib, Shell, St } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have // We can't import shell JS modules yet, because they may have
@ -58,123 +57,6 @@ function _patchLayoutClass(layoutClass, styleProps) {
}; };
} }
function _makeEaseCallback(params, cleanup) {
let onComplete = params.onComplete;
delete params.onComplete;
let onStopped = params.onStopped;
delete params.onStopped;
return isFinished => {
cleanup();
if (onStopped)
onStopped(isFinished);
if (onComplete && isFinished)
onComplete();
};
}
function _getPropertyTarget(actor, propName) {
if (!propName.startsWith('@'))
return [actor, propName];
let [type, name, prop] = propName.split('.');
switch (type) {
case '@layout':
return [actor.layout_manager, name];
case '@actions':
return [actor.get_action(name), prop];
case '@constraints':
return [actor.get_constraint(name), prop];
case '@effects':
return [actor.get_effect(name), prop];
}
throw new Error(`Invalid property name ${propName}`);
}
function _easeActor(actor, params) {
actor.save_easing_state();
if (params.duration != undefined)
actor.set_easing_duration(params.duration);
delete params.duration;
if (params.delay != undefined)
actor.set_easing_delay(params.delay);
delete params.delay;
if (params.mode != undefined)
actor.set_easing_mode(params.mode);
delete params.mode;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transitions
let animatedProps = Object.keys(params).map(p => p.replace('_', '-', 'g'));
animatedProps.forEach(p => actor.remove_transition(p));
actor.set(params);
actor.restore_easing_state();
let transition = animatedProps.map(p => actor.get_transition(p))
.find(t => t !== null);
if (transition)
transition.connect('stopped', (t, finished) => callback(finished));
else
callback(true);
}
function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease()
if (params.mode)
params.progress_mode = params.mode;
delete params.mode;
if (params.duration)
params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0);
// Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transition
actor.remove_transition(propName);
if (duration == 0) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
callback(true);
return;
}
let pspec = actor.find_property(propName);
let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true
}, params));
actor.add_transition(propName, transition);
transition.set_to(target);
transition.connect('stopped', (t, finished) => callback(finished));
}
function _loggingFunc(...args) { function _loggingFunc(...args) {
let fields = { 'MESSAGE': args.join(', ') }; let fields = { 'MESSAGE': args.join(', ') };
let domain = "GNOME Shell"; let domain = "GNOME Shell";
@ -211,27 +93,6 @@ function init() {
column_spacing: 'spacing-columns' }); column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' }); _patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
Clutter.Actor.prototype.set_easing_duration = function(msecs) {
origSetEasingDuration.call(this, adjustAnimationTime(msecs));
};
let origSetEasingDelay = Clutter.Actor.prototype.set_easing_delay;
Clutter.Actor.prototype.set_easing_delay = function(msecs) {
origSetEasingDelay.call(this, adjustAnimationTime(msecs));
};
Clutter.Actor.prototype.ease = function(props, easingParams) {
_easeActor(this, props, easingParams);
};
Clutter.Actor.prototype.ease_property = function(propName, target, params) {
_easeActorProperty(this, propName, target, params);
};
St.Adjustment.prototype.ease = function(target, params) {
// we're not an actor of course, but we implement the same
// transition API as Clutter.Actor, so this works anyway
_easeActorProperty(this, 'value', target, params);
};
Clutter.Actor.prototype.toString = function() { Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this); return St.describe_actor(this);
}; };
@ -245,12 +106,6 @@ 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; let origToString = Object.prototype.toString;
Object.prototype.toString = function() { Object.prototype.toString = function() {
let base = origToString.call(this); let base = origToString.call(this);
@ -273,7 +128,7 @@ function init() {
if (slowdownEnv) { if (slowdownEnv) {
let factor = parseFloat(slowdownEnv); let factor = parseFloat(slowdownEnv);
if (!isNaN(factor) && factor > 0.0) if (!isNaN(factor) && factor > 0.0)
St.Settings.get().slow_down_factor = factor; St.set_slow_down_factor(factor);
} }
// OK, now things are initialized enough that we can import shell JS // OK, now things are initialized enough that we can import shell JS
@ -283,17 +138,3 @@ function init() {
Tweener.init(); Tweener.init();
String.prototype.format = Format.format; String.prototype.format = Format.format;
} }
// adjustAnimationTime:
// @msecs: time in milliseconds
//
// Adjust @msecs to account for St's enable-animations
// and slow-down-factor settings
function adjustAnimationTime(msecs) {
let settings = St.Settings.get();
if (!settings.enable_animations)
return 1;
return settings.slow_down_factor * msecs;
}

View File

@ -1,14 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Clutter, Gio, GLib, GObject, Soup } = imports.gi;
const Config = imports.misc.config; const Config = imports.misc.config;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const ExtensionSystem = imports.ui.extensionSystem;
const FileUtils = imports.misc.fileUtils; const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
var REPOSITORY_URL_BASE = 'https://extensions.gnome.org'; var REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
@ -26,7 +24,7 @@ function installExtension(uuid, invocation) {
_httpSession.queue_message(message, (session, message) => { _httpSession.queue_message(message, (session, message) => {
if (message.status_code != Soup.KnownStatusCode.OK) { if (message.status_code != Soup.KnownStatusCode.OK) {
Main.extensionManager.logExtensionError(uuid, `downloading info: ${message.status_code}`); ExtensionSystem.logExtensionError(uuid, `downloading info: ${message.status_code}`);
invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString()); invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
return; return;
} }
@ -35,7 +33,7 @@ function installExtension(uuid, invocation) {
try { try {
info = JSON.parse(message.response_body.data); info = JSON.parse(message.response_body.data);
} catch (e) { } catch (e) {
Main.extensionManager.logExtensionError(uuid, `parsing info: ${e}`); ExtensionSystem.logExtensionError(uuid, `parsing info: ${e}`);
invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString()); invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
return; return;
} }
@ -46,7 +44,7 @@ function installExtension(uuid, invocation) {
} }
function uninstallExtension(uuid) { function uninstallExtension(uuid) {
let extension = Main.extensionManager.lookup(uuid); let extension = ExtensionUtils.extensions[uuid];
if (!extension) if (!extension)
return false; return false;
@ -54,7 +52,7 @@ function uninstallExtension(uuid) {
if (extension.type != ExtensionUtils.ExtensionType.PER_USER) if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
return false; return false;
if (!Main.extensionManager.unloadExtension(extension)) if (!ExtensionSystem.unloadExtension(extension))
return false; return false;
FileUtils.recursivelyDeleteDir(extension.dir, true); FileUtils.recursivelyDeleteDir(extension.dir, true);
@ -115,10 +113,10 @@ function updateExtension(uuid) {
_httpSession.queue_message(message, (session, message) => { _httpSession.queue_message(message, (session, message) => {
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => { gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => {
let oldExtension = Main.extensionManager.lookup(uuid); let oldExtension = ExtensionUtils.extensions[uuid];
let extensionDir = oldExtension.dir; let extensionDir = oldExtension.dir;
if (!Main.extensionManager.unloadExtension(oldExtension)) if (!ExtensionSystem.unloadExtension(oldExtension))
return; return;
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir); FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
@ -127,11 +125,11 @@ function updateExtension(uuid) {
let extension = null; let extension = null;
try { try {
extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER); extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension); ExtensionSystem.loadExtension(extension);
} catch (e) { } catch (e) {
if (extension) if (extension)
Main.extensionManager.unloadExtension(extension); ExtensionSystem.unloadExtension(extension);
logError(e, 'Error loading extension %s'.format(uuid)); logError(e, 'Error loading extension %s'.format(uuid));
@ -140,7 +138,7 @@ function updateExtension(uuid) {
// Restore what was there before. We can't do much if we // Restore what was there before. We can't do much if we
// fail here. // fail here.
Main.extensionManager.loadExtension(oldExtension); ExtensionSystem.loadExtension(oldExtension);
return; return;
} }
@ -153,9 +151,9 @@ function updateExtension(uuid) {
function checkForUpdates() { function checkForUpdates() {
let metadatas = {}; let metadatas = {};
Main.extensionManager.getUuids().forEach(uuid => { for (let uuid in ExtensionUtils.extensions) {
metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata; metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
}); }
let params = { shell_version: Config.PACKAGE_VERSION, let params = { shell_version: Config.PACKAGE_VERSION,
installed: JSON.stringify(metadatas) }; installed: JSON.stringify(metadatas) };
@ -186,15 +184,14 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this._info = info; this._info = info;
this._invocation = invocation; this._invocation = invocation;
this.setButtons([{ this.setButtons([{ label: _("Cancel"),
label: _("Cancel"), action: this._onCancelButtonPressed.bind(this),
action: this._onCancelButtonPressed.bind(this), key: Clutter.Escape
key: Clutter.Escape, },
}, { { label: _("Install"),
label: _("Install"), action: this._onInstallButtonPressed.bind(this),
action: this._onInstallButtonPressed.bind(this), default: true
default: true, }]);
}]);
let content = new Dialog.MessageDialogContent({ let content = new Dialog.MessageDialogContent({
title: _("Download and install “%s” from extensions.gnome.org?").format(info.name), title: _("Download and install “%s” from extensions.gnome.org?").format(info.name),
@ -206,12 +203,12 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.contentLayout.add(content); this.contentLayout.add(content);
} }
_onCancelButtonPressed() { _onCancelButtonPressed(button, event) {
this.close(); this.close();
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled'])); this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
} }
_onInstallButtonPressed() { _onInstallButtonPressed(button, event) {
let params = { shell_version: Config.PACKAGE_VERSION }; let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid); let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
@ -227,11 +224,16 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
} }
function callback() { 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 { try {
let extension = Main.extensionManager.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER); let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension); ExtensionSystem.loadExtension(extension);
if (!Main.extensionManager.enableExtension(uuid))
throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`);
} catch (e) { } catch (e) {
uninstallExtension(uuid); uninstallExtension(uuid);
errback('LoadExtensionError', e); errback('LoadExtensionError', e);

View File

@ -1,519 +1,374 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
const { Gio, St } = imports.gi; const { Gio, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main; const Main = imports.ui.main;
const { ExtensionState, ExtensionType } = ExtensionUtils; 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 ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
const DISABLED_EXTENSIONS_KEY = 'disabled-extensions';
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions'; const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
var ExtensionManager = class { var initted = false;
constructor() { var enabled;
this._initialized = false;
this._enabled = false;
this._extensions = new Map(); function disableExtension(uuid) {
this._enabledExtensions = []; let extension = ExtensionUtils.extensions[uuid];
this._extensionOrder = []; if (!extension)
return;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); if (extension.state != ExtensionState.ENABLED)
} return;
init() { // "Rebase" the extension order by disabling and then enabling extensions
this._sessionUpdated(); // in order to help prevent conflicts.
}
lookup(uuid) { // Example:
return this._extensions.get(uuid); // order = [A, B, C, D, E]
} // user disables C
// this should: disable E, disable D, disable C, enable D, enable E
getUuids() { let orderIdx = extensionOrder.indexOf(uuid);
return [...this._extensions.keys()]; let order = extensionOrder.slice(orderIdx + 1);
} let orderReversed = order.slice().reverse();
_callExtensionDisable(uuid) { for (let i = 0; i < orderReversed.length; i++) {
let extension = this.lookup(uuid); let uuid = orderReversed[i];
if (!extension) try {
return; ExtensionUtils.extensions[uuid].stateObj.disable();
} catch (e) {
if (extension.state != ExtensionState.ENABLED) logExtensionError(uuid, e);
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;
}
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);
}
}
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;
} 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;
}
}
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension);
return;
} catch (e) {
if (extension.stylesheet) { if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet); theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet; delete extension.stylesheet;
} }
logExtensionError(uuid, e);
try { return;
extension.stateObj.disable();
} catch (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);
}
} }
}
_callExtensionEnable(uuid) { function logExtensionError(uuid, error) {
if (!Main.sessionMode.allowExtensions) let extension = ExtensionUtils.extensions[uuid];
return; if (!extension)
return;
let extension = this.lookup(uuid); let message = `${error}`;
if (!extension)
return;
if (extension.state == ExtensionState.INITIALIZED) extension.state = ExtensionState.ERROR;
this._callExtensionInit(uuid); if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
if (extension.state != ExtensionState.DISABLED) log('Extension "%s" had error: %s'.format(uuid, message));
return; _signals.emit('extension-state-changed', { uuid: uuid,
error: message,
state: extension.state });
}
let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css']; function loadExtension(extension) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); // Default to error, we set success as the last step
for (let i = 0; i < stylesheetNames.length; i++) { extension.state = ExtensionState.ERROR;
try {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile; if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
break; extension.state = ExtensionState.OUT_OF_DATE;
} catch (e) { } else {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) let enabled = enabledExtensions.includes(extension.uuid);
continue; // not an error if (enabled) {
this.logExtensionError(uuid, e); if (!initExtension(extension.uuid))
return; return;
} if (extension.state == ExtensionState.DISABLED)
} enableExtension(extension.uuid);
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
this._extensionOrder.push(uuid);
this.emit('extension-state-changed', extension);
} catch (e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
this.logExtensionError(uuid, e);
}
}
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);
}
if (!enabledExtensions.includes(uuid)) {
enabledExtensions.push(uuid);
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
return true;
}
disableExtension(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 (enabledExtensions.includes(uuid)) {
enabledExtensions = enabledExtensions.filter(item => item !== uuid);
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
if (!disabledExtensions.includes(uuid)) {
disabledExtensions.push(uuid);
global.settings.set_strv(DISABLED_EXTENSIONS_KEY, disabledExtensions);
}
return true;
}
logExtensionError(uuid, error) {
let extension = this.lookup(uuid);
if (!extension)
return;
let message = `${error}`;
extension.error = message;
extension.state = ExtensionState.ERROR;
if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
logError(error, `Extension ${uuid}`);
this.emit('extension-state-changed', extension);
}
createExtensionObject(uuid, dir, type) {
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
let metadataContents, success_;
try {
[success_, metadataContents] = 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}`);
}
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 { } else {
let enabled = this._enabledExtensions.includes(extension.uuid); extension.state = ExtensionState.INITIALIZED;
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) { _signals.emit('extension-state-changed', 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; function unloadExtension(extension) {
this.emit('extension-state-changed', 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);
this._extensions.delete(extension.uuid); extension.state = ExtensionState.UNINSTALLED;
return true; _signals.emit('extension-state-changed', extension);
delete ExtensionUtils.extensions[extension.uuid];
return true;
}
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;
} }
reloadExtension(oldExtension) { loadExtension(newExtension);
// Grab the things we'll need to pass to createExtensionObject }
// to reload it.
let { uuid, dir, type } = oldExtension;
// Then unload the old extension. function initExtension(uuid) {
this.unloadExtension(oldExtension); let extension = ExtensionUtils.extensions[uuid];
let dir = extension.dir;
// Now, recreate the extension and load it. if (!extension)
let newExtension; throw new Error("Extension was not properly created. Call loadExtension first");
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
logExtensionError(uuid, new Error('Missing extension.js'));
return false;
}
let extensionModule;
let extensionState = null;
ExtensionUtils.installImporter(extension);
try {
extensionModule = extension.imports.extension;
} catch (e) {
logExtensionError(uuid, e);
return false;
}
if (extensionModule.init) {
try { try {
newExtension = this.createExtensionObject(uuid, dir, type); extensionState = extensionModule.init(extension);
} catch (e) { } catch (e) {
this.logExtensionError(uuid, e); logExtensionError(uuid, e);
return;
}
this.loadExtension(newExtension);
}
_callExtensionInit(uuid) {
if (!Main.sessionMode.allowExtensions)
return false;
let extension = this.lookup(uuid);
if (!extension)
throw new Error("Extension was not properly created. Call createExtensionObject first");
let dir = extension.dir;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
return false; 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;
} }
_getModeExtensions() { if (!extensionState)
if (Array.isArray(Main.sessionMode.enabledExtensions)) extensionState = extensionModule;
return Main.sessionMode.enabledExtensions; extension.stateObj = extensionState;
return [];
}
_updateCanChange(extension) { extension.state = ExtensionState.DISABLED;
let hasError = _signals.emit('extension-loaded', uuid);
extension.state == ExtensionState.ERROR || return true;
extension.state == ExtensionState.OUT_OF_DATE; }
let isMode = this._getModeExtensions().includes(extension.uuid); function getEnabledExtensions() {
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY); let extensions;
if (Array.isArray(Main.sessionMode.enabledExtensions))
extensions = Main.sessionMode.enabledExtensions;
else
extensions = [];
let changeKey = isMode if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
? DISABLE_USER_EXTENSIONS_KEY return extensions;
: ENABLED_EXTENSIONS_KEY;
extension.canChange = return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
!hasError && }
global.settings.is_writable(changeKey) &&
(isMode || !modeOnly);
}
_getEnabledExtensions() { function onEnabledExtensionsChanged() {
let extensions = this._getModeExtensions(); let newEnabledExtensions = getEnabledExtensions();
if (!global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) if (!enabled)
extensions = extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); return;
// filter out 'disabled-extensions' which takes precedence // Find and enable all the newly enabled extensions: UUIDs found in the
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY); // new setting, but not in the old one.
return extensions.filter(item => !disabledExtensions.includes(item)); newEnabledExtensions.filter(
} uuid => !enabledExtensions.includes(uuid)
).forEach(uuid => {
enableExtension(uuid);
});
_onUserExtensionsEnabledChanged() { // Find and disable all the newly disabled extensions: UUIDs found in the
this._onEnabledExtensionsChanged(); // old setting, but not in the new one.
this._onSettingsWritableChanged(); enabledExtensions.filter(
} item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
disableExtension(uuid);
});
_onEnabledExtensionsChanged() { enabledExtensions = newEnabledExtensions;
let newEnabledExtensions = this._getEnabledExtensions(); }
// Find and enable all the newly enabled extensions: UUIDs found in the function _onVersionValidationChanged() {
// new setting, but not in the old one. // we want to reload all extensions, but only enable
newEnabledExtensions.filter( // extensions when allowed by the sessionMode, so
uuid => !this._enabledExtensions.includes(uuid) // temporarily disable them all
).forEach(uuid => { enabledExtensions = [];
this._callExtensionEnable(uuid); for (let uuid in ExtensionUtils.extensions)
reloadExtension(ExtensionUtils.extensions[uuid]);
enabledExtensions = getEnabledExtensions();
if (Main.sessionMode.allowExtensions) {
enabledExtensions.forEach(uuid => {
enableExtension(uuid);
}); });
}
}
// Find and disable all the newly disabled extensions: UUIDs found in the function _loadExtensions() {
// old setting, but not in the new one. global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
this._extensionOrder.filter( global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
uuid => !newEnabledExtensions.includes(uuid) global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, _onVersionValidationChanged);
).reverse().forEach(uuid => {
this._callExtensionDisable(uuid); 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);
}); });
this._enabledExtensions = newEnabledExtensions;
} }
enabled = true;
}
_onSettingsWritableChanged() { function disableAllExtensions() {
for (let extension of this._extensions.values()) { if (!enabled)
this._updateCanChange(extension); return;
this.emit('extension-state-changed', extension);
}
}
_onVersionValidationChanged() { if (initted) {
// Disabling extensions modifies the order array, so use a copy
let extensionOrder = this._extensionOrder.slice();
// Disable enabled extensions in the reverse order first to avoid
// the "rebasing" done in _callExtensionDisable...
extensionOrder.slice().reverse().forEach(uuid => { extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid); disableExtension(uuid);
});
// ...and then reload and enable extensions in the correct order again.
[...this._extensions.values()].sort((a, b) => {
return extensionOrder.indexOf(a.uuid) - extensionOrder.indexOf(b.uuid);
}).forEach(extension => this.reloadExtension(extension));
}
_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);
}); });
} }
_enableAllExtensions() { enabled = false;
if (this._enabled) }
return;
if (!this._initialized) { function _sessionUpdated() {
this._loadExtensions(); // For now sessionMode.allowExtensions controls extensions from both the
this._initialized = true; // 'enabled-extensions' preference and the sessionMode.enabledExtensions
} else { // property; it might make sense to make enabledExtensions independent
this._enabledExtensions.forEach(uuid => { // from allowExtensions in the future
this._callExtensionEnable(uuid); if (Main.sessionMode.allowExtensions) {
}); if (initted)
} enabledExtensions = getEnabledExtensions();
this._enabled = true; enableAllExtensions();
} else {
disableAllExtensions();
} }
}
_disableAllExtensions() { function init() {
if (!this._enabled) Main.sessionMode.connect('updated', _sessionUpdated);
return; _sessionUpdated();
}
if (this._initialized) {
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) {
// Take care of added or removed sessionMode extensions
this._onEnabledExtensionsChanged();
this._enableAllExtensions();
} else {
this._disableAllExtensions();
}
}
};
Signals.addSignalMethods(ExtensionManager.prototype);

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GrabHelper */
const { Clutter, St } = imports.gi; const { Clutter, St } = imports.gi;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
const { Clutter, IBus, St } = imports.gi; const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -126,9 +125,6 @@ Signals.addSignalMethods(CandidateArea.prototype);
var CandidatePopup = class CandidatePopup { var CandidatePopup = class CandidatePopup {
constructor() { constructor() {
this._dummyCursor = new St.Widget({ opacity: 0 });
Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP); this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.visible = false; this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer'; this._boxPointer.style_class = 'candidate-popup-boxpointer';
@ -202,29 +198,29 @@ var CandidatePopup = class CandidatePopup {
this._setTextAttributes(this._preeditText.clutter_text, this._setTextAttributes(this._preeditText.clutter_text,
attrs); attrs);
}); });
panelService.connect('show-preedit-text', () => { panelService.connect('show-preedit-text', ps => {
this._preeditText.show(); this._preeditText.show();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('hide-preedit-text', () => { panelService.connect('hide-preedit-text', ps => {
this._preeditText.hide(); this._preeditText.hide();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('update-auxiliary-text', (_ps, text, visible) => { panelService.connect('update-auxiliary-text', (ps, text, visible) => {
this._auxText.visible = visible; this._auxText.visible = visible;
this._updateVisibility(); this._updateVisibility();
this._auxText.text = text.get_text(); this._auxText.text = text.get_text();
}); });
panelService.connect('show-auxiliary-text', () => { panelService.connect('show-auxiliary-text', ps => {
this._auxText.show(); this._auxText.show();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('hide-auxiliary-text', () => { panelService.connect('hide-auxiliary-text', ps => {
this._auxText.hide(); this._auxText.hide();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => { panelService.connect('update-lookup-table', (ps, lookupTable, visible) => {
this._candidateArea.actor.visible = visible; this._candidateArea.actor.visible = visible;
this._updateVisibility(); this._updateVisibility();
@ -260,26 +256,24 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.setOrientation(lookupTable.get_orientation()); this._candidateArea.setOrientation(lookupTable.get_orientation());
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages); this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
}); });
panelService.connect('show-lookup-table', () => { panelService.connect('show-lookup-table', ps => {
this._candidateArea.actor.show(); this._candidateArea.actor.show();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('hide-lookup-table', () => { panelService.connect('hide-lookup-table', ps => {
this._candidateArea.actor.hide(); this._candidateArea.actor.hide();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('focus-out', () => { panelService.connect('focus-out', ps => {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE); this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions(); Main.keyboard.resetSuggestions();
}); });
} }
_setDummyCursorGeometry(x, y, w, h) { _setDummyCursorGeometry(x, y, w, h) {
this._dummyCursor.set_position(Math.round(x), Math.round(y)); Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
this._dummyCursor.set_size(Math.round(w), Math.round(h));
if (this._boxPointer.visible) if (this._boxPointer.visible)
this._boxPointer.setPosition(this._dummyCursor, 0); this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
} }
_updateVisibility() { _updateVisibility() {
@ -289,7 +283,7 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.actor.visible)); this._candidateArea.actor.visible));
if (isVisible) { if (isVisible) {
this._boxPointer.setPosition(this._dummyCursor, 0); this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE); this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.raise_top(); this._boxPointer.raise_top();
} else { } else {

View File

@ -1,17 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, PaginatedIconGrid */
const { Clutter, GLib, GObject, Meta, St } = imports.gi; const { Clutter, GObject, Meta, St } = imports.gi;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main; const Main = imports.ui.main;
var ICON_SIZE = 96; var ICON_SIZE = 96;
var MIN_ICON_SIZE = 16; var MIN_ICON_SIZE = 16;
var EXTRA_SPACE_ANIMATION_TIME = 250; var EXTRA_SPACE_ANIMATION_TIME = 0.25;
var ANIMATION_TIME_IN = 350; var ANIMATION_TIME_IN = 0.350;
var ANIMATION_TIME_OUT = 1 / 2 * ANIMATION_TIME_IN; var ANIMATION_TIME_OUT = 1 / 2 * ANIMATION_TIME_IN;
var ANIMATION_MAX_DELAY_FOR_ITEM = 2 / 3 * ANIMATION_TIME_IN; var ANIMATION_MAX_DELAY_FOR_ITEM = 2 / 3 * ANIMATION_TIME_IN;
var ANIMATION_BASE_DELAY_FOR_ITEM = 1 / 4 * ANIMATION_MAX_DELAY_FOR_ITEM; var ANIMATION_BASE_DELAY_FOR_ITEM = 1 / 4 * ANIMATION_MAX_DELAY_FOR_ITEM;
@ -26,7 +26,7 @@ var AnimationDirection = {
}; };
var APPICON_ANIMATION_OUT_SCALE = 3; var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 250; var APPICON_ANIMATION_OUT_TIME = 0.25;
var BaseIcon = GObject.registerClass( var BaseIcon = GObject.registerClass(
class BaseIcon extends St.Bin { class BaseIcon extends St.Bin {
@ -56,10 +56,6 @@ class BaseIcon extends St.Bin {
if (params.showLabel) { if (params.showLabel) {
this.label = new St.Label({ text: label }); 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); this._box.add_actor(this.label);
} else { } else {
this.label = null; this.label = null;
@ -75,14 +71,14 @@ class BaseIcon extends St.Bin {
this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this)); 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 the actual height to keep the squared aspect
return this.get_preferred_height(-1); return this.get_preferred_height(-1);
} }
// This can be overridden by a subclass, or by the createIcon // This can be overridden by a subclass, or by the createIcon
// parameter to _init() // parameter to _init()
createIcon(_size) { createIcon(size) {
throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`); throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`);
} }
@ -141,14 +137,6 @@ class BaseIcon extends St.Bin {
// animating. // animating.
zoomOutActor(this.child); zoomOutActor(this.child);
} }
animateZoomOutAtPos(x, y) {
zoomOutActorAtPos(this.child, x, y);
}
update() {
this._createIconTexture(this.iconSize);
}
}); });
function clamp(value, min, max) { function clamp(value, min, max) {
@ -156,15 +144,10 @@ function clamp(value, min, max) {
} }
function zoomOutActor(actor) { function zoomOutActor(actor) {
let [x, y] = actor.get_transformed_position();
zoomOutActorAtPos(actor, x, y);
}
function zoomOutActorAtPos(actor, x, y) {
let actorClone = new Clutter.Clone({ source: actor, let actorClone = new Clutter.Clone({ source: actor,
reactive: false }); reactive: false });
let [width, height] = actor.get_transformed_size(); let [width, height] = actor.get_transformed_size();
let [x, y] = actor.get_transformed_position();
actorClone.set_size(width, height); actorClone.set_size(width, height);
actorClone.set_position(x, y); actorClone.set_position(x, y);
actorClone.opacity = 255; actorClone.opacity = 255;
@ -181,16 +164,18 @@ function zoomOutActorAtPos(actor, x, y) {
let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth); let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth);
let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight); let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight);
actorClone.ease({ Tweener.addTween(actorClone,
scale_x: APPICON_ANIMATION_OUT_SCALE, { time: APPICON_ANIMATION_OUT_TIME,
scale_y: APPICON_ANIMATION_OUT_SCALE, scale_x: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX, scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_y: containedY - scaledY, translation_x: containedX - scaledX,
opacity: 0, translation_y: containedY - scaledY,
duration: APPICON_ANIMATION_OUT_TIME, opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => actorClone.destroy() onComplete() {
}); actorClone.destroy();
}
});
} }
var IconGrid = GObject.registerClass({ var IconGrid = GObject.registerClass({
@ -221,8 +206,6 @@ var IconGrid = GObject.registerClass({
this.rightPadding = 0; this.rightPadding = 0;
this.leftPadding = 0; this.leftPadding = 0;
this._updateIconSizesLaterId = 0;
this._items = []; this._items = [];
this._clonesAnimating = []; this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here // Pulled from CSS, but hardcode some defaults here
@ -235,19 +218,11 @@ var IconGrid = GObject.registerClass({
// swarming into the void ... // swarming into the void ...
this.connect('notify::mapped', () => { this.connect('notify::mapped', () => {
if (!this.mapped) if (!this.mapped)
this._resetAnimationActors(); this._cancelAnimation();
}); });
this.connect('actor-added', this._childAdded.bind(this)); this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.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) { _keyFocusIn(actor) {
@ -256,35 +231,22 @@ var IconGrid = GObject.registerClass({
_childAdded(grid, child) { _childAdded(grid, child) {
child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this)); child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this));
child._paintVisible = child.opacity > 0;
child._opacityChangedId = child.connect('notify::opacity', () => {
let paintVisible = child._paintVisible;
child._paintVisible = child.opacity > 0;
if (paintVisible !== child._paintVisible)
this.queue_relayout();
});
} }
_childRemoved(grid, child) { _childRemoved(grid, child) {
child.disconnect(child._iconGridKeyFocusInId); child.disconnect(child._iconGridKeyFocusInId);
delete child._iconGridKeyFocusInId;
child.disconnect(child._opacityChangedId);
delete child._opacityChangedId;
delete child._paintVisible;
} }
vfunc_get_preferred_width(_forHeight) { vfunc_get_preferred_width(forHeight) {
if (this._fillParent) if (this._fillParent)
// Ignore all size requests of children and request a size of 0; // Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent // later we'll allocate as many children as fit the parent
return [0, 0]; return [0, 0];
let nChildren = this.get_n_children(); let nChildren = this.get_n_children();
let nColumns = this._colLimit let nColumns = this._colLimit ? Math.min(this._colLimit,
? Math.min(this._colLimit, nChildren) nChildren)
: nChildren; : nChildren;
let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing(); let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing();
// Kind of a lie, but not really an issue right now. If // Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would // we wanted to support some sort of hidden/overflow that would
@ -436,20 +398,21 @@ var IconGrid = GObject.registerClass({
* set of items to be animated. * set of items to be animated.
*/ */
_getChildrenToAnimate() { _getChildrenToAnimate() {
return this._getVisibleChildren().filter(child => child.opacity > 0); return this._getVisibleChildren();
} }
_resetAnimationActors() { _cancelAnimation() {
this._clonesAnimating.forEach(clone => clone.destroy());
this._clonesAnimating = [];
}
_animationDone() {
this._clonesAnimating.forEach(clone => { this._clonesAnimating.forEach(clone => {
clone.source.reactive = true; clone.source.reactive = true;
clone.source.opacity = 255; clone.source.opacity = 255;
clone.destroy(); clone.destroy();
}); });
this._clonesAnimating = []; this._clonesAnimating = [];
}
_animationDone() {
this._resetAnimationActors();
this.emit('animation-done'); this.emit('animation-done');
} }
@ -458,7 +421,7 @@ var IconGrid = GObject.registerClass({
throw new GObject.NotImplementedError("Pulse animation only implements " + throw new GObject.NotImplementedError("Pulse animation only implements " +
"'in' animation direction"); "'in' animation direction");
this._resetAnimationActors(); this._cancelAnimation();
let actors = this._getChildrenToAnimate(); let actors = this._getChildrenToAnimate();
if (actors.length == 0) { if (actors.length == 0) {
@ -481,32 +444,30 @@ var IconGrid = GObject.registerClass({
let delay = index / actors.length * maxDelay; let delay = index / actors.length * maxDelay;
let bounceUpTime = ANIMATION_TIME_IN / 4; let bounceUpTime = ANIMATION_TIME_IN / 4;
let isLastItem = index == actors.length - 1; let isLastItem = index == actors.length - 1;
actor.ease({ Tweener.addTween(actor,
scale_x: ANIMATION_BOUNCE_ICON_SCALE, { time: bounceUpTime,
scale_y: ANIMATION_BOUNCE_ICON_SCALE, transition: 'easeInOutQuad',
duration: bounceUpTime, delay: delay,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, scale_x: ANIMATION_BOUNCE_ICON_SCALE,
delay: delay, scale_y: ANIMATION_BOUNCE_ICON_SCALE,
onComplete: () => { onComplete: () => {
let duration = ANIMATION_TIME_IN - bounceUpTime; Tweener.addTween(actor,
actor.ease({ { time: ANIMATION_TIME_IN - bounceUpTime,
scale_x: 1, transition: 'easeInOutQuad',
scale_y: 1, scale_x: 1,
duration, scale_y: 1,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, onComplete: () => {
onComplete: () => { if (isLastItem)
if (isLastItem) this._animationDone();
this._animationDone(); }
actor.reactive = true; });
} }
}); });
}
});
} }
} }
animateSpring(animationDirection, sourceActor) { animateSpring(animationDirection, sourceActor) {
this._resetAnimationActors(); this._cancelAnimation();
let actors = this._getChildrenToAnimate(); let actors = this._getChildrenToAnimate();
if (actors.length == 0) { if (actors.length == 0) {
@ -560,25 +521,21 @@ var IconGrid = GObject.registerClass({
let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM; let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM;
let [finalX, finalY] = actor._transformedPosition; let [finalX, finalY] = actor._transformedPosition;
movementParams = { movementParams = { time: ANIMATION_TIME_IN,
x: finalX, transition: 'easeInOutQuad',
y: finalY, delay: delay,
scale_x: 1, x: finalX,
scale_y: 1, y: finalY,
duration: ANIMATION_TIME_IN, scale_x: 1,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, scale_y: 1,
delay onComplete: () => {
}; if (isLastItem)
this._animationDone();
if (isLastItem) } };
movementParams.onComplete = this._animationDone.bind(this); fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
fadeParams = { delay: delay,
opacity: 255, opacity: 255 };
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
} else { } else {
let isLastItem = actor._distance == maxDist; let isLastItem = actor._distance == maxDist;
@ -586,29 +543,26 @@ var IconGrid = GObject.registerClass({
actorClone.set_position(startX, startY); actorClone.set_position(startX, startY);
let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM; let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM;
movementParams = { movementParams = { time: ANIMATION_TIME_OUT,
x: adjustedSourcePositionX, transition: 'easeInOutQuad',
y: adjustedSourcePositionY, delay: delay,
scale_x: scaleX, x: adjustedSourcePositionX,
scale_y: scaleY, y: adjustedSourcePositionY,
duration: ANIMATION_TIME_OUT, scale_x: scaleX,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, scale_y: scaleY,
delay onComplete: () => {
}; if (isLastItem)
this._animationDone();
if (isLastItem) } };
movementParams.onComplete = this._animationDone.bind(this); fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
fadeParams = { delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM,
opacity: 0, opacity: 0 };
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM
};
} }
actorClone.ease(movementParams);
actorClone.ease(fadeParams); Tweener.addTween(actorClone, movementParams);
Tweener.addTween(actorClone, fadeParams);
} }
} }
@ -796,28 +750,24 @@ var IconGrid = GObject.registerClass({
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth; let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight; let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededSpacePerItem = (neededWidth > neededHeight) let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
? Math.ceil(neededWidth / this._minColumns) : Math.ceil(neededHeight / this._minRows);
: Math.ceil(neededHeight / this._minRows);
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE); this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE); this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._updateSpacingForSize(availWidth, availHeight); this._updateSpacingForSize(availWidth, availHeight);
} }
if (!this._updateIconSizesLaterId) Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, this._updateIconSizes.bind(this));
this._updateIconSizes.bind(this));
} }
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateIconSizes() { _updateIconSizes() {
this._updateIconSizesLaterId = 0;
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize); let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale); let newIconSize = Math.floor(ICON_SIZE * scale);
for (let i in this._items) { for (let i in this._items) {
this._items[i].icon.setIconSize(newIconSize); this._items[i].icon.setIconSize(newIconSize);
} }
return GLib.SOURCE_REMOVE;
} }
}); });
@ -834,7 +784,7 @@ var PaginatedIconGrid = GObject.registerClass({
this._childrenPerPage = 0; 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; let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height]; return [height, height];
} }
@ -894,7 +844,7 @@ var PaginatedIconGrid = GObject.registerClass({
// Overridden from IconGrid // Overridden from IconGrid
_getChildrenToAnimate() { _getChildrenToAnimate() {
let children = super._getChildrenToAnimate(); let children = this._getVisibleChildren();
let firstIndex = this._childrenPerPage * this.currentPage; let firstIndex = this._childrenPerPage * this.currentPage;
let lastIndex = firstIndex + this._childrenPerPage; let lastIndex = firstIndex + this._childrenPerPage;
@ -902,7 +852,7 @@ var PaginatedIconGrid = GObject.registerClass({
} }
_computePages(availWidthPerPage, availHeightPerPage) { _computePages(availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage); let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows; let nRows;
let children = this._getVisibleChildren(); let children = this._getVisibleChildren();
if (nColumns > 0) if (nColumns > 0)
@ -973,7 +923,8 @@ var PaginatedIconGrid = GObject.registerClass({
let childrenPerRow = this._childrenPerPage / this._rowsPerPage; let childrenPerRow = this._childrenPerPage / this._rowsPerPage;
let sourceRow = Math.floor((index - pageOffset) / childrenPerRow); let sourceRow = Math.floor((index - pageOffset) / childrenPerRow);
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 : sourceRow; let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1
: sourceRow;
let nRowsBelow = this._rowsPerPage - nRowsAbove; let nRowsBelow = this._rowsPerPage - nRowsAbove;
let nRowsUp, nRowsDown; let nRowsUp, nRowsDown;
@ -1013,14 +964,13 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
children[i].translation_y = 0; children[i].translation_y = 0;
let params = { let params = { translation_y: translationY,
translation_y: translationY, time: EXTRA_SPACE_ANIMATION_TIME,
duration: EXTRA_SPACE_ANIMATION_TIME, transition: 'easeInOutQuad'
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD };
};
if (i == (children.length - 1)) if (i == (children.length - 1))
params.onComplete = () => this.emit('space-opened'); params.onComplete = () => this.emit('space-opened');
children[i].ease(params); Tweener.addTween(children[i], params);
} }
} }
@ -1033,12 +983,12 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < this._translatedChildren.length; i++) { for (let i = 0; i < this._translatedChildren.length; i++) {
if (!this._translatedChildren[i].translation_y) if (!this._translatedChildren[i].translation_y)
continue; continue;
this._translatedChildren[i].ease({ Tweener.addTween(this._translatedChildren[i],
translation_y: 0, { translation_y: 0,
duration: EXTRA_SPACE_ANIMATION_TIME, time: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, transition: 'easeInOutQuad',
onComplete: () => this.emit('space-closed') onComplete: () => this.emit('space-closed')
}); });
} }
} }
}); });

View File

@ -1,4 +1,3 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi; const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
@ -76,9 +75,8 @@ var InhibitShortcutsDialog = GObject.registerClass({
let name = this._app ? this._app.get_name() : this._window.title; let name = this._app ? this._app.get_name() : this._window.title;
/* Translators: %s is an application name like "Settings" */ /* Translators: %s is an application name like "Settings" */
let title = name let title = name ? _("%s wants to inhibit shortcuts").format(name)
? _("%s wants to inhibit shortcuts").format(name) : _("Application wants to inhibit shortcuts");
: _("Application wants to inhibit shortcuts");
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' }); let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
let contentParams = { icon, title }; let contentParams = { icon, title };
@ -141,7 +139,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
return; return;
} }
let [permissions] = res; let [permissions, data] = res;
if (permissions[appId] === undefined) // Not found if (permissions[appId] === undefined) // Not found
this._dialog.open(); this._dialog.open();
else if (permissions[appId] == GRANTED) else if (permissions[appId] == GRANTED)

View File

@ -1,4 +1,3 @@
/* exported KbdA11yDialog */
const { Clutter, Gio, GObject } = imports.gi; const { Clutter, Gio, GObject } = imports.gi;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
@ -27,24 +26,24 @@ class KbdA11yDialog extends GObject.Object {
if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) { if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED; key = KEY_SLOW_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0; enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) ? true : false;
title = enabled title = enabled ?
? _("Slow Keys Turned On") _("Slow Keys Turned On") :
: _("Slow Keys Turned Off"); _("Slow Keys Turned Off");
body = _("You just held down the Shift key for 8 seconds. This is the shortcut " + body = _("You just held down the Shift key for 8 seconds. This is the shortcut " +
"for the Slow Keys feature, which affects the way your keyboard works."); "for the Slow Keys feature, which affects the way your keyboard works.");
} else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) { } else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED; key = KEY_STICKY_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0; enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) ? true : false;
title = enabled title = enabled ?
? _("Sticky Keys Turned On") _("Sticky Keys Turned On") :
: _("Sticky Keys Turned Off"); _("Sticky Keys Turned Off");
body = enabled body = enabled ?
? _("You just pressed the Shift key 5 times in a row. This is the shortcut " + _("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.") "for the Sticky Keys feature, which affects the way your keyboard works.") :
: _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " + _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works."); "This turns off the Sticky Keys feature, which affects the way your keyboard works.");
} else { } else {
return; return;
} }

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Keyboard */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -11,10 +10,11 @@ const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const PageIndicators = imports.ui.pageIndicators; const PageIndicators = imports.ui.pageIndicators;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Tweener = imports.ui.tweener;
var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2; var KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
var KEY_LONG_PRESS_TIME = 250; var KEY_LONG_PRESS_TIME = 250;
var PANEL_SWITCH_ANIMATION_TIME = 500; var PANEL_SWITCH_ANIMATION_TIME = 0.5;
var PANEL_SWITCH_RELATIVE_DISTANCE = 1 / 3; /* A third of the actor width */ var PANEL_SWITCH_RELATIVE_DISTANCE = 1 / 3; /* A third of the actor width */
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications'; const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
@ -100,14 +100,13 @@ class KeyContainer extends St.Widget {
this._rows = []; this._rows = [];
} }
appendRow() { appendRow(length) {
this._currentRow++; this._currentRow++;
this._currentCol = 0; this._currentCol = 0;
let row = { let row = new Object();
keys: [], row.keys = [];
width: 0, row.width = 0;
};
this._rows.push(row); this._rows.push(row);
} }
@ -194,12 +193,12 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
item = this.addAction(is.displayName, () => { item = this.addAction(is.displayName, () => {
inputSourceManager.activateInputSource(is, true); inputSourceManager.activateInputSource(is, true);
}); });
item.can_focus = false; item.actor.can_focus = false;
} }
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
item = this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop'); item = this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop');
item.can_focus = false; item.actor.can_focus = false;
this._capturedEventId = 0; this._capturedEventId = 0;
@ -475,7 +474,7 @@ var KeyboardModel = class {
_loadModel(groupName) { _loadModel(groupName) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(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) if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents); contents = imports.byteArray.toString(contents);
@ -570,27 +569,11 @@ var FocusTracker = class {
}; };
Signals.addSignalMethods(FocusTracker.prototype); Signals.addSignalMethods(FocusTracker.prototype);
var EmojiPager = GObject.registerClass({ var EmojiPager = class EmojiPager {
Properties: { constructor(sections, nCols, nRows) {
'delta': GObject.ParamSpec.int( this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
'delta', 'delta', 'delta', reactive: true,
GObject.ParamFlags.READWRITE, clip_to_allocation: true });
GLib.MININT32, GLib.MAXINT32, 0)
},
Signals: {
'emoji': { param_types: [GObject.TYPE_STRING] },
'page-changed': {
param_types: [GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_INT]
}
}
}, class EmojiPager extends St.Widget {
_init(sections, nCols, nRows) {
super._init({
layout_manager: new Clutter.BinLayout(),
reactive: true,
clip_to_allocation: true
});
this._sections = sections; this._sections = sections;
this._nCols = nCols; this._nCols = nCols;
this._nRows = nRows; this._nRows = nRows;
@ -612,7 +595,7 @@ var EmojiPager = GObject.registerClass({
panAction.connect('gesture-cancel', this._onPanCancel.bind(this)); panAction.connect('gesture-cancel', this._onPanCancel.bind(this));
panAction.connect('gesture-end', this._onPanEnd.bind(this)); panAction.connect('gesture-end', this._onPanEnd.bind(this));
this._panAction = panAction; this._panAction = panAction;
this.add_action(panAction); this.actor.add_action(panAction);
} }
get delta() { get delta() {
@ -625,11 +608,7 @@ var EmojiPager = GObject.registerClass({
else if (value < -this._width) else if (value < -this._width)
value = -this._width; value = -this._width;
if (this._delta == value)
return;
this._delta = value; this._delta = value;
this.notify('delta');
if (value == 0) if (value == 0)
return; return;
@ -646,8 +625,8 @@ var EmojiPager = GObject.registerClass({
if (followingPage != null) { if (followingPage != null) {
this._followingPanel = this._generatePanel(followingPage); this._followingPanel = this._generatePanel(followingPage);
this._followingPanel.set_pivot_point(0.5, 0.5); this._followingPanel.set_pivot_point(0.5, 0.5);
this.add_child(this._followingPanel); this.actor.add_child(this._followingPanel);
this.set_child_below_sibling(this._followingPanel, this._panel); this.actor.set_child_below_sibling(this._followingPanel, this._panel);
} }
this._followingPage = followingPage; this._followingPage = followingPage;
@ -683,7 +662,7 @@ var EmojiPager = GObject.registerClass({
} }
_onPan(action) { _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; this.delta = this.delta + dx;
if (this._currentKey != null) { if (this._currentKey != null) {
@ -695,12 +674,12 @@ var EmojiPager = GObject.registerClass({
} }
_onPanBegin() { _onPanBegin() {
this._width = this.width; this._width = this.actor.width;
return true; return true;
} }
_onPanEnd() { _onPanEnd() {
if (Math.abs(this._delta) < this.width * PANEL_SWITCH_RELATIVE_DISTANCE) { if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
this._onPanCancel(); this._onPanCancel();
} else { } else {
let value; let value;
@ -712,24 +691,28 @@ var EmojiPager = GObject.registerClass({
let relDelta = Math.abs(this._delta - value) / this._width; let relDelta = Math.abs(this._delta - value) / this._width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta); let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
this.remove_all_transitions(); Tweener.removeTweens(this);
this.ease_property('delta', value, { Tweener.addTween(this,
duration: time, { delta: value,
onComplete: () => { time: time,
this.setCurrentPage(this.getFollowingPage()); transition: 'easeInOutQuad',
} onComplete() {
}); this.setCurrentPage(this.getFollowingPage());
}
});
} }
} }
_onPanCancel() { _onPanCancel() {
let relDelta = Math.abs(this._delta) / this.width; let relDelta = Math.abs(this._delta) / this.actor.width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta); let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
this.remove_all_transitions(); Tweener.removeTweens(this);
this.ease_property('delta', 0, { Tweener.addTween(this,
duration: time, { delta: 0,
}); time: time,
transition: 'easeInOutQuad',
});
} }
_initPagingInfo() { _initPagingInfo() {
@ -839,7 +822,7 @@ var EmojiPager = GObject.registerClass({
if (!this._panel) { if (!this._panel) {
this._panel = this._generatePanel(nPage); this._panel = this._generatePanel(nPage);
this.add_child(this._panel); this.actor.add_child(this._panel);
} }
let page = this._pages[nPage]; let page = this._pages[nPage];
@ -856,7 +839,8 @@ var EmojiPager = GObject.registerClass({
} }
} }
} }
}); };
Signals.addSignalMethods(EmojiPager.prototype);
var EmojiSelection = class EmojiSelection { var EmojiSelection = class EmojiSelection {
constructor() { constructor() {
@ -920,7 +904,7 @@ var EmojiSelection = class EmojiSelection {
_populateSections() { _populateSections() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json'); 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) if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents); contents = imports.byteArray.toString(contents);
@ -1081,7 +1065,7 @@ var Keyboard = class Keyboard {
this.hide(); this.hide();
}); });
Meta.get_backend().connect('last-device-changed', Meta.get_backend().connect('last-device-changed',
(backend, deviceId) => { (backend, deviceId) => {
let manager = Clutter.DeviceManager.get_default(); let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId); let device = manager.get_device(deviceId);
@ -1187,7 +1171,7 @@ var Keyboard = class Keyboard {
this._emojiSelection = new EmojiSelection(); this._emojiSelection = new EmojiSelection();
this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this)); this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
this._emojiSelection.connect('hide', () => this.hide()); this._emojiSelection.connect('hide', (selection) => this.hide());
this._emojiSelection.connect('emoji-selected', (selection, emoji) => { this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
this._keyboardController.commitString(emoji); this._keyboardController.commitString(emoji);
}); });
@ -1298,7 +1282,7 @@ var Keyboard = class Keyboard {
} }
} }
}); });
button.connect('released', (actor, keyval, _str) => { button.connect('released', (actor, keyval, str) => {
if (keyval != 0) { if (keyval != 0) {
if (button._keyvalPress) if (button._keyvalPress)
this._keyboardController.keyvalRelease(keyval); this._keyboardController.keyvalRelease(keyval);
@ -1483,7 +1467,7 @@ var Keyboard = class Keyboard {
this._setActiveLayer(0); this._setActiveLayer(0);
} }
_onKeyboardGroupsChanged() { _onKeyboardGroupsChanged(keyboard) {
let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor]; let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor];
this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => { this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
c.destroy(); c.destroy();
@ -1669,23 +1653,19 @@ var Keyboard = class Keyboard {
return; return;
if (show) { if (show) {
windowActor.ease({ Tweener.addTween(windowActor,
y: windowActor.y - deltaY, { y: windowActor.y - deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME, time: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: this._windowSlideAnimationComplete,
this._windowSlideAnimationComplete(window, -deltaY); onCompleteParams: [window, -deltaY] });
}
});
} else { } else {
windowActor.ease({ Tweener.addTween(windowActor,
y: windowActor.y + deltaY, { y: windowActor.y + deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME, time: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD, transition: 'easeInQuad',
onComplete: () => { onComplete: this._windowSlideAnimationComplete,
this._windowSlideAnimationComplete(window, deltaY); onCompleteParams: [window, deltaY] });
}
});
} }
} }
@ -1749,7 +1729,7 @@ var KeyboardController = class {
this.emit('groups-changed'); this.emit('groups-changed');
} }
_onSourceChanged(inputSourceManager, _oldSource) { _onSourceChanged(inputSourceManager, oldSource) {
let source = inputSourceManager.currentSource; let source = inputSourceManager.currentSource;
this._currentSource = source; this._currentSource = source;
this.emit('active-group', source.id); this.emit('active-group', source.id);

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported MonitorConstraint, LayoutManager */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -11,11 +10,12 @@ const LoginManager = imports.misc.loginManager;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Ripples = imports.ui.ripples; const Ripples = imports.ui.ripples;
var STARTUP_ANIMATION_TIME = 500; var STARTUP_ANIMATION_TIME = 0.5;
var KEYBOARD_ANIMATION_TIME = 150; var KEYBOARD_ANIMATION_TIME = 0.15;
var BACKGROUND_FADE_ANIMATION_TIME = 1000; var BACKGROUND_FADE_ANIMATION_TIME = 1.0;
var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
@ -80,12 +80,10 @@ var MonitorConstraint = GObject.registerClass({
this.notify('index'); this.notify('index');
} }
// eslint-disable-next-line camelcase
get work_area() { get work_area() {
return this._workArea; return this._workArea;
} }
// eslint-disable-next-line camelcase
set work_area(v) { set work_area(v) {
if (v == this._workArea) if (v == this._workArea)
return; return;
@ -167,12 +165,12 @@ var Monitor = class Monitor {
const UiActor = GObject.registerClass( const UiActor = GObject.registerClass(
class UiActor extends St.Widget { class UiActor extends St.Widget {
vfunc_get_preferred_width (_forHeight) { vfunc_get_preferred_width (forHeight) {
let width = global.stage.width; let width = global.stage.width;
return [width, width]; return [width, width];
} }
vfunc_get_preferred_height (_forWidth) { vfunc_get_preferred_height (forWidth) {
let height = global.stage.height; let height = global.stage.height;
return [height, height]; return [height, height];
} }
@ -238,12 +236,11 @@ var LayoutManager = GObject.registerClass({
reactive: true }); reactive: true });
this.addChrome(this.overviewGroup); this.addChrome(this.overviewGroup);
this.screenShieldGroup = new St.Widget({ this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
name: 'screenShieldGroup', visible: false,
visible: false, clip_to_allocation: true,
clip_to_allocation: true, layout_manager: new Clutter.BinLayout(),
layout_manager: new Clutter.BinLayout(), });
});
this.addChrome(this.screenShieldGroup); this.addChrome(this.screenShieldGroup);
this.panelBox = new St.BoxLayout({ name: 'panelBox', this.panelBox = new St.BoxLayout({ name: 'panelBox',
@ -464,11 +461,10 @@ var LayoutManager = GObject.registerClass({
let backgroundActor = this._bgManagers[i].backgroundActor; let backgroundActor = this._bgManagers[i].backgroundActor;
backgroundActor.show(); backgroundActor.show();
backgroundActor.opacity = 0; backgroundActor.opacity = 0;
backgroundActor.ease({ Tweener.addTween(backgroundActor,
opacity: 255, { opacity: 255,
duration: BACKGROUND_FADE_ANIMATION_TIME, time: BACKGROUND_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad' });
});
} }
} }
} }
@ -699,23 +695,23 @@ var LayoutManager = GObject.registerClass({
} }
_startupAnimationGreeter() { _startupAnimationGreeter() {
this.panelBox.ease({ Tweener.addTween(this.panelBox,
translation_y: 0, { translation_y: 0,
duration: STARTUP_ANIMATION_TIME, time: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => this._startupAnimationComplete() onComplete: this._startupAnimationComplete,
}); onCompleteScope: this });
} }
_startupAnimationSession() { _startupAnimationSession() {
this.uiGroup.ease({ Tweener.addTween(this.uiGroup,
scale_x: 1, { scale_x: 1,
scale_y: 1, scale_y: 1,
opacity: 255, opacity: 255,
duration: STARTUP_ANIMATION_TIME, time: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => this._startupAnimationComplete() onComplete: this._startupAnimationComplete,
}); onCompleteScope: this });
} }
_startupAnimationComplete() { _startupAnimationComplete() {
@ -741,15 +737,14 @@ var LayoutManager = GObject.registerClass({
showKeyboard() { showKeyboard() {
this.keyboardBox.show(); this.keyboardBox.show();
this.keyboardBox.ease({ Tweener.addTween(this.keyboardBox,
anchor_y: this.keyboardBox.height, { anchor_y: this.keyboardBox.height,
opacity: 255, opacity: 255,
duration: KEYBOARD_ANIMATION_TIME, time: KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: this._showKeyboardComplete,
this._showKeyboardComplete(); onCompleteScope: this
} });
});
this.emit('keyboard-visible-changed', true); this.emit('keyboard-visible-changed', true);
} }
@ -768,15 +763,14 @@ var LayoutManager = GObject.registerClass({
this.keyboardBox.disconnect(this._keyboardHeightNotifyId); this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
this._keyboardHeightNotifyId = 0; this._keyboardHeightNotifyId = 0;
} }
this.keyboardBox.ease({ Tweener.addTween(this.keyboardBox,
anchor_y: 0, { anchor_y: 0,
opacity: 0, opacity: 0,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME, time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD, transition: 'easeInQuad',
onComplete: () => { onComplete: this._hideKeyboardComplete,
this._hideKeyboardComplete(); onCompleteScope: this
} });
});
this.emit('keyboard-visible-changed', false); this.emit('keyboard-visible-changed', false);
} }
@ -855,13 +849,12 @@ var LayoutManager = GObject.registerClass({
index = this._findActor(ancestor); index = this._findActor(ancestor);
} }
let ancestorData = ancestor let ancestorData = ancestor ? this._trackedActors[index]
? this._trackedActors[index] : defaultParams;
: defaultParams;
// We can't use Params.parse here because we want to drop // We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor // the extra values like ancestorData.actor
for (let prop in defaultParams) { for (let prop in defaultParams) {
if (!Object.prototype.hasOwnProperty.call(params, prop)) if (!params.hasOwnProperty(prop))
params[prop] = ancestorData[prop]; params[prop] = ancestorData[prop];
} }
@ -1015,6 +1008,11 @@ var LayoutManager = GObject.registerClass({
if (Main.modalCount > 0) if (Main.modalCount > 0)
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
// Bug workaround - get_transformed_position()/get_transformed_size() don't work after
// a change in stage size until the first pick or paint.
// https://bugzilla.gnome.org/show_bug.cgi?id=761565
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0);
let rects = [], struts = [], i; let rects = [], struts = [], i;
let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow); let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow);
let wantsInputRegion = !isPopupMenuVisible; let wantsInputRegion = !isPopupMenuVisible;
@ -1070,17 +1068,16 @@ var LayoutManager = GObject.registerClass({
side = Meta.Side.RIGHT; side = Meta.Side.RIGHT;
else else
continue; continue;
} else if (x1 <= monitor.x) { } else if (x1 <= monitor.x)
side = Meta.Side.LEFT; side = Meta.Side.LEFT;
} else if (y1 <= monitor.y) { else if (y1 <= monitor.y)
side = Meta.Side.TOP; side = Meta.Side.TOP;
} else if (x2 >= monitor.x + monitor.width) { else if (x2 >= monitor.x + monitor.width)
side = Meta.Side.RIGHT; side = Meta.Side.RIGHT;
} else if (y2 >= monitor.y + monitor.height) { else if (y2 >= monitor.y + monitor.height)
side = Meta.Side.BOTTOM; side = Meta.Side.BOTTOM;
} else { else
continue; continue;
}
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 }); let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 });
let strut = new Meta.Strut({ rect: strutRect, side: side }); let strut = new Meta.Strut({ rect: strutRect, side: side });
@ -1221,8 +1218,6 @@ var HotCorner = class HotCorner {
if (this.actor) if (this.actor)
this.actor.destroy(); this.actor.destroy();
this._ripples.destroy();
} }
_toggleOverview() { _toggleOverview() {
@ -1235,7 +1230,7 @@ var HotCorner = class HotCorner {
} }
} }
handleDragOver(source, _actor, _x, _y, _time) { handleDragOver(source, actor, x, y, time) {
if (source != Main.xdndHandler) if (source != Main.xdndHandler)
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
@ -1336,7 +1331,7 @@ var PressureBarrier = class PressureBarrier {
let threshold = this._lastTime - this._timeout; let threshold = this._lastTime - this._timeout;
while (i < this._barrierEvents.length) { while (i < this._barrierEvents.length) {
let [time, distance_] = this._barrierEvents[i]; let [time, distance] = this._barrierEvents[i];
if (time >= threshold) if (time >= threshold)
break; break;
i++; i++;
@ -1345,14 +1340,14 @@ var PressureBarrier = class PressureBarrier {
let firstNewEvent = i; let firstNewEvent = i;
for (i = 0; i < firstNewEvent; i++) { for (i = 0; i < firstNewEvent; i++) {
let [time_, distance] = this._barrierEvents[i]; let [time, distance] = this._barrierEvents[i];
this._currentPressure -= distance; this._currentPressure -= distance;
} }
this._barrierEvents = this._barrierEvents.slice(firstNewEvent); this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
} }
_onBarrierLeft(barrier, _event) { _onBarrierLeft(barrier, event) {
barrier._isHit = false; barrier._isHit = false;
if (this._barriers.every(b => !b._isHit)) { if (this._barriers.every(b => !b._isHit)) {
this._reset(); this._reset();

View File

@ -1,10 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Lightbox */
const { Clutter, GObject, Shell, St } = imports.gi; const { Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_FADE_FACTOR = 0.4; var DEFAULT_FADE_FACTOR = 0.4;
var VIGNETTE_BRIGHTNESS = 0.2; var VIGNETTE_BRIGHTNESS = 0.2;
@ -23,31 +23,16 @@ t = clamp(t, 0.0, 1.0);\n\
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\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);'; cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
var RadialShaderEffect = GObject.registerClass({ var RadialShaderQuad = GObject.registerClass(
Properties: { class RadialShaderQuad extends Shell.GLSLQuad {
'brightness': GObject.ParamSpec.float(
'brightness', 'brightness', 'brightness',
GObject.ParamFlags.READWRITE,
0, 1, 1
),
'sharpness': GObject.ParamSpec.float(
'sharpness', 'sharpness', 'sharpness',
GObject.ParamFlags.READWRITE,
0, 1, 0
)
}
}, class RadialShaderEffect extends Shell.GLSLEffect {
_init(params) { _init(params) {
this._brightness = undefined;
this._sharpness = undefined;
super._init(params); super._init(params);
this._brightnessLocation = this.get_uniform_location('brightness'); this._brightnessLocation = this.get_uniform_location('brightness');
this._sharpnessLocation = this.get_uniform_location('vignette_sharpness'); this._sharpnessLocation = this.get_uniform_location('vignette_sharpness');
this.brightness = 1.0; this.brightness = 1.0;
this.sharpness = 0.0; this.vignetteSharpness = 0.0;
} }
vfunc_build_pipeline() { vfunc_build_pipeline() {
@ -60,25 +45,19 @@ var RadialShaderEffect = GObject.registerClass({
} }
set brightness(v) { set brightness(v) {
if (this._brightness == v)
return;
this._brightness = v; this._brightness = v;
this.set_uniform_float(this._brightnessLocation, this.set_uniform_float(this._brightnessLocation,
1, [this._brightness]); 1, [this._brightness]);
this.notify('brightness');
} }
get sharpness() { get vignetteSharpness() {
return this._sharpness; return this._sharpness;
} }
set sharpness(v) { set vignetteSharpness(v) {
if (this._sharpness == v)
return;
this._sharpness = v; this._sharpness = v;
this.set_uniform_float(this._sharpnessLocation, this.set_uniform_float(this._sharpnessLocation,
1, [this._sharpness]); 1, [this._sharpness]);
this.notify('sharpness');
} }
}); });
@ -89,8 +68,8 @@ var RadialShaderEffect = GObject.registerClass({
* - inhibitEvents: whether to inhibit events for @container * - inhibitEvents: whether to inhibit events for @container
* - width: shade actor width * - width: shade actor width
* - height: shade actor height * - height: shade actor height
* - fadeInTime: milliseconds used to fade in * - fadeInTime: seconds used to fade in
* - fadeOutTime: milliseconds used to fade out * - fadeOutTime: seconds used to fade out
* *
* Lightbox creates a dark translucent "shade" actor to hide the * Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors * contents of @container, and allows you to specify particular actors
@ -108,25 +87,27 @@ var RadialShaderEffect = GObject.registerClass({
*/ */
var Lightbox = class Lightbox { var Lightbox = class Lightbox {
constructor(container, params) { constructor(container, params) {
params = Params.parse(params, { params = Params.parse(params, { inhibitEvents: false,
inhibitEvents: false, width: null,
width: null, height: null,
height: null, fadeFactor: DEFAULT_FADE_FACTOR,
fadeFactor: DEFAULT_FADE_FACTOR, radialEffect: false,
radialEffect: false, });
});
this._container = container; this._container = container;
this._children = container.get_children(); this._children = container.get_children();
this._fadeFactor = params.fadeFactor; this._fadeFactor = params.fadeFactor;
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect; this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
this.actor = new St.Bin({ reactive: params.inhibitEvents });
if (this._radialEffect) if (this._radialEffect)
this.actor.add_effect(new RadialShaderEffect({ name: 'radial' })); this.actor = new RadialShaderQuad({ x: 0,
y: 0,
reactive: params.inhibitEvents });
else else
this.actor.set({ opacity: 0, style_class: 'lightbox' }); this.actor = new St.Bin({ x: 0,
y: 0,
opacity: 0,
style_class: 'lightbox',
reactive: params.inhibitEvents });
container.add_actor(this.actor); container.add_actor(this.actor);
this.actor.raise_top(); this.actor.raise_top();
@ -173,52 +154,60 @@ var Lightbox = class Lightbox {
} }
show(fadeInTime) { show(fadeInTime) {
this.actor.remove_all_transitions(); fadeInTime = fadeInTime || 0;
let easeProps = { Tweener.removeTweens(this.actor);
duration: fadeInTime || 0, if (this._radialEffect) {
mode: Clutter.AnimationMode.EASE_OUT_QUAD Tweener.addTween(this.actor,
}; { brightness: VIGNETTE_BRIGHTNESS,
vignetteSharpness: VIGNETTE_SHARPNESS,
let onComplete = () => { time: fadeInTime,
this.shown = true; transition: 'easeOutQuad',
this.emit('shown'); onComplete: () => {
}; this.shown = true;
this.emit('shown');
}
});
} else {
Tweener.addTween(this.actor,
{ opacity: 255 * this._fadeFactor,
time: fadeInTime,
transition: 'easeOutQuad',
onComplete: () => {
this.shown = true;
this.emit('shown');
}
});
}
this.actor.show(); this.actor.show();
if (this._radialEffect) {
this.actor.ease_property(
'@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps);
this.actor.ease_property(
'@effects.radial.sharpness', VIGNETTE_SHARPNESS,
Object.assign({ onComplete }, easeProps));
} else {
this.actor.ease(Object.assign(easeProps, {
opacity: 255 * this._fadeFactor,
onComplete
}));
}
} }
hide(fadeOutTime) { hide(fadeOutTime) {
fadeOutTime = fadeOutTime || 0;
this.shown = false; this.shown = false;
this.actor.remove_all_transitions(); Tweener.removeTweens(this.actor);
let easeProps = {
duration: fadeOutTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => this.actor.hide();
if (this._radialEffect) { if (this._radialEffect) {
this.actor.ease_property( Tweener.addTween(this.actor,
'@effects.radial.brightness', 1.0, easeProps); { brightness: 1.0,
this.actor.ease_property( vignetteSharpness: 0.0,
'@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps)); opacity: 0,
time: fadeOutTime,
transition: 'easeOutQuad',
onComplete: () => {
this.actor.hide();
}
});
} else { } else {
this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete })); Tweener.addTween(this.actor,
{ opacity: 0,
time: fadeOutTime,
transition: 'easeOutQuad',
onComplete: () => {
this.actor.hide();
}
});
} }
} }

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LocatePointer */
const { Gio } = imports.gi; const { Gio } = imports.gi;
const Ripples = imports.ui.ripples; const Ripples = imports.ui.ripples;
@ -11,29 +10,15 @@ const LOCATE_POINTER_SCHEMA = "org.gnome.desktop.interface";
var LocatePointer = class { var LocatePointer = class {
constructor() { constructor() {
this._settings = new Gio.Settings({ schema_id: LOCATE_POINTER_SCHEMA }); this._settings = new Gio.Settings({ schema_id: LOCATE_POINTER_SCHEMA });
this._settings.connect(`changed::${LOCATE_POINTER_KEY}`, () => this._syncEnabled()); this._ripples = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location');
this._syncEnabled(); this._ripples.addTo(Main.uiGroup);
}
_syncEnabled() {
let enabled = this._settings.get_boolean(LOCATE_POINTER_KEY);
if (enabled == !!this._ripples)
return;
if (enabled) {
this._ripples = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location');
this._ripples.addTo(Main.uiGroup);
} else {
this._ripples.destroy();
this._ripples = null;
}
} }
show() { show() {
if (!this._ripples) if (!this._settings.get_boolean(LOCATE_POINTER_KEY))
return; return;
let [x, y] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
this._ripples.playAnimation(x, y); this._ripples.playAnimation(x, y);
} }
}; };

View File

@ -1,24 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */
const { Clutter, Cogl, Gio, GLib, const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi; GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const System = imports.system; const System = imports.system;
const History = imports.misc.history; const History = imports.misc.history;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main; const Main = imports.ui.main;
const JsParse = imports.misc.jsParse; const JsParse = imports.misc.jsParse;
const { ExtensionState } = ExtensionUtils;
const CHEVRON = '>>> '; const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */ /* Imports...feel free to add here as needed */
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' + var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
'const Main = imports.ui.main; ' + 'const Main = imports.ui.main; ' +
'const Mainloop = imports.mainloop; ' +
'const Tweener = imports.ui.tweener; ' +
/* Utility functions...we should probably be able to use these /* Utility functions...we should probably be able to use these
* in the shell core code too. */ * in the shell core code too. */
'const stage = global.stage; ' + 'const stage = global.stage; ' +
@ -30,11 +32,9 @@ var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = im
const HISTORY_KEY = 'looking-glass-history'; const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event // Time between tabs for them to count as a double-tab event
var AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500; var AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 200; var AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 0.2;
var AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords(); var AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() { function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new']; const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_') // Don't add the private properties of window (i.e., ones starting with '_')
@ -238,7 +238,7 @@ var Notebook = class Notebook {
Signals.addSignalMethods(Notebook.prototype); Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) { function objectToString(o) {
if (typeof o == typeof objectToString) { if (typeof(o) == typeof(objectToString)) {
// special case this since the default is way, way too verbose // special case this since the default is way, way too verbose
return '<js function>'; return '<js function>';
} else { } else {
@ -266,7 +266,7 @@ var ObjLink = class ObjLink {
this._lookingGlass = lookingGlass; this._lookingGlass = lookingGlass;
} }
_onClicked() { _onClicked(link) {
this._lookingGlass.inspectObject(this._obj, this.actor); this._lookingGlass.inspectObject(this._obj, this.actor);
} }
}; };
@ -304,9 +304,6 @@ var WindowList = class WindowList {
} }
_updateWindowList() { _updateWindowList() {
if (!this._lookingGlass.isOpen)
return;
this.actor.destroy_all_children(); this.actor.destroy_all_children();
let windows = global.get_window_actors(); let windows = global.get_window_actors();
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
@ -338,10 +335,6 @@ var WindowList = class WindowList {
} }
} }
} }
update() {
this._updateWindowList();
}
}; };
Signals.addSignalMethods(WindowList.prototype); Signals.addSignalMethods(WindowList.prototype);
@ -374,7 +367,7 @@ var ObjInspector = class ObjInspector {
let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' }); let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
this._container.add_actor(hbox); this._container.add_actor(hbox);
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof obj, let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof(obj),
objectToString(obj)) }); objectToString(obj)) });
label.single_line_mode = true; label.single_line_mode = true;
hbox.add(label, { expand: true, y_fill: false }); hbox.add(label, { expand: true, y_fill: false });
@ -392,7 +385,7 @@ var ObjInspector = class ObjInspector {
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' })); button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
button.connect('clicked', this.close.bind(this)); button.connect('clicked', this.close.bind(this));
hbox.add(button); hbox.add(button);
if (typeof obj == typeof {}) { if (typeof(obj) == typeof({})) {
let properties = []; let properties = [];
for (let propName in obj) { for (let propName in obj) {
properties.push(propName); properties.push(propName);
@ -424,12 +417,9 @@ var ObjInspector = class ObjInspector {
this.actor.show(); this.actor.show();
if (sourceActor) { if (sourceActor) {
this.actor.set_scale(0, 0); this.actor.set_scale(0, 0);
this.actor.ease({ Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
scale_x: 1, transition: 'easeOutQuad',
scale_y: 1, time: 0.2 });
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: 200
});
} else { } else {
this.actor.set_scale(1, 1); this.actor.set_scale(1, 1);
} }
@ -528,7 +518,7 @@ var Inspector = GObject.registerClass({
let primary = Main.layoutManager.primaryMonitor; let primary = Main.layoutManager.primaryMonitor;
let [, , natWidth, natHeight] = let [minWidth, minHeight, natWidth, natHeight] =
this._eventHandler.get_preferred_size(); this._eventHandler.get_preferred_size();
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
@ -633,16 +623,15 @@ var Extensions = class Extensions {
this._extensionsList.add(this._noExtensions); this._extensionsList.add(this._noExtensions);
this.actor.add(this._extensionsList); this.actor.add(this._extensionsList);
Main.extensionManager.getUuids().forEach(uuid => { for (let uuid in ExtensionUtils.extensions)
this._loadExtension(null, uuid); this._loadExtension(null, uuid);
});
Main.extensionManager.connect('extension-loaded', ExtensionSystem.connect('extension-loaded',
this._loadExtension.bind(this)); this._loadExtension.bind(this));
} }
_loadExtension(o, uuid) { _loadExtension(o, uuid) {
let extension = Main.extensionManager.lookup(uuid); let extension = ExtensionUtils.extensions[uuid];
// There can be cases where we create dummy extension metadata // There can be cases where we create dummy extension metadata
// that's not really a proper extension. Don't bother with these. // that's not really a proper extension. Don't bother with these.
if (!extension.metadata.name) if (!extension.metadata.name)
@ -699,16 +688,16 @@ var Extensions = class Extensions {
_stateToString(extensionState) { _stateToString(extensionState) {
switch (extensionState) { switch (extensionState) {
case ExtensionState.ENABLED: case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled"); return _("Enabled");
case ExtensionState.DISABLED: case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionState.INITIALIZED: case ExtensionSystem.ExtensionState.INITIALIZED:
return _("Disabled"); return _("Disabled");
case ExtensionState.ERROR: case ExtensionSystem.ExtensionState.ERROR:
return _("Error"); return _("Error");
case ExtensionState.OUT_OF_DATE: case ExtensionSystem.ExtensionState.OUT_OF_DATE:
return _("Out of date"); return _("Out of date");
case ExtensionState.DOWNLOADING: case ExtensionSystem.ExtensionState.DOWNLOADING:
return _("Downloading"); return _("Downloading");
} }
return 'Unknown'; // Not translated, shouldn't appear return 'Unknown'; // Not translated, shouldn't appear
@ -826,7 +815,7 @@ var LookingGlass = class LookingGlass {
gcIcon.connect('button-press-event', () => { gcIcon.connect('button-press-event', () => {
gcIcon.icon_name = 'user-trash'; gcIcon.icon_name = 'user-trash';
System.gc(); System.gc();
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => { this._timeoutId = Mainloop.timeout_add(500, () => {
gcIcon.icon_name = 'user-trash-full'; gcIcon.icon_name = 'user-trash-full';
this._timeoutId = 0; this._timeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
@ -865,7 +854,7 @@ var LookingGlass = class LookingGlass {
this._extensions = new Extensions(this); this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor); 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 // Hide any completions we are currently showing
this._hideCompletions(); this._hideCompletions();
@ -881,7 +870,7 @@ var LookingGlass = class LookingGlass {
return true; return true;
}); });
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY, this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entry.clutter_text }); entry: this._entry.clutter_text });
this._autoComplete = new AutoComplete(this._entry); this._autoComplete = new AutoComplete(this._entry);
@ -949,41 +938,35 @@ var LookingGlass = class LookingGlass {
this._completionActor.set_text(completions.join(', ')); this._completionActor.set_text(completions.join(', '));
// Setting the height to -1 allows us to get its actual preferred height rather than // Setting the height to -1 allows us to get its actual preferred height rather than
// whatever was last set when animating // whatever was last given in set_height by Tweener.
this._completionActor.set_height(-1); this._completionActor.set_height(-1);
let [, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width()); let [minHeight, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width());
// Don't reanimate if we are already visible // Don't reanimate if we are already visible
if (this._completionActor.visible) { if (this._completionActor.visible) {
this._completionActor.height = naturalHeight; this._completionActor.height = naturalHeight;
} else { } else {
let settings = St.Settings.get();
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
this._completionActor.show(); this._completionActor.show();
this._completionActor.remove_all_transitions(); Tweener.removeTweens(this._completionActor);
this._completionActor.ease({ Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
height: naturalHeight, transition: 'easeOutQuad',
opacity: 255, height: naturalHeight,
duration, opacity: 255
mode: Clutter.AnimationMode.EASE_OUT_QUAD });
});
} }
} }
_hideCompletions() { _hideCompletions() {
if (this._completionActor) { if (this._completionActor) {
let settings = St.Settings.get(); Tweener.removeTweens(this._completionActor);
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor; Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
this._completionActor.remove_all_transitions(); transition: 'easeOutQuad',
this._completionActor.ease({ height: 0,
height: 0, opacity: 0,
opacity: 0, onComplete: () => {
duration, this._completionActor.hide();
mode: Clutter.AnimationMode.EASE_OUT_QUAD, }
onComplete: () => { });
this._completionActor.hide();
}
});
} }
} }
@ -1015,11 +998,7 @@ var LookingGlass = class LookingGlass {
} }
getResult(idx) { getResult(idx) {
try { return this._results[idx - this._offset].o;
return this._results[idx - this._offset].o;
} catch (e) {
throw new Error(`Unknown result at index ${idx}`);
}
} }
toggle() { toggle() {
@ -1030,10 +1009,7 @@ var LookingGlass = class LookingGlass {
} }
_queueResize() { _queueResize() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => this._resize());
this._resize();
return GLib.SOURCE_REMOVE;
});
} }
_resize() { _resize() {
@ -1096,18 +1072,14 @@ var LookingGlass = class LookingGlass {
this._open = true; this._open = true;
this._history.lastItem(); this._history.lastItem();
this.actor.remove_all_transitions(); Tweener.removeTweens(this.actor);
// We inverse compensate for the slow-down so you can change the factor // We inverse compensate for the slow-down so you can change the factor
// through LookingGlass without long waits. // through LookingGlass without long waits.
let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor; Tweener.addTween(this.actor, { time: 0.5 / St.get_slow_down_factor(),
this.actor.ease({ transition: 'easeOutQuad',
y: this._targetY, y: this._targetY
duration, });
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._windowList.update();
} }
close() { close() {
@ -1117,25 +1089,19 @@ var LookingGlass = class LookingGlass {
this._objInspector.actor.hide(); this._objInspector.actor.hide();
this._open = false; this._open = false;
this.actor.remove_all_transitions(); Tweener.removeTweens(this.actor);
this.setBorderPaintTarget(null); this.setBorderPaintTarget(null);
Main.popModal(this._entry); Main.popModal(this._entry);
let settings = St.Settings.get(); Tweener.addTween(this.actor, { time: Math.min(0.5 / St.get_slow_down_factor(), 0.5),
let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor, transition: 'easeOutQuad',
LG_ANIMATION_TIME); y: this._hiddenY,
this.actor.ease({ onComplete: () => {
y: this._hiddenY, this.actor.hide();
duration, }
mode: Clutter.AnimationMode.EASE_OUT_QUAD, });
onComplete: () => this.actor.hide()
});
}
get isOpen() {
return this._open;
} }
}; };
Signals.addSignalMethods(LookingGlass.prototype); Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -2,6 +2,7 @@
const { Atspi, Clutter, GDesktopEnums, const { Atspi, Clutter, GDesktopEnums,
Gio, GLib, GObject, Meta, Shell, St } = imports.gi; Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const Background = imports.ui.background; const Background = imports.ui.background;
@ -106,7 +107,8 @@ var Magnifier = class Magnifier {
// Create the first ZoomRegion and initialize it according to the // Create the first ZoomRegion and initialize it according to the
// magnification settings. // magnification settings.
[this.xMouse, this.yMouse] = global.get_pointer(); let mask;
[this.xMouse, this.yMouse, mask] = global.get_pointer();
let aZoomRegion = new ZoomRegion(this, this._cursorRoot); let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
this._zoomRegions.push(aZoomRegion); this._zoomRegions.push(aZoomRegion);
@ -146,7 +148,7 @@ var Magnifier = class Magnifier {
setActive(activate) { setActive(activate) {
let isActive = this.isActive(); let isActive = this.isActive();
this._zoomRegions.forEach(zoomRegion => { this._zoomRegions.forEach((zoomRegion, index, array) => {
zoomRegion.setActive(activate); zoomRegion.setActive(activate);
}); });
@ -225,14 +227,14 @@ var Magnifier = class Magnifier {
* @return true. * @return true.
*/ */
scrollToMousePos() { scrollToMousePos() {
let [xMouse, yMouse] = global.get_pointer(); let [xMouse, yMouse, mask] = global.get_pointer();
if (xMouse != this.xMouse || yMouse != this.yMouse) { if (xMouse != this.xMouse || yMouse != this.yMouse) {
this.xMouse = xMouse; this.xMouse = xMouse;
this.yMouse = yMouse; this.yMouse = yMouse;
let sysMouseOverAny = false; let sysMouseOverAny = false;
this._zoomRegions.forEach(zoomRegion => { this._zoomRegions.forEach((zoomRegion, index, array) => {
if (zoomRegion.scrollToMousePos()) if (zoomRegion.scrollToMousePos())
sysMouseOverAny = true; sysMouseOverAny = true;
}); });
@ -264,7 +266,7 @@ var Magnifier = class Magnifier {
zoomRegion.setViewPort(viewPort); zoomRegion.setViewPort(viewPort);
// We ignore the redundant width/height on the ROI // We ignore the redundant width/height on the ROI
let fixedROI = Object.create(roi); let fixedROI = new Object(roi);
fixedROI.width = viewPort.width / xMagFactor; fixedROI.width = viewPort.width / xMagFactor;
fixedROI.height = viewPort.height / yMagFactor; fixedROI.height = viewPort.height / yMagFactor;
zoomRegion.setROI(fixedROI); zoomRegion.setROI(fixedROI);
@ -330,7 +332,7 @@ var Magnifier = class Magnifier {
this.setCrosshairsClip(clip); this.setCrosshairsClip(clip);
let theCrossHairs = this._crossHairs; let theCrossHairs = this._crossHairs;
this._zoomRegions.forEach (zoomRegion => { this._zoomRegions.forEach ((zoomRegion, index, array) => {
zoomRegion.addCrosshairs(theCrossHairs); zoomRegion.addCrosshairs(theCrossHairs);
}); });
} }
@ -358,7 +360,7 @@ var Magnifier = class Magnifier {
*/ */
setCrosshairsColor(color) { setCrosshairsColor(color) {
if (this._crossHairs) { if (this._crossHairs) {
let [res_, clutterColor] = Clutter.Color.from_string(color); let [res, clutterColor] = Clutter.Color.from_string(color);
this._crossHairs.setColor(clutterColor); this._crossHairs.setColor(clutterColor);
} }
} }
@ -451,11 +453,15 @@ var Magnifier = class Magnifier {
* @clip: Flag to indicate whether to clip the crosshairs. * @clip: Flag to indicate whether to clip the crosshairs.
*/ */
setCrosshairsClip(clip) { setCrosshairsClip(clip) {
if (!this._crossHairs) if (clip) {
return; if (this._crossHairs)
this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE);
// Setting no clipping on crosshairs means a zero sized clip rectangle. } else {
this._crossHairs.setClip(clip ? CROSSHAIRS_CLIP_SIZE : [0, 0]); // Setting no clipping on crosshairs means a zero sized clip
// rectangle.
if (this._crossHairs)
this._crossHairs.setClip([0, 0]);
}
} }
/** /**
@ -1139,7 +1145,7 @@ var ZoomRegion = class ZoomRegion {
_clearScrollContentsTimer() { _clearScrollContentsTimer() {
if (this._scrollContentsTimerId != 0) { if (this._scrollContentsTimerId != 0) {
GLib.source_remove(this._scrollContentsTimerId); Mainloop.source_remove(this._scrollContentsTimerId);
this._scrollContentsTimerId = 0; this._scrollContentsTimerId = 0;
} }
} }
@ -1151,7 +1157,7 @@ var ZoomRegion = class ZoomRegion {
} }
this._clearScrollContentsTimer(); this._clearScrollContentsTimer();
this._scrollContentsTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, POINTER_REST_TIME, () => { this._scrollContentsTimerId = Mainloop.timeout_add(POINTER_REST_TIME, () => {
this._scrollContentsToDelayed(x, y); this._scrollContentsToDelayed(x, y);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
@ -1509,7 +1515,7 @@ var ZoomRegion = class ZoomRegion {
} }
_centerFromPointProportional(xPoint, yPoint) { _centerFromPointProportional(xPoint, yPoint) {
let [xRoi_, yRoi_, widthRoi, heightRoi] = this.getROI(); let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI();
let halfScreenWidth = global.screen_width / 2; let halfScreenWidth = global.screen_width / 2;
let halfScreenHeight = global.screen_height / 2; let halfScreenHeight = global.screen_height / 2;
// We want to pad with a constant distance after zooming, so divide // We want to pad with a constant distance after zooming, so divide

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ShellMagnifier */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -125,7 +124,7 @@ var ShellMagnifier = class ShellMagnifier {
let zoomRegions = Main.magnifier.getZoomRegions(); let zoomRegions = Main.magnifier.getZoomRegions();
let objectPaths = []; let objectPaths = [];
let thoseZoomers = this._zoomers; let thoseZoomers = this._zoomers;
zoomRegions.forEach (aZoomRegion => { zoomRegions.forEach ((aZoomRegion, index, array) => {
let found = false; let found = false;
for (let objectPath in thoseZoomers) { for (let objectPath in thoseZoomers) {
let proxyAndZoomRegion = thoseZoomers[objectPath]; let proxyAndZoomRegion = thoseZoomers[objectPath];

View File

@ -1,14 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const AccessDialog = imports.ui.accessDialog; const AccessDialog = imports.ui.accessDialog;
const AudioDeviceSelection = imports.ui.audioDeviceSelection; const AudioDeviceSelection = imports.ui.audioDeviceSelection;
@ -53,7 +46,6 @@ const LOG_DOMAIN = 'GNOME Shell';
const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a'; const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
var componentManager = null; var componentManager = null;
var extensionManager = null;
var panel = null; var panel = null;
var overview = null; var overview = null;
var runDialog = null; var runDialog = null;
@ -229,17 +221,12 @@ function _initializeUI() {
EndSessionDialog.init(); EndSessionDialog.init();
// We're ready for the session manager to move to the next phase // We're ready for the session manager to move to the next phase
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { Meta.register_with_session();
Shell.util_sd_notify();
Meta.register_with_session();
return GLib.SOURCE_REMOVE;
});
_startDate = new Date(); _startDate = new Date();
ExtensionDownloader.init(); ExtensionDownloader.init();
extensionManager = new ExtensionSystem.ExtensionManager(); ExtensionSystem.init();
extensionManager.init();
if (sessionMode.isGreeter && screenShield) { if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', () => { layoutManager.connect('startup-prepared', () => {
@ -262,19 +249,6 @@ function _initializeUI() {
}); });
} }
let credentials = new Gio.Credentials();
if (credentials.get_unix_user() === 0) {
notify(_('Logged in as a privileged user'),
_('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
}
if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup' &&
screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM(); LoginManager.registerSessionWithGDM();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
@ -636,7 +610,7 @@ function _runDeferredWork(workId) {
_deferredWorkQueue.splice(index, 1); _deferredWorkQueue.splice(index, 1);
_deferredWorkData[workId].callback(); _deferredWorkData[workId].callback();
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) { if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
GLib.source_remove(_deferredTimeoutId); Mainloop.source_remove(_deferredTimeoutId);
_deferredTimeoutId = 0; _deferredTimeoutId = 0;
} }
} }
@ -682,7 +656,7 @@ function _queueBeforeRedraw(workId) {
* *
* Returns: A string work identifier * Returns: A string work identifier
*/ */
function initializeDeferredWork(actor, callback) { function initializeDeferredWork(actor, callback, props) {
// Turn into a string so we can use as an object property // Turn into a string so we can use as an object property
let workId = `${(++_deferredWorkSequence)}`; let workId = `${(++_deferredWorkSequence)}`;
_deferredWorkData[workId] = { 'actor': actor, _deferredWorkData[workId] = { 'actor': actor,
@ -722,8 +696,9 @@ function queueDeferredWork(workId) {
_deferredWorkQueue.push(workId); _deferredWorkQueue.push(workId);
if (data.actor.mapped) { if (data.actor.mapped) {
_queueBeforeRedraw(workId); _queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) { } else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => { _deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, () => {
_runAllDeferredWork(); _runAllDeferredWork();
_deferredTimeoutId = 0; _deferredTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;

View File

@ -4,9 +4,10 @@ const MessageTray = imports.ui.messageTray;
const Signals = imports.signals; const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util; const Util = imports.misc.util;
var MESSAGE_ANIMATION_TIME = 100; var MESSAGE_ANIMATION_TIME = 0.1;
var DEFAULT_EXPAND_LINES = 6; var DEFAULT_EXPAND_LINES = 6;
@ -129,12 +130,12 @@ var URLHighlighter = class URLHighlighter {
} }
_findUrlAtPos(event) { _findUrlAtPos(event) {
let success_; let success;
let [x, y] = event.get_coords(); 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; let findPos = -1;
for (let i = 0; i < this.actor.clutter_text.text.length; i++) { 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) if (py > y || py + lineHeight < y || x < px)
continue; continue;
findPos = i; findPos = i;
@ -439,17 +440,15 @@ var Message = class Message {
} }
if (animate) { if (animate) {
this._bodyStack.ease_property('@layout.expansion', 1, { Tweener.addTween(this._bodyStack.layout_manager,
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD, { expansion: 1,
duration: MessageTray.ANIMATION_TIME, time: MessageTray.ANIMATION_TIME,
}); transition: 'easeOutQuad' });
this._actionBin.scale_y = 0; this._actionBin.scale_y = 0;
this._actionBin.ease({ Tweener.addTween(this._actionBin,
scale_y: 1, { scale_y: 1,
duration: MessageTray.ANIMATION_TIME, time: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad' });
});
} else { } else {
this._bodyStack.layout_manager.expansion = 1; this._bodyStack.layout_manager.expansion = 1;
this._actionBin.scale_y = 1; this._actionBin.scale_y = 1;
@ -460,20 +459,18 @@ var Message = class Message {
unexpand(animate) { unexpand(animate) {
if (animate) { if (animate) {
this._bodyStack.ease_property('@layout.expansion', 0, { Tweener.addTween(this._bodyStack.layout_manager,
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD, { expansion: 0,
duration: MessageTray.ANIMATION_TIME, time: MessageTray.ANIMATION_TIME,
}); transition: 'easeOutQuad' });
Tweener.addTween(this._actionBin,
this._actionBin.ease({ { scale_y: 0,
scale_y: 0, time: MessageTray.ANIMATION_TIME,
duration: MessageTray.ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => {
onComplete: () => { this._actionBin.hide();
this._actionBin.hide(); this.expanded = false;
this.expanded = false; } });
}
});
} else { } else {
this._bodyStack.layout_manager.expansion = 0; this._bodyStack.layout_manager.expansion = 0;
this._actionBin.scale_y = 0; this._actionBin.scale_y = 0;
@ -584,12 +581,10 @@ var MessageListSection = class MessageListSection {
this._list.insert_child_at_index(obj.container, index); this._list.insert_child_at_index(obj.container, index);
if (animate) if (animate)
obj.container.ease({ Tweener.addTween(obj.container, { scale_x: 1,
scale_x: 1, scale_y: 1,
scale_y: 1, time: MESSAGE_ANIMATION_TIME,
duration: MESSAGE_ANIMATION_TIME, transition: 'easeOutQuad' });
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} }
moveMessage(message, index, animate) { moveMessage(message, index, animate) {
@ -602,20 +597,16 @@ var MessageListSection = class MessageListSection {
let onComplete = () => { let onComplete = () => {
this._list.set_child_at_index(obj.container, index); this._list.set_child_at_index(obj.container, index);
obj.container.ease({ Tweener.addTween(obj.container, { scale_x: 1,
scale_x: 1, scale_y: 1,
scale_y: 1, time: MESSAGE_ANIMATION_TIME,
duration: MESSAGE_ANIMATION_TIME, transition: 'easeOutQuad' });
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}; };
obj.container.ease({ Tweener.addTween(obj.container, { scale_x: 0,
scale_x: 0, scale_y: 0,
scale_y: 0, time: MESSAGE_ANIMATION_TIME,
duration: MESSAGE_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: onComplete });
onComplete
});
} }
removeMessage(message, animate) { removeMessage(message, animate) {
@ -628,16 +619,13 @@ var MessageListSection = class MessageListSection {
this._messages.delete(message); this._messages.delete(message);
if (animate) { if (animate) {
obj.container.ease({ Tweener.addTween(obj.container, { scale_x: 0, scale_y: 0,
scale_x: 0, time: MESSAGE_ANIMATION_TIME,
scale_y: 0, transition: 'easeOutQuad',
duration: MESSAGE_ANIMATION_TIME, onComplete() {
mode: Clutter.AnimationMode.EASE_OUT_QUAD, obj.container.destroy();
onComplete: () => { global.sync_pointer();
obj.container.destroy(); } });
global.sync_pointer();
}
});
} else { } else {
obj.container.destroy(); obj.container.destroy();
global.sync_pointer(); global.sync_pointer();
@ -659,14 +647,15 @@ var MessageListSection = class MessageListSection {
for (let i = 0; i < messages.length; i++) { for (let i = 0; i < messages.length; i++) {
let message = messages[i]; let message = messages[i];
let obj = this._messages.get(message); let obj = this._messages.get(message);
obj.container.ease({ Tweener.addTween(obj.container,
anchor_x: this._list.width, { anchor_x: this._list.width,
opacity: 0, opacity: 0,
duration: MESSAGE_ANIMATION_TIME, time: MESSAGE_ANIMATION_TIME,
delay: i * delay, delay: i * delay,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => message.close() onComplete() {
}); message.close();
} });
} }
} }
} }

View File

@ -1,9 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- 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 { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
@ -11,14 +9,15 @@ const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
var ANIMATION_TIME = 200; var ANIMATION_TIME = 0.2;
var NOTIFICATION_TIMEOUT = 4000; var NOTIFICATION_TIMEOUT = 4;
var HIDE_TIMEOUT = 200; var HIDE_TIMEOUT = 0.2;
var LONGER_HIDE_TIMEOUT = 600; var LONGER_HIDE_TIMEOUT = 0.6;
var MAX_NOTIFICATIONS_IN_QUEUE = 3; var MAX_NOTIFICATIONS_IN_QUEUE = 3;
var MAX_NOTIFICATIONS_PER_SOURCE = 3; var MAX_NOTIFICATIONS_PER_SOURCE = 3;
@ -136,14 +135,13 @@ var FocusGrabber = class FocusGrabber {
// A notification without a policy object will inherit the default one. // A notification without a policy object will inherit the default one.
var NotificationPolicy = class NotificationPolicy { var NotificationPolicy = class NotificationPolicy {
constructor(params) { constructor(params) {
params = Params.parse(params, { params = Params.parse(params, { enable: true,
enable: true, enableSound: true,
enableSound: true, showBanners: true,
showBanners: true, forceExpanded: false,
forceExpanded: false, showInLockScreen: true,
showInLockScreen: true, detailsInLockScreen: false
detailsInLockScreen: false, });
});
Object.getOwnPropertyNames(params).forEach(key => { Object.getOwnPropertyNames(params).forEach(key => {
let desc = Object.getOwnPropertyDescriptor(params, key); let desc = Object.getOwnPropertyDescriptor(params, key);
Object.defineProperty(this, `_${key}`, desc); Object.defineProperty(this, `_${key}`, desc);
@ -153,7 +151,6 @@ var NotificationPolicy = class NotificationPolicy {
// Do nothing for the default policy. These methods are only useful for the // Do nothing for the default policy. These methods are only useful for the
// GSettings policy. // GSettings policy.
store() { } store() { }
destroy() { } destroy() { }
get enable() { get enable() {
@ -335,7 +332,7 @@ class NotificationApplicationPolicy extends NotificationPolicy {
// event sound is played when the notification is shown (if the policy for // event sound is played when the notification is shown (if the policy for
// @source allows playing sounds). // @source allows playing sounds).
// //
// [1] https://developer.gnome.org/notification-spec/#markup // [1] https://developer.gnome.org/notification-spec/#markup
var Notification = class Notification { var Notification = class Notification {
constructor(source, title, banner, params) { constructor(source, title, banner, params) {
this.source = source; this.source = source;
@ -653,7 +650,7 @@ class SourceActorWithLabel extends SourceActor {
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
let [, , naturalWidth, naturalHeight] = this._counterBin.get_preferred_size(); let [minWidth, minHeight, naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let direction = this.get_text_direction(); let direction = this.get_text_direction();
if (direction == Clutter.TextDirection.LTR) { if (direction == Clutter.TextDirection.LTR) {
@ -735,9 +732,8 @@ var Source = class Source {
} }
get narrowestPrivacyScope() { get narrowestPrivacyScope() {
return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) ? PrivacyScope.SYSTEM
? PrivacyScope.SYSTEM : PrivacyScope.USER;
: PrivacyScope.USER;
} }
setTitle(newTitle) { setTitle(newTitle) {
@ -831,7 +827,7 @@ Signals.addSignalMethods(Source.prototype);
var MessageTray = class MessageTray { var MessageTray = class MessageTray {
constructor() { constructor() {
this._presence = new GnomeSession.Presence((proxy, _error) => { this._presence = new GnomeSession.Presence((proxy, error) => {
this._onStatusChanged(proxy.status); this._onStatusChanged(proxy.status);
}); });
this._busy = false; this._busy = false;
@ -1006,6 +1002,7 @@ var MessageTray = class MessageTray {
_addSource(source) { _addSource(source) {
let obj = { let obj = {
source: source,
notifyId: 0, notifyId: 0,
destroyId: 0, destroyId: 0,
}; };
@ -1092,7 +1089,7 @@ var MessageTray = class MessageTray {
_resetNotificationLeftTimeout() { _resetNotificationLeftTimeout() {
this._useLongerNotificationLeftTimeout = false; this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) { if (this._notificationLeftTimeoutId) {
GLib.source_remove(this._notificationLeftTimeoutId); Mainloop.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0; this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1; this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1; this._notificationLeftMouseY = -1;
@ -1130,15 +1127,15 @@ var MessageTray = class MessageTray {
// this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us // 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 // 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. // close to its previous position, we extend the timeout once.
let [x, y] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
this._notificationLeftMouseX = x; this._notificationLeftMouseX = x;
this._notificationLeftMouseY = y; this._notificationLeftMouseY = y;
// We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it. // We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it.
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned. // We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it. // That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT : HIDE_TIMEOUT; let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
this._notificationLeftTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._onNotificationLeftTimeout.bind(this)); this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout'); GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} }
} }
@ -1159,7 +1156,7 @@ var MessageTray = class MessageTray {
} }
_onNotificationLeftTimeout() { _onNotificationLeftTimeout() {
let [x, y] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
// We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side. // We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side.
if (this._notificationLeftMouseX > -1 && if (this._notificationLeftMouseX > -1 &&
y < this._notificationLeftMouseY + MOUSE_LEFT_ACTOR_THRESHOLD && y < this._notificationLeftMouseY + MOUSE_LEFT_ACTOR_THRESHOLD &&
@ -1167,10 +1164,8 @@ var MessageTray = class MessageTray {
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD && x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) { x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1; this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = GLib.timeout_add( this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
GLib.PRIORITY_DEFAULT, this._onNotificationLeftTimeout.bind(this));
LONGER_HIDE_TIMEOUT,
this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout'); GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else { } else {
this._notificationLeftTimeoutId = 0; this._notificationLeftTimeoutId = 0;
@ -1251,6 +1246,34 @@ var MessageTray = class MessageTray {
this._notificationExpired = false; this._notificationExpired = false;
} }
_tween(actor, statevar, value, params) {
let onComplete = params.onComplete;
let onCompleteScope = params.onCompleteScope;
let onCompleteParams = params.onCompleteParams;
params.onComplete = this._tweenComplete;
params.onCompleteScope = this;
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
// Remove other tweens that could mess with the state machine
Tweener.removeTweens(actor);
Tweener.addTween(actor, params);
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
this[statevar] = valuing;
}
_tweenComplete(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
this[statevar] = value;
if (onComplete)
onComplete.apply(onCompleteScope, onCompleteParams);
this._updateState();
}
_clampOpacity() {
this._bannerBin.opacity = Math.max(0, Math.min(this._bannerBin._opacity, 255));
}
_onIdleMonitorBecameActive() { _onIdleMonitorBecameActive() {
this._userActiveWhileNotificationShown = true; this._userActiveWhileNotificationShown = true;
this._updateNotificationTimeout(2000); this._updateNotificationTimeout(2000);
@ -1277,6 +1300,7 @@ var MessageTray = class MessageTray {
this._bannerBin.add_actor(this._banner.actor); this._bannerBin.add_actor(this._banner.actor);
this._bannerBin._opacity = 0;
this._bannerBin.opacity = 0; this._bannerBin.opacity = 0;
this._bannerBin.y = -this._banner.actor.height; this._bannerBin.y = -this._banner.actor.height;
this.actor.show(); this.actor.show();
@ -1284,7 +1308,7 @@ var MessageTray = class MessageTray {
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
this._updateShowingNotification(); this._updateShowingNotification();
let [x, y] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
// We save the position of the mouse at the time when we started showing the notification // 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 // 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 // the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't
@ -1322,45 +1346,39 @@ var MessageTray = class MessageTray {
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated // We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown. // notification is being shown.
this._notificationState = State.SHOWING; let tweenParams = { y: 0,
this._bannerBin.remove_all_transitions(); _opacity: 255,
this._bannerBin.ease({ time: ANIMATION_TIME,
opacity: 255, transition: 'easeOutBack',
duration: ANIMATION_TIME, onUpdate: this._clampOpacity,
mode: Clutter.AnimationMode.LINEAR onUpdateScope: this,
}); onComplete: this._showNotificationCompleted,
this._bannerBin.ease({ onCompleteScope: this
y: 0, };
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK, this._tween(this._bannerBin, '_notificationState', State.SHOWN, tweenParams);
onComplete: () => {
this._notificationState = State.SHOWN;
this._showNotificationCompleted();
this._updateState();
}
});
} }
_showNotificationCompleted() { _showNotificationCompleted() {
if (this._notification.urgency != Urgency.CRITICAL) if (this._notification.urgency != Urgency.CRITICAL)
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT); this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
} }
_updateNotificationTimeout(timeout) { _updateNotificationTimeout(timeout) {
if (this._notificationTimeoutId) { if (this._notificationTimeoutId) {
GLib.source_remove(this._notificationTimeoutId); Mainloop.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0; this._notificationTimeoutId = 0;
} }
if (timeout > 0) { if (timeout > 0) {
this._notificationTimeoutId = this._notificationTimeoutId =
GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, Mainloop.timeout_add(timeout,
this._notificationTimeout.bind(this)); this._notificationTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout'); GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout');
} }
} }
_notificationTimeout() { _notificationTimeout() {
let [x, y] = global.get_pointer(); let [x, y, mods] = global.get_pointer();
if (y < this._lastSeenMouseY - 10 && !this._notificationHovered) { if (y < this._lastSeenMouseY - 10 && !this._notificationHovered) {
// The mouse is moving towards the notification, so don't // The mouse is moving towards the notification, so don't
// hide it yet. (We just create a new timeout (and destroy // hide it yet. (We just create a new timeout (and destroy
@ -1396,26 +1414,20 @@ var MessageTray = class MessageTray {
} }
this._resetNotificationLeftTimeout(); this._resetNotificationLeftTimeout();
this._bannerBin.remove_all_transitions();
if (animate) { if (animate) {
this._notificationState = State.HIDING; this._tween(this._bannerBin, '_notificationState', State.HIDDEN,
this._bannerBin.ease({ { y: -this._bannerBin.height,
opacity: 0, _opacity: 0,
duration: ANIMATION_TIME, time: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK transition: 'easeOutBack',
}); onUpdate: this._clampOpacity,
this._bannerBin.ease({ onUpdateScope: this,
y: -this._bannerBin.height, onComplete: this._hideNotificationCompleted,
duration: ANIMATION_TIME, onCompleteScope: this
mode: Clutter.AnimationMode.EASE_OUT_BACK, });
onComplete: () => {
this._notificationState = State.HIDDEN;
this._hideNotificationCompleted();
this._updateState();
}
});
} else { } else {
Tweener.removeTweens(this._bannerBin);
this._bannerBin.y = -this._bannerBin.height; this._bannerBin.y = -this._bannerBin.height;
this._bannerBin.opacity = 0; this._bannerBin.opacity = 0;
this._notificationState = State.HIDDEN; this._notificationState = State.HIDDEN;

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModalDialog */
const { Atk, Clutter, GObject, Shell, St } = imports.gi; const { Atk, Clutter, GObject, Shell, St } = imports.gi;
@ -8,9 +7,10 @@ const Layout = imports.ui.layout;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var OPEN_AND_CLOSE_TIME = 100; var OPEN_AND_CLOSE_TIME = 0.1;
var FADE_OUT_DIALOG_TIME = 1000; var FADE_OUT_DIALOG_TIME = 1.0;
var State = { var State = {
OPENED: 0, OPENED: 0,
@ -124,15 +124,15 @@ var ModalDialog = GObject.registerClass({
this._lightbox.show(); this._lightbox.show();
this.opacity = 0; this.opacity = 0;
this.show(); this.show();
this.ease({ Tweener.addTween(this,
opacity: 255, { opacity: 255,
duration: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0, time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => {
this._setState(State.OPENED); this._setState(State.OPENED);
this.emit('opened'); this.emit('opened');
} }
}); });
} }
setInitialKeyFocus(actor) { setInitialKeyFocus(actor) {
@ -175,16 +175,15 @@ var ModalDialog = GObject.registerClass({
this.popModal(timestamp); this.popModal(timestamp);
this._savedKeyFocus = null; this._savedKeyFocus = null;
if (this._shouldFadeOut) { if (this._shouldFadeOut)
this.ease({ Tweener.addTween(this,
opacity: 0, { opacity: 0,
duration: OPEN_AND_CLOSE_TIME, time: OPEN_AND_CLOSE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => this._closeComplete() onComplete: this._closeComplete.bind(this)
}); });
} else { else
this._closeComplete(); this._closeComplete();
}
} }
// Drop modal status without closing the dialog; this makes the // Drop modal status without closing the dialog; this makes the
@ -249,11 +248,13 @@ var ModalDialog = GObject.registerClass({
return; return;
this.popModal(timestamp); this.popModal(timestamp);
this.dialogLayout.ease({ Tweener.addTween(this.dialogLayout,
opacity: 0, { opacity: 0,
duration: FADE_OUT_DIALOG_TIME, time: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => (this.state = State.FADED_OUT) onComplete: () => {
}); this._setState(State.FADED_OUT);
}
});
} }
}); });

View File

@ -1,4 +1,3 @@
/* exported MediaSection */
const { Gio, Shell, St } = imports.gi; const { Gio, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -71,9 +70,8 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
} }
let isPlaying = this._player.status == 'Playing'; let isPlaying = this._player.status == 'Playing';
let iconName = isPlaying let iconName = isPlaying ? 'media-playback-pause-symbolic'
? 'media-playback-pause-symbolic' : 'media-playback-start-symbolic';
: 'media-playback-start-symbolic';
this._playPauseButton.child.icon_name = iconName; this._playPauseButton.child.icon_name = iconName;
this._updateNavButton(this._prevButton, this._player.canGoPrevious); this._updateNavButton(this._prevButton, this._player.canGoPrevious);

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi; const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Config = imports.misc.config; const Config = imports.misc.config;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -64,7 +64,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
_imageForNotificationData(hints) { _imageForNotificationData(hints) {
if (hints['image-data']) { if (hints['image-data']) {
let [width, height, rowStride, hasAlpha, 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, return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride); bitsPerSample, width, height, rowStride);
} else if (hints['image-path']) { } else if (hints['image-path']) {
@ -170,7 +170,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// Ignore replacesId since we already sent back a // Ignore replacesId since we already sent back a
// NotificationClosed for that id. // NotificationClosed for that id.
id = this._nextNotificationId++; id = this._nextNotificationId++;
let idleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { let idleId = Mainloop.idle_add(() => {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED); this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
@ -259,7 +259,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
} }
_notifyForSource(source, ndata) { _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.id, ndata.icon, ndata.summary, ndata.body,
ndata.actions, ndata.hints, ndata.notification]; ndata.actions, ndata.hints, ndata.notification];
@ -346,9 +346,8 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
notification.setTransient(!!hints['transient']); notification.setTransient(!!hints['transient']);
let privacyScope = (hints['x-gnome-privacy-scope'] || 'user'); let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
notification.setPrivacyScope(privacyScope == 'system' notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM
? MessageTray.PrivacyScope.SYSTEM : MessageTray.PrivacyScope.USER);
: MessageTray.PrivacyScope.USER);
let sourceGIcon = source.useNotificationIcon ? gicon : null; let sourceGIcon = source.useNotificationIcon ? gicon : null;
source.processNotification(notification, sourceGIcon); source.processNotification(notification, sourceGIcon);
@ -541,23 +540,22 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
super(source); super(source);
this._serialized = GLib.Variant.new('a{sv}', notification); this._serialized = GLib.Variant.new('a{sv}', notification);
let { title, let { "title": title,
body, "body": body,
icon: gicon, "icon": gicon,
urgent, "urgent": urgent,
priority, "priority": priority,
buttons, "buttons": buttons,
"default-action": defaultAction, "default-action": defaultAction,
"default-action-target": defaultActionTarget, "default-action-target": defaultActionTarget,
timestamp: time } = notification; "timestamp": time } = notification;
if (priority) { if (priority) {
let urgency = PRIORITY_URGENCY_MAP[priority.unpack()]; let urgency = PRIORITY_URGENCY_MAP[priority.unpack()];
this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL); this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL);
} else if (urgent) { } else if (urgent) {
this.setUrgency(urgent.unpack() this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
? MessageTray.Urgency.CRITICAL : MessageTray.Urgency.NORMAL);
: MessageTray.Urgency.NORMAL);
} else { } else {
this.setUrgency(MessageTray.Urgency.NORMAL); this.setUrgency(MessageTray.Urgency.NORMAL);
} }
@ -590,8 +588,8 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
} }
_onButtonClicked(button) { _onButtonClicked(button) {
let { action, target } = button; let { 'action': action, 'target': actionTarget } = button;
this._activateAction(action.unpack(), target); this._activateAction(action.unpack(), actionTarget);
} }
activate() { activate() {
@ -618,7 +616,7 @@ function getPlatformData() {
function InvalidAppError() {} function InvalidAppError() {}
var GtkNotificationDaemonAppSource = var GtkNotificationDaemonAppSource =
class GtkNotificationDaemonAppSource extends MessageTray.Source { class GtkNotificationDaemonAppSource extends MessageTray.Source {
constructor(appId) { constructor(appId) {
let objectPath = objectPathFromAppId(appId); let objectPath = objectPathFromAppId(appId);
@ -751,33 +749,29 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
_loadNotifications() { _loadNotifications() {
this._isLoading = true; this._isLoading = true;
try { let value = global.get_persistent_state('a(sa(sv))', 'notifications');
let value = global.get_persistent_state('a(sa(sv))', 'notifications'); if (value) {
if (value) { let sources = value.deep_unpack();
let sources = value.deep_unpack(); sources.forEach(([appId, notifications]) => {
sources.forEach(([appId, notifications]) => { if (notifications.length == 0)
if (notifications.length == 0) return;
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
return; return;
throw e;
}
let source; notifications.forEach(([notificationId, notification]) => {
try { source.addNotification(notificationId, notification.deep_unpack(), false);
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
}); });
} });
} catch (e) {
logError(e, 'Failed to load saved notifications');
} finally {
this._isLoading = false;
} }
this._isLoading = false;
} }
_saveNotifications() { _saveNotifications() {

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdMonitorLabeler */
const { Clutter, Gio, Meta, St } = imports.gi; const { Clutter, Gio, Meta, St } = imports.gi;

View File

@ -1,15 +1,49 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdWindowManager */
const { Clutter, GLib, GObject, Meta, St } = imports.gi; const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const BarLevel = imports.ui.barLevel; const BarLevel = imports.ui.barLevel;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var HIDE_TIMEOUT = 1500; var HIDE_TIMEOUT = 1500;
var FADE_TIME = 100; var FADE_TIME = 0.1;
var LEVEL_ANIMATION_TIME = 100; 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( var OsdWindowConstraint = GObject.registerClass(
class OsdWindowConstraint extends Clutter.Constraint { class OsdWindowConstraint extends Clutter.Constraint {
@ -64,11 +98,8 @@ var OsdWindow = class {
this._label = new St.Label(); this._label = new St.Label();
this._box.add(this._label); this._box.add(this._label);
this._level = new BarLevel.BarLevel({ this._level = new LevelBar();
style_class: 'level', this._box.add(this._level.actor);
value: 0
});
this._box.add(this._level);
this._hideTimeoutId = 0; this._hideTimeoutId = 0;
this._reset(); this._reset();
@ -107,21 +138,21 @@ var OsdWindow = class {
this._label.text = label; this._label.text = label;
} }
setLevel(value) { setLevel(level) {
this._level.visible = (value != undefined); this._level.actor.visible = (level != undefined);
if (value != undefined) { if (level != undefined) {
if (this.actor.visible) if (this.actor.visible)
this._level.ease_property('value', value, { Tweener.addTween(this._level,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, { level: level,
duration: LEVEL_ANIMATION_TIME time: LEVEL_ANIMATION_TIME,
}); transition: 'easeOutQuad' });
else else
this._level.value = value; this._level.level = level;
} }
} }
setMaxLevel(maxLevel = 1) { setMaxLevel(maxLevel = 100) {
this._level.maximum_value = maxLevel; this._level.maxLevel = maxLevel;
} }
show() { show() {
@ -134,17 +165,16 @@ var OsdWindow = class {
this.actor.opacity = 0; this.actor.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null); this.actor.get_parent().set_child_above_sibling(this.actor, null);
this.actor.ease({ Tweener.addTween(this.actor,
opacity: 255, { opacity: 255,
duration: FADE_TIME, time: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD transition: 'easeOutQuad' });
});
} }
if (this._hideTimeoutId) if (this._hideTimeoutId)
GLib.source_remove(this._hideTimeoutId); Mainloop.source_remove(this._hideTimeoutId);
this._hideTimeoutId = GLib.timeout_add( this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT,
GLib.PRIORITY_DEFAULT, HIDE_TIMEOUT, this._hide.bind(this)); this._hide.bind(this));
GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide'); GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide');
} }
@ -152,21 +182,21 @@ var OsdWindow = class {
if (!this._hideTimeoutId) if (!this._hideTimeoutId)
return; return;
GLib.source_remove(this._hideTimeoutId); Mainloop.source_remove(this._hideTimeoutId);
this._hide(); this._hide();
} }
_hide() { _hide() {
this._hideTimeoutId = 0; this._hideTimeoutId = 0;
this.actor.ease({ Tweener.addTween(this.actor,
opacity: 0, { opacity: 0,
duration: FADE_TIME, time: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => {
this._reset(); this._reset();
Meta.enable_unredirect_for_display(global.display); Meta.enable_unredirect_for_display(global.display);
} }
}); });
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} }

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi; const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const Background = imports.ui.background; const Background = imports.ui.background;
@ -12,15 +12,16 @@ const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const OverviewControls = imports.ui.overviewControls; const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail; const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode // Time for initial animation going into Overview mode
var ANIMATION_TIME = 250; var ANIMATION_TIME = 0.25;
// Must be less than ANIMATION_TIME, since we switch to // Must be less than ANIMATION_TIME, since we switch to
// or from the overview completely after ANIMATION_TIME, // or from the overview completely after ANIMATION_TIME,
// and don't want the shading animation to get cut off // and don't want the shading animation to get cut off
var SHADE_ANIMATION_TIME = 200; var SHADE_ANIMATION_TIME = .20;
var DND_WINDOW_SWITCH_TIMEOUT = 750; var DND_WINDOW_SWITCH_TIMEOUT = 750;
@ -42,10 +43,9 @@ var ShellInfo = class {
} }
setMessage(text, options) { setMessage(text, options) {
options = Params.parse(options, { options = Params.parse(options, { undoCallback: null,
undoCallback: null, forFeedback: false
forFeedback: false, });
});
let undoCallback = options.undoCallback; let undoCallback = options.undoCallback;
let forFeedback = options.forFeedback; let forFeedback = options.forFeedback;
@ -173,28 +173,24 @@ var Overview = class {
_unshadeBackgrounds() { _unshadeBackgrounds() {
let backgrounds = this._backgroundGroup.get_children(); let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) { for (let i = 0; i < backgrounds.length; i++) {
backgrounds[i].ease_property('brightness', 1.0, { Tweener.addTween(backgrounds[i],
duration: SHADE_ANIMATION_TIME, { brightness: 1.0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD vignette_sharpness: 0.0,
}); time: SHADE_ANIMATION_TIME,
backgrounds[i].ease_property('vignette-sharpness', 0.0, { transition: 'easeOutQuad'
duration: SHADE_ANIMATION_TIME, });
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} }
} }
_shadeBackgrounds() { _shadeBackgrounds() {
let backgrounds = this._backgroundGroup.get_children(); let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) { for (let i = 0; i < backgrounds.length; i++) {
backgrounds[i].ease_property('brightness', Lightbox.VIGNETTE_BRIGHTNESS, { Tweener.addTween(backgrounds[i],
duration: SHADE_ANIMATION_TIME, { brightness: Lightbox.VIGNETTE_BRIGHTNESS,
mode: Clutter.AnimationMode.EASE_OUT_QUAD vignette_sharpness: Lightbox.VIGNETTE_SHARPNESS,
}); time: SHADE_ANIMATION_TIME,
backgrounds[i].ease_property('vignette-sharpness', Lightbox.VIGNETTE_SHARPNESS, { transition: 'easeOutQuad'
duration: SHADE_ANIMATION_TIME, });
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} }
} }
@ -300,7 +296,7 @@ var Overview = class {
_resetWindowSwitchTimeout() { _resetWindowSwitchTimeout() {
if (this._windowSwitchTimeoutId != 0) { if (this._windowSwitchTimeoutId != 0) {
GLib.source_remove(this._windowSwitchTimeoutId); Mainloop.source_remove(this._windowSwitchTimeoutId);
this._windowSwitchTimeoutId = 0; this._windowSwitchTimeoutId = 0;
} }
} }
@ -323,9 +319,7 @@ var Overview = class {
if (targetIsWindow) { if (targetIsWindow) {
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow; this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimeoutId = GLib.timeout_add( this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
GLib.PRIORITY_DEFAULT,
DND_WINDOW_SWITCH_TIMEOUT,
() => { () => {
this._windowSwitchTimeoutId = 0; this._windowSwitchTimeoutId = 0;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow, Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
@ -392,16 +386,16 @@ var Overview = class {
this.emit('windows-restacked', stackIndices); this.emit('windows-restacked', stackIndices);
} }
beginItemDrag(_source) { beginItemDrag(source) {
this.emit('item-drag-begin'); this.emit('item-drag-begin');
this._inItemDrag = true; this._inItemDrag = true;
} }
cancelledItemDrag(_source) { cancelledItemDrag(source) {
this.emit('item-drag-cancelled'); this.emit('item-drag-cancelled');
} }
endItemDrag(_source) { endItemDrag(source) {
if (!this._inItemDrag) if (!this._inItemDrag)
return; return;
this.emit('item-drag-end'); this.emit('item-drag-end');
@ -432,11 +426,10 @@ var Overview = class {
fadeInDesktop() { fadeInDesktop() {
this._desktopFade.opacity = 0; this._desktopFade.opacity = 0;
this._desktopFade.show(); this._desktopFade.show();
this._desktopFade.ease({ Tweener.addTween(this._desktopFade,
opacity: 255, { opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, time: ANIMATION_TIME,
duration: ANIMATION_TIME transition: 'easeOutQuad' });
});
} }
fadeOutDesktop() { fadeOutDesktop() {
@ -450,11 +443,11 @@ var Overview = class {
this._desktopFade.opacity = 255; this._desktopFade.opacity = 255;
this._desktopFade.show(); this._desktopFade.show();
this._desktopFade.ease({ Tweener.addTween(this._desktopFade,
opacity: 0, { opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, time: ANIMATION_TIME,
duration: ANIMATION_TIME transition: 'easeOutQuad'
}); });
} }
// Checks if the Activities button is currently sensitive to // Checks if the Activities button is currently sensitive to
@ -483,13 +476,15 @@ var Overview = class {
if (this._shown) { if (this._shown) {
let shouldBeModal = !this._inXdndDrag; let shouldBeModal = !this._inXdndDrag;
if (shouldBeModal && !this._modal) { if (shouldBeModal) {
let actionMode = Shell.ActionMode.OVERVIEW; if (!this._modal) {
if (Main.pushModal(this._overview, { actionMode })) { if (Main.pushModal(this._overview,
this._modal = true; { actionMode: Shell.ActionMode.OVERVIEW })) {
} else { this._modal = true;
this.hide(); } else {
return false; this.hide();
return false;
}
} }
} }
} else { } else {
@ -532,12 +527,13 @@ var Overview = class {
this.viewSelector.show(); this.viewSelector.show();
this._overview.opacity = 0; this._overview.opacity = 0;
this._overview.ease({ Tweener.addTween(this._overview,
opacity: 255, { opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
duration: ANIMATION_TIME, time: ANIMATION_TIME,
onComplete: () => this._showDone() onComplete: this._showDone,
}); onCompleteScope: this
});
this._shadeBackgrounds(); this._shadeBackgrounds();
this._coverPane.raise_top(); this._coverPane.raise_top();
@ -595,12 +591,13 @@ var Overview = class {
this.viewSelector.animateFromOverview(); this.viewSelector.animateFromOverview();
// Make other elements fade out. // Make other elements fade out.
this._overview.ease({ Tweener.addTween(this._overview,
opacity: 0, { opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
duration: ANIMATION_TIME, time: ANIMATION_TIME,
onComplete: () => this._hideDone() onComplete: this._hideDone,
}); onCompleteScope: this
});
this._unshadeBackgrounds(); this._unshadeBackgrounds();
this._coverPane.raise_top(); this._coverPane.raise_top();

View File

@ -1,21 +1,21 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ControlsManager */
const { Clutter, GObject, Meta, St } = imports.gi; const { Clutter, GObject, Meta, St } = imports.gi;
const Dash = imports.ui.dash; const Dash = imports.ui.dash;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector; const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail; const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
var SIDE_CONTROLS_ANIMATION_TIME = 160; var SIDE_CONTROLS_ANIMATION_TIME = 0.16;
function getRtlSlideDirection(direction, actor) { function getRtlSlideDirection(direction, actor) {
let rtl = (actor.text_direction == Clutter.TextDirection.RTL); let rtl = (actor.text_direction == Clutter.TextDirection.RTL);
if (rtl) if (rtl)
direction = (direction == SlideDirection.LEFT) direction = (direction == SlideDirection.LEFT) ?
? SlideDirection.RIGHT : SlideDirection.LEFT; SlideDirection.RIGHT : SlideDirection.LEFT;
return direction; return direction;
} }
@ -25,21 +25,11 @@ var SlideDirection = {
RIGHT: 1 RIGHT: 1
}; };
var SlideLayout = GObject.registerClass({ var SlideLayout = GObject.registerClass(
Properties: { class SlideLayout extends Clutter.FixedLayout {
'slide-x': GObject.ParamSpec.double(
'slide-x', 'slide-x', 'slide-x',
GObject.ParamFlags.READWRITE,
0, 1, 1),
'translation-x': GObject.ParamSpec.double(
'translation-x', 'translation-x', 'translation-x',
GObject.ParamFlags.READWRITE,
-Infinity, Infinity, 0)
}
}, class SlideLayout extends Clutter.FixedLayout {
_init(params) { _init(params) {
this._slideX = 1; this._slideX = 1;
this._translationX = 0; this._translationX = undefined;
this._direction = SlideDirection.LEFT; this._direction = SlideDirection.LEFT;
super._init(params); super._init(params);
@ -67,9 +57,8 @@ var SlideLayout = GObject.registerClass({
// flags only determine what to do if the allocated box is bigger // flags only determine what to do if the allocated box is bigger
// than the actor's box. // than the actor's box.
let realDirection = getRtlSlideDirection(this._direction, child); let realDirection = getRtlSlideDirection(this._direction, child);
let alignX = (realDirection == SlideDirection.LEFT) let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth)
? availWidth - natWidth : (availWidth - natWidth * this._slideX);
: availWidth - natWidth * this._slideX;
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
actorBox.x1 = box.x1 + alignX + this._translationX; actorBox.x1 = box.x1 + alignX + this._translationX;
@ -80,17 +69,12 @@ var SlideLayout = GObject.registerClass({
child.allocate(actorBox, flags); child.allocate(actorBox, flags);
} }
// eslint-disable-next-line camelcase set slideX(value) {
set slide_x(value) {
if (this._slideX == value)
return;
this._slideX = value; this._slideX = value;
this.notify('slide-x');
this.layout_changed(); this.layout_changed();
} }
// eslint-disable-next-line camelcase get slideX() {
get slide_x() {
return this._slideX; return this._slideX;
} }
@ -103,17 +87,12 @@ var SlideLayout = GObject.registerClass({
return this._direction; return this._direction;
} }
// eslint-disable-next-line camelcase set translationX(value) {
set translation_x(value) {
if (this._translationX == value)
return;
this._translationX = value; this._translationX = value;
this.notify('translation-x');
this.layout_changed(); this.layout_changed();
} }
// eslint-disable-next-line camelcase get translationX() {
get translation_x() {
return this._translationX; return this._translationX;
} }
}); });
@ -147,10 +126,9 @@ var SlidingControl = class {
} }
_updateSlide() { _updateSlide() {
this.actor.ease_property('@layout.slide-x', this._getSlide(), { Tweener.addTween(this.layout, { slideX: this._getSlide(),
mode: Clutter.AnimationMode.EASE_OUT_QUAD, time: SIDE_CONTROLS_ANIMATION_TIME,
duration: SIDE_CONTROLS_ANIMATION_TIME, transition: 'easeOutQuad' });
});
} }
getVisibleWidth() { getVisibleWidth() {
@ -182,14 +160,13 @@ var SlidingControl = class {
translationEnd = translation; translationEnd = translation;
} }
if (this.layout.translation_x == translationEnd) if (this.layout.translationX == translationEnd)
return; return;
this.layout.translation_x = translationStart; this.layout.translationX = translationStart;
this.actor.ease_property('@layout.translation-x', translationEnd, { Tweener.addTween(this.layout, { translationX: translationEnd,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, time: SIDE_CONTROLS_ANIMATION_TIME,
duration: SIDE_CONTROLS_ANIMATION_TIME, transition: 'easeOutQuad' });
});
} }
_onOverviewHiding() { _onOverviewHiding() {
@ -218,30 +195,28 @@ var SlidingControl = class {
} }
fadeIn() { fadeIn() {
this.actor.ease({ Tweener.addTween(this.actor, { opacity: 255,
opacity: 255, time: SIDE_CONTROLS_ANIMATION_TIME / 2,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2, transition: 'easeInQuad'
mode: Clutter.AnimationMode.EASE_IN_QUAD });
});
} }
fadeHalf() { fadeHalf() {
this.actor.ease({ Tweener.addTween(this.actor, { opacity: 128,
opacity: 128, time: SIDE_CONTROLS_ANIMATION_TIME / 2,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2, transition: 'easeOutQuad'
mode: Clutter.AnimationMode.EASE_OUT_QUAD });
});
} }
slideIn() { slideIn() {
this._visible = true; this._visible = true;
// we will update slide_x and the translation from pageEmpty // we will update slideX and the translation from pageEmpty
} }
slideOut() { slideOut() {
this._visible = false; this._visible = false;
this._updateTranslation(); this._updateTranslation();
// we will update slide_x from pageEmpty // we will update slideX from pageEmpty
} }
pageEmpty() { pageEmpty() {
@ -249,8 +224,7 @@ var SlidingControl = class {
// selector; this means we can now safely set the full slide for // selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called, // the next page, since slideIn or slideOut might have been called,
// changing the visiblity // changing the visiblity
this.actor.remove_transition('@layout.slide-x'); this.layout.slideX = this._getSlide();
this.layout.slide_x = this._getSlide();
this._updateTranslation(); this._updateTranslation();
} }
}; };
@ -449,6 +423,17 @@ var ControlsManager = class {
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this)); layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
Main.overview.connect('showing', this._updateSpacerVisibility.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() { _updateWorkspacesGeometry() {

Some files were not shown because too many files have changed in this diff Show More