Compare commits

..

3 Commits

Author SHA1 Message Date
Allan Day
34e9513e1f adjust UI to new text styles
With the new text styles, some UI needs to adjusted, primarily to
accommodate larger heading text.
2019-06-27 13:52:40 +01:00
Allan Day
40a772c884 theme: Standardise text styles
Initial attempt to use standard text styles, in line with what's
being done for GTK (https://gitlab.gnome.org/GNOME/gtk/issues/1808).

This is just changing the sizes and weights for now. Spacing
adjustments will be required further down the line.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/594
2019-06-27 13:51:14 +01:00
Allan Day
2ccd87ae44 theme: Remove unused message tray counters 2019-06-27 13:51:14 +01:00
272 changed files with 22082 additions and 41685 deletions

View File

@@ -1,6 +0,0 @@
{
"extends": [
"./lint/eslintrc-gjs.json",
"./lint/eslintrc-shell.json"
]
}

View File

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

View File

@@ -1,7 +1,7 @@
FROM registry.fedoraproject.org/fedora:latest
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 '{}' ';'`
dnf install -y findutils mozjs60-devel && \

View File

@@ -1,97 +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
}
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commit_range=$branch_point...$CI_COMMIT_SHA
list_commit_range_additions $commit_range > $LINE_CHANGES
# Don't bother with running lint when no JS changed
if is_empty $LINE_CHANGES; then
exit 0
fi
fi
echo Generating lint report using regular configuration
run_eslint REGULAR
echo Generating lint report using legacy configuration
run_eslint LEGACY
echo Done.
create_common
# Just show the report and succeed when not testing a MR
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
cat $OUTPUT_FINAL
exit 0
fi
copy_matched_lines $OUTPUT_FINAL $LINE_CHANGES $OUTPUT_MR
cat $OUTPUT_MR
is_empty $OUTPUT_MR

View File

@@ -84,6 +84,7 @@ don't use.
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
```
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
}`, `foo['bar']`.
## Animations
Most objects that are animated are actors, and most properties used in animations
are animatable, which means they can use implicit animations:
## Getters, setters, and Tweener
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
moveActor(actor, x, y) {
actor.ease({
x,
y,
duration: 500, // ms
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
```
The above is a convenience wrapper around the actual Clutter API, and should generally
be preferred over the more verbose:
```javascript
moveActor(actor, x, y) {
actor.save_easing_state();
actor.set_easing_duration(500);
actor.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
actor.set({
x,
y
});
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
});
}
var ANIMATION_TIME = 2000;
var MyClass = class {
constructor() {
this.actor = new St.BoxLayout();
this._position = 0;
}
get position() {
return this._position;
}
set position(value) {
this._position = value;
this.actor.set_position(value, value);
}
};
let myThing = new MyClass();
Tweener.addTween(myThing,
{ position: 100,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
```

103
NEWS
View File

@@ -1,106 +1,3 @@
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
======
* 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"/>
</method>
<!--
EnableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Enable an extension.
-->
<method name="EnableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!--
DisableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Disable an extension.
-->
<method name="DisableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!--
LaunchExtensionPrefs:
@uuid: The UUID of the extension
@@ -213,15 +189,6 @@
-->
<method name="CheckForUpdates"/>
<signal name="ExtensionStateChanged">
<arg type="s" name="uuid"/>
<arg type="a{sv}" name="state"/>
</signal>
<!--
ExtensionStatusChanged:
Deprecated for ExtensionStateChanged
-->
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>

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

@@ -9,7 +9,7 @@
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels">
<method name="ShowMonitorLabels2">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="HideMonitorLabels"/>

View File

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

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,25 +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

View File

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

View File

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

View File

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

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
desktopconf.set('bindir', bindir)
desktopconf.set('VERSION', meson.project_version())
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files
i18n.merge_file('desktop',
input: configure_file(
@@ -24,7 +22,7 @@ foreach desktop_file : desktop_files
configuration: desktopconf
),
output: desktop_file,
po_dir: po_dir,
po_dir: '../po',
install: true,
install_dir: desktopdir,
type: 'desktop'
@@ -100,23 +98,15 @@ if have_systemd
unitconf = configuration_data()
unitconf.set('bindir', bindir)
configure_file(
input: 'gnome-shell-x11.service.in',
output: 'gnome-shell-x11.service',
unit = configure_file(
input: 'gnome-shell.service.in',
output: 'gnome-shell.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
configure_file(
input: 'gnome-shell-wayland.service.in',
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')
units = files('gnome-shell-wayland.target',
'gnome-shell-x11.target')
install_data(units, install_dir: systemduserunitdir)
endif

View File

@@ -14,4 +14,3 @@ X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true
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.
</description>
</key>
<key name="disabled-extensions" type="as">
<default>[]</default>
<summary>UUIDs of extensions to force disabling</summary>
<description>
GNOME Shell extensions have a UUID property; this key lists extensions
which should be disabled, even if loaded as part of the current mode.
You can also manipulate this list with the EnableExtension and
DisableExtension D-Bus methods on org.gnome.Shell.
This key takes precedence over the “enabled-extensions” setting.
</description>
</key>
<key name="disable-user-extensions" type="b">
<default>false</default>
<summary>Disable user extensions</summary>
@@ -110,6 +99,7 @@
</description>
</key>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
</schema>
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
@@ -150,6 +140,11 @@
Keybinding to focus the active notification.
</description>
</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">
<default>["&lt;Super&gt;1"]</default>
<summary>Switch to application 1</summary>
@@ -188,6 +183,17 @@
</key>
</schema>
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="keyboard-type" type="s">
<default>'touch'</default>
<summary>Which keyboard to use</summary>
<description>
The type of keyboard to use.
</description>
</key>
</schema>
<schema id="org.gnome.shell.app-switcher"
path="/org/gnome/shell/app-switcher/"
gettext-domain="@GETTEXT_PACKAGE@">
@@ -228,36 +234,6 @@
</key>
</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 -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">

View File

@@ -25,10 +25,8 @@ $cakeisalie: "This stylesheet is generated, DO NOT EDIT";
/* GLOBALS */
$modal_radius: 9px;
$button_radius: 5px;
$panel-corner-radius: $button_radius + 1;
$panel-corner-radius: 6px;
$medium_radius: 9px;
$_trough_color: transparentize($fg_color, 0.9);
$_bubble_borders_color: lighten($borders_color, if($variant=='light', 0%, 5%));
@@ -48,7 +46,7 @@ stage {
/* Buttons */
.button, %button {
border-radius: $button_radius;
border-radius: 5px;
border-width: 1px;
min-height: 22px;
padding: 4px 32px;
@@ -70,21 +68,21 @@ stage {
border-top: 1px solid $_bubble_borders_color;
&:first-child {
border-radius: 0px 0px 0px $modal_radius;
border-radius: 0px 0px 0px $medium_radius;
}
&:last-child {
border-right-width: 0px;
border-radius: 0px 0px $modal_radius 0px;
border-radius: 0px 0px $medium_radius 0px;
}
&:first-child:last-child {
border-right-width: 0px;
border-radius: 0px 0px $modal_radius $modal_radius;
border-radius: 0px 0px $medium_radius $medium_radius;
}
}
/* Entries */
StEntry {
border-radius: $button_radius;
border-radius: 5px;
padding: 4px;
border-width: 1px;
color: $fg_color;
@@ -189,12 +187,12 @@ StScrollBar {
/* Modal Dialogs */
.headline { font-size: 110%; }
.headline { @extend %heading; }
.lightbox { background-color: black; }
.flashspot { background-color: white; }
.modal-dialog {
border-radius: $modal_radius;
border-radius: 9px;
@extend %bubble-panel;
.modal-dialog-content-box {
padding: 24px;
@@ -206,8 +204,7 @@ StScrollBar {
}
.run-dialog-button-box { padding-top: 1em; }
.run-dialog-label {
@include fontsize($font-size + 1.1);
font-weight: normal;
@extend %title-4;
color: $fg_color;
padding-bottom: .4em;
}
@@ -215,8 +212,8 @@ StScrollBar {
}
.mount-dialog-subject,
.end-session-dialog-subject { //this should be a generic header class
@include fontsize($font-size * 1.3);
.end-session-dialog-subject {
@extend %title-2;
}
/* Message Dialog */
@@ -236,12 +233,12 @@ StScrollBar {
}
.message-dialog-title {
font-weight: bold;
@extend %title-2;
}
.message-dialog-subtitle {
@extend %heading;
color: $fg_color;
font-weight: bold;
}
/* End Session Dialog */
@@ -255,6 +252,7 @@ StScrollBar {
}
.end-session-dialog-layout {
spacing: 12px;
padding-left: 17px;
&:rtl { padding-right: 17px; }
}
@@ -302,7 +300,7 @@ StScrollBar {
}
.end-session-dialog-list-header {
font-weight: bold;
@extend %heading;
&:rtl { text-align: right; }
}
@@ -313,12 +311,11 @@ StScrollBar {
.end-session-dialog-app-list-item-name,
.end-session-dialog-session-list-item-name {
font-weight: bold;
@extend %heading;
}
.end-session-dialog-app-list-item-description {
color: darken($fg_color,5%);
font-size: 10pt;
}
/* ShellMountOperation Dialogs */
@@ -374,11 +371,6 @@ StScrollBar {
&:rtl { padding-left: 17px; }
}
.mount-dialog-app-list-item-name {
font-size: 10pt;
}
/* Password or Authentication Dialog */
.prompt-dialog {
@@ -388,7 +380,7 @@ StScrollBar {
.message-dialog-main-layout { spacing: 24px; padding: 10px; }
.message-dialog-content { spacing: 16px; }
.message-dialog-title { color: lighten($fg_color,15%); }
.message-dialog-title { @extend %title-2; color: lighten($fg_color,15%); }
}
.prompt-dialog-description:rtl {
@@ -401,13 +393,11 @@ StScrollBar {
}
.prompt-dialog-error-label {
font-size: 10pt;
color: $warning_color;
padding-bottom: 8px;
}
.prompt-dialog-info-label {
font-size: 10pt;
padding-bottom: 8px;
}
@@ -416,7 +406,6 @@ StScrollBar {
}
.prompt-dialog-null-label {
font-size: 10pt;
padding-bottom: 8px;
}
@@ -472,7 +461,7 @@ StScrollBar {
}
.audio-selection-title {
font-weight: bold;
@extend %title-2;
text-align: center;
}
@@ -515,7 +504,7 @@ StScrollBar {
.extension-dialog {
@extend %bubble-panel;
.message-dialog-main-layout { spacing: 24px; padding: 10px; }
.message-dialog-title { font-weight: normal; color: $fg_color; }
.message-dialog-title { @extend %title-2; }
}
/* Inhibit-Shortcuts Dialog */
@@ -556,9 +545,9 @@ StScrollBar {
&:ltr { padding: .4em 1.75em .4em 0em; }
&:rtl { padding: .4em 0em .4em 1.75em; }
&:checked {
@extend %heading;
background-color: $bg_color;
box-shadow: inset 0 -1px 0px $_bubble_borders_color;
font-weight: bold;
}
&.selected {
background-color: transparentize(white, if($variant=='light', 0.2, 0.9));
@@ -591,7 +580,7 @@ StScrollBar {
}
.popup-menu-boxpointer,
.candidate-popup-boxpointer {
-arrow-border-radius: $button_radius+4;
-arrow-border-radius: $medium_radius;
-arrow-background-color: $bg_color;
-arrow-border-width: 1px;
-arrow-border-color: if($variant=='light', transparentize(black, 0.6), $borders_color);
@@ -619,18 +608,6 @@ StScrollBar {
app menu inside the main app window itself rather than the top bar
*/
/*************
* App Icons *
*************/
/* Outline for low res icons */
.lowres-icon {
icon-shadow: 0 1px 2px rgba(0,0,0,0.3);
}
/* Drapshadow for large icons */
.icon-dropshadow {
icon-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
/* OSD */
.osd-window {
@@ -641,7 +618,7 @@ StScrollBar {
min-width: 64px;
min-height: 64px;
.osd-monitor-label { font-size: 3em; }
.osd-monitor-label { @extend %title-1; }
.level {
height: 0.6em;
-barlevel-height: 0.6em;
@@ -740,8 +717,7 @@ StScrollBar {
spacing: 8px;
}
.ws-switcher-active-up, .ws-switcher-active-down,
.ws-switcher-active-left, .ws-switcher-active-right {
.ws-switcher-active-up, .ws-switcher-active-down {
height: 50px;
background-color: $selected_bg_color;
color: $selected_fg_color;
@@ -815,8 +791,8 @@ StScrollBar {
/* TOP BAR */
#panel {
@extend %heading;
background-color: black;
font-weight: bold;
height: 1.86em;
font-feature-settings: "tnum";
@@ -848,9 +824,9 @@ StScrollBar {
}
.panel-button {
@extend %heading;
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
.app-menu-icon {
@@ -942,33 +918,33 @@ StScrollBar {
.world-clocks-button,
.weather-button,
.events-section-title {
&:hover, &:focus { background-color: $_hover_bg_color }
&:hover, focus { background-color: $_hover_bg_color }
&:active { background-color: $_active_bg_color }
}
.datemenu-today-button .day-label {
@extend %heading;
}
.datemenu-today-button .date-label {
font-size: 1.5em;
font-weight: 300;
@extend %large-title;
}
.world-clocks-header,
.weather-header,
.events-section-title {
.events-section-title,
.calendar-month-label {
@extend %heading;
color: darken($fg_color,40%);
font-weight: bold;
}
.weather-header.location {
font-weight: normal;
font-size: 0.9em;
@extend %caption;
}
.world-clocks-grid,
.weather-grid {
spacing-rows: 0.4em;
spacing-rows: 0.8em;
spacing-columns: 0.8em;
}
@@ -976,35 +952,26 @@ StScrollBar {
spacing: 0.4em;
}
.world-clocks-city {
font-weight: bold;
font-size: 0.9em;
}
.world-clocks-time {
color: darken($fg_color,20%);
font-feature-settings: "tnum";
font-size: 1.2em;
font-feature-settings: "tnum";
}
.world-clocks-timezone {
color: $fg_color;
color: darken($fg_color,40%);
font-feature-settings: "tnum";
font-size: 0.9em;
@extend %caption;
}
.weather-forecast-icon {
icon-size: 2.18em;
icon-size: 32px;
}
.weather-forecast-time {
@extend %caption;
color: darken($fg_color,40%);
font-size: 0.8em;
}
.calendar-month-label {
color: lighten($fg_color,5%);
font-weight: bold;
padding: 8px 0;
&:focus {}
}
@@ -1013,7 +980,7 @@ StScrollBar {
background-color: transparent;
width: 32px;
border-radius: 4px;
&:hover, &:focus { background-color: $_hover_bg_color; }
&:hover, focus { background-color: $_hover_bg_color; }
&:active { background-color: transparentize($fg_color, 0.84); }
}
@@ -1022,23 +989,22 @@ StScrollBar {
}
.calendar-day-base {
font-size: 80%;
@extend %caption;
text-align: center;
width: 2.4em; height: 2.4em;
padding: 0.1em;
margin: 2px;
border-radius: 1.4em;
font-feature-settings: "tnum";
&:hover, &:focus { background-color: $_hover_bg_color; }
&:hover, focus { background-color: $_hover_bg_color; }
&:active,&:selected {
color: lighten($selected_fg_color,5%);
background-color: $selected_bg_color;
border-color: transparent; //avoid jumparound due to today
}
&.calendar-day-heading { //day of week heading
color: lighten($fg_color,5%);
margin-top: 1em;
font-size: 70%;
color: darken($fg_color,40%);
// margin-top: 1em;
}
}
.calendar-day { //border collapse hack - see calendar.js
@@ -1053,14 +1019,15 @@ StScrollBar {
color: $insensitive_fg_color;
}
.calendar-today {
font-weight: bold;
@extend %caption-heading;
//color: lighten($fg_color,10%);
//background-color: darken($bg_color,5%);
border: 1px solid $_bubble_borders_color;
}
.calendar-day-with-events {
@extend %caption-heading;
color: lighten($fg_color,10%);
font-weight: bold;
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
}
.calendar-other-month-day {
@@ -1068,8 +1035,7 @@ StScrollBar {
opacity: 0.5;
}
.calendar-week-number {
font-size: 70%;
font-weight: bold;
@extend %caption-heading;
width: 2.3em; height: 1.8em;
border-radius: 2px;
padding: 0.5em 0 0;
@@ -1126,11 +1092,11 @@ StScrollBar {
}
.message-secondary-bin > .event-time {
color: $fg_color;
font-size: 0.7em;
@extend %caption;
color: darken($fg_color,40%);
/* HACK: the label should be baseline-aligned with a 1em label,
fake this with some bottom padding */
padding-bottom: 0.13em;
padding-bottom: 1px;
}
.message-secondary-bin > StIcon {
@@ -1170,7 +1136,13 @@ StScrollBar {
// a little unstructured mess:
.system-switch-user-submenu-icon {
icon-size: 16px;
padding: 0 4px;
}
#appMenu {
spinner-image: url("resource:///org/gnome/shell/theme/process-working.svg");
spacing: 4px;
.label-shadow { color: transparent; }
@@ -1292,17 +1264,16 @@ StScrollBar {
.nm-dialog-airplane-box { spacing: 12px; }
.nm-dialog-airplane-headline {
font-weight: bold;
@extend %heading;
text-align: center;
}
.nm-dialog-airplane-text { color: $fg_color; }
.nm-dialog-header-icon { icon-size: 32px; }
.nm-dialog-scroll-view { border: 2px solid $borders_color; }
.nm-dialog-header { font-weight: bold; }
.nm-dialog-header { @extend %title-2; }
.nm-dialog-item {
font-size: 110%;
border-bottom: 1px solid $borders_color;
padding: 12px;
spacing: 20px;
@@ -1338,8 +1309,8 @@ StScrollBar {
.window-clone-border {
$_bg: transparentize(white, 0.65);
border: 7px solid $_bg;
border-radius: $modal_radius;
border: 5px solid $_bg;
border-radius: 6px;
// For window decorations with round corners we can't match
// the exact shape when the window is scaled. So apply a shadow
// to fix that case
@@ -1376,8 +1347,11 @@ StScrollBar {
//search results
#searchResultsContent {
#searchResultsBin {
max-width: 1000px;
}
#searchResultsContent {
padding-left: 20px;
padding-right: 20px;
spacing: 16px;
@@ -1406,7 +1380,7 @@ StScrollBar {
#dash {
@extend %overview-panel;
font-size: 9pt;
@extend %caption;
padding: 4px 0;
border-radius: 0px 9px 9px 0px;
@@ -1493,11 +1467,11 @@ StScrollBar {
.search-provider-icon,
.list-search-result {
@extend %icon_tile;
&:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); }
&:focus, &:selected, &:hover {
background-color: transparentize($osd_fg_color,.9);
transition-duration: 200ms;
}
&:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); }
}
.app-well-app,
.app-well-app.app-folder,
@@ -1506,6 +1480,10 @@ StScrollBar {
& .overview-icon {
@extend %icon_tile;
}
&:active .overview-icon,
&:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5);
}
&:hover .overview-icon,
&:focus .overview-icon,
&:selected .overview-icon {
@@ -1514,13 +1492,7 @@ StScrollBar {
border-image: none;
background-image: none;
}
&:drop .overview-icon {
background-color: transparentize($selected_bg_color,.15);
}
&:active .overview-icon,
&:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5);
}
}
.app-well-app-running-dot { //running apps indicator
@@ -1531,7 +1503,7 @@ StScrollBar {
%icon_tile {
color: $osd_fg_color;
border-radius: $button_radius+4;
border-radius: $medium_radius;
padding: 6px;
border: 1px solid transparent;
transition-duration: 100ms;
@@ -1610,6 +1582,7 @@ StScrollBar {
}
//Some hacks I don't even
.search-display > StBoxLayout,
.all-apps,
.frequent-apps > StBoxLayout {
// horizontal padding to make sure scrollbars or dash don't overlap content
@@ -1622,9 +1595,9 @@ StScrollBar {
border: none;
}
// Search status, like "Searching..." and "No results"
%status_text {
font-size: 2em;
font-weight: bold;
@extend %large-title;
color: $osd_fg_color;
}
@@ -1633,18 +1606,22 @@ StScrollBar {
.url-highlighter { link-color: lighten($selected_bg_color,10%); }
// Banners
.message-body {
@extend %caption;
padding-top: 2px;
}
.notification-banner {
font-size: 11pt;
width: 34em;
margin: 5px;
border-radius: $modal_radius;
border-radius: $medium-radius;
border: if($variant == 'light', none, $_bubble_borders_color);
min-height: 64px;
box-shadow: 0 1px 2px transparentize(black, 0.7);
&:hover { background: $bg_color; }
&, &:focus, &:active {
background-color: $bg_color;
.message-title { color: $fg_color }
.message-title { color: $fg_color; }
.message-content { color: $fg_color; }
}
@@ -1671,20 +1648,6 @@ StScrollBar {
border: none;
}
}
.summary-source-counter {
font-size: 10pt;
font-weight: bold;
height: 1.6em; width: 1.6em;
-shell-counter-overlap-x: 3px;
-shell-counter-overlap-y: 3px;
background-color: $selected_bg_color;
color: $selected_fg_color;
border: 2px solid $fg_color;
box-shadow: 0 2px 2px rgba(0,0,0,0.5);
border-radius: 0.9em; // should be 0.8 but whatever; wish I could do 50%;
}
.secondary-icon { icon-size: 1.09em; }
//chat bubbles
.chat-body { spacing: 5px; }
@@ -1701,9 +1664,8 @@ StScrollBar {
&:rtl { padding-left: 0; padding-right: 18pt; }
}
.chat-meta-message {
@extend %caption-heading;
padding-left: 4px;
font-size: 9pt;
font-weight: bold;
color: lighten($fg_color,18%);
&:rtl { padding-left: 0; padding-right: 4px; }
}
@@ -1789,36 +1751,30 @@ StScrollBar {
}
.keyboard-key {
$_key_bg: opacify(lighten($osd_bg_color, 9%), 1);
background-color: $_key_bg;
background-color: #393f3f;
min-height: 1.2em;
min-width: 1.2em;
font-size: 16pt;
border-radius: $button_radius;
border: 1px solid $osd_outer_borders_color;
color: $osd_fg_color;
border-radius: 3px;
border: 1px solid #464d4d;
color: #e5e5e5;
&:focus { @include button(focus); }
&:hover, &:checked { background-color: lighten($_key_bg, 3%); }
&:active { background-color: darken($_key_bg, 2%); }
&:hover,&:checked { @include button(hover); }
&:active { @include button(active);}
&:grayed { //FIXME
background-color: $osd_bg_color;
color: $osd_fg_color;
border-color: $osd_borders_color;
}
&.default-key {
$_default_key_bg: opacify($osd_bg_color, 1);
border-color: $osd_outer_borders_color;
background-color: $_default_key_bg;
border-color: #2d3232;
background-color: #1d2020;
background-size: 20px;
&:hover, &:checked { background-color: lighten($_default_key_bg, 3%); }
&:active { background-color: darken($_default_key_bg, 2%); }
}
&.enter-key {
border-color: lighten($selected_bg_color, 5%);
background-color: $selected_bg_color;
border-color: #005684;
background-color: #006098;
background-image: url("resource:///org/gnome/shell/theme/key-enter.svg");
&:hover, &:checked { background-color: lighten($selected_bg_color, 3%); }
&:active { background-color: darken($selected_bg_color, 2%); }
}
&.shift-key-lowercase {
background-image: url("resource:///org/gnome/shell/theme/key-shift.svg");
@@ -1857,8 +1813,8 @@ StScrollBar {
.emoji-panel {
.keyboard-key:latched {
border-color: lighten($selected_bg_color, 5%);
background-color: $selected_bg_color;
border-color: #005684;
background-color: #006098;
}
}
@@ -1922,7 +1878,7 @@ StScrollBar {
StEntry {
@extend %search_entry;
border-radius: $button_radius;
border-radius: 5px;
@if $variant=='dark' {
$_gdm_entry_bg: transparentize(lighten(desaturate(#241f31, 20%), 2%), 0.5);
background-color: $_gdm_entry_bg;
@@ -1995,8 +1951,7 @@ StScrollBar {
}
}
.login-dialog-not-listed-label {
font-size: 90%;
font-weight: bold;
@extend %heading;
color: darken($osd_fg_color,30%);
padding-top: 1em;
}
@@ -2025,8 +1980,7 @@ StScrollBar {
.login-dialog-username,
.user-widget-label {
color: $osd_fg_color;
font-size: 120%;
font-weight: bold;
@extend %title-3;
text-align: left;
padding-left: 15px;
}
@@ -2044,7 +1998,6 @@ StScrollBar {
.login-dialog-prompt-label {
color: darken($osd_fg_color, 20%);
font-size: 110%;
padding-top: 1em;
}
@@ -2116,7 +2069,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
.screen-shield-notification-label {
font-weight: bold;
@extend %heading;
padding: 0px 0px 0px 12px;
}
@@ -2156,9 +2109,9 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
}
.labels { spacing: 4px; }
.notebook-tab {
@extend %heading;
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100ms;
padding-left: .3em;
@@ -2219,7 +2172,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
}
.lg-extension-name {
font-weight: bold;
@extend %heading;
}
.lg-extension-meta {
@@ -2232,3 +2185,39 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
border-radius: 4px;
padding: 6px;
}
// text styles
%large-title {
font-weight: 300;
font-size: 24pt;
// letter-spacing: 0.2rem; this breaks the style
}
%title-1 {
font-weight: 800;
font-size: 20pt;
}
%title-2 {
font-weight: 800;
font-size: 15pt;
}
%title-3 {
font-weight: 700;
font-size: 15pt;
}
%title-4 {
font-weight: 700;
font-size: 13pt;
}
%heading {
font-weight: 700;
font-size: 11pt;
}
%caption-heading {
font-weight: 700;
font-size: 9pt;
}
%caption {
font-weight: 400;
font-size: 9pt;
}

View File

@@ -28,7 +28,7 @@ foreach iface : ifaces
output: 'doc-gen-' + iface[1],
command: [
'gdbus-codegen',
'--interface-prefix=@0@.'.format(iface[0]),
'--interface-prefix=@0@.'.format(iface),
'--generate-docbook', 'doc-gen',
'--output-directory', '@OUTDIR@',
'@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 { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
const Format = imports.format;
@@ -12,8 +8,6 @@ const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@@ -23,54 +17,74 @@ function stripPrefix(string, prefix) {
return string;
}
var Application = GObject.registerClass({
GTypeName: 'ExtensionPrefs_Application'
}, class Application extends Gtk.Application {
_init() {
var Application = class {
constructor() {
GLib.set_prgname('gnome-shell-extension-prefs');
super._init({
this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
});
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('command-line', this._onCommandLine.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
this._extensionPrefsModules = {};
this._startupUuid = null;
this._loaded = false;
this._skipMainWindow = false;
this._shellProxy = null;
}
get shellProxy() {
return this._shellProxy;
}
_extensionAvailable(uuid) {
let extension = ExtensionUtils.extensions[uuid];
_showPrefs(uuid) {
let row = this._extensionSelector.get_children().find(c => {
return c.uuid === uuid && c.hasPrefs;
});
if (!row)
if (!extension)
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))
return false;
return true;
}
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
if (this._extensionPrefsModules.hasOwnProperty(uuid))
return this._extensionPrefsModules[uuid];
ExtensionUtils.installImporter(extension);
let prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule;
}
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
return;
let extension = ExtensionUtils.extensions[uuid];
let widget;
try {
widget = row.prefsModule.buildPrefsWidget();
let prefsModule = this._getExtensionPrefsModule(extension);
widget = prefsModule.buildPrefsWidget();
} catch (e) {
widget = this._buildErrorUI(row, e);
widget = this._buildErrorUI(extension, e);
}
let dialog = new Gtk.Window({
modal: !this._skipMainWindow,
type_hint: Gdk.WindowTypeHint.DIALOG
});
dialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true
}));
let dialog = new Gtk.Window({ modal: !this._skipMainWindow,
type_hint: Gdk.WindowTypeHint.DIALOG });
dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true,
title: extension.metadata.name,
visible: true }));
if (this._skipMainWindow) {
this.add_window(dialog);
this.application.add_window(dialog);
if (this._window)
this._window.destroy();
this._window = dialog;
@@ -82,11 +96,9 @@ var Application = GObject.registerClass({
dialog.set_default_size(600, 400);
dialog.add(widget);
dialog.show();
return true;
}
_buildErrorUI(row, exc) {
_buildErrorUI(extension, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true
@@ -156,20 +168,13 @@ var Application = GObject.registerClass({
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${row.uuid} had an error:`,
'```',
`${exc}`,
'```',
'',
'Stack trace:',
'```',
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```',
''
];
clipboard.set_text(lines.join('\n'), -1);
let backticks = '```';
clipboard.set_text(
// markdown for pasting in gitlab issues
`The settings of extension ${extension.uuid} had an error:\n${
backticks}\n${exc}\n${backticks}\n\nStack trace:\n${
backticks}\n${exc.stack}${backticks}\n`, -1
);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
@@ -180,13 +185,13 @@ var Application = GObject.registerClass({
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: row.url != null
visible: extension.metadata.url != null
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(row.url, context);
Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context);
});
let expandedBox = new Gtk.Box({
@@ -201,8 +206,8 @@ var Application = GObject.registerClass({
return scroll;
}
_buildUI() {
this._window = new Gtk.ApplicationWindow({ application: this,
_buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER });
this._window.set_default_size(800, 500);
@@ -236,14 +241,18 @@ var Application = GObject.registerClass({
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this));
this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
if (ExtensionUtils.extensions[uuid] !== undefined)
this._scanExtensions();
});
this._window.show_all();
}
_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) {
@@ -254,55 +263,19 @@ var Application = GObject.registerClass({
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() {
this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => {
if (e) {
if (e instanceof Gio.DBusError) {
log(`Failed to connect to shell proxy: ${e}`);
this._mainStack.add_named(new NoShellPlaceholder(), 'noshell');
this._mainStack.visible_child_name = 'noshell';
} else
throw e;
return;
}
for (let uuid in extensionsMap) {
let extension = ExtensionUtils.deserializeExtension(extensionsMap[uuid]);
this._addExtensionRow(extension);
}
this._extensionsLoaded();
});
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', this._extensionFound.bind(this));
finder.scanExtensions();
this._extensionsLoaded();
}
_addExtensionRow(extension) {
let row = new ExtensionRow(extension);
_extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', () => {
this._showPrefs(row.uuid);
this._selectExtension(row.uuid);
});
row.show_all();
@@ -315,26 +288,24 @@ var Application = GObject.registerClass({
else
this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid)
this._showPrefs(this._startupUuid);
if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid);
this._startupUuid = null;
this._skipMainWindow = false;
this._loaded = true;
}
vfunc_activate() {
_onActivate() {
this._window.present();
}
vfunc_startup() {
super.vfunc_startup();
this._buildUI();
_onStartup(app) {
this._buildUI(app);
this._scanExtensions();
}
vfunc_command_line(commandLine) {
this.activate();
_onCommandLine(app, commandLine) {
app.activate();
let args = commandLine.get_arguments();
if (args.length) {
@@ -345,14 +316,16 @@ var Application = GObject.registerClass({
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///");
if (!this._loaded)
if (this._extensionAvailable(uuid))
this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid;
else if (!this._showPrefs(uuid))
else
this._skipMainWindow = false;
}
return 0;
}
});
};
var Expander = GObject.registerClass({
Properties: {
@@ -519,35 +492,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(
class DescriptionLabel extends Gtk.Label {
vfunc_get_preferred_height_for_width(width) {
@@ -560,55 +504,30 @@ class DescriptionLabel extends Gtk.Label {
var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow {
_init(extension) {
_init(uuid) {
super._init();
this._app = Gio.Application.get_default();
this._extension = extension;
this._prefsModule = null;
this.uuid = uuid;
this._extensionStateChangedId = this._app.shellProxy.connectSignal(
'ExtensionStateChanged', (p, sender, [uuid, newState]) => {
if (this.uuid !== uuid)
return;
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = (this._extension.state == ExtensionState.ENABLED);
this._switch.state = state;
this._switch.sensitive = this._canToggle();
this._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.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
}
get uuid() {
return this._extension.uuid;
}
get name() {
return this._extension.metadata.name;
}
get hasPrefs() {
return this._extension.hasPrefs;
}
get url() {
return this._extension.metadata.url;
}
_onDestroy() {
if (!this._app.shellProxy)
return;
if (this._extensionStateChangedId)
this._app.shellProxy.disconnectSignal(this._extensionStateChangedId);
this._extensionStateChangedId = 0;
}
_buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin_end: 24, spacing: 24,
margin: 12 });
@@ -618,20 +537,19 @@ class ExtensionRow extends Gtk.ListBoxRow {
spacing: 6, hexpand: true });
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>',
use_markup: true,
halign: Gtk.Align.START });
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,
ellipsize: Pango.EllipsizeMode.END,
xalign: 0, yalign: 0 });
vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
visible: this.hasPrefs,
no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
@@ -641,37 +559,51 @@ class ExtensionRow extends Gtk.ListBoxRow {
this.prefsButton = button;
this._switch = new Gtk.Switch({
valign: Gtk.Align.CENTER,
sensitive: this._canToggle(),
state: this._extension.state === ExtensionState.ENABLED
});
this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
sensitive: this._canEnable(),
state: this._isEnabled() });
this._switch.connect('notify::active', () => {
if (this._switch.active)
this._app.shellProxy.EnableExtensionRemote(this.uuid);
this._enable();
else
this._app.shellProxy.DisableExtensionRemote(this.uuid);
this._disable();
});
this._switch.connect('state-set', () => true);
hbox.add(this._switch);
}
_canToggle() {
return this._extension.canChange;
_canEnable() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
}
get prefsModule() {
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
_isEnabled() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
}
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
_enable() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
extensions.push(this.uuid);
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);
}
});
@@ -679,12 +611,12 @@ function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
window.global = {
log(...args) {
print(args.join(', '));
log() {
print([].join.call(arguments, ', '));
},
logError(s) {
log(`ERROR: ${s}`);
log('ERROR: ' + s);
},
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
@@ -699,5 +631,6 @@ function main(argv) {
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
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 Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000;
var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
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 = {
UNLOCK_ONLY: 0,
@@ -58,23 +59,23 @@ var AuthPrompt = class {
this.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('next', () => {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('key-press-event', (actor, event) => {
if (event.get_key_symbol() == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
});
if (event.get_key_symbol() == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
});
this._userWell = new St.Bin({ x_fill: true,
x_align: St.Align.START });
@@ -111,7 +112,7 @@ var AuthPrompt = class {
this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
vertical: false });
this.actor.add(this._buttonBox,
{ expand: true,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
@@ -137,7 +138,7 @@ var AuthPrompt = class {
reactive: true,
can_focus: true,
label: _("Cancel") });
this.cancelButton.connect('clicked', () => this.cancel());
this.cancelButton.connect('clicked', () => { this.cancel(); });
this._buttonBox.add(this.cancelButton,
{ expand: false,
x_fill: false,
@@ -156,7 +157,7 @@ var AuthPrompt = class {
reactive: true,
can_focus: true,
label: _("Next") });
this.nextButton.connect('clicked', () => this.emit('next'));
this.nextButton.connect('clicked', () => { this.emit('next'); });
this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add(this.nextButton,
{ expand: false,
@@ -266,7 +267,7 @@ var AuthPrompt = class {
let oldActor = this._defaultButtonWellActor;
if (oldActor)
oldActor.remove_all_transitions();
Tweener.removeTweens(oldActor);
let wasSpinner;
if (oldActor == this._spinner.actor)
@@ -289,18 +290,19 @@ var AuthPrompt = class {
this._spinner.stop();
}
} else {
oldActor.ease({
opacity: 0,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
Tweener.addTween(oldActor,
{ opacity: 0,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
}
}
@@ -311,12 +313,11 @@ var AuthPrompt = class {
if (!animate)
actor.opacity = 255;
else
actor.ease({
opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR
});
Tweener.addTween(actor,
{ opacity: 255,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear' });
}
this._defaultButtonWellActor = actor;
@@ -365,12 +366,12 @@ var AuthPrompt = class {
_fadeOutMessage() {
if (this._message.opacity == 0)
return;
this._message.remove_all_transitions();
this._message.ease({
opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.removeTweens(this._message);
Tweener.addTween(this._message,
{ opacity: 0,
time: MESSAGE_FADE_OUT_ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
setMessage(message, type) {
@@ -385,7 +386,7 @@ var AuthPrompt = class {
this._message.remove_style_class_name('login-dialog-message-hint');
if (message) {
this._message.remove_all_transitions();
Tweener.removeTweens(this._message);
this._message.text = message;
this._message.opacity = 255;
} else {

View File

@@ -20,7 +20,7 @@
* 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,
* 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:
*
@@ -44,7 +44,6 @@
* replaced by something else.
*/
const { GObject } = imports.gi;
const Signals = imports.signals;
var Task = class {
@@ -177,36 +176,36 @@ Signals.addSignalMethods(Batch.prototype);
var ConcurrentBatch = class extends Batch {
process() {
let hold = this.runTask();
let hold = this.runTask();
if (hold) {
this.hold.acquireUntilAfter(hold);
}
if (hold) {
this.hold.acquireUntilAfter(hold);
}
// Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run
// concurrently.
this.nextTask();
// Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run
// concurrently.
this.nextTask();
}
};
Signals.addSignalMethods(ConcurrentBatch.prototype);
var ConsecutiveBatch = class extends Batch {
process() {
let hold = this.runTask();
let hold = this.runTask();
if (hold && hold.isAcquired()) {
// This task is inhibiting the batch. Wait on it
// before processing the next one.
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();
}
if (hold && hold.isAcquired()) {
// This task is inhibiting the batch. Wait on it
// before processing the next one.
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();
}
}
};
Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported FprintManager */
const Gio = imports.gi.Gio;
@@ -24,8 +23,8 @@ function FprintManager() {
try {
self.init(null);
} catch (e) {
log(`Failed to connect to Fprint service: ${e.message}`);
} catch(e) {
log('Failed to connect to Fprint service: ' + e.message);
return null;
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LoginDialog */
/*
* Copyright 2011 Red Hat, Inc
*
@@ -31,10 +30,11 @@ const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Realmd = imports.gdm.realmd;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500;
const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5;
@@ -43,7 +43,7 @@ var UserListItem = class {
constructor(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
this._onUserChanged.bind(this));
this._onUserChanged.bind(this));
let layout = new St.BoxLayout({ vertical: true });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
@@ -150,7 +150,7 @@ Signals.addSignalMethods(UserListItem.prototype);
var UserList = class {
constructor() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
@@ -187,6 +187,8 @@ var UserList = class {
}
updateStyle(isExpanded) {
let tasks = [];
if (isExpanded)
this._box.add_style_pseudo_class('expanded');
else
@@ -204,10 +206,11 @@ var UserList = class {
let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: _SCROLL_ANIMATION_TIME
});
Tweener.removeTweens(adjustment);
Tweener.addTween (adjustment,
{ value: value,
time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' });
}
jumpToItem(item) {
@@ -241,7 +244,7 @@ var UserList = class {
return;
if (user.locked)
return;
return;
let userName = user.get_user_name();
@@ -258,7 +261,7 @@ var UserList = class {
item.connect('activate', this._onItemActivated.bind(this));
// Try to keep the focused item front-and-center
item.actor.connect('key-focus-in', () => this.scrollToItem(item));
item.actor.connect('key-focus-in', () => { this.scrollToItem(item); });
this._moveFocusToItems();
@@ -316,17 +319,17 @@ var SessionMenuButton = class {
this._menu.actor.hide();
this._menu.connect('open-state-changed', (menu, isOpen) => {
if (isOpen)
this._button.add_style_pseudo_class('active');
else
this._button.remove_style_pseudo_class('active');
if (isOpen)
this._button.add_style_pseudo_class('active');
else
this._button.remove_style_pseudo_class('active');
});
this._manager = new PopupMenu.PopupMenuManager(this._button,
{ actionMode: Shell.ActionMode.NONE });
this._manager.addMenu(this._menu);
this._button.connect('clicked', () => this._menu.toggle());
this._button.connect('clicked', () => { this._menu.toggle(); });
this._items = {};
this._activeSessionId = null;
@@ -350,11 +353,11 @@ var SessionMenuButton = class {
}
setActiveSession(sessionId) {
if (sessionId == this._activeSessionId)
return;
if (sessionId == this._activeSessionId)
return;
this._activeSessionId = sessionId;
this._updateOrnament();
this._activeSessionId = sessionId;
this._updateOrnament();
}
close() {
@@ -371,7 +374,7 @@ var SessionMenuButton = class {
}
for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription_] = Gdm.get_session_name_and_description(ids[i]);
let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
let id = ids[i];
let item = new PopupMenu.PopupMenuItem(sessionName);
@@ -400,18 +403,18 @@ var LoginDialog = GObject.registerClass({
this.connect('destroy', this._onDestroy.bind(this));
parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default();
this._userManager = AccountsService.UserManager.get_default()
this._gdmClient = new Gdm.Client();
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`,
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
this._updateBanner.bind(this));
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`,
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
this._updateBanner.bind(this));
this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`,
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
this._updateDisableUserList.bind(this));
this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`,
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
this._updateLogo.bind(this));
this._textureCache = St.TextureCache.get_default();
@@ -517,7 +520,7 @@ var LoginDialog = GObject.registerClass({
_getBannerAllocation(dialogBox) {
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;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -531,7 +534,7 @@ var LoginDialog = GObject.registerClass({
_getLogoBinAllocation(dialogBox) {
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;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -545,7 +548,7 @@ var LoginDialog = GObject.registerClass({
_getCenterActorAllocation(dialogBox, actor) {
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 centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
@@ -572,15 +575,19 @@ var LoginDialog = GObject.registerClass({
// First find out what space the children require
let bannerAllocation = null;
let bannerHeight = 0;
let bannerWidth = 0;
if (this._bannerView.visible) {
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
}
let authPromptAllocation = null;
let authPromptHeight = 0;
let authPromptWidth = 0;
if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
}
@@ -612,64 +619,64 @@ var LoginDialog = GObject.registerClass({
let leftOverYSpace = bannerSpace - bannerHeight;
if (leftOverYSpace > 0) {
// First figure out how much left over space is up top
let leftOverTopSpace = leftOverYSpace / 2;
// First figure out how much left over space is up top
let leftOverTopSpace = leftOverYSpace / 2;
// Then, shift the banner into the middle of that extra space
let yShift = Math.floor(leftOverTopSpace / 2);
// Then, shift the banner into the middle of that extra space
let yShift = Math.floor(leftOverTopSpace / 2);
bannerAllocation.y1 += yShift;
bannerAllocation.y2 += yShift;
bannerAllocation.y1 += yShift;
bannerAllocation.y2 += yShift;
} else {
// Then figure out how much space there would be if we switched to a
// wide layout with banner on one side and authprompt on the other.
let leftOverXSpace = dialogWidth - authPromptWidth;
// Then figure out how much space there would be if we switched to a
// wide layout with banner on one side and authprompt on the other.
let leftOverXSpace = dialogWidth - authPromptWidth;
// In a wide view, half of the available space goes to the banner,
// and the other half goes to the margins.
let wideBannerWidth = leftOverXSpace / 2;
let wideSpacing = leftOverXSpace - wideBannerWidth;
// In a wide view, half of the available space goes to the banner,
// and the other half goes to the margins.
let wideBannerWidth = leftOverXSpace / 2;
let wideSpacing = leftOverXSpace - wideBannerWidth;
// If we do go with a wide layout, we need there to be at least enough
// space for the banner and the auth prompt to be the same width,
// so it doesn't look unbalanced.
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
let centerX = dialogBox.x1 + dialogWidth / 2;
let centerY = dialogBox.y1 + dialogHeight / 2;
// If we do go with a wide layout, we need there to be at least enough
// space for the banner and the auth prompt to be the same width,
// so it doesn't look unbalanced.
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
let centerX = dialogBox.x1 + dialogWidth / 2;
let centerY = dialogBox.y1 + dialogHeight / 2;
// A small portion of the spacing goes down the center of the
// screen to help delimit the two columns of the wide view
let centerGap = wideSpacing / 8;
// A small portion of the spacing goes down the center of the
// screen to help delimit the two columns of the wide view
let centerGap = wideSpacing / 8;
// place the banner along the left edge of the center margin
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// place the banner along the left edge of the center margin
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// figure out how tall it would like to be and try to accommodate
// but don't let it get too close to the logo
let [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
// figure out how tall it would like to be and try to accommodate
// but don't let it get too close to the logo
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
// place the auth prompt along the right edge of the center margin
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
} else {
// If we aren't going to do a wide view, then we need to limit
// the height of the banner so it will present scrollbars
// place the auth prompt along the right edge of the center margin
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
} else {
// If we aren't going to do a wide view, then we need to limit
// the height of the banner so it will present scrollbars
// First figure out how much space there is without the banner
leftOverYSpace += bannerHeight;
// First figure out how much space there is without the banner
leftOverYSpace += bannerHeight;
// Then figure out how much of that space is up top
let availableTopSpace = Math.floor(leftOverYSpace / 2);
// Then figure out how much of that space is up top
let availableTopSpace = Math.floor(leftOverYSpace / 2);
// Then give all of that space to the banner
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
}
// Then give all of that space to the banner
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
}
}
} else if (userSelectionAllocation) {
// Grow the user list to fill the space
@@ -757,15 +764,14 @@ var LoginDialog = GObject.registerClass({
_fadeInBannerView() {
this._bannerView.show();
this._bannerView.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this._bannerView,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
}
_hideBannerView() {
this._bannerView.remove_all_transitions();
Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0;
this._bannerView.hide();
}
@@ -845,10 +851,10 @@ var LoginDialog = GObject.registerClass({
_shouldShowSessionMenuButton() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
return false;
return false;
if (this._user && this._user.is_loaded && this._user.is_logged_in())
return false;
return false;
return true;
}
@@ -858,11 +864,10 @@ var LoginDialog = GObject.registerClass({
return;
this._authPrompt.actor.opacity = 0;
this._authPrompt.actor.show();
this._authPrompt.actor.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this._authPrompt.actor,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._fadeInBannerView();
}
@@ -906,31 +911,28 @@ var LoginDialog = GObject.registerClass({
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() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
return;
this._bindOpacity();
this.actor.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
this._unbindOpacity();
}
});
Tweener.addTween(this,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
onComplete() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
},
onCompleteScope: this });
}
_gotGreeterSessionProxy(proxy) {
@@ -943,27 +945,34 @@ var LoginDialog = GObject.registerClass({
}
_startSession(serviceName) {
this._bindOpacity();
this.actor.ease({
opacity: 0,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
this._unbindOpacity();
}
});
Tweener.addTween(this,
{ opacity: 0,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
onComplete() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
},
onCompleteScope: this });
}
_onSessionOpened(client, serviceName) {
this._authPrompt.finish(() => this._startSession(serviceName));
this._authPrompt.finish(() => { this._startSession(serviceName); });
}
_waitForItemForUser(userName) {
let item = this._userList.getItemFromUserName(userName);
if (item)
return null;
return null;
let hold = new Batch.Hold();
let signalId = this._userList.connect('item-added',
@@ -974,7 +983,7 @@ var LoginDialog = GObject.registerClass({
hold.release();
});
hold.connect('release', () => this._userList.disconnect(signalId));
hold.connect('release', () => { this._userList.disconnect(signalId); });
return hold;
}
@@ -1038,7 +1047,6 @@ var LoginDialog = GObject.registerClass({
return this._blockTimedLoginUntilIdle();
} else {
animationTime = delay;
return null;
}
},
@@ -1074,12 +1082,12 @@ var LoginDialog = GObject.registerClass({
// Restart timed login on user interaction
global.stage.connect('captured-event', (actor, event) => {
if (event.type() == Clutter.EventType.KEY_PRESS ||
if (event.type() == Clutter.EventType.KEY_PRESS ||
event.type() == Clutter.EventType.BUTTON_PRESS) {
this._startTimedLogin(userName, seconds);
}
this._startTimedLogin(userName, seconds);
}
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_PROPAGATE;
});
}
@@ -1225,11 +1233,10 @@ var LoginDialog = GObject.registerClass({
Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
this.ease({
opacity: 255,
duration: 1000,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
Tweener.addTween(this,
{ opacity: 255,
time: 1,
transition: 'easeInQuad' });
return true;
}
@@ -1243,7 +1250,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(_unichar) {
addCharacter(unichar) {
// 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 -*-
/* exported getOVirtCredentialsManager */
const Gio = imports.gi.Gio;
const Signals = imports.signals;

View File

@@ -15,11 +15,11 @@ const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = class {
constructor() {
constructor(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
this._reloadRealms.bind(this));
this._reloadRealms.bind(this))
this._realms = {};
this._signalId = this._aggregateProvider.connect('g-properties-changed',
@@ -36,10 +36,10 @@ var Manager = class {
return;
for (let i = 0; i < realmPaths.length; i++) {
Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
this._onRealmLoaded.bind(this));
let realm = Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
this._onRealmLoaded.bind(this));
}
}
@@ -98,10 +98,10 @@ var Manager = class {
Service(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
service => service.ReleaseRemote());
service => { service.ReleaseRemote(); });
this._aggregateProvider.disconnect(this._signalId);
this._realms = { };
this._updateLoginFormat();
}
};
Signals.addSignalMethods(Manager.prototype);
Signals.addSignalMethods(Manager.prototype)

View File

@@ -1,6 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals;
@@ -11,13 +9,14 @@ const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main;
const Params = imports.misc.params;
const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
var OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
var FADE_ANIMATION_TIME = 160;
var CLONE_FADE_ANIMATION_TIME = 250;
var FADE_ANIMATION_TIME = 0.16;
var CLONE_FADE_ANIMATION_TIME = 0.25;
var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
@@ -31,7 +30,7 @@ var LOGO_KEY = 'logo';
var DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 48ms to read each character of a PAM message
var USER_READ_TIME = 48;
var USER_READ_TIME = 48
var MessageType = {
NONE: 0,
@@ -46,20 +45,20 @@ function fadeInActor(actor) {
let hold = new Batch.Hold();
actor.show();
let [, naturalHeight] = actor.get_preferred_height(-1);
let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
actor.opacity = 0;
actor.set_height(0);
actor.ease({
opacity: 255,
height: naturalHeight,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.set_height(-1);
hold.release();
}
});
Tweener.addTween(actor,
{ opacity: 255,
height: naturalHeight,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
this.set_height(-1);
hold.release();
},
});
return hold;
}
@@ -72,17 +71,17 @@ function fadeOutActor(actor) {
}
let hold = new Batch.Hold();
actor.ease({
opacity: 0,
height: 0,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.hide();
this.set_height(-1);
hold.release();
}
});
Tweener.addTween(actor,
{ opacity: 0,
height: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
this.hide();
this.set_height(-1);
hold.release();
},
});
return hold;
}
@@ -102,15 +101,15 @@ function cloneAndFadeOutActor(actor) {
clone.set_position(x, y);
let hold = new Batch.Hold();
clone.ease({
opacity: 0,
duration: CLONE_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
clone.destroy();
hold.release();
}
});
Tweener.addTween(clone,
{ opacity: 0,
time: CLONE_FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
clone.destroy();
hold.release();
}
});
return hold;
}
@@ -304,7 +303,7 @@ var ShellUserVerifier = class {
});
}
_oVirtUserAuthenticated(_token) {
_oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
}
@@ -343,7 +342,7 @@ var ShellUserVerifier = class {
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch (e) {
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
@@ -370,7 +369,7 @@ var ShellUserVerifier = class {
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
} catch (e) {
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to obtain user verifier', e);
@@ -424,31 +423,36 @@ var ShellUserVerifier = class {
_startService(serviceName) {
this._hold.acquire();
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
(obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
});
this._hold.release();
});
} else {
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._userVerifier.call_begin_verification(serviceName,
this._cancellable,
(obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
});
this._hold.release();
});
}
}

View File

@@ -1,37 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, isOutOfDate, installImporter,
serializeExtension, deserializeExtension */
// Common utils for the extension system and the extension
// preferences tool
const { Gio, GLib } = imports.gi;
const Gettext = imports.gettext;
const Lang = imports.lang;
const Signals = imports.signals;
const Gio = imports.gi.Gio;
const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
var ExtensionType = {
SYSTEM: 1,
PER_USER: 2
};
var ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99
};
const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange'];
// Maps uuid -> metadata object
var extensions = {};
/**
* getCurrentExtension:
@@ -45,7 +31,7 @@ function getCurrentExtension() {
// Search for an occurrence of an extension stack frame
// Start at 1 because 0 is the stack frame of this function
for (let i = 1; i < stack.length; i++) {
if (stack[i].includes('/gnome-shell/extensions/')) {
if (stack[i].indexOf('/gnome-shell/extensions/') > -1) {
extensionStackLine = stack[i];
break;
}
@@ -63,17 +49,13 @@ function getCurrentExtension() {
if (!match)
return null;
// local import, as the module is used from outside the gnome-shell process
// as well (not this function though)
let extensionManager = imports.ui.main.extensionManager;
let path = match[1];
let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with
// the same UUID as a directory name.
while (file != null) {
let extension = extensionManager.lookup(file.get_basename());
let extension = extensions[file.get_basename()];
if (extension !== undefined)
return extension;
file = file.get_parent();
@@ -179,50 +161,54 @@ function isOutOfDate(extension) {
return false;
}
function serializeExtension(extension) {
let obj = {};
Lang.copyProperties(extension.metadata, obj);
function createExtensionObject(uuid, dir, type) {
let info;
SERIALIZED_PROPERTIES.forEach(prop => {
obj[prop] = extension[prop];
});
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
let res = {};
for (let key in obj) {
let val = obj[key];
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
case 'boolean':
type = 'b';
break;
default:
continue;
let metadataContents, success, tag;
try {
[success, metadataContents, tag] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) {
throw new Error('Failed to load metadata.json: ' + e);
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error('Failed to parse metadata.json: ' + e);
}
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');
}
res[key] = GLib.Variant.new(type, val);
}
return res;
}
function deserializeExtension(variant) {
let res = { metadata: {} };
for (let prop in variant) {
let val = variant[prop].unpack();
if (SERIALIZED_PROPERTIES.includes(prop))
res[prop] = val;
else
res.metadata[prop] = val;
if (uuid != meta.uuid) {
throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
}
// add the 2 additional properties to create a valid extension object, as createExtensionObject()
res.uuid = res.metadata.uuid;
res.dir = Gio.File.new_for_path(res.path);
return res;
let extension = {};
extension.metadata = meta;
extension.uuid = meta.uuid;
extension.type = type;
extension.dir = dir;
extension.path = dir.get_path();
extension.error = '';
extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
extensions[uuid] = extension;
return extension;
}
function installImporter(extension) {
@@ -233,3 +219,36 @@ function installImporter(extension) {
extension.imports = imports[extension.uuid];
imports.searchPath = oldSearchPath;
}
var ExtensionFinder = class {
_loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = extensions[uuid];
if (existing) {
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
return;
}
let extension;
let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = createExtensionObject(uuid, extensionDir, type);
} catch(e) {
logError(e, 'Could not load extension %s'.format(uuid));
return;
}
this.emit('extension-found', extension);
}
scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
this._loadExtension(dir, info, perUserDir);
});
}
};
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@@ -1,6 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported collectFromDatadirs, deleteGFile, recursivelyDeleteDir,
recursivelyMoveDir, loadInterfaceXML */
const { Gio, GLib } = imports.gi;
const Config = imports.misc.config;
@@ -38,7 +36,7 @@ function recursivelyDeleteDir(dir, deleteParent) {
let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
let info;
let info, child;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let child = dir.get_child(info.get_name());
@@ -59,7 +57,7 @@ function recursivelyMoveDir(srcDir, destDir) {
if (!destDir.query_exists(null))
destDir.make_directory_with_parents(null);
let info;
let info, child;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let srcChild = srcDir.get_child(info.get_name());
@@ -86,13 +84,13 @@ function loadInterfaceXML(iface) {
let f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
let [ok, bytes] = f.load_contents(null);
if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes);
xml = imports.byteArray.toString(bytes)
else
xml = bytes.toString();
} catch (e) {
log(`Failed to load D-Bus interface ${iface}`);
log('Failed to load D-Bus interface ' + iface);
}
return xml;

View File

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

View File

@@ -18,7 +18,7 @@ var HistoryManager = class {
this._historyIndex = 0;
if (this._key) {
this._history = global.settings.get_strv(this._key);
global.settings.connect(`changed::${this._key}`,
global.settings.connect('changed::' + this._key,
this._historyChanged.bind(this));
} else {
@@ -66,7 +66,7 @@ var HistoryManager = class {
this._indexChanged();
}
return this._historyIndex ? this._history[this._historyIndex - 1] : null;
return this._historyIndex ? this._history[this._historyIndex -1] : null;
}
addItem(input) {

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;
@@ -43,7 +42,7 @@ var IBusManager = class {
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null;
this._engines = new Map();
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
@@ -59,31 +58,29 @@ var IBusManager = class {
this._spawn();
}
_spawn(extraArgs = []) {
_spawn() {
try {
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs];
Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
} catch(e) {
log('Failed to launch ibus-daemon: ' + e.message);
}
}
restartDaemon(extraArgs = []) {
this._spawn(['-r', ...extraArgs]);
}
_clear() {
if (this._panelService)
this._panelService.destroy();
this._panelService = null;
this._candidatePopup.setPanelService(null);
this._engines.clear();
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
this.emit('ready', false);
this._spawn();
}
_onConnected() {
@@ -99,7 +96,7 @@ var IBusManager = class {
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
this._engines[name] = enginesList[i];
}
this._updateReadiness();
} else {
@@ -122,7 +119,7 @@ var IBusManager = class {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit ('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
this._panelService.connect('focus-out', () => { this.emit('focus-out'); });
try {
// IBus versions older than 1.5.10 have a bug which
@@ -141,7 +138,7 @@ var IBusManager = class {
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch (e) {
} catch(e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
@@ -153,7 +150,8 @@ var IBusManager = class {
}
_updateReadiness() {
this._ready = this._engines.size > 0 && this._panelService != null;
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready);
}
@@ -191,10 +189,10 @@ var IBusManager = class {
}
getEngineDesc(id) {
if (!this._ready || !this._engines.has(id))
if (!this._ready || !this._engines.hasOwnProperty(id))
return null;
return this._engines.get(id);
return this._engines[id];
}
setEngine(id, callback) {

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */
const { Clutter, GLib, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
@@ -75,7 +74,7 @@ class InputMethod extends Clutter.InputMethod {
this._context = null;
this._hints = 0;
this._purpose = 0;
this._preeditStr = '';
this._preeditStr = ''
this._preeditPos = 0;
this._preeditVisible = false;
}
@@ -85,15 +84,15 @@ class InputMethod extends Clutter.InputMethod {
this.emit('request-surrounding');
}
_onCommitText(_context, text) {
_onCommitText(context, text) {
this.commit(text.get_text());
}
_onDeleteSurroundingText() {
_onDeleteSurroundingText(context) {
this.delete_surrounding();
}
_onUpdatePreeditText(_context, text, pos, visible) {
_onUpdatePreeditText(context, text, pos, visible) {
if (text == null)
return;
@@ -109,17 +108,17 @@ class InputMethod extends Clutter.InputMethod {
this._preeditVisible = visible;
}
_onShowPreeditText() {
_onShowPreeditText(context) {
this._preeditVisible = true;
this.set_preedit_text(this._preeditStr, this._preeditPos);
}
_onHidePreeditText() {
_onHidePreeditText(context) {
this.set_preedit_text(null, this._preeditPos);
this._preeditVisible = false;
}
_onForwardKeyEvent(_context, keyval, keycode, state) {
_onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~(IBus.ModifierType.RELEASE_MASK);
@@ -263,7 +262,7 @@ class InputMethod extends Clutter.InputMethod {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);
} catch (e) {
log(`Error processing key on IM: ${e.message}`);
log('Error processing key on IM: ' + e.message);
}
});
return true;

View File

@@ -1,4 +1,3 @@
/* exported IntrospectService */
const { Gio, GLib, Meta, Shell } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell';
@@ -47,11 +46,11 @@ var IntrospectService = class {
}
_isIntrospectEnabled() {
return this._settings.get_boolean(INTROSPECT_KEY);
return this._settings.get_boolean(INTROSPECT_KEY);
}
_isSenderWhitelisted(sender) {
return APP_WHITELIST.includes(sender);
return APP_WHITELIST.includes(sender);
}
_getSandboxedAppId(app) {

View File

@@ -1,5 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
// Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
@@ -9,7 +8,7 @@
// This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr_, base;
let expr, base;
let attrHead = '';
if (globalCompletionList == null) {
globalCompletionList = [];
@@ -22,7 +21,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/);
if (matches) {
[expr_, base, attrHead] = matches;
[expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead
@@ -33,7 +32,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/);
if (text == '' || matches) {
[expr_, attrHead] = matches;
[expr, attrHead] = matches;
methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
@@ -52,14 +51,14 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// if we encounter anything that isn't a letter, '.', ')', or ']',
// we should stop parsing.
function isStopChar(c) {
return !c.match(/[\w.)\]]/);
return !c.match(/[\w\.\)\]]/);
}
// Given the ending position of a quoted string, find where it starts
function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') {
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
return i;
}
}
@@ -69,7 +68,7 @@ function findMatchingQuote(expr, offset) {
// Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') {
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
return i;
}
}
@@ -82,7 +81,7 @@ function findMatchingSlash(expr, offset) {
// findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset);
let openBrace = ({ ')': '(', ']': '[' })[closeBrace];
let openBrace = ({')': '(', ']': '['})[closeBrace];
function findTheBrace(expr, offset) {
if (offset < 0) {
@@ -118,11 +117,11 @@ function getExpressionOffset(expr, offset) {
while (offset >= 0) {
let currChar = expr.charAt(offset);
if (isStopChar(currChar)) {
if (isStopChar(currChar)){
return offset + 1;
}
if (currChar.match(/[)\]]/)) {
if (currChar.match(/[\)\]]/)) {
offset = findMatchingBrace(expr, offset);
}
@@ -152,11 +151,15 @@ function getAllProps(obj) {
// e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _.
function getPropertyNamesFromExpression(expr, commandHeader = '') {
function getPropertyNamesFromExpression(expr, commandHeader) {
if (commandHeader == null) {
commandHeader = '';
}
let obj = {};
if (!isUnsafeExpression(expr)) {
try {
obj = eval(commandHeader + expr);
obj = eval(commandHeader + expr);
} catch (e) {
return [];
}
@@ -165,7 +168,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
}
let propsUnique = {};
if (typeof obj === 'object') {
if (typeof obj === 'object'){
let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.'
allProps = allProps.filter( isValidPropertyName );
@@ -231,10 +234,10 @@ function isUnsafeExpression(str) {
function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(s => {
let base_, keyword;
let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/);
if (match) {
[base_, keyword] = match;
[base, keyword] = match;
ret.push(keyword);
}
});

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop, Meta } = imports.gi;
@@ -61,7 +60,7 @@ var KeyboardManager = class {
this._currentKeymap.options == options)
return;
this._currentKeymap = { layouts, variants, options };
this._currentKeymap = {layouts, variants, options};
Meta.get_backend().set_keymap(layouts, variants, options);
}
@@ -126,7 +125,7 @@ var KeyboardManager = class {
_getLocaleLayout() {
let locale = GLib.get_language_names()[0];
if (!locale.includes('_'))
if (locale.indexOf('_') == -1)
locale = DEFAULT_LOCALE;
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported canLock, getLoginManager, registerSessionWithGDM */
const { GLib, Gio } = imports.gi;
const Signals = imports.signals;
@@ -44,7 +43,7 @@ function canLock() {
let version = result.deep_unpack()[0].deep_unpack();
return haveSystemd() && versionCompare('3.5.91', version);
} catch (e) {
} catch(e) {
return false;
}
}
@@ -110,7 +109,7 @@ var LoginManagerSystemd = class {
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.');
let [session, objectPath_] = this._userProxy.Display;
let [session, objectPath] = this._userProxy.Display;
if (session) {
log(`Will monitor session ${session}`);
sessionId = session;
@@ -183,10 +182,10 @@ var LoginManagerSystemd = class {
(proxy, result) => {
let fd = -1;
try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) {
} catch(e) {
logError(e, "Error getting systemd inhibitor");
callback(null);
}
@@ -200,7 +199,7 @@ var LoginManagerSystemd = class {
Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = class {
getCurrentSessionProxy(_callback) {
getCurrentSessionProxy(callback) {
// we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer

View File

@@ -26,33 +26,33 @@ function _getMobileProvidersDatabase() {
}
// _findProviderForMccMnc:
// @operatorName: operator name
// @operatorCode: operator code
// @operator_name: operator name
// @operator_code: operator code
//
// Given an operator name string (which may not be a real operator name) and an
// operator code string, tries to find a proper operator name to display.
//
function _findProviderForMccMnc(operatorName, operatorCode) {
if (operatorName) {
if (operatorName.length != 0 &&
(operatorName.length > 6 || operatorName.length < 5)) {
function _findProviderForMccMnc(operator_name, operator_code) {
if (operator_name) {
if (operator_name.length != 0 &&
(operator_name.length > 6 || operator_name.length < 5)) {
// this looks like a valid name, i.e. not an MCCMNC (that some
// devices return when not yet connected
return operatorName;
return operator_name;
}
if (isNaN(parseInt(operatorName))) {
if (isNaN(parseInt(operator_name))) {
// name is definitely not a MCCMNC, so it may be a name
// after all; return that
return operatorName;
return operator_name;
}
}
let needle;
if ((!operatorName || operatorName.length == 0) && operatorCode)
needle = operatorCode;
else if (operatorName && (operatorName.length == 6 || operatorName.length == 5))
needle = operatorName;
if ((!operator_name || operator_name.length == 0) && operator_code)
needle = operator_code;
else if (operator_name && (operator_name.length == 6 || operator_name.length == 5))
needle = operator_name;
else // nothing to search
return null;
@@ -110,7 +110,7 @@ var ModemGsm = class {
this.signal_quality = quality;
this.emit('notify::signal-quality');
});
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [_status, code, name]) => {
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [status, code, name]) => {
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
@@ -120,7 +120,7 @@ var ModemGsm = class {
return;
}
let [status_, code, name] = result;
let [status, code, name] = result;
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
@@ -171,9 +171,9 @@ var ModemCdma = class {
// it will return an error if the device is not connected
this.operator_name = null;
} else {
let [bandClass_, band_, sid] = result;
let [bandClass, band, sid] = result;
this.operator_name = _findProviderForSid(sid);
this.operator_name = _findProviderForSid(sid)
}
this.emit('notify::operator-name');
});
@@ -224,23 +224,23 @@ var BroadbandModem = class {
}
_reloadSignalQuality() {
let [quality, recent_] = this._proxy.SignalQuality;
let [quality, recent] = this._proxy.SignalQuality;
this.signal_quality = quality;
this.emit('notify::signal-quality');
}
_reloadOperatorName() {
let newName = "";
let new_name = "";
if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0)
newName += this.operator_name_3gpp;
new_name += this.operator_name_3gpp;
if (this.operator_name_cdma && this.operator_name_cdma.length > 0) {
if (newName != "")
newName += ", ";
newName += this.operator_name_cdma;
if (new_name != "")
new_name += ", ";
new_name += this.operator_name_cdma;
}
this.operator_name = newName;
this.operator_name = new_name;
this.emit('notify::operator-name');
}

View File

@@ -77,51 +77,54 @@ var ObjectManager = class {
let info = this._interfaceInfos[interfaceName];
if (!info) {
if (onFinished)
onFinished();
return;
if (onFinished)
onFinished();
return;
}
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
try {
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
(initable, result) => {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize proxy for interface ' + interfaceName);
if (onFinished)
onFinished();
return;
}
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
if (onFinished)
onFinished();
});
}
@@ -152,10 +155,11 @@ var ObjectManager = class {
}
_onManagerProxyLoaded(initable, result) {
let error = null;
try {
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`);
} catch(e) {
logError(e, 'could not initialize object manager for object ' + this._serviceName);
this._tryToCompleteLoad();
return;
@@ -193,7 +197,7 @@ var ObjectManager = class {
this._managerProxy.GetManagedObjectsRemote((result, error) => {
if (!result) {
if (error) {
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
}
this._tryToCompleteLoad();

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported parse */
// parse:
// @params: caller-provided parameter object, or %null
@@ -15,13 +14,22 @@
//
// Return value: a new object, containing the merged parameters from
// @params and @defaults
function parse(params = {}, defaults, allowExtras) {
if (!allowExtras) {
for (let prop in params)
if (!(prop in defaults))
throw new Error(`Unrecognized parameter "${prop}"`);
function parse(params, defaults, allowExtras) {
let ret = {}, prop;
if (!params)
params = {};
for (prop in params) {
if (!(prop in defaults) && !allowExtras)
throw new Error('Unrecognized parameter "' + prop + '"');
ret[prop] = params[prop];
}
let defaultsCopy = Object.assign({}, defaults);
return Object.assign(defaultsCopy, params);
}
for (prop in defaults) {
if (!(prop in params))
ret[prop] = defaults[prop];
}
return ret;
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PermissionStore */
const Gio = imports.gi.Gio;
@@ -13,4 +12,4 @@ function PermissionStore(initCallback, cancellable) {
'org.freedesktop.impl.portal.PermissionStore',
'/org/freedesktop/impl/portal/PermissionStore',
initCallback, cancellable);
}
};

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getSmartcardManager */
const Gio = imports.gi.Gio;
const Signals = imports.signals;
@@ -30,7 +29,7 @@ var SmartcardManager = class {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
knownInterfaces: [SmartcardTokenIface],
knownInterfaces: [ SmartcardTokenIface ],
onLoaded: this._onLoaded.bind(this) });
this._insertedTokens = {};
this._loginToken = null;

View File

@@ -1,4 +1,3 @@
/* exported getDefault */
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
@@ -84,54 +83,48 @@ const SystemActions = GObject.registerClass({
this._canHaveSuspend = true;
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID, {
// Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown;reboot;restart").split(/[; ]/),
available: false
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
// Translators: The name of the lock screen action in search
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/),
available: false
});
this._actions.set(LOGOUT_ACTION_ID, {
// Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false
});
this._actions.set(SUSPEND_ACTION_ID, {
// Translators: The name of the suspend action in search
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
available: false
});
this._actions.set(SWITCH_USER_ACTION_ID, {
// Translators: The name of the switch user action in search
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/),
available: false
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
// Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock Orientation"),
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
available: false
});
this._actions.set(POWER_OFF_ACTION_ID,
{ // Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown;reboot;restart").split(/[; ]/),
available: false });
this._actions.set(LOCK_SCREEN_ACTION_ID,
{ // Translators: The name of the lock screen action in search
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/),
available: false });
this._actions.set(LOGOUT_ACTION_ID,
{ // Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false });
this._actions.set(SUSPEND_ACTION_ID,
{ // Translators: The name of the suspend action in search
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
available: false });
this._actions.set(SWITCH_USER_ACTION_ID,
{ // Translators: The name of the switch user action in search
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/),
available: false });
this._actions.set(LOCK_ORIENTATION_ACTION_ID,
{ // Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock Orientation"),
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
available: false });
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
@@ -144,96 +137,92 @@ const SystemActions = GObject.registerClass({
this._userManager = AccountsService.UserManager.get_default();
this._userManager.connect('notify::is-loaded',
() => this._updateMultiUser());
() => { this._updateMultiUser(); });
this._userManager.connect('notify::has-multiple-users',
() => this._updateMultiUser());
() => { this._updateMultiUser(); });
this._userManager.connect('user-added',
() => this._updateMultiUser());
() => { this._updateMultiUser(); });
this._userManager.connect('user-removed',
() => this._updateMultiUser());
() => { this._updateMultiUser(); });
this._lockdownSettings.connect(`changed::${DISABLE_USER_SWITCH_KEY}`,
() => this._updateSwitchUser());
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
() => this._updateLogout());
global.settings.connect(`changed::${ALWAYS_SHOW_LOG_OUT_KEY}`,
() => this._updateLogout());
this._lockdownSettings.connect('changed::' + DISABLE_USER_SWITCH_KEY,
() => { this._updateSwitchUser(); });
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => { this._updateLogout(); });
global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
() => { this._updateLogout(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOCK_SCREEN_KEY}`,
() => this._updateLockScreen());
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
() => { this._updateLockScreen(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
() => this._updateHaveShutdown());
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => { this._updateHaveShutdown(); });
this.forceUpdate();
this._orientationSettings.connect('changed::orientation-lock',
() => {
this._updateOrientationLock();
this._updateOrientationLockIcon();
});
() => { this._updateOrientationLock();
this._updateOrientationLockIcon(); });
Main.layoutManager.connect('monitors-changed',
() => this._updateOrientationLock());
this._sensorProxy = new SensorProxy(Gio.DBus.system,
SENSOR_BUS_NAME,
SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error)
log(error.message);
},
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(); });
Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
Gio.BusNameWatcherFlags.NONE,
() => { this._sensorProxyAppeared(); },
() => {
this._sensorProxy = null;
this._updateOrientationLock();
});
this._updateOrientationLock();
this._updateOrientationLockIcon();
Main.sessionMode.connect('updated', () => this._sessionUpdated());
Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
this._sessionUpdated();
}
// eslint-disable-next-line camelcase
get can_power_off() {
return this._actions.get(POWER_OFF_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_lock_screen() {
return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_switch_user() {
return this._actions.get(SWITCH_USER_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_lock_orientation() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get orientation_lock_icon() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
}
_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() {
let available = false;
if (this._sensorProxy.g_name_owner)
if (this._sensorProxy)
available = this._sensorProxy.HasAccelerometer &&
this._monitorManager.get_is_builtin_display_on();
@@ -268,11 +257,11 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map((term) => term.toLowerCase());
terms = terms.map((term) => { return term.toLowerCase(); });
let results = [];
for (let [key, { available, keywords }] of this._actions)
for (let [key, {available, keywords}] of this._actions)
if (available && terms.every(t => keywords.some(k => k.startsWith(t))))
results.push(key);
@@ -289,24 +278,24 @@ const SystemActions = GObject.registerClass({
activateAction(id) {
switch (id) {
case POWER_OFF_ACTION_ID:
this.activatePowerOff();
break;
case LOCK_SCREEN_ACTION_ID:
this.activateLockScreen();
break;
case LOGOUT_ACTION_ID:
this.activateLogout();
break;
case SUSPEND_ACTION_ID:
this.activateSuspend();
break;
case SWITCH_USER_ACTION_ID:
this.activateSwitchUser();
break;
case LOCK_ORIENTATION_ACTION_ID:
this.activateLockOrientation();
break;
case POWER_OFF_ACTION_ID:
this.activatePowerOff();
break;
case LOCK_SCREEN_ACTION_ID:
this.activateLockScreen();
break;
case LOGOUT_ACTION_ID:
this.activateLogout();
break;
case SUSPEND_ACTION_ID:
this.activateSuspend();
break;
case SWITCH_USER_ACTION_ID:
this.activateSwitchUser();
break;
case LOCK_ORIENTATION_ACTION_ID:
this.activateLockOrientation();
break;
}
}

View File

@@ -1,16 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Params = imports.misc.params;
var SCROLL_TIME = 100;
var SCROLL_TIME = 0.1;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)';
@@ -18,7 +17,7 @@ const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _urlRegexp = new RegExp(
`(^|${_leadingJunk})` +
'(^|' + _leadingJunk + ')' +
'(' +
'(?:' +
'(?:http|https|ftp)://' + // scheme://
@@ -30,12 +29,12 @@ const _urlRegexp = new RegExp(
'(?:' + // one or more:
'[^\\s()<>]+' + // run of non-space non-()
'|' + // or
`${_balancedParens}` + // balanced parens
_balancedParens + // balanced parens
')+' +
'(?:' + // end with:
`${_balancedParens}` + // balanced parens
_balancedParens + // balanced parens
'|' + // or
`${_notTrailingJunk}` + // last non-junk char
_notTrailingJunk + // last non-junk char
')' +
')', 'gi');
@@ -70,16 +69,16 @@ function spawn(argv) {
}
// spawnCommandLine:
// @commandLine: a command line
// @command_line: a command line
//
// Runs @commandLine in the background, handling any errors that
// Runs @command_line in the background, handling any errors that
// occur when trying to parse or start the program.
function spawnCommandLine(commandLine) {
function spawnCommandLine(command_line) {
try {
let [success_, argv] = GLib.shell_parse_argv(commandLine);
let [success, argv] = GLib.shell_parse_argv(command_line);
trySpawn(argv);
} catch (err) {
_handleSpawnError(commandLine, err);
_handleSpawnError(command_line, err);
}
}
@@ -94,7 +93,7 @@ function spawnApp(argv) {
let context = global.create_app_launch_context(0, -1);
app.launch([], context);
} catch (err) {
} catch(err) {
_handleSpawnError(argv[0], err);
}
}
@@ -104,12 +103,13 @@ function spawnApp(argv) {
//
// Runs @argv in the background. If launching @argv fails,
// this will throw an error.
function trySpawn(argv) {
var success_, pid;
function trySpawn(argv)
{
var success, pid;
try {
[success_, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
[success, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
} catch (err) {
/* Rewrite the error in case of ENOENT */
if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) {
@@ -135,19 +135,19 @@ function trySpawn(argv) {
}
// trySpawnCommandLine:
// @commandLine: a command line
// @command_line: a command line
//
// Runs @commandLine in the background. If launching @commandLine
// Runs @command_line in the background. If launching @command_line
// fails, this will throw an error.
function trySpawnCommandLine(commandLine) {
let success_, argv;
function trySpawnCommandLine(command_line) {
let success, argv;
try {
[success_, argv] = GLib.shell_parse_argv(commandLine);
[success, argv] = GLib.shell_parse_argv(command_line);
} catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer
err.message = err.message.replace(/[^:]*: /, `${_("Could not parse command:")}\n`);
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
throw err;
}
@@ -222,7 +222,7 @@ function formatTime(time, params) {
/* Translators: Time in 24h format */
format = N_("%H\u2236%M");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo < 2)
else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format
@@ -251,7 +251,7 @@ function formatTime(time, params) {
/* Translators: Time in 12h format */
format = N_("%l\u2236%M %p");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo < 2)
else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format
@@ -289,7 +289,7 @@ function createTimeLabel(date, params) {
let id = _desktopSettings.connect('changed::clock-format', () => {
label.text = formatTime(date, params);
});
label.connect('destroy', () => _desktopSettings.disconnect(id));
label.connect('destroy', () => { _desktopSettings.disconnect(id); });
return label;
}
@@ -346,7 +346,7 @@ function insertSorted(array, val, cmp) {
var CloseButton = GObject.registerClass(
class CloseButton extends St.Button {
_init(boxpointer) {
super._init({ style_class: 'notification-close' });
super._init({ style_class: 'notification-close'});
// This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for
@@ -380,7 +380,7 @@ class CloseButton extends St.Button {
let themeNode = this.get_theme_node();
let offY = this._computeBoxPointerOffset();
this.translation_x = themeNode.get_length('-shell-close-overlap-x');
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
}
@@ -396,7 +396,7 @@ function makeCloseButton(boxpointer) {
function ensureActorVisibleInScrollView(scrollView, actor) {
let adjustment = scrollView.vscroll.adjustment;
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let offset = 0;
let vfade = scrollView.get_effect("fade");
@@ -424,8 +424,97 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
else
return;
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SCROLL_TIME
});
Tweener.addTween(adjustment,
{ value: value,
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 -*-
const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
const { Geoclue, Gio, GLib, GWeather } = imports.gi;
const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore;
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';
const Util = imports.misc.util;
// Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@@ -35,7 +26,7 @@ var WeatherClient = class {
this._weatherAuthorized = false;
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) {
log(`Failed to connect to permissionStore: ${error.message}`);
log('Failed to connect to permissionStore: ' + error.message);
return;
}
@@ -49,7 +40,7 @@ var WeatherClient = class {
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error)
log(`Error looking up permission: ${error.message}`);
log('Error looking up permission: ' + error.message);
let [perms, data] = error ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms];
@@ -75,38 +66,17 @@ var WeatherClient = class {
this.emit('changed');
});
this._weatherApp = null;
this._weatherProxy = null;
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather'
});
this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._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();
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
'org.gnome.Weather');
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
this._weatherAppMon.watchSetting('automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations',
this._onLocationsChanged.bind(this));
}
get available() {
return this._weatherApp != null;
return this._weatherAppMon.available;
}
get loading() {
@@ -122,8 +92,7 @@ var WeatherClient = class {
}
activateApp() {
if (this._weatherApp)
this._weatherApp.activate();
this._weatherAppMon.activateApp();
}
update() {
@@ -145,38 +114,6 @@ var WeatherClient = class {
this._weatherAuthorized;
}
_onWeatherProxyReady(o, res) {
try {
this._weatherProxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
}
this._weatherProxy.connect('g-properties-changed',
this._onWeatherPropertiesChanged.bind(this));
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() {
let id = this._weatherInfo.connect('updated', () => {
this._weatherInfo.disconnect(id);
@@ -241,8 +178,8 @@ var WeatherClient = class {
(o, res) => {
try {
this._gclueService = Geoclue.Simple.new_finish(res);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
} catch(e) {
log('Failed to connect to Geoclue2 service: ' + e.message);
this._setLocation(this._mostRecentLocation);
return;
}
@@ -261,8 +198,8 @@ var WeatherClient = class {
this._setLocation(location);
}
_onAutomaticLocationChanged() {
let useAutoLocation = this._settings.get_boolean('automatic-location');
_onAutomaticLocationChanged(settings, key) {
let useAutoLocation = settings.get_boolean(key);
if (this._autoLocationRequested == useAutoLocation)
return;
@@ -280,9 +217,8 @@ var WeatherClient = class {
this._setLocation(this._mostRecentLocation);
}
_onLocationsChanged() {
let locations = this._settings.get_value('locations').deep_unpack();
let serialized = locations.shift();
_onLocationsChanged(settings, key) {
let serialized = settings.get_value(key).deep_unpack().shift();
let mostRecentLocation = null;
if (serialized)
@@ -298,7 +234,7 @@ var WeatherClient = class {
}
_onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted_, data_, perms] = params;
let [table, id, deleted, data, perms] = params;
if (table != 'gnome' || id != 'geolocation')
return;

View File

@@ -1,9 +1,4 @@
// -*- 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;
@@ -24,7 +19,7 @@ var METRICS = {
units: "frames / s" },
overviewLatencySubsequent:
{ description: "Time to first frame after triggering overview, second time",
units: "us" },
units: "us"},
overviewFpsSubsequent:
{ description: "Frames rate when going to the overview, second time",
units: "frames / s" },
@@ -57,7 +52,7 @@ var METRICS = {
units: "us" },
applicationsShowTimeSubsequent:
{ description: "Time to switch to applications view, second time",
units: "us" }
units: "us"}
};
let WINDOW_CONFIGS = [
@@ -126,11 +121,9 @@ function *run() {
for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = false;
yield Scripting.waitLeisure();
}
@@ -143,6 +136,7 @@ let overviewFrames;
let overviewLatency;
let mallocUsedSize = 0;
let overviewShowCount = 0;
let firstOverviewUsedSize;
let haveSwapComplete = false;
let applicationsShowStart;
let applicationsShowCount = 0;
@@ -154,7 +148,7 @@ function script_overviewShowStart(time) {
overviewFrames = 0;
}
function script_overviewShowDone(_time) {
function script_overviewShowDone(time) {
// We've set up the state at the end of the zoom out, but we
// need to wait for one more frame to paint before we count
// ourselves as done.
@@ -173,7 +167,7 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
}
function script_afterShowHide(_time) {
function script_afterShowHide(time) {
if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize;
} else {

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 Main = imports.ui.main;
const Scripting = imports.ui.scripting;
@@ -39,7 +30,7 @@ var METRICS = {
geditStartTime:
{ description: "Time from gedit launch to window drawn",
units: "us" },
};
}
function waitAndDraw(milliseconds) {
let cb;
@@ -47,7 +38,7 @@ function waitAndDraw(milliseconds) {
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame', (_timeline, _frame) => {
timeline.connect('new-frame', (timeline, frame) => {
global.stage.queue_redraw();
});
@@ -57,7 +48,7 @@ function waitAndDraw(milliseconds) {
cb();
});
return callback => cb = callback;
return callback => { cb = callback; };
}
function waitSignal(object, signal) {
@@ -69,7 +60,7 @@ function waitSignal(object, signal) {
cb();
});
return callback => cb = callback;
return callback => { cb = callback; };
}
function extractBootTimestamp() {
@@ -82,8 +73,8 @@ function extractBootTimestamp() {
let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) { // eslint-disable-line no-constant-condition
let [line, length_] = datastream.read_line_utf8(null);
while (true) {
let [line, length] = datastream.read_line_utf8(null);
if (line === null)
break;
@@ -126,7 +117,6 @@ function *run() {
yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
@@ -167,7 +157,7 @@ function *run() {
Main.overview.hide();
yield Scripting.createTestWindow({ maximized: true,
redraws: true });
redraws: true});
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
@@ -244,31 +234,31 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart;
}
function script_mainViewDrawStart(_time) {
function script_mainViewDrawStart(time) {
redrawTiming = 'mainView';
}
function script_mainViewDrawDone(_time) {
function script_mainViewDrawDone(time) {
redrawTiming = null;
}
function script_overviewDrawStart(_time) {
function script_overviewDrawStart(time) {
redrawTiming = 'overview';
}
function script_overviewDrawDone(_time) {
function script_overviewDrawDone(time) {
redrawTiming = null;
}
function script_redrawTestStart(_time) {
function script_redrawTestStart(time) {
redrawTiming = 'application';
}
function script_redrawTestDone(_time) {
function script_redrawTestDone(time) {
redrawTiming = null;
}
function script_collectTimings(_time) {
function script_collectTimings(time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort((a, b) => a - b);
@@ -279,11 +269,11 @@ function script_collectTimings(_time) {
if (len == 0)
median = -1;
else if (len % 2 == 1)
median = times[(len - 1) / 2];
median = times[(len - 1)/ 2];
else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[`${timing}RedrawTime`].value = median;
METRICS[timing + 'RedrawTime'].value = median;
}
}

View File

@@ -1,4 +1,3 @@
/* exported main */
const Format = imports.format;
const Gettext = imports.gettext;
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi;
@@ -20,6 +19,7 @@ const PortalHelperSecurityLevel = {
INSECURE: 2
};
const INACTIVITY_TIMEOUT = 30000; //ms
const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
@@ -59,7 +59,7 @@ class PortalHeaderBar extends Gtk.HeaderBar {
single_line_mode: true,
ellipsize: Pango.EllipsizeMode.END,
valign: Gtk.Align.BASELINE,
selectable: true });
selectable: true});
this.subtitleLabel.get_style_context().add_class('subtitle');
hbox.add(this.subtitleLabel);
@@ -152,7 +152,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._webView.load_uri(this._originalUrl);
}
vfunc_delete_event(_event) {
vfunc_delete_event(event) {
if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK);
else
@@ -178,7 +178,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
}
_onLoadFailedWithTlsErrors(view, failingURI, certificate, _errors) {
_onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
let uri = new Soup.URI(failingURI);
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
@@ -265,7 +265,7 @@ class WebPortalHelper extends Gtk.Application {
this._queue = [];
let action = new Gio.SimpleAction({ name: 'quit' });
action.connect('activate', () => this.active_window.destroyWindow());
action.connect('activate', () => { this.active_window.destroyWindow(); });
this.add_action(action);
}

View File

@@ -1,4 +1,3 @@
/* exported AccessDialogDBus */
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi;
const CheckBox = imports.ui.checkBox;
@@ -70,7 +69,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this.addButton({ label: grantLabel,
action: () => {
this._sendResponse(DialogResponse.OK);
} });
}});
}
open() {
@@ -80,7 +79,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this._requestExported = this._request.export(connection, this._handle);
}
CloseAsync(invocation, _params) {
CloseAsync(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
@@ -133,10 +132,10 @@ var AccessDialogDBus = class {
return;
}
let [handle, appId, parentWindow_, title, subtitle, body, options] = params;
let [handle, appId, parentWindow, title, subtitle, body, options] = params;
// We probably want to use parentWindow and global.display.focus_window
// for this check in the future
if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) {
if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'Only the focused app is allowed to show a system access dialog');
@@ -147,7 +146,7 @@ var AccessDialogDBus = class {
subtitle, body, options);
dialog.open();
dialog.connect('closed', () => this._accessDialog = null);
dialog.connect('closed', () => { this._accessDialog = null; });
this._accessDialog = dialog;
}

View File

@@ -1,18 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AppSwitcherPopup, GroupCyclerPopup, WindowSwitcherPopup,
WindowCyclerPopup */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
const Tweener = imports.ui.tweener;
var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
var THUMBNAIL_DEFAULT_SIZE = 256;
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 APP_ICON_SIZE = 96;
@@ -37,7 +36,7 @@ function _createWindowClone(window, size) {
// usual hack for the usual bug in ClutterBinLayout...
x_expand: true,
y_expand: true });
}
};
function getWindows(workspace) {
// We ignore skip-taskbar windows in switchers, but if they are attached
@@ -88,9 +87,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let hPadding = leftPadding + rightPadding;
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 [, 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));
if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) {
let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding;
@@ -104,7 +103,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
childBox.x2 = primary.x + primary.width - rightPadding;
childBox.y1 = this._switcherList.allocation.y2 + spacing;
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags);
}
@@ -361,15 +360,15 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_destroyThumbnails() {
let thumbnailsActor = this._thumbnails;
this._thumbnails.ease({
opacity: 0,
duration: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
}
});
Tweener.addTween(thumbnailsActor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
}
});
this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex])
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.opacity = 0;
this._thumbnails.ease({
opacity: 255,
duration: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.thumbnailsVisible = true;
}
});
Tweener.addTween(this._thumbnails,
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => { this.thumbnailsVisible = true; }
});
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
}
@@ -462,7 +459,7 @@ class CyclerHighlight {
_onDestroy() {
this.window = null;
}
}
};
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
@@ -472,7 +469,7 @@ var CyclerList = GObject.registerClass({
'item-removed': { param_types: [GObject.TYPE_INT] },
'item-highlighted': { param_types: [GObject.TYPE_INT] } },
}, class CyclerList extends St.Widget {
highlight(index, _justOutline) {
highlight(index, justOutline) {
this.emit('item-highlighted', index);
}
});
@@ -497,7 +494,7 @@ var CyclerPopup = GObject.registerClass({
});
}
_highlightItem(index, _justOutline) {
_highlightItem(index, justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null);
}
@@ -663,10 +660,17 @@ class AppIcon extends St.BoxLayout {
this.add(this.label, { x_fill: false });
}
// eslint-disable-next-line camelcase
set_size(size) {
this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon;
this._iconBin.set_size(size, size);
}
vfunc_get_preferred_width(forHeight) {
let [minWidth, ] = super.vfunc_get_preferred_width(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
}
});
@@ -720,16 +724,15 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_setIconSize() {
let j = 0;
while (this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++;
while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++;
}
let themeNode = this._items[j].get_theme_node();
this._list.ensure_style();
let iconPadding = themeNode.get_horizontal_padding();
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = labelNaturalHeight + iconPadding + iconBorder;
let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = iconNaturalHeight + iconPadding + iconBorder;
let totalSpacing = this._list.spacing * (this._items.length - 1);
// We just assume the whole screen here due to weirdness happing with the passed width
@@ -742,7 +745,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
let iconSize = baseIconSizes[0];
if (this._items.length > 1) {
for (let i = 0; i < baseIconSizes.length; i++) {
for(let i = 0; i < baseIconSizes.length; i++) {
iconSize = baseIconSizes[i];
let height = iconSizes[i] + iconSpacing;
let w = height * this._items.length + totalSpacing;
@@ -753,7 +756,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._iconSize = iconSize;
for (let i = 0; i < this.icons.length; i++) {
for(let i = 0; i < this.icons.length; i++) {
if (this.icons[i].icon != null)
break;
this.icons[i].set_size(iconSize);
@@ -799,13 +802,12 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else {
this._itemEntered(index);
}
} else
this._itemEntered(index);
}
_enterItem(index) {
let [x, y] = global.get_pointer();
let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor))
this._itemEntered(index);
@@ -846,8 +848,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._removeIcon(app);
});
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM));
arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
this.add_actor(arrow);
this._arrows.push(arrow);
@@ -912,7 +915,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding();
totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding();
let [, 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 scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;
@@ -988,23 +991,23 @@ class WindowIcon extends St.BoxLayout {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
switch (mode) {
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
break;
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
break;
case AppIconMode.BOTH:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
case AppIconMode.BOTH:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL));
break;
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL));
break;
case AppIconMode.APP_ICON_ONLY:
size = APP_ICON_SIZE;
this._icon.add_actor(this._createAppIcon(this.app, size));
case AppIconMode.APP_ICON_ONLY:
size = APP_ICON_SIZE;
this._icon.add_actor(this._createAppIcon(this.app, size));
}
this._icon.set_size(size * scaleFactor, size * scaleFactor);
@@ -1041,7 +1044,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
this._removeWindow(window);
this._removeWindow(window)
});
}
@@ -1077,7 +1080,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM)
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;

View File

@@ -1,12 +1,13 @@
// -*- 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 SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = class {
constructor(file, width, height, speed) {
@@ -61,11 +62,11 @@ var Animation = class {
if (!validResourceScale)
return;
let textureCache = St.TextureCache.get_default();
let texture_cache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this._animations = texture_cache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
}
@@ -122,7 +123,7 @@ var AnimatedIcon = class extends Animation {
};
var Spinner = class extends AnimatedIcon {
constructor(size, animate = false) {
constructor(size, animate=false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size);
@@ -136,15 +137,15 @@ var Spinner = class extends AnimatedIcon {
}
play() {
this.actor.remove_all_transitions();
Tweener.removeTweens(this.actor);
if (this._animate) {
super.play();
this.actor.ease({
Tweener.addTween(this.actor, {
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR
time: SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
this.actor.opacity = 255;
@@ -153,14 +154,16 @@ var Spinner = class extends AnimatedIcon {
}
stop() {
this.actor.remove_all_transitions();
Tweener.removeTweens(this.actor);
if (this._animate) {
this.actor.ease({
Tweener.addTween(this.actor, {
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => super.stop()
onComplete: () => {
this.stop(false);
}
});
} else {
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 -*-
/* exported getAppFavorites */
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@@ -64,7 +63,7 @@ class AppFavorites {
constructor() {
this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {};
global.settings.connect(`changed::${this.FAVORITE_APPS_KEY}`, this._onFavsChanged.bind(this));
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
this.reload();
}
@@ -188,7 +187,7 @@ class AppFavorites {
}
});
}
}
};
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;

View File

@@ -1,4 +1,3 @@
/* exported AudioDeviceSelectionDBus */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
@@ -35,7 +34,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
throw new Error('Too few devices for a selection');
}
_buildLayout() {
_buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER });
@@ -55,28 +54,28 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
}
_getDeviceLabel(device) {
switch (device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
case AudioDevice.HEADSET:
return _("Headset");
case AudioDevice.MICROPHONE:
return _("Microphone");
default:
return null;
switch(device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
case AudioDevice.HEADSET:
return _("Headset");
case AudioDevice.MICROPHONE:
return _("Microphone");
default:
return null;
}
}
_getDeviceIcon(device) {
switch (device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
case AudioDevice.HEADSET:
return 'audio-headset-symbolic';
case AudioDevice.MICROPHONE:
return 'audio-input-microphone-symbolic';
default:
return null;
switch(device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
case AudioDevice.HEADSET:
return 'audio-headset-symbolic';
case AudioDevice.MICROPHONE:
return 'audio-input-microphone-symbolic';
default:
return null;
}
}
@@ -86,7 +85,6 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
box.connect('notify::height', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
box.width = box.height;
return GLib.SOURCE_REMOVE;
});
});
@@ -112,11 +110,11 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
}
_openSettings() {
let desktopFile = 'gnome-sound-panel.desktop';
let desktopFile = 'gnome-sound-panel.desktop'
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
if (!app) {
log(`Settings panel for desktop file ${desktopFile} could not be loaded!`);
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
return;
}
@@ -161,12 +159,12 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
deviceNames.forEach(n => { devices |= AudioDevice[n.toUpperCase()]; });
let dialog;
try {
dialog = new AudioDeviceSelectionDialog(devices);
} catch (e) {
} catch(e) {
invocation.return_value(null);
return;
}

View File

@@ -99,6 +99,7 @@ const Signals = imports.signals;
const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
@@ -107,9 +108,10 @@ const PRIMARY_COLOR_KEY = 'primary-color';
const SECONDARY_COLOR_KEY = 'secondary-color';
const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_OPACITY_KEY = 'picture-opacity';
const PICTURE_URI_KEY = 'picture-uri';
var FADE_ANIMATION_TIME = 1000;
var FADE_ANIMATION_TIME = 1.0;
// These parameters affect how often we redraw.
// The first is how different (percent crossfaded) the slide show
@@ -332,12 +334,12 @@ var Background = class Background {
}
_loadPattern() {
let colorString, res_, color, secondColor;
let colorString, res, color, secondColor;
colorString = this._settings.get_string(PRIMARY_COLOR_KEY);
[res_, color] = Clutter.Color.from_string(colorString);
[res, color] = Clutter.Color.from_string(colorString);
colorString = this._settings.get_string(SECONDARY_COLOR_KEY);
[res_, secondColor] = Clutter.Color.from_string(colorString);
[res, secondColor] = Clutter.Color.from_string(colorString);
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
@@ -431,12 +433,12 @@ var Background = class Background {
return;
this._updateAnimationTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
interval,
() => {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
});
interval,
() => {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
}
@@ -463,9 +465,9 @@ var Background = class Background {
let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file);
if (image.is_loaded()) {
if (image.is_loaded())
this._setLoaded();
} else {
else {
let id = image.connect('loaded', () => {
this._setLoaded();
image.disconnect(id);
@@ -632,9 +634,9 @@ var Animation = class Animation {
}
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;
if (callback)
callback();
@@ -650,7 +652,7 @@ var Animation = class Animation {
if (this._show.get_num_slides() < 1)
return;
let [progress, duration, isFixed_, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
let [progress, duration, isFixed, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
this.transitionDuration = duration;
this.transitionProgress = progress;
@@ -709,12 +711,14 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = null;
this.emit('changed');
oldBackgroundActor.ease({
opacity: 0,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => oldBackgroundActor.destroy()
});
Tweener.addTween(oldBackgroundActor,
{ opacity: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
oldBackgroundActor.destroy();
}
});
}
_updateBackgroundActor() {

View File

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

View File

@@ -1,106 +1,74 @@
/* -*- 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({
Properties: {
'value': GObject.ParamSpec.double(
'value', 'value', 'value',
GObject.ParamFlags.READWRITE,
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) {
var BarLevel = class {
constructor(value, params) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
this._maxValue = 1;
this._value = 0;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this._overdriveStart = 1;
this._barLevelWidth = 0;
let defaultParams = {
style_class: 'barlevel',
accessible_role: Atk.Role.LEVEL_BAR
};
super._init(Object.assign(defaultParams, params));
this.connect('allocation-changed', (actor, box) => {
if (params == undefined)
params = {}
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false,
reactive: params['reactive'] || false,
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this);
this.set_accessible(this._customAccessible);
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.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('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() {
return this._value;
setValue(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) {
value = Math.max(Math.min(value, this._maxValue), 0);
setMaximumValue(value) {
if (isNaN(value))
throw TypeError('The bar level max value must be a number');
if (this._value == value)
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._maxValue = Math.max(value, 1);
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.notify('maximum-value');
this.queue_repaint();
this.actor.queue_repaint();
}
// eslint-disable-next-line camelcase
get overdrive_start() {
return this._overdriveStart;
}
// eslint-disable-next-line camelcase
set overdrive_start(value) {
if (this._overdriveStart == value)
return;
setOverdriveStart(value) {
if (isNaN(value))
throw TypeError('The overdrive limit value must be a number');
if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`);
this._overdriveStart = value;
this.notify('overdrive-start');
this.queue_repaint();
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
}
vfunc_repaint() {
let cr = this.get_context();
let themeNode = this.get_theme_node();
let [width, height] = this.get_surface_size();
_barLevelRepaint(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
@@ -137,7 +105,7 @@ var BarLevel = GObject.registerClass({
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
/* background bar */
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
@@ -149,12 +117,12 @@ var BarLevel = GObject.registerClass({
/* normal progress bar */
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (1 / 4), TAU * (3 / 4));
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
cr.lineTo(x, (height - barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
if (this._value > 0)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
@@ -177,17 +145,17 @@ var BarLevel = GObject.registerClass({
/* end progress bar arc */
if (this._value > 0) {
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
}
/* draw overdrive separator */
@@ -207,27 +175,32 @@ var BarLevel = GObject.registerClass({
cr.$dispose();
}
_getCurrentValue() {
_getCurrentValue(actor) {
return this._value;
}
_getOverdriveStart() {
_getOverdriveStart(actor) {
return this._overdriveStart;
}
_getMinimumValue() {
_getMinimumValue(actor) {
return 0;
}
_getMaximumValue() {
_getMaximumValue(actor) {
return this._maxValue;
}
_setCurrentValue(_actor, value) {
_setCurrentValue(actor, value) {
this._value = value;
}
_valueChanged() {
_valueChanged(barLevel, value, property) {
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 -*-
/* exported BoxPointer */
const { Clutter, GObject, Shell, St } = imports.gi;
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var PopupAnimation = {
NONE: 0,
@@ -12,7 +12,7 @@ var PopupAnimation = {
FULL: ~0,
};
var POPUP_ANIMATION_TIME = 150;
var POPUP_ANIMATION_TIME = 0.15;
/**
* BoxPointer:
@@ -90,33 +90,31 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
this.translation_y = -rise;
break;
case St.Side.BOTTOM:
this.translation_y = rise;
break;
case St.Side.LEFT:
this.translation_x = -rise;
break;
case St.Side.RIGHT:
this.translation_x = rise;
break;
case St.Side.TOP:
this.translation_y = -rise;
break;
case St.Side.BOTTOM:
this.translation_y = rise;
break;
case St.Side.LEFT:
this.translation_x = -rise;
break;
case St.Side.RIGHT:
this.translation_x = rise;
break;
}
}
this.ease({
opacity: 255,
translation_x: 0,
translation_y: 0,
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._unmuteInput();
if (onComplete)
onComplete();
}
});
Tweener.addTween(this, { opacity: 255,
translation_x: 0,
translation_y: 0,
transition: 'linear',
onComplete: () => {
this._unmuteInput();
if (onComplete)
onComplete();
},
time: animationTime });
}
close(animate, onComplete) {
@@ -132,39 +130,38 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
translationY = rise;
break;
case St.Side.BOTTOM:
translationY = -rise;
break;
case St.Side.LEFT:
translationX = rise;
break;
case St.Side.RIGHT:
translationX = -rise;
break;
case St.Side.TOP:
translationY = rise;
break;
case St.Side.BOTTOM:
translationY = -rise;
break;
case St.Side.LEFT:
translationX = rise;
break;
case St.Side.RIGHT:
translationX = -rise;
break;
}
}
this._muteInput();
this.remove_all_transitions();
this.ease({
opacity: fade ? 0 : 255,
translation_x: translationX,
translation_y: translationY,
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this.hide();
this.opacity = 0;
this.translation_x = 0;
this.translation_y = 0;
if (onComplete)
onComplete();
}
});
Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255,
translation_x: translationX,
translation_y: translationY,
transition: 'linear',
time: animationTime,
onComplete: () => {
this.hide();
this.opacity = 0;
this.translation_x = 0;
this.translation_y = 0;
if (onComplete)
onComplete();
}
});
}
_adjustAllocationForArrow(isWidth, minSize, natSize) {
@@ -223,18 +220,18 @@ var BoxPointer = GObject.registerClass({
childBox.x2 = availWidth - borderWidth;
childBox.y2 = availHeight - borderWidth;
switch (this._arrowSide) {
case St.Side.TOP:
childBox.y1 += rise;
break;
case St.Side.BOTTOM:
childBox.y2 -= rise;
break;
case St.Side.LEFT:
childBox.x1 += rise;
break;
case St.Side.RIGHT:
childBox.x2 -= rise;
break;
case St.Side.TOP:
childBox.y1 += rise;
break;
case St.Side.BOTTOM:
childBox.y2 -= rise;
break;
case St.Side.LEFT:
childBox.x1 += rise;
break;
case St.Side.RIGHT:
childBox.x2 -= rise;
break;
}
this.bin.allocate(childBox, flags);
@@ -267,7 +264,7 @@ var BoxPointer = GObject.registerClass({
let borderRadius = themeNode.get_length('-arrow-border-radius');
let halfBorder = borderWidth / 2;
let halfBase = Math.floor(base / 2);
let halfBase = Math.floor(base/2);
let backgroundColor = themeNode.get_color('-arrow-background-color');
@@ -348,7 +345,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopRight) {
cr.lineTo(x2 - borderRadius, y1);
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
3 * Math.PI / 2, Math.PI * 2);
3*Math.PI/2, Math.PI*2);
}
if (this._arrowSide == St.Side.RIGHT && rise) {
@@ -369,7 +366,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomRight) {
cr.lineTo(x2, y2 - borderRadius);
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
0, Math.PI / 2);
0, Math.PI/2);
}
if (this._arrowSide == St.Side.BOTTOM && rise) {
@@ -390,7 +387,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomLeft) {
cr.lineTo(x1 + borderRadius, y2);
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
Math.PI / 2, Math.PI);
Math.PI/2, Math.PI);
}
if (this._arrowSide == St.Side.LEFT && rise) {
@@ -399,7 +396,7 @@ var BoxPointer = GObject.registerClass({
cr.lineTo(x1 - rise, y1);
cr.lineTo(x1 + borderRadius, y1);
} else if (skipBottomLeft) {
cr.lineTo(x1 - rise, y2);
cr.lineTo(x1 - rise, y2)
cr.lineTo(x1 - rise, y2 - halfBase);
} else {
cr.lineTo(x1, this._arrowOrigin + halfBase);
@@ -411,7 +408,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopLeft) {
cr.lineTo(x1, y1 + borderRadius);
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
Math.PI, 3 * Math.PI / 2);
Math.PI, 3*Math.PI/2);
}
Clutter.cairo_set_source_color(cr, backgroundColor);
@@ -440,7 +437,7 @@ var BoxPointer = GObject.registerClass({
this._sourceActorDestroyId = this._sourceActor.connect('destroy', () => {
this._sourceActor = null;
delete this._sourceActorDestroyId;
});
})
}
}
@@ -472,7 +469,7 @@ var BoxPointer = GObject.registerClass({
let sourceAllocation = this._sourceAllocation;
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [, , 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
// edge by the same distance as the main part of the box is
@@ -516,7 +513,7 @@ var BoxPointer = GObject.registerClass({
// of the box to maintain the arrow's accuracy.
let arrowOrigin;
let halfBase = Math.floor(arrowBase / 2);
let halfBase = Math.floor(arrowBase/2);
let halfBorder = borderWidth / 2;
let halfMargin = margin / 2;
let [x1, y1] = [halfBorder, halfBorder];
@@ -597,7 +594,7 @@ var BoxPointer = GObject.registerClass({
_calculateArrowSide(arrowSide) {
let sourceAllocation = this._sourceAllocation;
let [, , boxWidth, boxHeight] = this.get_preferred_size();
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let workarea = this._workArea;
switch (arrowSide) {

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -18,7 +17,7 @@ var ELLIPSIS_CHAR = '\u2026';
var MESSAGE_ICON_SIZE = -1; // pick up from CSS
var NC_ = (context, str) => `${context}\u0004${str}`;
var NC_ = (context, str) => context + '\u0004' + str;
function sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear());
@@ -39,7 +38,7 @@ function isToday(date) {
function _isWorkDay(date) {
/* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */
let days = C_('calendar-no-work', "06");
return !days.includes(date.getDay().toString());
return days.indexOf(date.getDay().toString()) == -1;
}
function _getBeginningOfDay(date) {
@@ -110,15 +109,15 @@ var EmptyEventSource = class EmptyEventSource {
destroy() {
}
requestRange(_begin, _end) {
requestRange(begin, end) {
}
getEvents(_begin, _end) {
getEvents(begin, end) {
let result = [];
return result;
}
hasEvents(_day) {
hasEvents(day) {
return false;
}
};
@@ -144,7 +143,8 @@ function _datesEqual(a, b) {
return true;
}
function _dateIntervalsOverlap(a0, a1, b0, b1) {
function _dateIntervalsOverlap(a0, a1, b0, b1)
{
if (a1 <= b0)
return false;
else if (b1 <= a0)
@@ -168,7 +168,7 @@ var DBusEventSource = class DBusEventSource {
try {
this._dbusProxy.init_finish(result);
loaded = true;
} catch (e) {
} catch(e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
@@ -178,7 +178,7 @@ var DBusEventSource = class DBusEventSource {
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
log(`Error loading calendars: ${e.message}`);
log('Error loading calendars: ' + e.message);
return;
}
}
@@ -221,13 +221,13 @@ var DBusEventSource = class DBusEventSource {
this._lastRequestEnd = null;
}
_onNameAppeared() {
_onNameAppeared(owner) {
this._initialized = true;
this._resetCache();
this._loadEvents(true);
}
_onNameVanished() {
_onNameVanished(oldOwner) {
this._resetCache();
this.emit('changed');
}
@@ -236,20 +236,22 @@ var DBusEventSource = class DBusEventSource {
this._loadEvents(false);
}
_onEventsReceived(results, _error) {
_onEventsReceived(results, error) {
let newEvents = [];
let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) {
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
let appointments = results ? results[0] : null;
if (appointments != null) {
for (let n = 0; n < appointments.length; n++) {
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
this._events = newEvents;
this.isLoading = false;
@@ -261,7 +263,7 @@ var DBusEventSource = class DBusEventSource {
if (!this._initialized)
return;
if (this._curRequestBegin && this._curRequestEnd) {
if (this._curRequestBegin && this._curRequestEnd){
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
@@ -283,7 +285,7 @@ var DBusEventSource = class DBusEventSource {
getEvents(begin, end) {
let result = [];
for (let n = 0; n < this._events.length; n++) {
for(let n = 0; n < this._events.length; n++) {
let event = this._events[n];
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
@@ -318,7 +320,7 @@ var Calendar = class Calendar {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
this._settings.connect(`changed::${SHOW_WEEKDATE_KEY}`, this._onSettingsChange.bind(this));
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, this._onSettingsChange.bind(this));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
/**
@@ -400,8 +402,8 @@ var Calendar = class Calendar {
this._topBox.add(this._backButton);
this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this));
this._monthLabel = new St.Label({ style_class: 'calendar-month-label',
can_focus: true });
this._monthLabel = new St.Label({style_class: 'calendar-month-label',
can_focus: true });
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward pager-button',
@@ -464,7 +466,8 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
newDate = new Date(newDate.getFullYear() - 1, 11, day);
}
} else {
}
else {
newDate.setMonth(oldMonth - 1);
if (newDate.getMonth() != oldMonth - 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
@@ -487,7 +490,8 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
newDate = new Date(newDate.getFullYear() + 1, 0, day);
}
} else {
}
else {
newDate.setMonth(oldMonth + 1);
if (newDate.getMonth() != oldMonth + 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
@@ -542,6 +546,8 @@ var Calendar = class Calendar {
this._calendarBegin = new Date(beginDate);
this._markedAsToday = now;
let year = beginDate.getYear();
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
let startsOnWeekStart = daysToWeekStart == 0;
let weekPadding = startsOnWeekStart ? 7 : 0;
@@ -553,7 +559,7 @@ var Calendar = class Calendar {
let row = 2;
// nRows here means 6 weeks + one header + one navbar
let nRows = 8;
while (row < nRows) {
while (row < 8) {
// xgettext:no-javascript-format
let button = new St.Button({ label: iter.toLocaleFormat(C_("date day number format", "%d")),
can_focus: true });
@@ -579,12 +585,12 @@ var Calendar = class Calendar {
// Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2)
styleClass = `calendar-day-top ${styleClass}`;
styleClass = 'calendar-day-top ' + styleClass;
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
if (leftMost)
styleClass = `calendar-day-left ${styleClass}`;
styleClass = 'calendar-day-left ' + styleClass;
if (sameDay(now, iter))
styleClass += ' calendar-today';
@@ -642,9 +648,9 @@ var Calendar = class Calendar {
button.add_style_pseudo_class('selected');
if (this._shouldDateGrabFocus)
button.grab_key_focus();
} else {
button.remove_style_pseudo_class('selected');
}
else
button.remove_style_pseudo_class('selected');
});
}
};
@@ -735,7 +741,7 @@ class NotificationMessage extends MessageList.Message {
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
}
_onUpdated(n, _clear) {
_onUpdated(n, clear) {
this.setIcon(this._getIcon());
this.setTitle(n.title);
this.setBody(n.bannerBodyText);
@@ -1071,7 +1077,7 @@ var CalendarMessageList = class CalendarMessageList {
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()];
sections.forEach((s) => s.clear());
sections.forEach((s) => { s.clear(); });
});
box.add_actor(this._clearButton);
@@ -1097,7 +1103,7 @@ var CalendarMessageList = class CalendarMessageList {
_addSection(section) {
let obj = {
destroyId: 0,
visibleId: 0,
visibleId: 0,
emptyChangedId: 0,
canClearChangedId: 0,
keyFocusId: 0

View File

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

View File

@@ -1,17 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var FROZEN_WINDOW_BRIGHTNESS = -0.3;
var DIALOG_TRANSITION_TIME = 150;
var FROZEN_WINDOW_BRIGHTNESS = -0.3
var DIALOG_TRANSITION_TIME = 0.15
var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({
Implements: [Meta.CloseDialog],
Implements: [ Meta.CloseDialog ],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
},
@@ -56,12 +56,12 @@ var CloseDialog = GObject.registerClass({
this._dialog.height = windowActor.height;
this._dialog.addContent(this._createDialogContent());
this._dialog.addButton({ label: _('Force Quit'),
action: this._onClose.bind(this),
this._dialog.addButton({ label: _('Force Quit'),
action: this._onClose.bind(this),
default: true });
this._dialog.addButton({ label: _('Wait'),
this._dialog.addButton({ label: _('Wait'),
action: this._onWait.bind(this),
key: Clutter.Escape });
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
}
@@ -148,12 +148,12 @@ var CloseDialog = GObject.registerClass({
this._dialog.scale_y = 0;
this._dialog.set_pivot_point(0.5, 0.5);
this._dialog.ease({
scale_y: 1,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this)
});
Tweener.addTween(this._dialog,
{ scale_y: 1,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this)
});
}
vfunc_hide() {
@@ -165,7 +165,7 @@ var CloseDialog = GObject.registerClass({
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
global.display.disconnect(this._windowFocusChangedId);
global.display.disconnect(this._windowFocusChangedId)
this._windowFocusChangedId = 0;
global.stage.disconnect(this._keyFocusChangedId);
@@ -175,12 +175,14 @@ var CloseDialog = GObject.registerClass({
this._dialog = null;
this._removeWindowEffect();
dialog.ease({
scale_y: 0,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: () => dialog.destroy()
});
Tweener.addTween(dialog,
{ scale_y: 0,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: () => {
dialog.destroy();
}
});
}
vfunc_focus() {

View File

@@ -1,4 +1,3 @@
/* exported ComponentManager */
const Main = imports.ui.main;
var ComponentManager = class {
@@ -14,13 +13,13 @@ var ComponentManager = class {
let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter(
name => !this._enabledComponents.includes(name)
name => this._enabledComponents.indexOf(name) == -1
).forEach(name => {
this._enableComponent(name);
});
this._enabledComponents.filter(
name => !newEnabledComponents.includes(name)
name => newEnabledComponents.indexOf(name) == -1
).forEach(name => {
this._disableComponent(name);
});
@@ -38,8 +37,8 @@ var ComponentManager = class {
if (component)
return component;
if (Main.sessionMode.isLocked)
return null;
if (Main.sessionMode.isLocked)
return null;
let constructor = this._importComponent(name);
component = new constructor();
@@ -49,7 +48,7 @@ var ComponentManager = class {
_enableComponent(name) {
let component = this._ensureComponent(name);
if (component)
if (component)
component.enable();
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
@@ -56,7 +55,7 @@ var AutomountManager = class {
}
}
_InhibitorsChanged(_object, _senderName, [_inhibitor]) {
_InhibitorsChanged(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
(result, error) => {
if (!error) {
@@ -110,23 +109,25 @@ var AutomountManager = class {
// we force stop/eject in this case, so we don't have to pass a
// mount operation object
if (drive.can_stop()) {
drive.stop(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
log(`Unable to stop the drive after drive-eject-button ${e.toString()}`);
}
});
drive.stop
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
log("Unable to stop the drive after drive-eject-button " + e.toString());
}
});
} else if (drive.can_eject()) {
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
log(`Unable to eject the drive after drive-eject-button ${e.toString()}`);
}
});
drive.eject_with_operation
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
log("Unable to eject the drive after drive-eject-button " + e.toString());
}
});
}
}
@@ -212,7 +213,7 @@ var AutomountManager = class {
}
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log(`Unable to mount volume ${volume.get_name()}: ${e.toString()}`);
log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString());
this._closeOperation(volume);
}
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, St } = imports.gi;
@@ -41,7 +40,7 @@ function isMountRootHidden(root) {
let path = root.get_path();
// skip any mounts in hidden directory hierarchies
return (path.includes('/.'));
return (path.indexOf('/.') != -1);
}
function isMountNonLocal(mount) {
@@ -66,7 +65,8 @@ function startAppForMount(app, mount) {
retval = app.launch(files,
global.create_app_launch_context(0, -1));
} catch (e) {
log(`Unable to launch the application ${app.get_name()}: ${e}`);
log('Unable to launch the application ' + app.get_name()
+ ': ' + e.toString());
}
return retval;
@@ -107,7 +107,8 @@ var ContentTypeDiscoverer = class {
try {
contentTypes = mount.guess_content_type_finish(res);
} catch (e) {
log(`Unable to guess content types on added mount ${mount.get_name()}: ${e}`);
log('Unable to guess content types on added mount ' + mount.get_name()
+ ': ' + e.toString());
}
if (contentTypes.length) {
@@ -123,7 +124,10 @@ var ContentTypeDiscoverer = class {
}
}
_emitCallback(mount, contentTypes = []) {
_emitCallback(mount, contentTypes) {
if (!contentTypes)
contentTypes = [];
// we're not interested in win32 software content types here
contentTypes = contentTypes.filter(
type => (type != 'x-content/win32-software')
@@ -188,15 +192,15 @@ var AutorunDispatcher = class {
_getAutorunSettingForType(contentType) {
let runApp = this._settings.get_strv(SETTING_START_APP);
if (runApp.includes(contentType))
if (runApp.indexOf(contentType) != -1)
return AutorunSetting.RUN;
let ignore = this._settings.get_strv(SETTING_IGNORE);
if (ignore.includes(contentType))
if (ignore.indexOf(contentType) != -1)
return AutorunSetting.IGNORE;
let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER);
if (openFiles.includes(contentType))
if (openFiles.indexOf(contentType) != -1)
return AutorunSetting.FILES;
return AutorunSetting.ASK;

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
@@ -163,7 +162,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
// NOTE: ModalDialog.open() is safe to call if the dialog is
// already open - it just returns true without side-effects
if (this.open())
return true;
return true;
// The above fail if e.g. unable to get input grab
//
@@ -173,25 +172,25 @@ class KeyringDialog extends ModalDialog.ModalDialog {
log('keyringPrompt: Failed to show modal dialog.' +
' Dismissing prompt request');
this.prompt.cancel();
this.prompt.cancel()
return false;
}
_onShowPassword() {
_onShowPassword(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._passwordEntry.grab_key_focus();
}
_onShowConfirm() {
_onShowConfirm(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._continueButton.grab_key_focus();
}
_onHidePrompt() {
_onHidePrompt(prompt) {
this.close();
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -81,9 +80,8 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
secret.valid = secret.value.length > 0;
this._updateOkButton();
});
} else {
} else
secret.valid = true;
}
if (rtl) {
layout.attach(secret.entry, 0, pos, 1, 1);
@@ -107,19 +105,19 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
}
this._okButton = { label: _("Connect"),
this._okButton = { label: _("Connect"),
action: this._onOk.bind(this),
default: true
};
this.setButtons([{ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
key: Clutter.KEY_Escape,
},
this._okButton]);
@@ -178,29 +176,28 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
let value = secret.value;
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
return false;
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'z')
|| (value[i] >= 'A' && value[i] <= 'Z')))
return false;
}
} else {
} else
return false;
}
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64)
return false;
}
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64)
return false;
}
return true;
}
_getWirelessSecrets(secrets, _wirelessSetting) {
_getWirelessSecrets(secrets, wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
if (this._settingName == '802-1x') {
@@ -217,7 +214,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
validate: this._validateWpaPsk, password: true });
break;
case 'none': // static WEP
secrets.push({ label: _("Key: "), key: `wep-key${wirelessSecuritySetting.wep_tx_keyidx}`,
secrets.push({ label: _("Key: "), key: 'wep-key' + wirelessSecuritySetting.wep_tx_keyidx,
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
wep_key_type: wirelessSecuritySetting.wep_key_type,
validate: this._validateStaticWep, password: true });
@@ -233,12 +230,13 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._get8021xSecrets(secrets);
break;
default:
log(`Invalid wireless key management: ${wirelessSecuritySetting.key_mgmt}`);
log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
}
}
_get8021xSecrets(secrets) {
let ieee8021xSetting = this._connection.get_setting_802_1x();
let phase2method;
/* If hints were given we know exactly what we need to ask */
if (this._settingName == "802-1x" && this._hints.length) {
@@ -275,7 +273,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
value: ieee8021xSetting.private_key_password || '', password: true });
break;
default:
log(`Invalid EAP/IEEE802.1x method: ${ieee8021xSetting.get_eap_method(0)}`);
log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
}
}
@@ -306,13 +304,13 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
let ssid;
let content = { };
content.secrets = [];
content.secrets = [ ];
switch (connectionType) {
case '802-11-wireless':
wirelessSetting = this._connection.get_setting_wireless();
ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
content.title = _("Authentication required by wireless network");
content.title = _("Authentication required");
content.message = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
this._getWirelessSecrets(content.secrets, wirelessSetting);
break;
@@ -329,7 +327,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._getPPPoESecrets(content.secrets);
break;
case 'gsm':
if (this._hints.includes('pin')) {
if (this._hints.indexOf('pin') != -1) {
let gsmSetting = this._connection.get_setting_gsm();
content.title = _("PIN code required");
content.message = _("PIN code is needed for the mobile broadband device");
@@ -340,13 +338,13 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
// fall through
case 'cdma':
case 'bluetooth':
content.title = _("Mobile broadband network password");
content.title = _("Mobile broadband password");
content.message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
this._getMobileSecrets(content.secrets, connectionType);
break;
default:
log(`Invalid connection type: ${connectionType}`);
}
log('Invalid connection type: ' + connectionType);
};
return content;
}
@@ -361,15 +359,16 @@ var VPNRequestHandler = class {
this._pluginOutBuffer = [];
this._title = null;
this._description = null;
this._content = [];
this._content = [ ];
this._shellDialog = null;
let connectionSetting = connection.get_setting_connection();
let argv = [authHelper.fileName,
'-u', connectionSetting.uuid,
'-n', connectionSetting.id,
'-s', serviceType];
let argv = [ authHelper.fileName,
'-u', connectionSetting.uuid,
'-n', connectionSetting.id,
'-s', serviceType
];
if (authHelper.externalUIMode)
argv.push('--external-ui-mode');
if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
@@ -386,7 +385,7 @@ var VPNRequestHandler = class {
this._newStylePlugin = authHelper.externalUIMode;
try {
let [success_, pid, stdin, stdout, stderr] =
let [success, pid, stdin, stdout, stderr] =
GLib.spawn_async_with_pipes(null, /* pwd */
argv,
null, /* envp */
@@ -408,7 +407,7 @@ var VPNRequestHandler = class {
this._vpnChildFinished.bind(this));
this._writeConnection();
} catch (e) {
} catch(e) {
logError(e, 'error while spawning VPN auth helper');
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
@@ -425,7 +424,7 @@ var VPNRequestHandler = class {
} else {
try {
this._stdin.write('QUIT\n\n', null);
} catch (e) { /* ignore broken pipe errors */ }
} catch(e) { /* ignore broken pipe errors */ }
}
this.destroy();
@@ -445,7 +444,7 @@ var VPNRequestHandler = class {
this._destroyed = true;
}
_vpnChildFinished(pid, status, _requestObj) {
_vpnChildFinished(pid, status, requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions
@@ -460,9 +459,8 @@ var VPNRequestHandler = class {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
else
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
} else {
} else
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
}
this.destroy();
}
@@ -475,7 +473,7 @@ var VPNRequestHandler = class {
if (line == '' && this._previousLine == '') {
try {
this._stdin.write('QUIT\n\n', null);
} catch (e) { /* ignore broken pipe errors */ }
} catch(e) { /* ignore broken pipe errors */ }
} else {
this._agent.set_password(this._requestId, this._previousLine, line);
this._previousLine = undefined;
@@ -487,7 +485,7 @@ var VPNRequestHandler = class {
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
let [line, len] = this._dataStdout.read_line_finish_utf8(result);
if (line == null) {
// end of file
@@ -542,7 +540,7 @@ var VPNRequestHandler = class {
message: keyfile.get_string(VPN_UI_GROUP, 'Description'),
secrets: [] };
let [groups, len_] = keyfile.get_groups();
let [groups, len] = keyfile.get_groups();
for (let i = 0; i < groups.length; i++) {
if (groups[i] == VPN_UI_GROUP)
continue;
@@ -563,7 +561,7 @@ var VPNRequestHandler = class {
this._agent.set_password(this._requestId, groups[i], value);
}
}
} catch (e) {
} catch(e) {
// No output is a valid case it means "both secrets are stored"
if (data.length > 0) {
logError(e, 'error while reading VPN plugin output keyfile');
@@ -589,15 +587,15 @@ var VPNRequestHandler = class {
try {
vpnSetting.foreach_data_item((key, value) => {
this._stdin.write(`DATA_KEY=${key}\n`, null);
this._stdin.write(`DATA_VAL=${value || ''}\n\n`, null);
this._stdin.write('DATA_KEY=' + key + '\n', null);
this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
});
vpnSetting.foreach_secret((key, value) => {
this._stdin.write(`SECRET_KEY=${key}\n`, null);
this._stdin.write(`SECRET_VAL=${value || ''}\n\n`, null);
this._stdin.write('SECRET_KEY=' + key + '\n', null);
this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
});
this._stdin.write('DONE\n\n', null);
} catch (e) {
} catch(e) {
logError(e, 'internal error while writing connection to helper');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
@@ -621,9 +619,9 @@ var NetworkAgent = class {
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => this._vpnCacheBuilt = false);
} catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
monitor.connect('changed', () => { this._vpnCacheBuilt = false; });
} catch(e) {
log('Failed to create monitor for VPN plugin dir: ' + e.message);
}
this._native.connect('new-request', this._newRequest.bind(this));
@@ -634,7 +632,7 @@ var NetworkAgent = class {
try {
this._native.init_finish(res);
this._initialized = true;
} catch (e) {
} catch(e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
@@ -682,13 +680,12 @@ var NetworkAgent = class {
let connectionSetting = connection.get_setting_connection();
let connectionType = connectionSetting.get_connection_type();
switch (connectionType) {
case '802-11-wireless': {
case '802-11-wireless':
let wirelessSetting = connection.get_setting_wireless();
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
title = _("Authentication required by wireless network");
title = _("Authentication required");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break;
}
case '802-3-ethernet':
title = _("Wired 802.1X authentication");
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
@@ -698,7 +695,8 @@ var NetworkAgent = class {
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
break;
case 'gsm':
if (hints.includes('pin')) {
if (hints.indexOf('pin') != -1) {
let gsmSetting = connection.get_setting_gsm();
title = _("PIN code required");
body = _("PIN code is needed for the mobile broadband device");
break;
@@ -710,7 +708,7 @@ var NetworkAgent = class {
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
break;
default:
log(`Invalid connection type: ${connectionType}`);
log('Invalid connection type: ' + connectionType);
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
return;
}

View File

@@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { AccountsService, Clutter, Gio, GLib,
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
const Signals = imports.signals;
const Animation = imports.ui.animation;
const Dialog = imports.ui.dialog;
@@ -39,19 +39,19 @@ var AuthenticationDialog = GObject.registerClass({
this.contentLayout.add_actor(content);
if (userNames.length > 1) {
log(`polkitAuthenticationAgent: Received ${userNames.length} ` +
'identities that can be used for authentication. Only ' +
log('polkitAuthenticationAgent: Received ' + userNames.length +
' identities that can be used for authentication. Only ' +
'considering one.');
}
let userName = GLib.get_user_name();
if (!userNames.includes(userName))
if (userNames.indexOf(userName) < 0)
userName = 'root';
if (!userNames.includes(userName))
if (userNames.indexOf(userName) < 0)
userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name();
let userRealName = this._user.get_real_name()
this._userLoadedId = this._user.connect('notify::is_loaded',
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
@@ -78,15 +78,15 @@ var AuthenticationDialog = GObject.registerClass({
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
text: userRealName }));
userBox.add(userLabel,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
}
@@ -99,7 +99,7 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: "",
can_focus: true });
can_focus: true});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordBox.add(this._passwordEntry,
@@ -128,7 +128,7 @@ var AuthenticationDialog = GObject.registerClass({
* gnome-shell.css sets the color to be transparent
*/
this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label',
text: 'abc' });
text: 'abc'});
this._nullMessageLabel.add_style_class_name('hidden');
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._nullMessageLabel.clutter_text.line_wrap = true;
@@ -138,7 +138,7 @@ var AuthenticationDialog = GObject.registerClass({
this._cancelButton = this.addButton({ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"),
this._okButton = this.addButton({ label: _("Authenticate"),
action: this._onAuthenticateButtonPressed.bind(this),
default: true });
@@ -181,9 +181,9 @@ var AuthenticationDialog = GObject.registerClass({
//
// We could add retrying if this turns out to be a problem
log('polkitAuthenticationAgent: Failed to show modal dialog. ' +
`Dismissing authentication request for action-id ${this.actionId} ` +
`cookie ${this._cookie}`);
log('polkitAuthenticationAgent: Failed to show modal dialog.' +
' Dismissing authentication request for action-id ' + this.actionId +
' cookie ' + this._cookie);
this._emitDone(true);
}
}
@@ -251,14 +251,14 @@ var AuthenticationDialog = GObject.registerClass({
}
}
_onSessionRequest(session, request, echoOn) {
_onSessionRequest(session, request, echo_on) {
// Cheap localization trick
if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:"));
else
this._passwordLabel.set_text(request);
if (echoOn)
if (echo_on)
this._passwordEntry.clutter_text.set_password_char('');
else
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
@@ -343,7 +343,7 @@ var AuthenticationAgent = class {
enable() {
try {
this._native.register();
} catch (e) {
} catch(e) {
log('Failed to register AuthenticationAgent');
}
}
@@ -351,7 +351,7 @@ var AuthenticationAgent = class {
disable() {
try {
this._native.unregister();
} catch (e) {
} catch(e) {
log('Failed to unregister AuthenticationAgent');
}
}
@@ -384,11 +384,11 @@ var AuthenticationAgent = class {
this._currentDialog.performAuthentication();
}
_onCancel(_nativeAgent) {
_onCancel(nativeAgent) {
this._completeRequest(false);
}
_onDialogDone(_dialog, dismissed) {
_onDialogDone(dialog, dismissed) {
this._completeRequest(dismissed);
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
@@ -9,7 +8,7 @@ var Tpl = null;
var Tp = null;
try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
} catch (e) {
} catch(e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@@ -41,8 +40,10 @@ var NotificationDirection = {
RECEIVED: 'chat-received'
};
var N_ = s => s;
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags_] = tpMessage.to_text();
let [text, flags] = tpMessage.to_text();
let timestamp = tpMessage.get_sent_timestamp();
if (timestamp == 0)
@@ -88,7 +89,7 @@ var TelepathyComponent = class {
try {
this._client.register();
} catch (e) {
throw new Error(`Could not register Telepathy client. Error: ${e}`);
throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
}
if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
@@ -148,20 +149,20 @@ class TelepathyClient extends Tp.BaseClient {
this._delegatedChannelsCb.bind(this));
}
vfunc_observe_channels(...args) {
let [account, conn, channels, dispatchOp_, requests_, context] = args;
vfunc_observe_channels(account, conn, channels,
dispatchOp, requests, context) {
let len = channels.length;
for (let i = 0; i < len; i++) {
let channel = channels[i];
let [targetHandle_, targetHandleType] = channel.get_handle();
let [targetHandle, targetHandleType] = channel.get_handle();
if (channel.get_invalidated())
continue;
continue;
/* Only observe contact text channels */
if ((!(channel instanceof Tp.TextChannel)) ||
targetHandleType != Tp.HandleType.CONTACT)
continue;
continue;
this._createChatSource(account, conn, channel, channel.get_target_contact());
}
@@ -181,8 +182,8 @@ class TelepathyClient extends Tp.BaseClient {
});
}
vfunc_handle_channels(...args) {
let [account, conn, channels, requests_, userActionTime_, context] = args;
vfunc_handle_channels(account, conn, channels, requests,
user_action_time, context) {
this._handlingChannels(account, conn, channels, true);
context.accept();
}
@@ -199,7 +200,7 @@ class TelepathyClient extends Tp.BaseClient {
}
if (channel.get_invalidated())
continue;
continue;
// 'notify' will be true when coming from an actual HandleChannels
// call, and not when from a successful Claim call. The point is
@@ -221,8 +222,8 @@ class TelepathyClient extends Tp.BaseClient {
}
}
vfunc_add_dispatch_operation(...args) {
let [account, conn, channels, dispatchOp, context] = args;
vfunc_add_dispatch_operation(account, conn, channels,
dispatchOp, context) {
let channel = channels[0];
let chanType = channel.get_channel_type();
@@ -240,7 +241,7 @@ class TelepathyClient extends Tp.BaseClient {
}
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle_, targetHandleType] = channel.get_handle();
let [targetHandle, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
@@ -254,14 +255,14 @@ class TelepathyClient extends Tp.BaseClient {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log(`Failed to Claim channel: ${err}`);
log('Failed to Claim channel: ' + err);
}
});
context.accept();
}
_delegatedChannelsCb(_client, _channels) {
_delegatedChannelsCb(client, channels) {
// Nothing to do as we don't make a distinction between observed and
// handled channels.
}
@@ -361,28 +362,28 @@ var ChatSource = class extends MessageTray.Source {
let presenceType = this._contact.get_presence_type();
switch (presenceType) {
case Tp.ConnectionPresenceType.AVAILABLE:
iconName = 'user-available';
break;
case Tp.ConnectionPresenceType.BUSY:
iconName = 'user-busy';
break;
case Tp.ConnectionPresenceType.OFFLINE:
iconName = 'user-offline';
break;
case Tp.ConnectionPresenceType.HIDDEN:
iconName = 'user-invisible';
break;
case Tp.ConnectionPresenceType.AWAY:
iconName = 'user-away';
break;
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
iconName = 'user-idle';
break;
default:
iconName = 'user-offline';
}
return new Gio.ThemedIcon({ name: iconName });
case Tp.ConnectionPresenceType.AVAILABLE:
iconName = 'user-available';
break;
case Tp.ConnectionPresenceType.BUSY:
iconName = 'user-busy';
break;
case Tp.ConnectionPresenceType.OFFLINE:
iconName = 'user-offline';
break;
case Tp.ConnectionPresenceType.HIDDEN:
iconName = 'user-invisible';
break;
case Tp.ConnectionPresenceType.AWAY:
iconName = 'user-away';
break;
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
iconName = 'user-idle';
break;
default:
iconName = 'user-offline';
}
return new Gio.ThemedIcon({ name: iconName });
}
_updateAvatarIcon() {
@@ -428,7 +429,7 @@ var ChatSource = class extends MessageTray.Source {
}
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
let [success, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification();
@@ -563,7 +564,7 @@ var ChatSource = class extends MessageTray.Source {
// This is called for both messages we send from
// our client and other clients as well.
_messageSent(channel, message, _flags, _token) {
_messageSent(channel, message, flags, token) {
this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
@@ -596,12 +597,12 @@ var ChatSource = class extends MessageTray.Source {
// keep track of it with the ChatStateChanged signal but it is good
// enough right now.
if (state != this._chatState) {
this._chatState = state;
this._channel.set_chat_state_async(state, null);
this._chatState = state;
this._channel.set_chat_state_async(state, null);
}
}
_presenceChanged(_contact, _presence, _status, _message) {
_presenceChanged(contact, presence, status, message) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CtrlAltTabManager */
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
@@ -8,6 +7,7 @@ const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params;
var POPUP_APPICON_SIZE = 96;
var POPUP_FADE_TIME = 0.1; // seconds
var SortGroup = {
TOP: 0,
@@ -33,7 +33,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
item.iconName = icon;
this._items.push(item);
root.connect('destroy', () => this.removeGroup(root));
root.connect('destroy', () => { this.removeGroup(root); });
if (root instanceof St.Widget)
global.focus_manager.add_group(root);
}
@@ -64,8 +64,9 @@ var CtrlAltTabManager = class CtrlAltTabManager {
if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup;
let [ax] = a.proxy.get_transformed_position();
let [bx] = b.proxy.get_transformed_position();
let ax, bx, y;
[ax, y] = a.proxy.get_transformed_position();
[bx, y] = b.proxy.get_transformed_position();
return ax - bx;
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -10,10 +9,11 @@ const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var DASH_ANIMATION_TIME = 200;
var DASH_ITEM_LABEL_SHOW_TIME = 150;
var DASH_ITEM_LABEL_HIDE_TIME = 100;
var DASH_ANIMATION_TIME = 0.2;
var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
var DASH_ITEM_LABEL_HIDE_TIME = 0.1;
var DASH_ITEM_HOVER_TIMEOUT = 300;
function getAppFromSource(source) {
@@ -24,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
// when requesting a size
var DashItemContainer = GObject.registerClass(
@@ -55,24 +31,20 @@ class DashItemContainer extends St.Widget {
_init() {
super._init({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
scale_x: 0,
scale_y: 0,
opacity: 0,
x_expand: true,
x_align: Clutter.ActorAlign.CENTER });
this._labelText = "";
this.label = new St.Label({ style_class: 'dash-label' });
this.label = new St.Label({ style_class: 'dash-label'});
this.label.hide();
Main.layoutManager.addChrome(this.label);
this.label_actor = this.label;
this.child = null;
this._childScale = 0;
this._childOpacity = 0;
this.animatingOut = false;
this.connect('notify::scale-x', () => this.queue_relayout());
this.connect('notify::scale-y', () => this.queue_relayout());
this.connect('destroy', () => {
if (this.child != null)
this.child.destroy();
@@ -109,7 +81,7 @@ class DashItemContainer extends St.Widget {
let itemHeight = this.allocation.y2 - this.allocation.y1;
let labelHeight = this.label.get_height();
let yOffset = Math.floor((itemHeight - labelHeight) / 2);
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
let y = stageY + yOffset;
@@ -123,11 +95,11 @@ class DashItemContainer extends St.Widget {
x = stageX + this.get_width() + xOffset;
this.label.set_position(x, y);
this.label.ease({
opacity: 255,
duration: DASH_ITEM_LABEL_SHOW_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this.label,
{ opacity: 255,
time: DASH_ITEM_LABEL_SHOW_TIME,
transition: 'easeOutQuad',
});
}
setLabelText(text) {
@@ -136,12 +108,14 @@ class DashItemContainer extends St.Widget {
}
hideLabel() {
this.label.ease({
opacity: 0,
duration: DASH_ITEM_LABEL_HIDE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.label.hide()
});
Tweener.addTween(this.label,
{ opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.label.hide();
}
});
}
setChild(actor) {
@@ -152,6 +126,9 @@ class DashItemContainer extends St.Widget {
this.child = actor;
this.add_actor(this.child);
this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity);
}
show(animate) {
@@ -159,13 +136,12 @@ class DashItemContainer extends St.Widget {
return;
let time = animate ? DASH_ANIMATION_TIME : 0;
this.ease({
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: time,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this,
{ childScale: 1.0,
childOpacity: 255,
time: time,
transition: 'easeOutQuad'
});
}
animateOutAndDestroy() {
@@ -177,14 +153,37 @@ class DashItemContainer extends St.Widget {
}
this.animatingOut = true;
this.ease({
scale_x: 0,
scale_y: 0,
opacity: 0,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.destroy()
});
Tweener.addTween(this,
{ childScale: 0.0,
childOpacity: 0,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
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;
}
});
@@ -199,9 +198,9 @@ class ShowAppsIcon extends DashItemContainer {
toggle_mode: true });
this._iconActor = null;
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
{ setSizeManually: true,
showLabel: false,
createIcon: this._createIcon.bind(this) });
{ setSizeManually: true,
showLabel: false,
createIcon: this._createIcon.bind(this) });
this.toggleButton.add_actor(this.icon);
this.toggleButton._delegate = this;
@@ -242,14 +241,14 @@ class ShowAppsIcon extends DashItemContainer {
this.setLabelText(_("Show Applications"));
}
handleDragOver(source, _actor, _x, _y, _time) {
handleDragOver(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP;
}
acceptDrop(source, _actor, _x, _y, _time) {
acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source);
if (!this._canRemoveApp(app))
return false;
@@ -297,7 +296,7 @@ class DashActor extends St.Widget {
this.set_allocation(box, flags);
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();
childBox.x1 = contentBox.x1;
@@ -322,14 +321,14 @@ class DashActor extends St.Widget {
let themeNode = this.get_theme_node();
let adjustedForWidth = themeNode.adjust_for_width(forWidth);
let [, showAppsButton] = this.get_children();
let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth);
[minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight);
let [minHeight, ] = showAppsButton.get_preferred_height(adjustedForWidth);
[minHeight, ] = themeNode.adjust_preferred_height(minHeight, natHeight);
return [minHeight, natHeight];
}
});
const baseIconSizes = [16, 22, 24, 32, 48, 64];
const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
var Dash = class Dash {
constructor() {
@@ -352,7 +351,8 @@ var Dash = class Dash {
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._showAppsIcon = new ShowAppsIcon();
this._showAppsIcon.show(false);
this._showAppsIcon.childScale = 1;
this._showAppsIcon.childOpacity = 255;
this._showAppsIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(this._showAppsIcon);
@@ -474,7 +474,19 @@ var Dash = class Dash {
}
_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, opened) => {
@@ -621,12 +633,12 @@ var Dash = class Dash {
icon.icon.set_size(icon.icon.width * scale,
icon.icon.height * scale);
icon.icon.ease({
width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(icon.icon,
{ width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
});
}
}
@@ -636,10 +648,10 @@ var Dash = class Dash {
let running = this._appSystem.get_running();
let children = this._box.get_children().filter(actor => {
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
});
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
});
// Apps currently in the dash
let oldApps = children.map(actor => actor.child._delegate.app);
// Apps supposed to be in the dash
@@ -688,14 +700,14 @@ var Dash = class Dash {
}
// App removed at oldIndex
if (oldApp && !newApps.includes(oldApp)) {
if (oldApp && newApps.indexOf(oldApp) == -1) {
removedActors.push(children[oldIndex]);
oldIndex++;
continue;
}
// App added at newIndex
if (newApp && !oldApps.includes(newApp)) {
if (newApp && oldApps.indexOf(newApp) == -1) {
addedItems.push({ app: newApp,
item: this._createAppItem(newApp),
pos: newIndex });
@@ -778,7 +790,7 @@ var Dash = class Dash {
}
}
handleDragOver(source, actor, x, y, _time) {
handleDragOver(source, actor, x, y, time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps
@@ -856,7 +868,7 @@ var Dash = class Dash {
}
// Draggable target interface
acceptDrop(source, _actor, _x, _y, _time) {
acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps

View File

@@ -1,7 +1,6 @@
// -*- 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;
const Util = imports.misc.util;
@@ -11,13 +10,8 @@ const Calendar = imports.ui.calendar;
const Weather = imports.misc.weather;
const System = imports.system;
const { loadInterfaceXML } = imports.misc.fileUtils;
const MAX_FORECASTS = 5;
const ClocksIntegrationIface = loadInterfaceXML('org.gnome.Shell.ClocksIntegration');
const ClocksProxy = Gio.DBusProxy.makeProxyWrapper(ClocksIntegrationIface);
function _isToday(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
@@ -53,7 +47,7 @@ var TodayButton = class TodayButton {
this._calendar.connect('selected-date-changed', (calendar, date) => {
// Make the button reactive only if the selected date is not the
// current date.
this.actor.reactive = !_isToday(date);
this.actor.reactive = !_isToday(date)
});
}
@@ -88,8 +82,7 @@ var WorldClocksSection = class WorldClocksSection {
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
if (this._clocksApp)
this._clocksApp.activate();
this._clockAppMon.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
@@ -102,40 +95,29 @@ var WorldClocksSection = class WorldClocksSection {
this.actor.child = this._grid;
this._clocksApp = null;
this._clocksProxy = new ClocksProxy(
Gio.DBus.session,
'org.gnome.clocks',
'/org/gnome/clocks',
this._onProxyReady.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._clockAppMon = new Util.AppSettingsMonitor('org.gnome.clocks.desktop',
'org.gnome.clocks');
this._clockAppMon.connect('available-changed',
this._sync.bind(this));
this._clockAppMon.watchSetting('world-clocks',
this._clocksChanged.bind(this));
this._sync();
}
_sync() {
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
this.actor.visible = this._clocksApp != null;
this.actor.visible = this._clockAppMon.available;
}
_clocksChanged() {
_clocksChanged(settings) {
this._grid.destroy_all_children();
this._locations = [];
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++) {
let l = world.deserialize(clocks[i]);
if (!clocks[i].location)
continue;
let l = world.deserialize(clocks[i].location);
if (l && l.get_timezone() != null)
this._locations.push({ location: l });
}
@@ -214,25 +196,6 @@ var WorldClocksSection = class WorldClocksSection {
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 {
@@ -254,7 +217,7 @@ var WeatherSection = class WeatherSection {
});
let box = new St.BoxLayout({ style_class: 'weather-box',
vertical: true });
vertical: true });
this.actor.child = box;
@@ -286,12 +249,12 @@ var WeatherSection = class WeatherSection {
let current = info;
let infos = [info];
for (let i = 0; i < forecasts.length; i++) {
let [ok_, timestamp] = forecasts[i].get_value_update();
let [ok, timestamp] = forecasts[i].get_value_update();
let datetime = new Date(timestamp * 1000);
if (!_isToday(datetime))
continue; // Ignore forecasts from other days
[ok_, timestamp] = current.get_value_update();
[ok, timestamp] = current.get_value_update();
let currenttime = new Date(timestamp * 1000);
if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h
@@ -312,7 +275,7 @@ var WeatherSection = class WeatherSection {
let col = 0;
infos.forEach(fc => {
let [ok_, timestamp] = fc.get_value_update();
let [ok, timestamp] = fc.get_value_update();
let timeStr = Util.formatTime(new Date(timestamp * 1000), {
timeOnly: true
});
@@ -394,7 +357,7 @@ var MessagesIndicator = class MessagesIndicator {
Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
let sources = Main.messageTray.getSources();
sources.forEach(source => this._onSourceAdded(null, source));
sources.forEach(source => { this._onSourceAdded(null, source); });
}
_onSourceAdded(tray, source) {
@@ -410,7 +373,7 @@ var MessagesIndicator = class MessagesIndicator {
_updateCount() {
let count = 0;
this._sources.forEach(source => count += source.unseenCount);
this._sources.forEach(source => { count += source.unseenCount; });
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);
@@ -421,8 +384,8 @@ var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
_init(actor) {
this._source = actor;
this._source.connect('notify::visible', () => this.queue_relayout());
this._source.connect('notify::size', () => this.queue_relayout());
this._source.connect('notify::visible', () => { this.queue_relayout(); });
this._source.connect('notify::size', () => { this.queue_relayout(); });
super._init();
}
@@ -496,6 +459,7 @@ class CalendarColumnLayout extends Clutter.BoxLayout {
var DateMenuButton = GObject.registerClass(
class DateMenuButton extends PanelMenu.Button {
_init() {
let item;
let hbox;
let vbox;

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent */
const { Clutter, Gio, GObject, Pango, St } = imports.gi;
@@ -26,9 +25,9 @@ class Dialog extends St.Widget {
_createDialog() {
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
vertical: true });
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
vertical: true });
// modal dialogs are fixed width and grow vertically; set the request
// mode accordingly so wrapped labels are handled correctly during
@@ -39,13 +38,13 @@ class Dialog extends St.Widget {
this.contentLayout = new St.BoxLayout({ vertical: true,
style_class: "modal-dialog-content-box" });
this._dialog.add(this.contentLayout,
{ expand: true,
x_fill: true,
y_fill: true,
{ expand: true,
x_fill: true,
y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous:true }) });
this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE,
y_align: St.Align.START });
@@ -117,11 +116,11 @@ class Dialog extends St.Widget {
let button = new St.Button({ style_class: 'modal-dialog-linked-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
x_expand: true,
y_expand: true,
label: label });
reactive: true,
can_focus: true,
x_expand: true,
y_expand: true,
label: label });
button.connect('clicked', action);
buttonInfo['button'] = button;
@@ -181,8 +180,10 @@ var MessageDialogContent = GObject.registerClass({
this._subtitle.clutter_text.set(textProps);
this._body.clutter_text.set(textProps);
let defaultParams = { style_class: 'message-dialog-main-layout' };
super._init(Object.assign(defaultParams, params));
if (!params.hasOwnProperty('style_class'))
params.style_class = 'message-dialog-main-layout';
super._init(params);
this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
x_expand: true,

View File

@@ -1,18 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addDragMonitor, removeDragMonitor, makeDraggable */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
// Time to scale down to maxDragActorSize
var SCALE_ANIMATION_TIME = 250;
var SCALE_ANIMATION_TIME = 0.25;
// 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
var REVERT_ANIMATION_TIME = 750;
var REVERT_ANIMATION_TIME = 0.75;
var DragMotionResult = {
NO_DROP: 0,
@@ -111,6 +111,9 @@ var _Draggable = class _Draggable {
if (event.get_button() != 1)
return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true;
this._grabActor(event.get_device());
@@ -136,6 +139,9 @@ var _Draggable = class _Draggable {
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._buttonDown = true;
this._grabActor(event.get_device(), event.get_event_sequence());
@@ -422,22 +428,20 @@ var _Draggable = class _Draggable {
// to the final position because that tween would
// fight with updates as the user continues dragging
// the mouse; instead we do the position computations in
// a ::new-frame handler.
this._dragActor.ease({
scale_x: scale * origScale,
scale_y: scale * origScale,
duration: SCALE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._dragActor.get_transition('scale-x').connect('new-frame', () => {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
this._dragActor.set_position(
this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
});
// an onUpdate() function.
Tweener.addTween(this._dragActor,
{ scale_x: scale * origScale,
scale_y: scale * origScale,
time: SCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
this._dragActor.set_position(this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
},
onUpdateScope: this });
}
}
}
@@ -500,7 +504,7 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
let [r_, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
let [r, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
@@ -557,11 +561,11 @@ var _Draggable = class _Draggable {
let dropFunc = dragMonitors[i].dragDrop;
if (dropFunc)
switch (dropFunc(dropEvent)) {
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
}
}
@@ -572,7 +576,7 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
let [r, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
@@ -584,9 +588,8 @@ var _Draggable = class _Draggable {
if (this._restoreOnSuccess) {
this._restoreDragActor(event.get_time());
return true;
} else {
} else
this._dragActor.destroy();
}
}
this._dragState = DragState.INIT;
@@ -610,15 +613,15 @@ var _Draggable = class _Draggable {
if (this._dragActorSource && this._dragActorSource.visible) {
// Snap the clone back to its source
[x, y] = this._dragActorSource.get_transformed_position();
let [sourceScaledWidth] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? sourceScaledWidth / this._dragActor.width : 0;
let [sourceScaledWidth, sourceScaledHeight] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0;
} else if (this._dragOrigParent) {
// Snap the actor back to its original position within
// its parent, adjusting for the fact that the parent
// may have been moved or scaled
let [parentX, parentY] = this._dragOrigParent.get_transformed_position();
let [parentWidth] = this._dragOrigParent.get_size();
let [parentScaledWidth] = this._dragOrigParent.get_transformed_size();
let [parentWidth, parentHeight] = this._dragOrigParent.get_size();
let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size();
let parentScale = 1.0;
if (parentWidth != 0)
parentScale = parentScaledWidth / parentWidth;
@@ -654,13 +657,13 @@ var _Draggable = class _Draggable {
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
this._animateDragEnd(eventTime, {
x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
duration: SNAP_BACK_ANIMATION_TIME
});
this._animateDragEnd(eventTime,
{ x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
time: SNAP_BACK_ANIMATION_TIME,
});
}
_restoreDragActor(eventTime) {
@@ -672,27 +675,26 @@ var _Draggable = class _Draggable {
this._dragActor.set_scale(restoreScale, restoreScale);
this._dragActor.opacity = 0;
this._animateDragEnd(eventTime, {
duration: REVERT_ANIMATION_TIME
});
this._animateDragEnd(eventTime,
{ time: REVERT_ANIMATION_TIME });
}
_animateDragEnd(eventTime, params) {
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
this._dragActor.ease(Object.assign(params, {
opacity: this._dragOrigOpacity,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._onAnimationComplete(this._dragActor, eventTime);
}
}));
Tweener.addTween(this._dragActor, params)
}
_finishAnimation() {
if (!this._animationInProgress)
return;
return
this._animationInProgress = false;
if (!this._buttonDown)

View File

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

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, EndSessionDialog */
/*
* Copyright 2010-2016 Red Hat, Inc
*
@@ -30,9 +29,13 @@ const UserWidget = imports.ui.userWidget;
const { loadInterfaceXML } = imports.misc.fileUtils;
let _endSessionDialog = null;
const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 48;
var GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = loadInterfaceXML('org.gnome.SessionManager.EndSessionDialog');
const logoutDialogContent = {
@@ -50,7 +53,7 @@ const logoutDialogContent = {
},
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedLogout',
label: C_("button", "Log Out") }],
label: C_("button", "Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon',
showOtherSessions: false,
};
@@ -66,9 +69,9 @@ const shutdownDialogContent = {
checkBoxText: C_("checkbox", "Install pending software updates"),
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") },
label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }],
label: C_("button", "Power Off") }],
iconName: 'system-shutdown-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
@@ -83,7 +86,7 @@ const restartDialogContent = {
},
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
label: C_("button", "Restart") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
@@ -99,7 +102,7 @@ const restartUpdateDialogContent = {
},
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
label: C_("button", "Restart &amp; Install") }],
unusedFutureButtonForTranslation: C_("button", "Install &amp; Power Off"),
unusedFutureCheckBoxForTranslation: C_("checkbox", "Power off after updates are installed"),
iconName: 'view-refresh-symbolic',
@@ -119,18 +122,18 @@ const restartUpgradeDialogContent = {
disableTimer: true,
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
label: C_("button", "Restart &amp; Install") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const DialogType = {
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3,
UPGRADE_RESTART: 4
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3,
UPGRADE_RESTART: 4
};
const DialogContent = {
@@ -156,7 +159,7 @@ function findAppFromInhibitor(inhibitor) {
let desktopFile;
try {
[desktopFile] = inhibitor.GetAppIdSync();
} catch (e) {
} catch(e) {
// XXX -- sometimes JIT inhibitors generated by gnome-session
// get removed too soon. Don't fail in this case.
log('gnome-session gave us a dead inhibitor: %s'.format(inhibitor.get_object_path()));
@@ -220,7 +223,7 @@ function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
(new EndSessionDialog());
_endSessionDialog = new EndSessionDialog();
}
var EndSessionDialog = GObject.registerClass(
@@ -232,13 +235,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
this._updatesPermission = null;
this._pkOfflineProxy = new PkOfflineProxy(Gio.DBus.system,
'org.freedesktop.PackageKit',
'/org/freedesktop/PackageKit',
this._onPkOfflineProxyCreated.bind(this));
(proxy, error) => {
if (error)
log(error.message);
});
this._powerProxy = new UPowerProxy(Gio.DBus.system,
'org.freedesktop.UPower',
'/org/freedesktop/UPower',
@@ -272,8 +276,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._iconBin = new St.Bin();
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
@@ -286,7 +290,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
messageLayout.add(this._subjectLabel,
{ x_fill: false,
y_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
@@ -295,7 +299,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add(this._descriptionLabel,
{ y_fill: true,
{ y_fill: true,
y_align: St.Align.START });
this._checkBox = new CheckBox.CheckBox();
@@ -333,36 +337,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._inhibitorSection.add_actor(this._sessionHeader);
this._inhibitorSection.add_actor(this._sessionList);
try {
this._updatesPermission = Polkit.Permission.new_sync("org.freedesktop.packagekit.trigger-offline-update", null, null);
} catch(e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
}
_onPkOfflineProxyCreated(proxy, error) {
if (error) {
log(error.message);
return;
}
// Creating a D-Bus proxy won't propagate SERVICE_UNKNOWN or NAME_HAS_NO_OWNER
// errors if PackageKit is not available, but the GIO implementation will make
// sure in that case that the proxy's g-name-owner is set to null, so check that.
if (this._pkOfflineProxy.g_name_owner === null) {
this._pkOfflineProxy = null;
return;
}
// It only makes sense to check for this permission if PackageKit is available.
Polkit.Permission.new(
'org.freedesktop.packagekit.trigger-offline-update', null, null,
(source, res) => {
try {
this._updatesPermission = Polkit.Permission.new_finish(res);
} catch (e) {
log(`No permission to trigger offline updates: ${e}`);
}
});
}
_onDestroy() {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
@@ -407,8 +391,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
// Use a different description when we are installing a system upgrade
// if the PackageKit proxy is available (i.e. PackageKit is available).
if (this._pkOfflineProxy && dialogContent.upgradeDescription) {
if (dialogContent.upgradeDescription) {
let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
@@ -445,8 +428,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
_updateButtons() {
let dialogContent = DialogContent[this._type];
let buttons = [{ action: this.cancel.bind(this),
label: _("Cancel"),
key: Clutter.Escape }];
label: _("Cancel"),
key: Clutter.Escape }];
for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
let signal = dialogContent.confirmButtons[i].signal;
@@ -493,19 +476,19 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
// Trigger the offline update as requested
if (this._checkBox.actor.checked) {
switch (signal) {
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
break;
case "ConfirmedShutdown":
// To actually trigger the offline update, we need to
// reboot to do the upgrade. When the upgrade is complete,
// the computer will shut down automatically.
signal = "ConfirmedReboot";
this._triggerOfflineUpdateShutdown(callback);
break;
default:
callback();
break;
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
break;
case "ConfirmedShutdown":
// To actually trigger the offline update, we need to
// reboot to do the upgrade. When the upgrade is complete,
// the computer will shut down automatically.
signal = "ConfirmedReboot";
this._triggerOfflineUpdateShutdown(callback);
break;
default:
callback();
break;
}
} else {
this._triggerOfflineUpdateCancel(callback);
@@ -517,12 +500,6 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateReboot(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.TriggerRemote('reboot', (result, error) => {
if (error)
log(error.message);
@@ -532,12 +509,6 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateShutdown(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.TriggerRemote('power-off', (result, error) => {
if (error)
log(error.message);
@@ -547,12 +518,6 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateCancel(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.CancelRemote((result, error) => {
if (error)
log(error.message);
@@ -620,7 +585,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
_onInhibitorLoaded(inhibitor) {
if (!this._applications.includes(inhibitor)) {
if (this._applications.indexOf(inhibitor) < 0) {
// Stale inhibitor
return;
}
@@ -672,7 +637,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._loginManager.listSessions(result => {
let n = 0;
for (let i = 0; i < result.length; i++) {
let [id_, uid_, userName, seat_, sessionPath] = result[i];
let[id, uid, userName, seat, sessionPath] = result[i];
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
@@ -715,8 +680,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type;
// Only consider updates and upgrades if PackageKit is available.
if (this._pkOfflineProxy && this._type == DialogType.RESTART) {
if (this._type == DialogType.RESTART) {
if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART;
else if (this._pkOfflineProxy.UpgradeTriggered)
@@ -738,7 +702,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let dialogContent = DialogContent[this._type];
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], (proxy, error) => {
this._onInhibitorLoaded(proxy);
});
@@ -748,9 +712,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
if (dialogContent.showOtherSessions)
this._loadSessions();
// Only consider updates and upgrades if PackageKit is available.
let updateTriggered = this._pkOfflineProxy ? this._pkOfflineProxy.UpdateTriggered : false;
let updatePrepared = this._pkOfflineProxy ? this._pkOfflineProxy.UpdatePrepared : false;
let updateTriggered = this._pkOfflineProxy.UpdateTriggered;
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
@@ -782,7 +745,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
});
}
Close(_parameters, _invocation) {
Close(parameters, invocation) {
this.close();
}
});

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init */
const Config = imports.misc.config;
@@ -58,118 +57,8 @@ function _patchLayoutClass(layoutClass, styleProps) {
};
}
function _makeEaseCallback(params) {
let onComplete = params.onComplete;
delete params.onComplete;
let onStopped = params.onStopped;
delete params.onStopped;
if (!onComplete && !onStopped)
return null;
return isFinished => {
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;
let callback = _makeEaseCallback(params);
// 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();
if (callback) {
let transition = actor.get_transition(animatedProps[0]);
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);
let callback = _makeEaseCallback(params);
// cancel overwritten transition
actor.remove_transition(propName);
if (duration == 0) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
if (callback)
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);
if (callback)
transition.connect('stopped', (t, finished) => callback(finished));
}
function _loggingFunc(...args) {
let fields = { 'MESSAGE': args.join(', ') };
function _loggingFunc() {
let fields = {'MESSAGE': [].join.call(arguments, ', ')};
let domain = "GNOME Shell";
// If the caller is an extension, add it as metadata
@@ -204,27 +93,6 @@ function init() {
column_spacing: 'spacing-columns' });
_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() {
return St.describe_actor(this);
};
@@ -238,21 +106,15 @@ function init() {
}
});
St.set_slow_down_factor = function(factor) {
let { stack } = new Error();
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);
St.Settings.get().slow_down_factor = factor;
};
let origToString = Object.prototype.toString;
Object.prototype.toString = function() {
let base = origToString.call(this);
try {
if ('actor' in this && this.actor instanceof Clutter.Actor)
return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
else
return base;
} catch (e) {
} catch(e) {
return base;
}
};
@@ -266,7 +128,7 @@ function init() {
if (slowdownEnv) {
let factor = parseFloat(slowdownEnv);
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
@@ -276,17 +138,3 @@ function init() {
Tweener.init();
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,20 +1,20 @@
// -*- 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, Pango, Soup, St } = imports.gi;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const ExtensionUtils = imports.misc.extensionUtils;
const ExtensionSystem = imports.ui.extensionSystem;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const _signals = ExtensionSystem._signals;
var REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
var REPOSITORY_URL_DOWNLOAD = `${REPOSITORY_URL_BASE}/download-extension/%s.shell-extension.zip`;
var REPOSITORY_URL_INFO = `${REPOSITORY_URL_BASE}/extension-info/`;
var REPOSITORY_URL_UPDATE = `${REPOSITORY_URL_BASE}/update-info/`;
var REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
var REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
var REPOSITORY_URL_UPDATE = REPOSITORY_URL_BASE + '/update-info/';
let _httpSession;
@@ -26,7 +26,7 @@ function installExtension(uuid, invocation) {
_httpSession.queue_message(message, (session, message) => {
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());
return;
}
@@ -35,7 +35,7 @@ function installExtension(uuid, invocation) {
try {
info = JSON.parse(message.response_body.data);
} 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());
return;
}
@@ -46,7 +46,7 @@ function installExtension(uuid, invocation) {
}
function uninstallExtension(uuid) {
let extension = Main.extensionManager.lookup(uuid);
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return false;
@@ -54,7 +54,7 @@ function uninstallExtension(uuid) {
if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
return false;
if (!Main.extensionManager.unloadExtension(extension))
if (!ExtensionSystem.unloadExtension(extension))
return false;
FileUtils.recursivelyDeleteDir(extension.dir, true);
@@ -115,10 +115,10 @@ function updateExtension(uuid) {
_httpSession.queue_message(message, (session, message) => {
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => {
let oldExtension = Main.extensionManager.lookup(uuid);
let oldExtension = ExtensionUtils.extensions[uuid];
let extensionDir = oldExtension.dir;
if (!Main.extensionManager.unloadExtension(oldExtension))
if (!ExtensionSystem.unloadExtension(oldExtension))
return;
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
@@ -127,11 +127,11 @@ function updateExtension(uuid) {
let extension = null;
try {
extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension);
} catch (e) {
extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
} catch(e) {
if (extension)
Main.extensionManager.unloadExtension(extension);
ExtensionSystem.unloadExtension(extension);
logError(e, 'Error loading extension %s'.format(uuid));
@@ -140,7 +140,7 @@ function updateExtension(uuid) {
// Restore what was there before. We can't do much if we
// fail here.
Main.extensionManager.loadExtension(oldExtension);
ExtensionSystem.loadExtension(oldExtension);
return;
}
@@ -153,9 +153,9 @@ function updateExtension(uuid) {
function checkForUpdates() {
let metadatas = {};
Main.extensionManager.getUuids().forEach(uuid => {
metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata;
});
for (let uuid in ExtensionUtils.extensions) {
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
}
let params = { shell_version: Config.PACKAGE_VERSION,
installed: JSON.stringify(metadatas) };
@@ -188,9 +188,9 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.setButtons([{ label: _("Cancel"),
action: this._onCancelButtonPressed.bind(this),
key: Clutter.Escape
key: Clutter.Escape
},
{ label: _("Install"),
{ label: _("Install"),
action: this._onInstallButtonPressed.bind(this),
default: true
}]);
@@ -205,12 +205,12 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.contentLayout.add(content);
}
_onCancelButtonPressed() {
_onCancelButtonPressed(button, event) {
this.close();
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
}
_onInstallButtonPressed() {
_onInstallButtonPressed(button, event) {
let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
@@ -222,16 +222,21 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
function errback(code, message) {
let msg = message ? message.toString() : '';
log('Error while installing %s: %s (%s)'.format(uuid, code, msg));
invocation.return_dbus_error(`org.gnome.Shell.${code}`, msg);
invocation.return_dbus_error('org.gnome.Shell.' + code, msg);
}
function callback() {
// Add extension to 'enabled-extensions' for the user, always...
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
if (enabledExtensions.indexOf(uuid) == -1) {
enabledExtensions.push(uuid);
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
try {
let extension = Main.extensionManager.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension);
if (!Main.extensionManager.enableExtension(uuid))
throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`);
} catch (e) {
let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
} catch(e) {
uninstallExtension(uuid);
errback('LoadExtensionError', e);
return;

View File

@@ -1,523 +1,374 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
const { Gio, St } = imports.gi;
const Signals = imports.signals;
const ExtensionUtils = imports.misc.extensionUtils;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
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 DISABLED_EXTENSIONS_KEY = 'disabled-extensions';
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
var ExtensionManager = class {
constructor() {
this._initted = false;
this._enabled = false;
var initted = false;
var enabled;
this._extensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
function disableExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
}
if (extension.state != ExtensionState.ENABLED)
return;
init() {
this._sessionUpdated();
}
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
lookup(uuid) {
return this._extensions.get(uuid);
}
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
getUuids() {
return [...this._extensions.keys()];
}
let orderIdx = extensionOrder.indexOf(uuid);
let order = extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
_callExtensionDisable(uuid) {
let extension = this.lookup(uuid);
if (!extension)
return;
if (extension.state != ExtensionState.ENABLED)
return;
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
let orderIdx = this._extensionOrder.indexOf(uuid);
let order = this._extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
this.lookup(uuid).stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
ExtensionUtils.extensions[uuid].stateObj.disable();
} catch(e) {
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) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
try {
extension.stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
for (let i = 0; i < order.length; i++) {
let 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);
}
logExtensionError(uuid, e);
return;
}
}
_callExtensionEnable(uuid) {
let extension = this.lookup(uuid);
if (!extension)
return;
function logExtensionError(uuid, error) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
if (extension.state == ExtensionState.INITIALIZED)
this._callExtensionInit(uuid);
let message = '' + error;
if (extension.state != ExtensionState.DISABLED)
return;
extension.state = ExtensionState.ERROR;
if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
this._extensionOrder.push(uuid);
log('Extension "%s" had error: %s'.format(uuid, message));
_signals.emit('extension-state-changed', { uuid: uuid,
error: message,
state: extension.state });
}
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}`);
function loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else {
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) {
if (!initExtension(extension.uuid))
return;
}
}
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
this.emit('extension-state-changed', extension);
return;
} catch (e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
this.logExtensionError(uuid, e);
return;
}
}
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);
log('Extension "%s" had error: %s'.format(uuid, message));
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;
if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid);
} else {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
if (!this._callExtensionInit(extension.uuid))
return;
if (extension.state == ExtensionState.DISABLED)
this._callExtensionEnable(extension.uuid);
} else {
extension.state = ExtensionState.INITIALIZED;
}
extension.state = ExtensionState.INITIALIZED;
}
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
unloadExtension(extension) {
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
this._callExtensionDisable(extension.uuid);
_signals.emit('extension-state-changed', extension);
}
extension.state = ExtensionState.UNINSTALLED;
this.emit('extension-state-changed', extension);
function unloadExtension(extension) {
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
disableExtension(extension.uuid);
this._extensions.delete(extension.uuid);
return true;
extension.state = ExtensionState.UNINSTALLED;
_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) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
loadExtension(newExtension);
}
// Then unload the old extension.
this.unloadExtension(oldExtension);
function initExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let dir = extension.dir;
// Now, recreate the extension and load it.
let newExtension;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
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 {
newExtension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
this.logExtensionError(uuid, e);
return;
}
this.loadExtension(newExtension);
}
_callExtensionInit(uuid) {
let extension = this.lookup(uuid);
let dir = extension.dir;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
extensionState = extensionModule.init(extension);
} catch(e) {
logExtensionError(uuid, e);
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 (Array.isArray(Main.sessionMode.enabledExtensions))
return Main.sessionMode.enabledExtensions;
return [];
}
if (!extensionState)
extensionState = extensionModule;
extension.stateObj = extensionState;
_updateCanChange(extension) {
let hasError =
extension.state == ExtensionState.ERROR ||
extension.state == ExtensionState.OUT_OF_DATE;
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-loaded', uuid);
return true;
}
let isMode = this._getModeExtensions().includes(extension.uuid);
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
function getEnabledExtensions() {
let extensions;
if (Array.isArray(Main.sessionMode.enabledExtensions))
extensions = Main.sessionMode.enabledExtensions;
else
extensions = [];
let changeKey = isMode
? DISABLE_USER_EXTENSIONS_KEY
: ENABLED_EXTENSIONS_KEY;
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
return extensions;
extension.canChange =
!hasError &&
global.settings.is_writable(changeKey) &&
(isMode || !modeOnly);
}
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
}
_getEnabledExtensions() {
let extensions = this._getModeExtensions();
function onEnabledExtensionsChanged() {
let newEnabledExtensions = getEnabledExtensions();
if (!global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
extensions = extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
if (!enabled)
return;
// filter out 'disabled-extensions' which takes precedence
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY);
return extensions.filter(item => !disabledExtensions.includes(item));
}
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
uuid => !enabledExtensions.includes(uuid)
).forEach(uuid => {
enableExtension(uuid);
});
_onUserExtensionsEnabledChanged() {
this._onEnabledExtensionsChanged();
this._onSettingsWritableChanged();
}
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
disableExtension(uuid);
});
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
enabledExtensions = newEnabledExtensions;
}
if (!this._enabled)
return;
function _onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
enabledExtensions = [];
for (let uuid in ExtensionUtils.extensions)
reloadExtension(ExtensionUtils.extensions[uuid]);
enabledExtensions = getEnabledExtensions();
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
uuid => !this._enabledExtensions.includes(uuid)
).forEach(uuid => {
this._callExtensionEnable(uuid);
if (Main.sessionMode.allowExtensions) {
enabledExtensions.forEach(uuid => {
enableExtension(uuid);
});
}
}
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
this._enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
this._callExtensionDisable(uuid);
function _loadExtensions() {
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
global.settings.connect('changed::' + DISABLE_USER_EXTENSIONS_KEY, onEnabledExtensionsChanged);
global.settings.connect('changed::' + EXTENSION_DISABLE_VERSION_CHECK_KEY, _onVersionValidationChanged);
enabledExtensions = getEnabledExtensions();
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', (finder, extension) => {
loadExtension(extension);
});
finder.scanExtensions();
}
function enableAllExtensions() {
if (enabled)
return;
if (!initted) {
_loadExtensions();
initted = true;
} else {
enabledExtensions.forEach(uuid => {
enableExtension(uuid);
});
this._enabledExtensions = newEnabledExtensions;
}
enabled = true;
}
_onSettingsWritableChanged() {
for (let extension of this._extensions.values()) {
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
}
function disableAllExtensions() {
if (!enabled)
return;
_onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
this._enabledExtensions = [];
// The loop modifies the extensions map, so iterate over a copy
let extensions = [...this._extensions.values()];
for (let extension of extensions)
this.reloadExtension(extension);
this._enabledExtensions = this._getEnabledExtensions();
if (Main.sessionMode.allowExtensions) {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
}
_loadExtensions() {
global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`,
this._onEnabledExtensionsChanged.bind(this));
global.settings.connect(`changed::${DISABLED_EXTENSIONS_KEY}`,
this._onEnabledExtensionsChanged.bind(this));
global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`,
this._onUserExtensionsEnabledChanged.bind(this));
global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`,
this._onVersionValidationChanged.bind(this));
global.settings.connect(`writable-changed::${ENABLED_EXTENSIONS_KEY}`,
this._onSettingsWritableChanged.bind(this));
global.settings.connect(`writable-changed::${DISABLED_EXTENSIONS_KEY}`,
this._onSettingsWritableChanged.bind(this));
this._enabledExtensions = this._getEnabledExtensions();
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = this.lookup(uuid);
if (existing) {
log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`);
return;
}
let extension;
let type = dir.has_prefix(perUserDir)
? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
logError(e, `Could not load extension ${uuid}`);
return;
}
this.loadExtension(extension);
if (initted) {
extensionOrder.slice().reverse().forEach(uuid => {
disableExtension(uuid);
});
}
_enableAllExtensions() {
if (this._enabled)
return;
enabled = false;
}
if (!this._initted) {
this._loadExtensions();
this._initted = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
this._enabled = true;
function _sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (initted)
enabledExtensions = getEnabledExtensions();
enableAllExtensions();
} else {
disableAllExtensions();
}
}
_disableAllExtensions() {
if (!this._enabled)
return;
if (this._initted) {
this._extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
}
this._enabled = false;
}
_sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (this._initted)
this._enabledExtensions = this._getEnabledExtensions();
this._enableAllExtensions();
} else {
this._disableAllExtensions();
}
}
};
Signals.addSignalMethods(ExtensionManager.prototype);
function init() {
Main.sessionMode.connect('updated', _sessionUpdated);
_sessionUpdated();
}

View File

@@ -49,15 +49,15 @@ var FocusCaretTracker = class FocusCaretTracker {
this._atspiInited = true;
}
return this._atspiInited;
return this._atspiInited;
}
registerFocusListener() {
if (!this._initAtspi() || this._focusListenerRegistered)
return;
this._atspiListener.register(`${STATECHANGED}:focused`);
this._atspiListener.register(`${STATECHANGED}:selected`);
this._atspiListener.register(STATECHANGED + ':focused');
this._atspiListener.register(STATECHANGED + ':selected');
this._focusListenerRegistered = true;
}
@@ -73,8 +73,8 @@ var FocusCaretTracker = class FocusCaretTracker {
if (!this._focusListenerRegistered)
return;
this._atspiListener.deregister(`${STATECHANGED}:focused`);
this._atspiListener.deregister(`${STATECHANGED}:selected`);
this._atspiListener.deregister(STATECHANGED + ':focused');
this._atspiListener.deregister(STATECHANGED + ':selected');
this._focusListenerRegistered = false;
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GrabHelper */
const { Clutter, St } = imports.gi;
@@ -88,7 +87,7 @@ var GrabHelper = class GrabHelper {
_isWithinGrabbedActor(actor) {
let currentActor = this.currentGrab.actor;
while (actor) {
if (this._actors.includes(actor))
if (this._actors.indexOf(actor) != -1)
return true;
if (actor == currentActor)
return true;

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals;
@@ -9,8 +8,8 @@ const Main = imports.ui.main;
var MAX_CANDIDATES_PER_PAGE = 16;
var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
var DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ];
var CandidateArea = class CandidateArea {
constructor() {
@@ -38,14 +37,14 @@ var CandidateArea = class CandidateArea {
this.actor.connect('scroll-event', (actor, event) => {
let direction = event.get_scroll_direction();
switch (direction) {
switch(direction) {
case Clutter.ScrollDirection.UP:
this.emit('cursor-up');
break;
case Clutter.ScrollDirection.DOWN:
this.emit('cursor-down');
break;
}
};
return Clutter.EVENT_PROPAGATE;
});
@@ -182,7 +181,7 @@ var CandidatePopup = class CandidatePopup {
let window = global.display.focus_window.get_compositor_private();
this._setDummyCursorGeometry(window.x + x, window.y + y, w, h);
});
} catch (e) {
} catch(e) {
// Only recent IBus versions have support for this signal
// which is used for wayland clients. In order to work
// with older IBus versions we can silently ignore the
@@ -199,29 +198,29 @@ var CandidatePopup = class CandidatePopup {
this._setTextAttributes(this._preeditText.clutter_text,
attrs);
});
panelService.connect('show-preedit-text', () => {
panelService.connect('show-preedit-text', ps => {
this._preeditText.show();
this._updateVisibility();
});
panelService.connect('hide-preedit-text', () => {
panelService.connect('hide-preedit-text', ps => {
this._preeditText.hide();
this._updateVisibility();
});
panelService.connect('update-auxiliary-text', (_ps, text, visible) => {
panelService.connect('update-auxiliary-text', (ps, text, visible) => {
this._auxText.visible = visible;
this._updateVisibility();
this._auxText.text = text.get_text();
});
panelService.connect('show-auxiliary-text', () => {
panelService.connect('show-auxiliary-text', ps => {
this._auxText.show();
this._updateVisibility();
});
panelService.connect('hide-auxiliary-text', () => {
panelService.connect('hide-auxiliary-text', ps => {
this._auxText.hide();
this._updateVisibility();
});
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
panelService.connect('update-lookup-table', (ps, lookupTable, visible) => {
this._candidateArea.actor.visible = visible;
this._updateVisibility();
@@ -236,7 +235,7 @@ var CandidatePopup = class CandidatePopup {
let indexes = [];
let indexLabel;
for (let i = 0; (indexLabel = lookupTable.get_label(i)); ++i)
indexes.push(indexLabel.get_text());
indexes.push(indexLabel.get_text());
Main.keyboard.resetSuggestions();
@@ -257,15 +256,15 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.setOrientation(lookupTable.get_orientation());
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
});
panelService.connect('show-lookup-table', () => {
panelService.connect('show-lookup-table', ps => {
this._candidateArea.actor.show();
this._updateVisibility();
});
panelService.connect('hide-lookup-table', () => {
panelService.connect('hide-lookup-table', ps => {
this._candidateArea.actor.hide();
this._updateVisibility();
});
panelService.connect('focus-out', () => {
panelService.connect('focus-out', ps => {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});

View File

@@ -1,22 +1,22 @@
// -*- 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 Tweener = imports.ui.tweener;
const Main = imports.ui.main;
var ICON_SIZE = 96;
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_OUT = 1 / 2 * 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_MAX_DELAY_OUT_FOR_ITEM = 2 / 3 * ANIMATION_TIME_OUT;
var ANIMATION_FADE_IN_TIME_FOR_ITEM = 1 / 4 * ANIMATION_TIME_IN;
var ANIMATION_TIME_IN = 0.350;
var ANIMATION_TIME_OUT = 1/2 * 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_MAX_DELAY_OUT_FOR_ITEM = 2/3 * ANIMATION_TIME_OUT;
var ANIMATION_FADE_IN_TIME_FOR_ITEM = 1/4 * ANIMATION_TIME_IN;
var ANIMATION_BOUNCE_ICON_SCALE = 1.1;
@@ -26,7 +26,7 @@ var AnimationDirection = {
};
var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 250;
var APPICON_ANIMATION_OUT_TIME = 0.25;
var BaseIcon = GObject.registerClass(
class BaseIcon extends St.Bin {
@@ -56,10 +56,6 @@ class BaseIcon extends St.Bin {
if (params.showLabel) {
this.label = new St.Label({ text: label });
this.label.clutter_text.set({
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER
});
this._box.add_actor(this.label);
} else {
this.label = null;
@@ -75,14 +71,14 @@ class BaseIcon extends St.Bin {
this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this));
}
vfunc_get_preferred_width(_forHeight) {
vfunc_get_preferred_width(forHeight) {
// Return the actual height to keep the squared aspect
return this.get_preferred_height(-1);
}
// This can be overridden by a subclass, or by the createIcon
// parameter to _init()
createIcon(_size) {
createIcon(size) {
throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`);
}
@@ -141,15 +137,11 @@ class BaseIcon extends St.Bin {
// animating.
zoomOutActor(this.child);
}
update() {
this._createIconTexture(this.iconSize);
}
});
function clamp(value, min, max) {
return Math.max(Math.min(value, max), min);
}
};
function zoomOutActor(actor) {
let actorClone = new Clutter.Clone({ source: actor,
@@ -172,21 +164,23 @@ function zoomOutActor(actor) {
let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth);
let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight);
actorClone.ease({
scale_x: APPICON_ANIMATION_OUT_SCALE,
scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX,
translation_y: containedY - scaledY,
opacity: 0,
duration: APPICON_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => actorClone.destroy()
});
Tweener.addTween(actorClone,
{ time: APPICON_ANIMATION_OUT_TIME,
scale_x: APPICON_ANIMATION_OUT_SCALE,
scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX,
translation_y: containedY - scaledY,
opacity: 0,
transition: 'easeOutQuad',
onComplete() {
actorClone.destroy();
}
});
}
var IconGrid = GObject.registerClass({
Signals: { 'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype] } },
Signals: {'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype]} },
}, class IconGrid extends St.Widget {
_init(params) {
super._init({ style_class: 'icon-grid',
@@ -212,8 +206,6 @@ var IconGrid = GObject.registerClass({
this.rightPadding = 0;
this.leftPadding = 0;
this._updateIconSizesLaterId = 0;
this._items = [];
this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here
@@ -226,19 +218,11 @@ var IconGrid = GObject.registerClass({
// swarming into the void ...
this.connect('notify::mapped', () => {
if (!this.mapped)
this._resetAnimationActors();
this._cancelAnimation();
});
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._updateIconSizesLaterId) {
Meta.later_remove (this._updateIconSizesLaterId);
this._updateIconSizesLaterId = 0;
}
}
_keyFocusIn(actor) {
@@ -253,7 +237,7 @@ var IconGrid = GObject.registerClass({
child.disconnect(child._iconGridKeyFocusInId);
}
vfunc_get_preferred_width(_forHeight) {
vfunc_get_preferred_width(forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
@@ -292,7 +276,7 @@ var IconGrid = GObject.registerClass({
if (forWidth < 0)
nColumns = children.length;
else
[nColumns] = this._computeLayout(forWidth);
[nColumns, ] = this._computeLayout(forWidth);
let nRows;
if (nColumns > 0)
@@ -327,15 +311,15 @@ var IconGrid = GObject.registerClass({
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
switch(this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let animating = this._clonesAnimating.length > 0;
@@ -393,15 +377,15 @@ var IconGrid = GObject.registerClass({
return true;
for (let child = this.get_first_child();
child != null;
child = child.get_next_sibling()) {
child != null;
child = child.get_next_sibling()) {
if (!child.visible || !child.opacity)
continue;
let childVolume = child.get_transformed_paint_volume(this);
if (!childVolume)
return false;
return false
paintVolume.union(childVolume);
}
@@ -417,17 +401,18 @@ var IconGrid = GObject.registerClass({
return this._getVisibleChildren();
}
_resetAnimationActors() {
_cancelAnimation() {
this._clonesAnimating.forEach(clone => { clone.destroy(); });
this._clonesAnimating = [];
}
_animationDone() {
this._clonesAnimating.forEach(clone => {
clone.source.reactive = true;
clone.source.opacity = 255;
clone.destroy();
});
this._clonesAnimating = [];
}
_animationDone() {
this._resetAnimationActors();
this.emit('animation-done');
}
@@ -436,7 +421,7 @@ var IconGrid = GObject.registerClass({
throw new GObject.NotImplementedError("Pulse animation only implements " +
"'in' animation direction");
this._resetAnimationActors();
this._cancelAnimation();
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
@@ -459,32 +444,30 @@ var IconGrid = GObject.registerClass({
let delay = index / actors.length * maxDelay;
let bounceUpTime = ANIMATION_TIME_IN / 4;
let isLastItem = index == actors.length - 1;
actor.ease({
scale_x: ANIMATION_BOUNCE_ICON_SCALE,
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
duration: bounceUpTime,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: delay,
onComplete: () => {
let duration = ANIMATION_TIME_IN - bounceUpTime;
actor.ease({
scale_x: 1,
scale_y: 1,
duration,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
onComplete: () => {
if (isLastItem)
this._animationDone();
actor.reactive = true;
}
});
}
});
Tweener.addTween(actor,
{ time: bounceUpTime,
transition: 'easeInOutQuad',
delay: delay,
scale_x: ANIMATION_BOUNCE_ICON_SCALE,
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
onComplete: () => {
Tweener.addTween(actor,
{ time: ANIMATION_TIME_IN - bounceUpTime,
transition: 'easeInOutQuad',
scale_x: 1,
scale_y: 1,
onComplete: () => {
if (isLastItem)
this._animationDone();
}
});
}
});
}
}
animateSpring(animationDirection, sourceActor) {
this._resetAnimationActors();
this._cancelAnimation();
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
@@ -521,7 +504,7 @@ var IconGrid = GObject.registerClass({
this._clonesAnimating.push(actorClone);
Main.uiGroup.add_actor(actorClone);
let [width, height] = this._getAllocatedChildSizeAndSpacing(actor);
let [width, height,,] = this._getAllocatedChildSizeAndSpacing(actor);
actorClone.set_size(width, height);
let scaleX = sourceScaledWidth / width;
let scaleY = sourceScaledHeight / height;
@@ -538,25 +521,21 @@ var IconGrid = GObject.registerClass({
let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM;
let [finalX, finalY] = actor._transformedPosition;
movementParams = {
x: finalX,
y: finalY,
scale_x: 1,
scale_y: 1,
duration: ANIMATION_TIME_IN,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
if (isLastItem)
movementParams.onComplete = this._animationDone.bind(this);
fadeParams = {
opacity: 255,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
movementParams = { time: ANIMATION_TIME_IN,
transition: 'easeInOutQuad',
delay: delay,
x: finalX,
y: finalY,
scale_x: 1,
scale_y: 1,
onComplete: () => {
if (isLastItem)
this._animationDone();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: delay,
opacity: 255 };
} else {
let isLastItem = actor._distance == maxDist;
@@ -564,29 +543,26 @@ var IconGrid = GObject.registerClass({
actorClone.set_position(startX, startY);
let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM;
movementParams = {
x: adjustedSourcePositionX,
y: adjustedSourcePositionY,
scale_x: scaleX,
scale_y: scaleY,
duration: ANIMATION_TIME_OUT,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay
};
if (isLastItem)
movementParams.onComplete = this._animationDone.bind(this);
fadeParams = {
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
};
movementParams = { time: ANIMATION_TIME_OUT,
transition: 'easeInOutQuad',
delay: delay,
x: adjustedSourcePositionX,
y: adjustedSourcePositionY,
scale_x: scaleX,
scale_y: scaleY,
onComplete: () => {
if (isLastItem)
this._animationDone();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM,
opacity: 0 };
}
actorClone.ease(movementParams);
actorClone.ease(fadeParams);
Tweener.addTween(actorClone, movementParams);
Tweener.addTween(actorClone, fadeParams);
}
}
@@ -626,8 +602,6 @@ var IconGrid = GObject.registerClass({
}
_computeLayout(forWidth) {
this.ensure_style();
let nColumns = 0;
let usedWidth = this.leftPadding + this.rightPadding;
let spacing = this._getSpacing();
@@ -736,8 +710,8 @@ var IconGrid = GObject.registerClass({
if (this._padWithSpacing) {
// minRows + 1 because we want to put spacing before the first row, so it is like we have one more row
// to divide the empty space
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows + 1));
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns + 1));
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows +1));
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns +1));
} else {
if (this._minRows <= 1)
maxVSpacing = maxEmptyVArea;
@@ -769,10 +743,11 @@ var IconGrid = GObject.registerClass({
this._fixedHItemSize = this._hItemSize;
this._fixedVItemSize = this._vItemSize;
this._updateSpacingForSize(availWidth, availHeight);
let spacing = this._getSpacing();
if (this.columnsForWidth(availWidth) < this._minColumns || this.rowsForHeight(availHeight) < this._minRows) {
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight ;
let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
@@ -781,26 +756,23 @@ var IconGrid = GObject.registerClass({
this._updateSpacingForSize(availWidth, availHeight);
}
if (!this._updateIconSizesLaterId)
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
}
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateIconSizes() {
this._updateIconSizesLaterId = 0;
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale);
for (let i in this._items) {
this._items[i].icon.setIconSize(newIconSize);
}
return GLib.SOURCE_REMOVE;
}
});
var PaginatedIconGrid = GObject.registerClass({
Signals: { 'space-opened': {},
'space-closed': {} },
Signals: {'space-opened': {},
'space-closed': {} },
}, class PaginatedIconGrid extends IconGrid {
_init(params) {
super._init(params);
@@ -811,13 +783,13 @@ var PaginatedIconGrid = GObject.registerClass({
this._childrenPerPage = 0;
}
vfunc_get_preferred_height(_forWidth) {
vfunc_get_preferred_height(forWidth) {
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
}
vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
this.set_allocation(box, flags);
@@ -830,24 +802,26 @@ var PaginatedIconGrid = GObject.registerClass({
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
switch(this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
@@ -857,15 +831,15 @@ var PaginatedIconGrid = GObject.registerClass({
columnIndex++;
if (columnIndex == nColumns) {
columnIndex = 0;
rowIndex++;
}
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage == 0)
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else {
} else
x += this._getHItemSize() + spacing;
}
}
}
@@ -879,7 +853,7 @@ var PaginatedIconGrid = GObject.registerClass({
}
_computePages(availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage);
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows;
let children = this._getVisibleChildren();
if (nColumns > 0)
@@ -889,6 +863,7 @@ var PaginatedIconGrid = GObject.registerClass({
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let spacing = this._getSpacing();
// We want to contain the grid inside the parent box with padding
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
this._nPages = Math.ceil(nRows / this._rowsPerPage);
@@ -917,7 +892,7 @@ var PaginatedIconGrid = GObject.registerClass({
if (!this._nPages)
return 0;
let firstPageItem = pageNumber * this._childrenPerPage;
let firstPageItem = pageNumber * this._childrenPerPage
let childBox = this._getVisibleChildren()[firstPageItem].get_allocation_box();
return childBox.y1 - this.topPadding;
}
@@ -991,14 +966,13 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < children.length; i++) {
children[i].translation_y = 0;
let params = {
translation_y: translationY,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD
};
let params = { translation_y: translationY,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad'
};
if (i == (children.length - 1))
params.onComplete = () => this.emit('space-opened');
children[i].ease(params);
params.onComplete = () => { this.emit('space-opened'); };
Tweener.addTween(children[i], params);
}
}
@@ -1011,12 +985,12 @@ var PaginatedIconGrid = GObject.registerClass({
for (let i = 0; i < this._translatedChildren.length; i++) {
if (!this._translatedChildren[i].translation_y)
continue;
this._translatedChildren[i].ease({
translation_y: 0,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
onComplete: () => this.emit('space-closed')
});
Tweener.addTween(this._translatedChildren[i],
{ translation_y: 0,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad',
onComplete: () => { this.emit('space-closed'); }
});
}
}
});

View File

@@ -1,4 +1,3 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
@@ -112,7 +111,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
}
vfunc_show() {
if (this._app && APP_WHITELIST.includes(this._app.get_id())) {
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1) {
this._emitResponse(DialogResponse.ALLOW);
return;
}
@@ -140,7 +139,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
return;
}
let [permissions] = res;
let [permissions, data] = res;
if (permissions[appId] === undefined) // Not found
this._dialog.open();
else if (permissions[appId] == GRANTED)

View File

@@ -1,4 +1,3 @@
/* exported KbdA11yDialog */
const { Clutter, Gio, GObject } = imports.gi;
const Dialog = imports.ui.dialog;

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Keyboard */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals;
@@ -11,10 +10,11 @@ const Layout = imports.ui.layout;
const Main = imports.ui.main;
const PageIndicators = imports.ui.pageIndicators;
const PopupMenu = imports.ui.popupMenu;
const Tweener = imports.ui.tweener;
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 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 */
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
@@ -24,29 +24,29 @@ const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const KEY_SIZE = 2;
const defaultKeysPre = [
[[], [], [{ width: 1.5, level: 1, extraClassName: 'shift-key-lowercase' }], [{ label: '?123', width: 1.5, level: 2 }]],
[[], [], [{ width: 1.5, level: 0, extraClassName: 'shift-key-uppercase' }], [{ label: '?123', width: 1.5, level: 2 }]],
[[], [], [{ label: '=/<', width: 1.5, level: 3 }], [{ label: 'ABC', width: 1.5, level: 0 }]],
[[], [], [{ label: '?123', width: 1.5, level: 2 }], [{ label: 'ABC', width: 1.5, level: 0 }]],
[ [], [], [{ width: 1.5, level: 1, extraClassName: 'shift-key-lowercase' }], [{ label: '?123', width: 1.5, level: 2 }] ],
[ [], [], [{ width: 1.5, level: 0, extraClassName: 'shift-key-uppercase' }], [{ label: '?123', width: 1.5, level: 2 }] ],
[ [], [], [{ label: '=/<', width: 1.5, level: 3 }], [{ label: 'ABC', width: 1.5, level: 0 }] ],
[ [], [], [{ label: '?123', width: 1.5, level: 2 }], [{ label: 'ABC', width: 1.5, level: 0 }] ],
];
const defaultKeysPost = [
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '=/<', width: 3, level: 3, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '?123', width: 3, level: 2, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '=/<', width: 3, level: 3, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '?123', width: 3, level: 2, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
];
var AspectContainer = GObject.registerClass(
@@ -100,7 +100,7 @@ class KeyContainer extends St.Widget {
this._rows = [];
}
appendRow() {
appendRow(length) {
this._currentRow++;
this._currentCol = 0;
@@ -297,7 +297,7 @@ var Key = class Key {
}
_press(key) {
this.emit('activated');
this.emit('activated')
if (key != this.key || this._extended_keys.length == 0) {
this.emit('pressed', this._getKeyval(key), key);
@@ -405,6 +405,9 @@ var Key = class Key {
return Clutter.EVENT_PROPAGATE;
});
button.connect('touch-event', (actor, event) => {
let device = event.get_device();
let sequence = event.get_event_sequence();
// We only handle touch events here on wayland. On X11
// we do get emulated pointer events, which already works
// for single-touch cases. Besides, the X11 passive touch grab
@@ -474,7 +477,7 @@ var KeyboardModel = class {
_loadModel(groupName) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName));
let [success_, contents] = file.load_contents(null);
let [success, contents] = file.load_contents(null);
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
@@ -569,27 +572,11 @@ var FocusTracker = class {
};
Signals.addSignalMethods(FocusTracker.prototype);
var EmojiPager = GObject.registerClass({
Properties: {
'delta': GObject.ParamSpec.int(
'delta', 'delta', 'delta',
GObject.ParamFlags.READWRITE,
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
});
var EmojiPager = class EmojiPager {
constructor(sections, nCols, nRows) {
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
reactive: true,
clip_to_allocation: true });
this._sections = sections;
this._nCols = nCols;
this._nRows = nRows;
@@ -611,7 +598,7 @@ var EmojiPager = GObject.registerClass({
panAction.connect('gesture-cancel', this._onPanCancel.bind(this));
panAction.connect('gesture-end', this._onPanEnd.bind(this));
this._panAction = panAction;
this.add_action(panAction);
this.actor.add_action(panAction);
}
get delta() {
@@ -624,11 +611,7 @@ var EmojiPager = GObject.registerClass({
else if (value < -this._width)
value = -this._width;
if (this._delta == value)
return;
this._delta = value;
this.notify('delta');
if (value == 0)
return;
@@ -645,8 +628,8 @@ var EmojiPager = GObject.registerClass({
if (followingPage != null) {
this._followingPanel = this._generatePanel(followingPage);
this._followingPanel.set_pivot_point(0.5, 0.5);
this.add_child(this._followingPanel);
this.set_child_below_sibling(this._followingPanel, this._panel);
this.actor.add_child(this._followingPanel);
this.actor.set_child_below_sibling(this._followingPanel, this._panel);
}
this._followingPage = followingPage;
@@ -682,7 +665,7 @@ var EmojiPager = GObject.registerClass({
}
_onPan(action) {
let [dist_, dx, dy_] = action.get_motion_delta(0);
let [dist, dx, dy] = action.get_motion_delta(0);
this.delta = this.delta + dx;
if (this._currentKey != null) {
@@ -694,13 +677,13 @@ var EmojiPager = GObject.registerClass({
}
_onPanBegin() {
this._width = this.width;
this._width = this.actor.width;
return true;
}
_onPanEnd() {
if (Math.abs(this._delta) < this.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
this._onPanCancel();
if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
this._onPanCancel()
} else {
let value;
if (this._delta > 0)
@@ -711,24 +694,28 @@ var EmojiPager = GObject.registerClass({
let relDelta = Math.abs(this._delta - value) / this._width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
this.remove_all_transitions();
this.ease_property('delta', value, {
duration: time,
onComplete: () => {
this.setCurrentPage(this.getFollowingPage());
}
});
Tweener.removeTweens(this);
Tweener.addTween(this,
{ delta: value,
time: time,
transition: 'easeInOutQuad',
onComplete() {
this.setCurrentPage(this.getFollowingPage());
}
});
}
}
_onPanCancel() {
let relDelta = Math.abs(this._delta) / this.width;
let relDelta = Math.abs(this._delta) / this.actor.width;
let time = PANEL_SWITCH_ANIMATION_TIME * Math.abs(relDelta);
this.remove_all_transitions();
this.ease_property('delta', 0, {
duration: time,
});
Tweener.removeTweens(this);
Tweener.addTween(this,
{ delta: 0,
time: time,
transition: 'easeInOutQuad',
});
}
_initPagingInfo() {
@@ -838,7 +825,7 @@ var EmojiPager = GObject.registerClass({
if (!this._panel) {
this._panel = this._generatePanel(nPage);
this.add_child(this._panel);
this.actor.add_child(this._panel);
}
let page = this._pages[nPage];
@@ -855,7 +842,8 @@ var EmojiPager = GObject.registerClass({
}
}
}
});
};
Signals.addSignalMethods(EmojiPager.prototype);
var EmojiSelection = class EmojiSelection {
constructor() {
@@ -877,7 +865,7 @@ var EmojiSelection = class EmojiSelection {
x_expand: true,
y_expand: true,
vertical: true });
this.actor.connect('notify::mapped', () => this._emojiPager.setCurrentPage(0));
this.actor.connect('notify::mapped', () => { this._emojiPager.setCurrentPage(0); });
this._emojiPager = new EmojiPager(this._sections, 11, 3);
this._emojiPager.connect('page-changed', (pager, section, page, nPages) => {
@@ -919,12 +907,13 @@ var EmojiSelection = class EmojiSelection {
_populateSections() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json');
let [success_, contents] = file.load_contents(null);
let [success, contents] = file.load_contents(null);
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
let emoji = JSON.parse(contents);
let pages = [];
let variants = [];
let currentKey = 0;
let currentSection = null;
@@ -959,14 +948,14 @@ var EmojiSelection = class EmojiSelection {
key = new Key('ABC', []);
key.keyButton.add_style_class_name('default-key');
key.connect('released', () => this.emit('toggle'));
key.connect('released', () => { this.emit('toggle'); });
row.appendKey(key.actor, 1.5);
for (let i = 0; i < this._sections.length; i++) {
let section = this._sections[i];
key = new Key(section.label, []);
key.connect('released', () => this._emojiPager.setCurrentSection(section, 0));
key.connect('released', () => { this._emojiPager.setCurrentSection(section, 0) });
row.appendKey(key.actor);
section.button = key;
@@ -1085,7 +1074,7 @@ var Keyboard = class Keyboard {
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId);
if (!device.get_device_name().includes('XTEST')) {
if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDeviceId = deviceId;
this._syncEnabled();
}
@@ -1186,7 +1175,7 @@ var Keyboard = class Keyboard {
this._emojiSelection = new EmojiSelection();
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._keyboardController.commitString(emoji);
});
@@ -1239,12 +1228,12 @@ var Keyboard = class Keyboard {
}
if (!this._showIdleId) {
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex);
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex);
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
}
}
@@ -1297,7 +1286,7 @@ var Keyboard = class Keyboard {
}
}
});
button.connect('released', (actor, keyval, _str) => {
button.connect('released', (actor, keyval, str) => {
if (keyval != 0) {
if (button._keyvalPress)
this._keyboardController.keyvalRelease(keyval);
@@ -1417,6 +1406,8 @@ var Keyboard = class Keyboard {
}
_getDefaultKeysForRow(row, numRows, level) {
let pre, post;
/* The first 2 rows in defaultKeysPre/Post belong together with
* the first 2 rows on each keymap. On keymaps that have more than
* 4 rows, the last 2 default key rows must be respectively
@@ -1457,8 +1448,8 @@ var Keyboard = class Keyboard {
numOfVertSlots = rows.length;
for (let i = 0; i < rows.length; ++i) {
let keyboardRow = rows[i];
let keys = keyboardRow.get_children();
let keyboard_row = rows[i];
let keys = keyboard_row.get_children();
numOfHorizSlots = Math.max(numOfHorizSlots, keys.length);
}
@@ -1482,7 +1473,7 @@ var Keyboard = class Keyboard {
this._setActiveLayer(0);
}
_onKeyboardGroupsChanged() {
_onKeyboardGroupsChanged(keyboard) {
let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor];
this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
c.destroy();
@@ -1655,7 +1646,8 @@ var Keyboard = class Keyboard {
}
_windowSlideAnimationComplete(window, delta) {
// Synchronize window positions again.
// Synchronize window and actor positions again.
let windowActor = window.get_compositor_private();
let frameRect = window.get_frame_rect();
frameRect.y += delta;
window.move_frame(true, frameRect.x, frameRect.y);
@@ -1668,23 +1660,19 @@ var Keyboard = class Keyboard {
return;
if (show) {
windowActor.ease({
y: windowActor.y - deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._windowSlideAnimationComplete(window, -deltaY);
}
});
Tweener.addTween(windowActor,
{ y: windowActor.y - deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, -deltaY] });
} else {
windowActor.ease({
y: windowActor.y + deltaY,
duration: Layout.KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._windowSlideAnimationComplete(window, deltaY);
}
});
Tweener.addTween(windowActor,
{ y: windowActor.y + deltaY,
time: Layout.KEYBOARD_ANIMATION_TIME,
transition: 'easeInQuad',
onComplete: this._windowSlideAnimationComplete,
onCompleteParams: [window, deltaY] });
}
}
@@ -1700,11 +1688,12 @@ var Keyboard = class Keyboard {
this._animFocusedWindow = window;
}
setCursorLocation(window, x, y, w, h) {
setCursorLocation(window, x, y , w, h) {
let monitor = Main.layoutManager.keyboardMonitor;
if (window && monitor) {
let keyboardHeight = Main.layoutManager.keyboardBox.height;
let focusObscured = false;
if (y + h >= monitor.y + monitor.height - keyboardHeight) {
if (this._keyboardVisible)
@@ -1748,13 +1737,14 @@ var KeyboardController = class {
this.emit('groups-changed');
}
_onSourceChanged(inputSourceManager, _oldSource) {
_onSourceChanged(inputSourceManager, oldSource) {
let source = inputSourceManager.currentSource;
this._currentSource = source;
this.emit('active-group', source.id);
}
_onContentPurposeHintsChanged(method) {
let hints = method.content_hints;
let purpose = method.content_purpose;
let emojiVisible = false;
let keypadVisible = false;
@@ -1769,13 +1759,13 @@ var KeyboardController = class {
purpose == Clutter.InputContentPurpose.PHONE)
keypadVisible = true;
this.emit('emoji-visible', emojiVisible);
this.emit('emoji-visible', emojiVisible)
this.emit('keypad-visible', keypadVisible);
}
getGroups() {
let inputSources = this._inputSourceManager.inputSources;
let groups = [];
let groups = []
for (let i in inputSources) {
let is = inputSources[i];

View File

@@ -1,7 +1,6 @@
// -*- 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, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -11,17 +10,18 @@ const LoginManager = imports.misc.loginManager;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Ripples = imports.ui.ripples;
var STARTUP_ANIMATION_TIME = 500;
var KEYBOARD_ANIMATION_TIME = 150;
var BACKGROUND_FADE_ANIMATION_TIME = 1000;
var STARTUP_ANIMATION_TIME = 0.5;
var KEYBOARD_ANIMATION_TIME = 0.15;
var BACKGROUND_FADE_ANIMATION_TIME = 1.0;
var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
function isPopupMetaWindow(actor) {
switch (actor.meta_window.get_window_type()) {
switch(actor.meta_window.get_window_type()) {
case Meta.WindowType.DROPDOWN_MENU:
case Meta.WindowType.POPUP_MENU:
case Meta.WindowType.COMBO:
@@ -32,20 +32,18 @@ function isPopupMetaWindow(actor) {
}
var MonitorConstraint = GObject.registerClass({
Properties: {
'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1),
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)
},
Properties: {'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1),
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)},
}, class MonitorConstraint extends Clutter.Constraint {
_init(props) {
this._primary = false;
@@ -80,12 +78,10 @@ var MonitorConstraint = GObject.registerClass({
this.notify('index');
}
// eslint-disable-next-line camelcase
get work_area() {
return this._workArea;
}
// eslint-disable-next-line camelcase
set work_area(v) {
if (v == this._workArea)
return;
@@ -151,13 +147,13 @@ var MonitorConstraint = GObject.registerClass({
});
var Monitor = class Monitor {
constructor(index, geometry, geometryScale) {
constructor(index, geometry, geometry_scale) {
this.index = index;
this.x = geometry.x;
this.y = geometry.y;
this.width = geometry.width;
this.height = geometry.height;
this.geometry_scale = geometryScale;
this.geometry_scale = geometry_scale;
}
get inFullscreen() {
@@ -167,12 +163,12 @@ var Monitor = class Monitor {
const UiActor = GObject.registerClass(
class UiActor extends St.Widget {
vfunc_get_preferred_width (_forHeight) {
vfunc_get_preferred_width (forHeight) {
let width = global.stage.width;
return [width, width];
}
vfunc_get_preferred_height (_forWidth) {
vfunc_get_preferred_height (forWidth) {
let height = global.stage.height;
return [height, height];
}
@@ -276,13 +272,6 @@ var LayoutManager = GObject.registerClass({
this._backgroundGroup.lower_bottom();
this._bgManagers = [];
this._interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface'
});
this._interfaceSettings.connect('changed::enable-hot-corners',
this._updateHotCorners.bind(this));
// Need to update struts on new workspaces when they are added
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
@@ -386,11 +375,6 @@ var LayoutManager = GObject.registerClass({
});
this.hotCorners = [];
if (!this._interfaceSettings.get_boolean('enable-hot-corners')) {
this.emit('hot-corners-changed');
return;
}
let size = this.panelBox.height;
// build new hot corners
@@ -463,11 +447,10 @@ var LayoutManager = GObject.registerClass({
let backgroundActor = this._bgManagers[i].backgroundActor;
backgroundActor.show();
backgroundActor.opacity = 0;
backgroundActor.ease({
opacity: 255,
duration: BACKGROUND_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(backgroundActor,
{ opacity: 255,
time: BACKGROUND_FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
}
}
}
@@ -698,23 +681,23 @@ var LayoutManager = GObject.registerClass({
}
_startupAnimationGreeter() {
this.panelBox.ease({
translation_y: 0,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete()
});
Tweener.addTween(this.panelBox,
{ translation_y: 0,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
}
_startupAnimationSession() {
this.uiGroup.ease({
scale_x: 1,
scale_y: 1,
opacity: 255,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete()
});
Tweener.addTween(this.uiGroup,
{ scale_x: 1,
scale_y: 1,
opacity: 255,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this });
}
_startupAnimationComplete() {
@@ -740,15 +723,14 @@ var LayoutManager = GObject.registerClass({
showKeyboard() {
this.keyboardBox.show();
this.keyboardBox.ease({
anchor_y: this.keyboardBox.height,
opacity: 255,
duration: KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._showKeyboardComplete();
}
});
Tweener.addTween(this.keyboardBox,
{ anchor_y: this.keyboardBox.height,
opacity: 255,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showKeyboardComplete,
onCompleteScope: this
});
this.emit('keyboard-visible-changed', true);
}
@@ -767,16 +749,14 @@ var LayoutManager = GObject.registerClass({
this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
this._keyboardHeightNotifyId = 0;
}
this.keyboardBox.ease({
anchor_y: 0,
opacity: 0,
duration: immediate ? 0
: KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._hideKeyboardComplete();
}
});
Tweener.addTween(this.keyboardBox,
{ anchor_y: 0,
opacity: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeInQuad',
onComplete: this._hideKeyboardComplete,
onCompleteScope: this
});
this.emit('keyboard-visible-changed', false);
}
@@ -847,7 +827,7 @@ var LayoutManager = GObject.registerClass({
// @params can have any of the same values as in addChrome(),
// though some possibilities don't make sense. By default, @actor has
// the same params as its chrome ancestor.
trackChrome(actor, params = {}) {
trackChrome(actor, params) {
let ancestor = actor.get_parent();
let index = this._findActor(ancestor);
while (ancestor && index == -1) {
@@ -857,6 +837,8 @@ var LayoutManager = GObject.registerClass({
let ancestorData = ancestor ? this._trackedActors[index]
: defaultParams;
if (!params)
params = {};
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
@@ -1085,7 +1067,7 @@ var LayoutManager = GObject.registerClass({
else
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 });
struts.push(strut);
}
@@ -1236,7 +1218,7 @@ var HotCorner = class HotCorner {
}
}
handleDragOver(source, _actor, _x, _y, _time) {
handleDragOver(source, actor, x, y, time) {
if (source != Main.xdndHandler)
return DND.DragMotionResult.CONTINUE;
@@ -1337,7 +1319,7 @@ var PressureBarrier = class PressureBarrier {
let threshold = this._lastTime - this._timeout;
while (i < this._barrierEvents.length) {
let [time, distance_] = this._barrierEvents[i];
let [time, distance] = this._barrierEvents[i];
if (time >= threshold)
break;
i++;
@@ -1346,14 +1328,14 @@ var PressureBarrier = class PressureBarrier {
let firstNewEvent = i;
for (i = 0; i < firstNewEvent; i++) {
let [time_, distance] = this._barrierEvents[i];
let [time, distance] = this._barrierEvents[i];
this._currentPressure -= distance;
}
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
}
_onBarrierLeft(barrier, _event) {
_onBarrierLeft(barrier, event) {
barrier._isHit = false;
if (this._barriers.every(b => !b._isHit)) {
this._reset();

View File

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

View File

@@ -1,25 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LocatePointer */
const { Gio } = imports.gi;
const { Clutter, Gio, GLib, St } = imports.gi;
const Ripples = imports.ui.ripples;
const Main = imports.ui.main;
const LOCATE_POINTER_KEY = "locate-pointer";
const LOCATE_POINTER_SCHEMA = "org.gnome.desktop.interface";
const LOCATE_POINTER_SCHEMA = "org.gnome.desktop.interface"
var LocatePointer = class {
var locatePointer = class {
constructor() {
this._settings = new Gio.Settings({ schema_id: LOCATE_POINTER_SCHEMA });
this._settings = new Gio.Settings({schema_id: LOCATE_POINTER_SCHEMA});
this._ripples = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location');
this._ripples.addTo(Main.uiGroup);
}
show() {
if (!this._settings.get_boolean(LOCATE_POINTER_KEY))
if (!this._settings.get_boolean("locate-pointer"))
return;
let [x, y] = global.get_pointer();
let [x, y, mods] = global.get_pointer();
this._ripples.playAnimation(x, y);
}
};

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
@@ -8,19 +7,20 @@ const Signals = imports.signals;
const System = imports.system;
const History = imports.misc.history;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionUtils = imports.misc.extensionUtils;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const JsParse = imports.misc.jsParse;
const { ExtensionState } = ExtensionUtils;
const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
'const Main = imports.ui.main; ' +
'const Mainloop = imports.mainloop; ' +
'const Tweener = imports.ui.tweener; ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
'const stage = global.stage; ' +
@@ -32,11 +32,9 @@ var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = im
const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event
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();
const LG_ANIMATION_TIME = 500;
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_')
@@ -70,10 +68,10 @@ var AutoComplete = class AutoComplete {
if (commonPrefix.length > 0) {
this.additionalCompletionText(commonPrefix, event.attrHead);
this.emit('completion', { completion: commonPrefix, type: 'prefix' });
this.emit('suggest', { completions: event.completions });
this.emit('suggest', { completions: event.completions});
}
} else if (event.completions.length > 1 && event.tabType === 'double') {
this.emit('suggest', { completions: event.completions });
this.emit('suggest', { completions: event.completions});
}
}
@@ -148,8 +146,8 @@ var Notebook = class Notebook {
this.actor.add(scrollview, { expand: true });
let vAdjust = scrollview.vscroll.adjustment;
vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData));
vAdjust.connect('notify::value', () => this._onAdjustValueChanged(tabData));
vAdjust.connect('changed', () => { this._onAdjustScopeChanged(tabData); });
vAdjust.connect('notify::value', () => { this._onAdjustValueChanged(tabData); });
if (this._selectedIndex == -1)
this.selectIndex(0);
@@ -187,9 +185,9 @@ var Notebook = class Notebook {
}
selectChild(child) {
if (child == null) {
if (child == null)
this.selectIndex(-1);
} else {
else {
for (let i = 0; i < this._tabs.length; i++) {
let tabData = this._tabs[i];
if (tabData.child == child) {
@@ -244,7 +242,7 @@ function objectToString(o) {
// special case this since the default is way, way too verbose
return '<js function>';
} else {
return `${o}`;
return '' + o;
}
}
@@ -268,7 +266,7 @@ var ObjLink = class ObjLink {
this._lookingGlass = lookingGlass;
}
_onClicked() {
_onClicked(link) {
this._lookingGlass.inspectObject(this._obj, this.actor);
}
};
@@ -286,7 +284,7 @@ var Result = class Result {
this.actor.add(cmdTxt);
let box = new St.BoxLayout({});
this.actor.add(box);
let resultTxt = new St.Label({ text: `r(${index}) = ` });
let resultTxt = new St.Label({ text: 'r(' + index + ') = ' });
resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
box.add(resultTxt);
let objLink = new ObjLink(this._lookingGlass, o);
@@ -322,7 +320,7 @@ var WindowList = class WindowList {
box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false });
let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
box.add(propsBox);
propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` }));
propsBox.add(new St.Label({ text: 'wmclass: ' + metaWindow.get_wm_class() }));
let app = tracker.get_window_app(metaWindow);
if (app != null && !app.is_window_backed()) {
let icon = app.create_icon_texture(22);
@@ -396,6 +394,7 @@ var ObjInspector = class ObjInspector {
for (let i = 0; i < properties.length; i++) {
let propName = properties[i];
let valueStr;
let link;
try {
let prop = obj[propName];
@@ -404,7 +403,8 @@ var ObjInspector = class ObjInspector {
link = new St.Label({ text: '<error>' });
}
let hbox = new St.BoxLayout();
hbox.add(new St.Label({ text: `${propName}: ` }));
let propText = propName + ': ' + valueStr;
hbox.add(new St.Label({ text: propName + ': ' }));
hbox.add(link);
this._container.add_actor(hbox);
}
@@ -419,12 +419,9 @@ var ObjInspector = class ObjInspector {
this.actor.show();
if (sourceActor) {
this.actor.set_scale(0, 0);
this.actor.ease({
scale_x: 1,
scale_y: 1,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
time: 200
});
Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
transition: 'easeOutQuad',
time: 0.2 });
} else {
this.actor.set_scale(1, 1);
}
@@ -496,13 +493,8 @@ var Inspector = GObject.registerClass({
eventHandler.connect('button-press-event', this._onButtonPressEvent.bind(this));
eventHandler.connect('scroll-event', this._onScrollEvent.bind(this));
eventHandler.connect('motion-event', this._onMotionEvent.bind(this));
let dm = Clutter.DeviceManager.get_default();
this._pointerDevice = dm.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
this._keyboardDevice = dm.get_core_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
this._pointerDevice.grab(eventHandler);
this._keyboardDevice.grab(eventHandler);
Clutter.grab_pointer(eventHandler);
Clutter.grab_keyboard(eventHandler);
// this._target is the actor currently shown by the inspector.
// this._pointerTarget is the actor directly under the pointer.
@@ -523,7 +515,7 @@ var Inspector = GObject.registerClass({
let primary = Main.layoutManager.primaryMonitor;
let [, , natWidth, natHeight] =
let [minWidth, minHeight, natWidth, natHeight] =
this._eventHandler.get_preferred_size();
let childBox = new Clutter.ActorBox();
@@ -535,8 +527,8 @@ var Inspector = GObject.registerClass({
}
_close() {
this._pointerDevice.ungrab();
this._keyboardDevice.ungrab();
Clutter.ungrab_pointer();
Clutter.ungrab_keyboard();
this._eventHandler.destroy();
this._eventHandler = null;
this.emit('closed');
@@ -559,7 +551,7 @@ var Inspector = GObject.registerClass({
_onScrollEvent(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP: {
case Clutter.ScrollDirection.UP:
// select parent
let parent = this._target.get_parent();
if (parent != null) {
@@ -567,7 +559,6 @@ var Inspector = GObject.registerClass({
this._update(event);
}
break;
}
case Clutter.ScrollDirection.DOWN:
// select child
@@ -607,9 +598,9 @@ var Inspector = GObject.registerClass({
this._target = target;
this._pointerTarget = target;
let position = `[inspect x: ${stageX} y: ${stageY}]`;
let position = '[inspect x: ' + stageX + ' y: ' + stageY + ']';
this._displayText.text = '';
this._displayText.text = `${position} ${this._target}`;
this._displayText.text = position + ' ' + this._target;
this._lookingGlass.setBorderPaintTarget(this._target);
}
@@ -621,23 +612,22 @@ var Extensions = class Extensions {
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
text: _("No extensions installed") });
text: _("No extensions installed") });
this._numExtensions = 0;
this._extensionsList = new St.BoxLayout({ vertical: true,
style_class: 'lg-extensions-list' });
this._extensionsList.add(this._noExtensions);
this.actor.add(this._extensionsList);
Main.extensionManager.getUuids().forEach(uuid => {
for (let uuid in ExtensionUtils.extensions)
this._loadExtension(null, uuid);
});
Main.extensionManager.connect('extension-loaded',
this._loadExtension.bind(this));
ExtensionSystem.connect('extension-loaded',
this._loadExtension.bind(this));
}
_loadExtension(o, uuid) {
let extension = Main.extensionManager.lookup(uuid);
let extension = ExtensionUtils.extensions[uuid];
// There can be cases where we create dummy extension metadata
// that's not really a proper extension. Don't bother with these.
if (!extension.metadata.name)
@@ -694,17 +684,17 @@ var Extensions = class Extensions {
_stateToString(extensionState) {
switch (extensionState) {
case ExtensionState.ENABLED:
return _("Enabled");
case ExtensionState.DISABLED:
case ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionState.ERROR:
return _("Error");
case ExtensionState.OUT_OF_DATE:
return _("Out of date");
case ExtensionState.DOWNLOADING:
return _("Downloading");
case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionSystem.ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
return _("Error");
case ExtensionSystem.ExtensionState.OUT_OF_DATE:
return _("Out of date");
case ExtensionSystem.ExtensionState.DOWNLOADING:
return _("Downloading");
}
return 'Unknown'; // Not translated, shouldn't appear
}
@@ -712,7 +702,7 @@ var Extensions = class Extensions {
_createExtensionDisplay(extension) {
let box = new St.BoxLayout({ style_class: 'lg-extension', vertical: true });
let name = new St.Label({ style_class: 'lg-extension-name',
text: extension.metadata.name });
text: extension.metadata.name });
box.add(name, { expand: true });
let description = new St.Label({ style_class: 'lg-extension-description',
text: extension.metadata.description || 'No description' });
@@ -720,6 +710,7 @@ var Extensions = class Extensions {
let metaBox = new St.BoxLayout({ style_class: 'lg-extension-meta' });
box.add(metaBox);
let stateString = this._stateToString(extension.state);
let state = new St.Label({ style_class: 'lg-extension-state',
text: this._stateToString(extension.state) });
metaBox.add(state);
@@ -804,7 +795,7 @@ var LookingGlass = class LookingGlass {
inspectIcon.connect('button-press-event', () => {
let inspector = new Inspector(this);
inspector.connect('target', (i, target, stageX, stageY) => {
this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
this._pushResult('inspect(' + Math.round(stageX) + ', ' + Math.round(stageY) + ')', target);
});
inspector.connect('closed', () => {
this.actor.show();
@@ -819,15 +810,15 @@ var LookingGlass = class LookingGlass {
toolbar.add_actor(gcIcon);
gcIcon.reactive = true;
gcIcon.connect('button-press-event', () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
gcIcon.icon_name = 'user-trash-full';
this._timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'user-trash-full\'');
return Clutter.EVENT_PROPAGATE;
});
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'user-trash-full\'');
return Clutter.EVENT_PROPAGATE;
});
let notebook = new Notebook();
@@ -860,7 +851,7 @@ var LookingGlass = class LookingGlass {
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', (o, _e) => {
this._entry.clutter_text.connect('activate', (o, e) => {
// Hide any completions we are currently showing
this._hideCompletions();
@@ -898,11 +889,9 @@ var LookingGlass = class LookingGlass {
let fontDesc = Pango.FontDescription.from_string(fontName);
// We ignore everything but size and style; you'd be crazy to set your system-wide
// monospace font to be bold/oblique/etc. Could easily be added here.
let size = fontDesc.get_size() / 1024.;
let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt';
this.actor.style = `
font-size: ${size}${unit};
font-family: "${fontDesc.get_family()}";`;
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
}
setBorderPaintTarget(obj) {
@@ -944,41 +933,35 @@ var LookingGlass = class LookingGlass {
this._completionActor.set_text(completions.join(', '));
// 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);
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
if (this._completionActor.visible) {
this._completionActor.height = naturalHeight;
} else {
let settings = St.Settings.get();
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
this._completionActor.show();
this._completionActor.remove_all_transitions();
this._completionActor.ease({
height: naturalHeight,
opacity: 255,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: naturalHeight,
opacity: 255
});
}
}
_hideCompletions() {
if (this._completionActor) {
let settings = St.Settings.get();
let duration = AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor;
this._completionActor.remove_all_transitions();
this._completionActor.ease({
height: 0,
opacity: 0,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._completionActor.hide();
}
});
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: 0,
opacity: 0,
onComplete: () => {
this._completionActor.hide();
}
});
}
}
@@ -994,7 +977,7 @@ var LookingGlass = class LookingGlass {
try {
resultObj = Function(fullCmd)();
} catch (e) {
resultObj = `<exception ${e}>`;
resultObj = '<exception ' + e + '>';
}
this._pushResult(command, resultObj);
@@ -1021,10 +1004,7 @@ var LookingGlass = class LookingGlass {
}
_queueResize() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._resize();
return GLib.SOURCE_REMOVE;
});
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._resize(); });
}
_resize() {
@@ -1087,16 +1067,14 @@ var LookingGlass = class LookingGlass {
this._open = true;
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
// through LookingGlass without long waits.
let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor;
this.actor.ease({
y: this._targetY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this.actor, { time: 0.5 / St.get_slow_down_factor(),
transition: 'easeOutQuad',
y: this._targetY
});
}
close() {
@@ -1106,21 +1084,19 @@ var LookingGlass = class LookingGlass {
this._objInspector.actor.hide();
this._open = false;
this.actor.remove_all_transitions();
Tweener.removeTweens(this.actor);
this.setBorderPaintTarget(null);
Main.popModal(this._entry);
let settings = St.Settings.get();
let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
LG_ANIMATION_TIME);
this.actor.ease({
y: this._hiddenY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.actor.hide()
});
Tweener.addTween(this.actor, { time: Math.min(0.5 / St.get_slow_down_factor(), 0.5),
transition: 'easeOutQuad',
y: this._hiddenY,
onComplete: () => {
this.actor.hide();
}
});
}
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@@ -41,8 +41,10 @@ const CROSS_HAIRS_OPACITY_KEY = 'cross-hairs-opacity';
const CROSS_HAIRS_LENGTH_KEY = 'cross-hairs-length';
const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
let magDBusService = null;
var MouseSpriteContent = GObject.registerClass({
Implements: [Clutter.Content],
Implements: [ Clutter.Content ],
}, class MouseSpriteContent extends GObject.Object {
_init() {
super._init();
@@ -107,7 +109,8 @@ var Magnifier = class Magnifier {
// Create the first ZoomRegion and initialize it according to the
// 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);
this._zoomRegions.push(aZoomRegion);
@@ -119,7 +122,7 @@ var Magnifier = class Magnifier {
});
// Export to dbus.
(new MagnifierDBus.ShellMagnifier());
magDBusService = new MagnifierDBus.ShellMagnifier();
this.setActive(St.Settings.get().magnifier_active);
}
@@ -147,7 +150,7 @@ var Magnifier = class Magnifier {
setActive(activate) {
let isActive = this.isActive();
this._zoomRegions.forEach(zoomRegion => {
this._zoomRegions.forEach ((zoomRegion, index, array) => {
zoomRegion.setActive(activate);
});
@@ -226,14 +229,14 @@ var Magnifier = class Magnifier {
* @return true.
*/
scrollToMousePos() {
let [xMouse, yMouse] = global.get_pointer();
let [xMouse, yMouse, mask] = global.get_pointer();
if (xMouse != this.xMouse || yMouse != this.yMouse) {
this.xMouse = xMouse;
this.yMouse = yMouse;
let sysMouseOverAny = false;
this._zoomRegions.forEach(zoomRegion => {
this._zoomRegions.forEach((zoomRegion, index, array) => {
if (zoomRegion.scrollToMousePos())
sysMouseOverAny = true;
});
@@ -281,7 +284,7 @@ var Magnifier = class Magnifier {
* @zoomRegion: The zoomRegion to add.
*/
addZoomRegion(zoomRegion) {
if (zoomRegion) {
if(zoomRegion) {
this._zoomRegions.push(zoomRegion);
if (!this.isTrackingMouse())
this.startTrackingMouse();
@@ -331,7 +334,7 @@ var Magnifier = class Magnifier {
this.setCrosshairsClip(clip);
let theCrossHairs = this._crossHairs;
this._zoomRegions.forEach (zoomRegion => {
this._zoomRegions.forEach ((zoomRegion, index, array) => {
zoomRegion.addCrosshairs(theCrossHairs);
});
}
@@ -346,7 +349,8 @@ var Magnifier = class Magnifier {
if (!this._crossHairs)
this.addCrosshairs();
this._crossHairs.show();
} else {
}
else {
if (this._crossHairs)
this._crossHairs.hide();
}
@@ -359,7 +363,7 @@ var Magnifier = class Magnifier {
*/
setCrosshairsColor(color) {
if (this._crossHairs) {
let [res_, clutterColor] = Clutter.Color.from_string(color);
let [res, clutterColor] = Clutter.Color.from_string(color);
this._crossHairs.setColor(clutterColor);
}
}
@@ -373,9 +377,9 @@ var Magnifier = class Magnifier {
if (this._crossHairs) {
let clutterColor = this._crossHairs.getColor();
return clutterColor.to_string();
} else {
return '#00000000';
}
else
return '#00000000';
}
/**
@@ -455,7 +459,8 @@ var Magnifier = class Magnifier {
if (clip) {
if (this._crossHairs)
this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE);
} else {
}
else {
// Setting no clipping on crosshairs means a zero sized clip
// rectangle.
if (this._crossHairs)
@@ -468,14 +473,14 @@ var Magnifier = class Magnifier {
* Get whether the crosshairs are clipped by the mouse image.
* @return: Whether the crosshairs are clipped.
*/
getCrosshairsClip() {
getCrosshairsClip() {
if (this._crossHairs) {
let [clipWidth, clipHeight] = this._crossHairs.getClip();
return (clipWidth > 0 && clipHeight > 0);
} else {
return false;
}
}
else
return false;
}
//// Private methods ////
@@ -499,61 +504,61 @@ var Magnifier = class Magnifier {
_settingsInit(zoomRegion) {
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
this._settings.connect(`changed::${SCREEN_POSITION_KEY}`,
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
this._updateScreenPosition.bind(this));
this._settings.connect(`changed::${MAG_FACTOR_KEY}`,
this._settings.connect('changed::' + MAG_FACTOR_KEY,
this._updateMagFactor.bind(this));
this._settings.connect(`changed::${LENS_MODE_KEY}`,
this._settings.connect('changed::' + LENS_MODE_KEY,
this._updateLensMode.bind(this));
this._settings.connect(`changed::${CLAMP_MODE_KEY}`,
this._settings.connect('changed::' + CLAMP_MODE_KEY,
this._updateClampMode.bind(this));
this._settings.connect(`changed::${MOUSE_TRACKING_KEY}`,
this._settings.connect('changed::' + MOUSE_TRACKING_KEY,
this._updateMouseTrackingMode.bind(this));
this._settings.connect(`changed::${FOCUS_TRACKING_KEY}`,
this._settings.connect('changed::' + FOCUS_TRACKING_KEY,
this._updateFocusTrackingMode.bind(this));
this._settings.connect(`changed::${CARET_TRACKING_KEY}`,
this._settings.connect('changed::' + CARET_TRACKING_KEY,
this._updateCaretTrackingMode.bind(this));
this._settings.connect(`changed::${INVERT_LIGHTNESS_KEY}`,
this._settings.connect('changed::' + INVERT_LIGHTNESS_KEY,
this._updateInvertLightness.bind(this));
this._settings.connect(`changed::${COLOR_SATURATION_KEY}`,
this._settings.connect('changed::' + COLOR_SATURATION_KEY,
this._updateColorSaturation.bind(this));
this._settings.connect(`changed::${BRIGHT_RED_KEY}`,
this._settings.connect('changed::' + BRIGHT_RED_KEY,
this._updateBrightness.bind(this));
this._settings.connect(`changed::${BRIGHT_GREEN_KEY}`,
this._settings.connect('changed::' + BRIGHT_GREEN_KEY,
this._updateBrightness.bind(this));
this._settings.connect(`changed::${BRIGHT_BLUE_KEY}`,
this._settings.connect('changed::' + BRIGHT_BLUE_KEY,
this._updateBrightness.bind(this));
this._settings.connect(`changed::${CONTRAST_RED_KEY}`,
this._settings.connect('changed::' + CONTRAST_RED_KEY,
this._updateContrast.bind(this));
this._settings.connect(`changed::${CONTRAST_GREEN_KEY}`,
this._settings.connect('changed::' + CONTRAST_GREEN_KEY,
this._updateContrast.bind(this));
this._settings.connect(`changed::${CONTRAST_BLUE_KEY}`,
this._settings.connect('changed::' + CONTRAST_BLUE_KEY,
this._updateContrast.bind(this));
this._settings.connect(`changed::${SHOW_CROSS_HAIRS_KEY}`, () => {
this._settings.connect('changed::' + SHOW_CROSS_HAIRS_KEY, () => {
this.setCrosshairsVisible(this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY));
});
this._settings.connect(`changed::${CROSS_HAIRS_THICKNESS_KEY}`, () => {
this._settings.connect('changed::' + CROSS_HAIRS_THICKNESS_KEY, () => {
this.setCrosshairsThickness(this._settings.get_int(CROSS_HAIRS_THICKNESS_KEY));
});
this._settings.connect(`changed::${CROSS_HAIRS_COLOR_KEY}`, () => {
this._settings.connect('changed::' + CROSS_HAIRS_COLOR_KEY, () => {
this.setCrosshairsColor(this._settings.get_string(CROSS_HAIRS_COLOR_KEY));
});
this._settings.connect(`changed::${CROSS_HAIRS_OPACITY_KEY}`, () => {
this._settings.connect('changed::' + CROSS_HAIRS_OPACITY_KEY, () => {
this.setCrosshairsOpacity(this._settings.get_double(CROSS_HAIRS_OPACITY_KEY));
});
this._settings.connect(`changed::${CROSS_HAIRS_LENGTH_KEY}`, () => {
this._settings.connect('changed::' + CROSS_HAIRS_LENGTH_KEY, () => {
this.setCrosshairsLength(this._settings.get_int(CROSS_HAIRS_LENGTH_KEY));
});
this._settings.connect(`changed::${CROSS_HAIRS_CLIP_KEY}`, () => {
this._settings.connect('changed::' + CROSS_HAIRS_CLIP_KEY, () => {
this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY));
});
@@ -605,7 +610,7 @@ var Magnifier = class Magnifier {
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
this.addCrosshairs();
this.setCrosshairsVisible(showCrosshairs);
}
}
_updateScreenPosition() {
// Applies only to the first zoom region.
@@ -795,8 +800,8 @@ var ZoomRegion = class ZoomRegion {
let extents;
try {
extents = component.get_extents(Atspi.CoordType.SCREEN);
} catch (e) {
log(`Failed to read extents of focused component: ${e.message}`);
} catch(e) {
log('Failed to read extents of focused component: ' + e.message);
return;
}
@@ -812,8 +817,8 @@ var ZoomRegion = class ZoomRegion {
let extents;
try {
extents = text.get_character_extents(text.get_caret_offset(), 0);
} catch (e) {
log(`Failed to read extents of text caret: ${e.message}`);
} catch(e) {
log('Failed to read extents of text caret: ' + e.message);
return;
}
@@ -1025,7 +1030,7 @@ var ZoomRegion = class ZoomRegion {
viewPort.x = 0;
viewPort.y = 0;
viewPort.width = global.screen_width;
viewPort.height = global.screen_height / 2;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.TOP_HALF;
}
@@ -1037,9 +1042,9 @@ var ZoomRegion = class ZoomRegion {
setBottomHalf() {
let viewPort = {};
viewPort.x = 0;
viewPort.y = global.screen_height / 2;
viewPort.y = global.screen_height/2;
viewPort.width = global.screen_width;
viewPort.height = global.screen_height / 2;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF;
}
@@ -1052,7 +1057,7 @@ var ZoomRegion = class ZoomRegion {
let viewPort = {};
viewPort.x = 0;
viewPort.y = 0;
viewPort.width = global.screen_width / 2;
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.LEFT_HALF;
@@ -1064,9 +1069,9 @@ var ZoomRegion = class ZoomRegion {
*/
setRightHalf() {
let viewPort = {};
viewPort.x = global.screen_width / 2;
viewPort.x = global.screen_width/2;
viewPort.y = 0;
viewPort.width = global.screen_width / 2;
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF;
@@ -1098,21 +1103,21 @@ var ZoomRegion = class ZoomRegion {
*/
setScreenPosition(inPosition) {
switch (inPosition) {
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
}
}
@@ -1455,9 +1460,11 @@ var ZoomRegion = class ZoomRegion {
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
return this._centerFromPointProportional(xMouse, yMouse);
} else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
return this._centerFromPointPush(xMouse, yMouse);
} else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
return this._centerFromPointCentered(xMouse, yMouse);
}
@@ -1514,7 +1521,7 @@ var ZoomRegion = class ZoomRegion {
}
_centerFromPointProportional(xPoint, yPoint) {
let [xRoi_, yRoi_, widthRoi, heightRoi] = this.getROI();
let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI();
let halfScreenWidth = global.screen_width / 2;
let halfScreenHeight = global.screen_height / 2;
// We want to pad with a constant distance after zooming, so divide
@@ -1525,7 +1532,7 @@ var ZoomRegion = class ZoomRegion {
let xProportion = (xPoint - halfScreenWidth) / halfScreenWidth; // -1 ... 1
let yProportion = (yPoint - halfScreenHeight) / halfScreenHeight; // -1 ... 1
let xPos = xPoint - xProportion * (widthRoi / 2 - xPadding);
let yPos = yPoint - yProportion * (heightRoi / 2 - yPadding);
let yPos = yPoint - yProportion * (heightRoi /2 - yPadding);
return [xPos, yPos];
}
@@ -1627,7 +1634,7 @@ var Crosshairs = class Crosshairs {
this.reCenter();
}
/**
/**
* addToZoomRegion
* Either add the crosshairs actor to the given ZoomRegion, or, if it is
* already part of some other ZoomRegion, create a clone of the crosshairs
@@ -1655,7 +1662,7 @@ var Crosshairs = class Crosshairs {
container.raise_child(magnifiedMouse, crosshairsActor);
let [xMouse, yMouse] = magnifiedMouse.get_position();
let [crosshairsWidth, crosshairsHeight] = crosshairsActor.get_size();
crosshairsActor.set_position(xMouse - crosshairsWidth / 2, yMouse - crosshairsHeight / 2);
crosshairsActor.set_position(xMouse - crosshairsWidth / 2 , yMouse - crosshairsHeight / 2);
}
}
return crosshairsActor;
@@ -1771,12 +1778,13 @@ var Crosshairs = class Crosshairs {
// mouse.
this._clipSize = size;
this.reCenter();
} else {
}
else {
// Restore the missing chunk.
this._clipSize = [0, 0];
this.reCenter();
}
}
}
/**
* show:
@@ -1810,7 +1818,9 @@ var Crosshairs = class Crosshairs {
reCenter(clipSize) {
let [groupWidth, groupHeight] = this._actor.get_size();
let leftLength = this._horizLeftHair.get_width();
let rightLength = this._horizRightHair.get_width();
let topLength = this._vertTopHair.get_height();
let bottomLength = this._vertBottomHair.get_height();
let thickness = this._horizLeftHair.get_height();
// Deal with clip rectangle.
@@ -1917,8 +1927,8 @@ var MagShaderEffects = class MagShaderEffects {
// a null first argument.
let [bRed, bGreen, bBlue] = this._brightnessContrast.get_brightness();
this._brightnessContrast.set_enabled(
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
);
}
};

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ShellMagnifier */
const Gio = imports.gi.Gio;
const Main = imports.ui.main;
@@ -86,7 +85,7 @@ var ShellMagnifier = class ShellMagnifier {
let ROI = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
let viewBox = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
let realZoomRegion = Main.magnifier.createZoomRegion(xMagFactor, yMagFactor, ROI, viewBox);
let objectPath = `${ZOOM_SERVICE_PATH}/zoomer${_zoomRegionInstanceCount}`;
let objectPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
_zoomRegionInstanceCount++;
let zoomRegionProxy = new ShellMagnifierZoomRegion(objectPath, realZoomRegion);
@@ -107,9 +106,9 @@ var ShellMagnifier = class ShellMagnifier {
if (proxyAndZoomRegion && proxyAndZoomRegion.zoomRegion) {
Main.magnifier.addZoomRegion(proxyAndZoomRegion.zoomRegion);
return true;
} else {
return false;
}
else
return false;
}
/**
@@ -125,7 +124,7 @@ var ShellMagnifier = class ShellMagnifier {
let zoomRegions = Main.magnifier.getZoomRegions();
let objectPaths = [];
let thoseZoomers = this._zoomers;
zoomRegions.forEach (aZoomRegion => {
zoomRegions.forEach ((aZoomRegion, index, array) => {
let found = false;
for (let objectPath in thoseZoomers) {
let proxyAndZoomRegion = thoseZoomers[objectPath];
@@ -180,74 +179,74 @@ var ShellMagnifier = class ShellMagnifier {
* Set the crosswire size of all ZoomRegions.
* @size: The thickness of each line in the cross wire.
*/
setCrosswireSize(size) {
setCrosswireSize(size) {
Main.magnifier.setCrosshairsThickness(size);
}
}
/**
* getCrosswireSize:
* Get the crosswire size of all ZoomRegions.
* @return: The thickness of each line in the cross wire.
*/
getCrosswireSize() {
getCrosswireSize() {
return Main.magnifier.getCrosshairsThickness();
}
}
/**
* setCrosswireLength:
* Set the crosswire length of all zoom-regions..
* @size: The length of each line in the cross wire.
*/
setCrosswireLength(length) {
setCrosswireLength(length) {
Main.magnifier.setCrosshairsLength(length);
}
}
/**
* setCrosswireSize:
* Set the crosswire size of all zoom-regions.
* @size: The thickness of each line in the cross wire.
*/
getCrosswireLength() {
getCrosswireLength() {
return Main.magnifier.getCrosshairsLength();
}
}
/**
* setCrosswireClip:
* Set if the crosswire will be clipped by the cursor image..
* @clip: Flag to indicate whether to clip the crosswire.
*/
setCrosswireClip(clip) {
setCrosswireClip(clip) {
Main.magnifier.setCrosshairsClip(clip);
}
}
/**
* getCrosswireClip:
* Get the crosswire clip value.
* @return: Whether the crosswire is clipped by the cursor image.
*/
getCrosswireClip() {
getCrosswireClip() {
return Main.magnifier.getCrosshairsClip();
}
}
/**
* setCrosswireColor:
* Set the crosswire color of all ZoomRegions.
* @color: Unsigned int of the form rrggbbaa.
*/
setCrosswireColor(color) {
setCrosswireColor(color) {
Main.magnifier.setCrosshairsColor('#%08x'.format(color));
}
}
/**
* getCrosswireClip:
* Get the crosswire color of all ZoomRegions.
* @return: The crosswire color as an unsigned int in the form rrggbbaa.
*/
getCrosswireColor() {
getCrosswireColor() {
let colorString = Main.magnifier.getCrosshairsColor();
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
}
};
/**

View File

@@ -1,12 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported componentManager, notificationDaemon, windowAttentionHandler,
ctrlAltTabManager, padOsdService, osdWindowManager,
osdMonitorLabeler, shellMountOpDBusService, shellDBusService,
shellAccessDialogDBusService, shellAudioSelectionDBusService,
screenSaverDBus, screencastService, uiGroup, magnifier,
xdndHandler, keyboard, kbdA11yDialog, introspectService,
start, pushModal, popModal, activateWindow, createLookingGlass,
initializeDeferredWork, getThemeStylesheet, setThemeStylesheet */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -54,7 +46,6 @@ const LOG_DOMAIN = 'GNOME Shell';
const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
var componentManager = null;
var extensionManager = null;
var panel = null;
var overview = null;
var runDialog = null;
@@ -93,6 +84,7 @@ let _cssStylesheet = null;
let _a11ySettings = null;
let _themeResource = null;
let _oskResource = null;
let pointerA11yTimeout = null;
function _sessionUpdated() {
if (sessionMode.isPrimary)
@@ -180,7 +172,7 @@ function _initializeUI() {
kbdA11yDialog = new KbdA11yDialog.KbdA11yDialog();
wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier();
locatePointer = new LocatePointer.LocatePointer();
locatePointer = new LocatePointer.locatePointer();
if (LoginManager.canLock())
screenShield = new ScreenShield.ScreenShield();
@@ -200,7 +192,7 @@ function _initializeUI() {
layoutManager.init();
overview.init();
(new PointerA11yTimeout.PointerA11yTimeout());
pointerA11yTimeout = new PointerA11yTimeout.PointerA11yTimeout();
_a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
@@ -235,8 +227,7 @@ function _initializeUI() {
_startDate = new Date();
ExtensionDownloader.init();
extensionManager = new ExtensionSystem.ExtensionManager();
extensionManager.init();
ExtensionSystem.init();
if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', () => {
@@ -264,7 +255,7 @@ function _initializeUI() {
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval(`imports.perf.${perfModuleName};`);
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
});
@@ -400,9 +391,9 @@ function notify(msg, details) {
function notifyError(msg, details) {
// Also print to stderr so it's logged somewhere
if (details)
log(`error: ${msg}: ${details}`);
log('error: ' + msg + ': ' + details);
else
log(`error: ${msg}`);
log('error: ' + msg);
notify(msg, details);
}
@@ -666,13 +657,13 @@ function _queueBeforeRedraw(workId) {
*
* 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
let workId = `${(++_deferredWorkSequence)}`;
let workId = '' + (++_deferredWorkSequence);
_deferredWorkData[workId] = { 'actor': actor,
'callback': callback };
actor.connect('notify::mapped', () => {
if (!(actor.mapped && _deferredWorkQueue.includes(workId)))
if (!(actor.mapped && _deferredWorkQueue.indexOf(workId) >= 0))
return;
_queueBeforeRedraw(workId);
});
@@ -702,7 +693,7 @@ function queueDeferredWork(workId) {
logError(new Error(message), message);
return;
}
if (!_deferredWorkQueue.includes(workId))
if (_deferredWorkQueue.indexOf(workId) < 0)
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);

View File

@@ -4,9 +4,10 @@ const MessageTray = imports.ui.messageTray;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
var MESSAGE_ANIMATION_TIME = 100;
var MESSAGE_ANIMATION_TIME = 0.1;
var DEFAULT_EXPAND_LINES = 6;
@@ -32,7 +33,9 @@ function _fixMarkup(text, allowMarkup) {
}
var URLHighlighter = class URLHighlighter {
constructor(text = '', lineWrap, allowMarkup) {
constructor(text, lineWrap, allowMarkup) {
if (!text)
text = '';
this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter',
x_expand: true, x_align: Clutter.ActorAlign.START });
this._linkColor = '#ccccff';
@@ -69,7 +72,7 @@ var URLHighlighter = class URLHighlighter {
let urlId = this._findUrlAtPos(event);
if (urlId != -1) {
let url = this._urls[urlId].url;
if (!url.includes(':'))
if (url.indexOf(':') == -1)
url = 'http://' + url;
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1));
@@ -129,21 +132,21 @@ var URLHighlighter = class URLHighlighter {
}
_findUrlAtPos(event) {
let success_;
let success;
let [x, y] = event.get_coords();
[success_, x, y] = this.actor.transform_stage_point(x, y);
let findPos = -1;
[success, x, y] = this.actor.transform_stage_point(x, y);
let find_pos = -1;
for (let i = 0; i < this.actor.clutter_text.text.length; i++) {
let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + lineHeight < y || x < px)
let [success, px, py, line_height] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + line_height < y || x < px)
continue;
findPos = i;
find_pos = i;
}
if (findPos != -1) {
if (find_pos != -1) {
for (let i = 0; i < this._urls.length; i++)
if (findPos >= this._urls[i].pos &&
this._urls[i].pos + this._urls[i].url.length > findPos)
return i;
if (find_pos >= this._urls[i].pos &&
this._urls[i].pos + this._urls[i].url.length > find_pos)
return i;
}
return -1;
}
@@ -194,14 +197,12 @@ class ScaleLayout extends Clutter.BinLayout {
});
var LabelExpanderLayout = GObject.registerClass({
Properties: {
'expansion': GObject.ParamSpec.double('expansion',
'Expansion',
'Expansion of the layout, between 0 (collapsed) ' +
'and 1 (fully expanded',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
0, 1, 0)
},
Properties: { 'expansion': GObject.ParamSpec.double('expansion',
'Expansion',
'Expansion of the layout, between 0 (collapsed) ' +
'and 1 (fully expanded',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
0, 1, 0)},
}, class LabelExpanderLayout extends Clutter.LayoutManager {
_init(params) {
this._expansion = 0;
@@ -439,17 +440,15 @@ var Message = class Message {
}
if (animate) {
this._bodyStack.ease_property('@layout.expansion', 1, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: MessageTray.ANIMATION_TIME,
});
Tweener.addTween(this._bodyStack.layout_manager,
{ expansion: 1,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
this._actionBin.scale_y = 0;
this._actionBin.ease({
scale_y: 1,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(this._actionBin,
{ scale_y: 1,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
} else {
this._bodyStack.layout_manager.expansion = 1;
this._actionBin.scale_y = 1;
@@ -460,20 +459,19 @@ var Message = class Message {
unexpand(animate) {
if (animate) {
this._bodyStack.ease_property('@layout.expansion', 0, {
progress_mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: MessageTray.ANIMATION_TIME,
});
this._actionBin.ease({
scale_y: 0,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._actionBin.hide();
this.expanded = false;
}
});
Tweener.addTween(this._bodyStack.layout_manager,
{ expansion: 0,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad' });
Tweener.addTween(this._actionBin,
{ scale_y: 0,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete() {
this._actionBin.hide();
this.expanded = false;
}});
} else {
this._bodyStack.layout_manager.expansion = 0;
this._actionBin.scale_y = 0;
@@ -584,12 +582,10 @@ var MessageListSection = class MessageListSection {
this._list.insert_child_at_index(obj.container, index);
if (animate)
obj.container.ease({
scale_x: 1,
scale_y: 1,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(obj.container, { scale_x: 1,
scale_y: 1,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad' });
}
moveMessage(message, index, animate) {
@@ -602,20 +598,16 @@ var MessageListSection = class MessageListSection {
let onComplete = () => {
this._list.set_child_at_index(obj.container, index);
obj.container.ease({
scale_x: 1,
scale_y: 1,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
Tweener.addTween(obj.container, { scale_x: 1,
scale_y: 1,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad' });
};
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
Tweener.addTween(obj.container, { scale_x: 0,
scale_y: 0,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: onComplete });
}
removeMessage(message, animate) {
@@ -628,16 +620,13 @@ var MessageListSection = class MessageListSection {
this._messages.delete(message);
if (animate) {
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
obj.container.destroy();
global.sync_pointer();
}
});
Tweener.addTween(obj.container, { scale_x: 0, scale_y: 0,
time: MESSAGE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
obj.container.destroy();
global.sync_pointer();
}});
} else {
obj.container.destroy();
global.sync_pointer();
@@ -659,14 +648,15 @@ var MessageListSection = class MessageListSection {
for (let i = 0; i < messages.length; i++) {
let message = messages[i];
let obj = this._messages.get(message);
obj.container.ease({
anchor_x: this._list.width,
opacity: 0,
duration: MESSAGE_ANIMATION_TIME,
delay: i * delay,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => message.close()
});
Tweener.addTween(obj.container,
{ anchor_x: this._list.width,
opacity: 0,
time: MESSAGE_ANIMATION_TIME,
delay: i * delay,
transition: 'easeOutQuad',
onComplete() {
message.close();
}});
}
}
}

View File

@@ -1,7 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationPolicy, NotificationGenericPolicy,
NotificationApplicationPolicy, Source, SourceActor, SourceActorWithLabel,
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -12,14 +9,15 @@ const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
var ANIMATION_TIME = 200;
var NOTIFICATION_TIMEOUT = 4000;
var ANIMATION_TIME = 0.2;
var NOTIFICATION_TIMEOUT = 4;
var HIDE_TIMEOUT = 200;
var LONGER_HIDE_TIMEOUT = 600;
var HIDE_TIMEOUT = 0.2;
var LONGER_HIDE_TIMEOUT = 0.6;
var MAX_NOTIFICATIONS_IN_QUEUE = 3;
var MAX_NOTIFICATIONS_PER_SOURCE = 3;
@@ -220,17 +218,17 @@ class NotificationApplicationPolicy extends NotificationPolicy {
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications.application',
path: `/org/gnome/desktop/notifications/application/${this._canonicalId}/` });
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
this._masterSettings.connect('changed', this._changed.bind(this));
this._settings.connect('changed', this._changed.bind(this));
}
store() {
this._settings.set_string('application-id', `${this.id}.desktop`);
this._settings.set_string('application-id', this.id + '.desktop');
let apps = this._masterSettings.get_strv('application-children');
if (!apps.includes(this._canonicalId)) {
if (apps.indexOf(this._canonicalId) < 0) {
apps.push(this._canonicalId);
this._masterSettings.set_strv('application-children', apps);
}
@@ -250,7 +248,7 @@ class NotificationApplicationPolicy extends NotificationPolicy {
_canonicalizeId(id) {
// Keys are restricted to lowercase alphanumeric characters and dash,
// and two dashes cannot be in succession
return id.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-');
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
}
get enable() {
@@ -475,7 +473,9 @@ var Notification = class Notification {
this.destroy();
}
destroy(reason = NotificationDestroyedReason.DISMISSED) {
destroy(reason) {
if (!reason)
reason = NotificationDestroyedReason.DISMISSED;
this.emit('destroy', reason);
}
};
@@ -590,11 +590,11 @@ class SourceActor extends St.Widget {
});
this._actorDestroyed = false;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._iconBin = new St.Bin({ x_fill: true,
x_expand: true,
height: size * scaleFactor,
width: size * scaleFactor });
height: size * scale_factor,
width: size * scale_factor });
this.add_actor(this._iconBin);
@@ -616,77 +616,6 @@ class SourceActor extends St.Widget {
}
});
var SourceActorWithLabel = GObject.registerClass(
class SourceActorWithLabel extends SourceActor {
_init(source, size) {
super._init(source, size);
this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
this._counterBin = new St.Bin({ style_class: 'summary-source-counter',
child: this._counterLabel,
layout_manager: new Clutter.BinLayout() });
this._counterBin.hide();
this._counterBin.connect('style-changed', () => {
let themeNode = this._counterBin.get_theme_node();
this._counterBin.translation_x = themeNode.get_length('-shell-counter-overlap-x');
this._counterBin.translation_y = themeNode.get_length('-shell-counter-overlap-y');
});
this.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this));
this._updateCount();
this.connect('destroy', () => {
this._source.disconnect(this._countUpdatedId);
});
}
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
let childBox = new Clutter.ActorBox();
let [, , naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let direction = this.get_text_direction();
if (direction == Clutter.TextDirection.LTR) {
// allocate on the right in LTR
childBox.x1 = box.x2 - naturalWidth;
childBox.x2 = box.x2;
} else {
// allocate on the left in RTL
childBox.x1 = 0;
childBox.x2 = naturalWidth;
}
childBox.y1 = box.y2 - naturalHeight;
childBox.y2 = box.y2;
this._counterBin.allocate(childBox, flags);
}
_updateCount() {
if (this._actorDestroyed)
return;
this._counterBin.visible = this._source.countVisible;
let text;
if (this._source.count < 100)
text = this._source.count.toString();
else
text = String.fromCharCode(0x22EF); // midline horizontal ellipsis
this._counterLabel.set_text(text);
}
});
var Source = class Source {
constructor(title, iconName) {
this.SOURCE_ICON_SIZE = 48;
@@ -772,7 +701,7 @@ var Source = class Source {
}
pushNotification(notification) {
if (this.notifications.includes(notification))
if (this.notifications.indexOf(notification) >= 0)
return;
while (this.notifications.length >= MAX_NOTIFICATIONS_PER_SOURCE)
@@ -829,7 +758,7 @@ Signals.addSignalMethods(Source.prototype);
var MessageTray = class MessageTray {
constructor() {
this._presence = new GnomeSession.Presence((proxy, _error) => {
this._presence = new GnomeSession.Presence((proxy, error) => {
this._onStatusChanged(proxy.status);
});
this._busy = false;
@@ -988,7 +917,7 @@ var MessageTray = class MessageTray {
add(source) {
if (this.contains(source)) {
log(`Trying to re-add source ${source.title}`);
log('Trying to re-add source ' + source.title);
return;
}
@@ -1069,7 +998,7 @@ var MessageTray = class MessageTray {
// If a new notification is updated while it is being hidden,
// we stop hiding it and show it again.
this._updateShowingNotification();
} else if (!this._notificationQueue.includes(notification)) {
} else if (this._notificationQueue.indexOf(notification) < 0) {
// If the queue is "full", we skip banner mode and just show a small
// indicator in the panel; however do make an exception for CRITICAL
// notifications, as only banner mode allows expansion.
@@ -1129,14 +1058,14 @@ var MessageTray = class MessageTray {
// this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us
// to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still
// close to its previous position, we extend the timeout once.
let [x, y] = global.get_pointer();
let [x, y, mods] = global.get_pointer();
this._notificationLeftMouseX = x;
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 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.
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT : HIDE_TIMEOUT;
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
}
@@ -1158,7 +1087,7 @@ var MessageTray = class MessageTray {
}
_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.
if (this._notificationLeftMouseX > -1 &&
y < this._notificationLeftMouseY + MOUSE_LEFT_ACTOR_THRESHOLD &&
@@ -1166,8 +1095,8 @@ var MessageTray = class MessageTray {
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT,
this._onNotificationLeftTimeout.bind(this));
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else {
this._notificationLeftTimeoutId = 0;
@@ -1248,6 +1177,34 @@ var MessageTray = class MessageTray {
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() {
this._userActiveWhileNotificationShown = true;
this._updateNotificationTimeout(2000);
@@ -1274,6 +1231,7 @@ var MessageTray = class MessageTray {
this._bannerBin.add_actor(this._banner.actor);
this._bannerBin._opacity = 0;
this._bannerBin.opacity = 0;
this._bannerBin.y = -this._banner.actor.height;
this.actor.show();
@@ -1281,7 +1239,7 @@ var MessageTray = class MessageTray {
Meta.disable_unredirect_for_display(global.display);
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
// 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
@@ -1319,28 +1277,22 @@ var MessageTray = class MessageTray {
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown.
this._notificationState = State.SHOWING;
this._bannerBin.remove_all_transitions();
this._bannerBin.ease({
opacity: 255,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR
});
this._bannerBin.ease({
y: 0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK,
onComplete: () => {
this._notificationState = State.SHOWN;
this._showNotificationCompleted();
this._updateState();
}
});
let tweenParams = { y: 0,
_opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutBack',
onUpdate: this._clampOpacity,
onUpdateScope: this,
onComplete: this._showNotificationCompleted,
onCompleteScope: this
};
this._tween(this._bannerBin, '_notificationState', State.SHOWN, tweenParams);
}
_showNotificationCompleted() {
if (this._notification.urgency != Urgency.CRITICAL)
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT);
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
}
_updateNotificationTimeout(timeout) {
@@ -1357,7 +1309,7 @@ var MessageTray = class MessageTray {
}
_notificationTimeout() {
let [x, y] = global.get_pointer();
let [x, y, mods] = global.get_pointer();
if (y < this._lastSeenMouseY - 10 && !this._notificationHovered) {
// The mouse is moving towards the notification, so don't
// hide it yet. (We just create a new timeout (and destroy
@@ -1393,26 +1345,20 @@ var MessageTray = class MessageTray {
}
this._resetNotificationLeftTimeout();
this._bannerBin.remove_all_transitions();
if (animate) {
this._notificationState = State.HIDING;
this._bannerBin.ease({
opacity: 0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK
});
this._bannerBin.ease({
y: -this._bannerBin.height,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK,
onComplete: () => {
this._notificationState = State.HIDDEN;
this._hideNotificationCompleted();
this._updateState();
}
});
this._tween(this._bannerBin, '_notificationState', State.HIDDEN,
{ y: -this._bannerBin.height,
_opacity: 0,
time: ANIMATION_TIME,
transition: 'easeOutBack',
onUpdate: this._clampOpacity,
onUpdateScope: this,
onComplete: this._hideNotificationCompleted,
onCompleteScope: this
});
} else {
Tweener.removeTweens(this._bannerBin);
this._bannerBin.y = -this._bannerBin.height;
this._bannerBin.opacity = 0;
this._notificationState = State.HIDDEN;

View File

@@ -1,16 +1,17 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModalDialog */
const { Atk, Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Dialog = imports.ui.dialog;
const Layout = imports.ui.layout;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var OPEN_AND_CLOSE_TIME = 100;
var FADE_OUT_DIALOG_TIME = 1000;
var OPEN_AND_CLOSE_TIME = 0.1;
var FADE_OUT_DIALOG_TIME = 1.0;
var State = {
OPENED: 0,
@@ -21,13 +22,11 @@ var State = {
};
var ModalDialog = GObject.registerClass({
Properties: {
'state': GObject.ParamSpec.int('state', 'Dialog state', 'state',
GObject.ParamFlags.READABLE,
Math.min(...Object.values(State)),
Math.max(...Object.values(State)),
State.CLOSED)
},
Properties: { 'state': GObject.ParamSpec.int('state', 'Dialog state', 'state',
GObject.ParamFlags.READABLE,
Math.min(...Object.values(State)),
Math.max(...Object.values(State)),
State.CLOSED) },
Signals: { 'opened': {}, 'closed': {} }
}, class ModalDialog extends St.Widget {
_init(params) {
@@ -124,15 +123,15 @@ var ModalDialog = GObject.registerClass({
this._lightbox.show();
this.opacity = 0;
this.show();
this.ease({
opacity: 255,
duration: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._setState(State.OPENED);
this.emit('opened');
}
});
Tweener.addTween(this,
{ opacity: 255,
time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
transition: 'easeOutQuad',
onComplete: () => {
this._setState(State.OPENED);
this.emit('opened');
}
});
}
setInitialKeyFocus(actor) {
@@ -175,16 +174,15 @@ var ModalDialog = GObject.registerClass({
this.popModal(timestamp);
this._savedKeyFocus = null;
if (this._shouldFadeOut) {
this.ease({
opacity: 0,
duration: OPEN_AND_CLOSE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._closeComplete()
});
} else {
if (this._shouldFadeOut)
Tweener.addTween(this,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: this._closeComplete.bind(this)
})
else
this._closeComplete();
}
}
// Drop modal status without closing the dialog; this makes the
@@ -249,11 +247,13 @@ var ModalDialog = GObject.registerClass({
return;
this.popModal(timestamp);
this.dialogLayout.ease({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.state = State.FADED_OUT
});
Tweener.addTween(this.dialogLayout,
{ opacity: 0,
time: FADE_OUT_DIALOG_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._setState(State.FADED_OUT);
}
});
}
});

View File

@@ -1,4 +1,3 @@
/* exported MediaSection */
const { Gio, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -136,7 +135,7 @@ var MprisPlayer = class MprisPlayer {
// so prefer activating the app via .desktop file if possible
let app = null;
if (this._mprisProxy.DesktopEntry) {
let desktopId = `${this._mprisProxy.DesktopEntry}.desktop`;
let desktopId = this._mprisProxy.DesktopEntry + '.desktop';
app = Shell.AppSystem.get_default().lookup_app(desktopId);
}

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -65,7 +64,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
_imageForNotificationData(hints) {
if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels_, data] = hints['image-data'];
bitsPerSample, nChannels, data] = hints['image-data'];
return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
} else if (hints['image-path']) {
@@ -77,13 +76,13 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
_fallbackIconForNotificationData(hints) {
let stockIcon;
switch (hints.urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'dialog-information';
break;
case Urgency.CRITICAL:
stockIcon = 'dialog-error';
break;
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'dialog-information';
break;
case Urgency.CRITICAL:
stockIcon = 'dialog-error';
break;
}
return new Gio.ThemedIcon({ name: stockIcon });
}
@@ -171,11 +170,11 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = this._nextNotificationId++;
let idleId = Mainloop.idle_add(() => {
let idle_id = Mainloop.idle_add(() => {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(idleId, '[gnome-shell] this._emitNotificationClosed');
GLib.Source.set_name_by_id(idle_id, '[gnome-shell] this._emitNotificationClosed');
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
@@ -232,7 +231,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return invocation.return_value(GLib.Variant.new('(u)', [id]));
return invocation.return_value(GLib.Variant.new('(u)', [id]));;
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => {
@@ -260,7 +259,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
_notifyForSource(source, ndata) {
let [id_, icon, summary, body, actions, hints, notification] =
let [id, icon, summary, body, actions, hints, notification] =
[ndata.id, ndata.icon, ndata.summary, ndata.body,
ndata.actions, ndata.hints, ndata.notification];
@@ -271,15 +270,15 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
delete this._notifications[ndata.id];
let notificationClosedReason;
switch (reason) {
case MessageTray.NotificationDestroyedReason.EXPIRED:
notificationClosedReason = NotificationClosedReason.EXPIRED;
break;
case MessageTray.NotificationDestroyedReason.DISMISSED:
notificationClosedReason = NotificationClosedReason.DISMISSED;
break;
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
break;
case MessageTray.NotificationDestroyedReason.EXPIRED:
notificationClosedReason = NotificationClosedReason.EXPIRED;
break;
case MessageTray.NotificationDestroyedReason.DISMISSED:
notificationClosedReason = NotificationClosedReason.DISMISSED;
break;
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
break;
}
this._emitNotificationClosed(ndata.id, notificationClosedReason);
});
@@ -310,7 +309,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
if (actions.length) {
for (let i = 0; i < actions.length - 1; i += 2) {
let [actionId, label] = [actions[i], actions[i + 1]];
let [actionId, label] = [actions[i], actions[i+1]];
if (actionId == 'default')
hasDefaultAction = true;
else
@@ -331,15 +330,15 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
switch (hints.urgency) {
case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
break;
case Urgency.NORMAL:
notification.setUrgency(MessageTray.Urgency.NORMAL);
break;
case Urgency.CRITICAL:
notification.setUrgency(MessageTray.Urgency.CRITICAL);
break;
case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
break;
case Urgency.NORMAL:
notification.setUrgency(MessageTray.Urgency.NORMAL);
break;
case Urgency.CRITICAL:
notification.setUrgency(MessageTray.Urgency.CRITICAL);
break;
}
notification.setResident(!!hints.resident);
// 'transient' is a reserved keyword in JS, so we have to retrieve the value
@@ -438,7 +437,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
_createPolicy() {
if (this.app && this.app.get_app_info()) {
let id = this.app.get_id().replace(/\.desktop$/, '');
let id = this.app.get_id().replace(/\.desktop$/,'');
return new MessageTray.NotificationApplicationPolicy(id);
} else {
return new MessageTray.NotificationGenericPolicy();
@@ -475,7 +474,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
return app;
if (appId) {
app = Shell.AppSystem.get_default().lookup_app(`${appId}.desktop`);
app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
if (app != null)
return app;
}
@@ -574,7 +573,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
this.update(title.unpack(), body ? body.unpack() : null,
{ gicon: gicon ? Gio.icon_deserialize(gicon) : null,
datetime: time ? GLib.DateTime.new_from_unix_local(time.unpack()) : null });
datetime : time ? GLib.DateTime.new_from_unix_local(time.unpack()) : null });
}
_activateAction(namespacedActionId, target) {
@@ -611,7 +610,7 @@ function objectPathFromAppId(appId) {
}
function getPlatformData() {
let startupId = GLib.Variant.new('s', `_TIME${global.get_current_time()}`);
let startupId = GLib.Variant.new('s', '_TIME' + global.get_current_time());
return { "desktop-startup-id": startupId };
}
@@ -624,7 +623,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError();
let app = Shell.AppSystem.get_default().lookup_app(`${appId}.desktop`);
let app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
if (!app)
throw new InvalidAppError();
@@ -750,33 +749,29 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
_loadNotifications() {
this._isLoading = true;
try {
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
return;
let source;
try {
source = this._ensureAppSource(appId);
} catch(e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
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() {
@@ -798,7 +793,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
} catch(e) {
if (e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;

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