Compare commits

..

23 Commits

Author SHA1 Message Date
6fd0aafada authPrompt: Wiggle on failure
WIP
2019-10-15 21:34:35 +02:00
e5091ff17c environment: Parse repeat-count and auto-reverse
Those are two useful ClutterTimeline properties and
will be needed for wiggling the search entry when
failing the password.

Add support for passing repeat-count and auto-reverse
to ClutterActor.ease and ClutterActor.ease_property.
2019-10-15 21:32:21 +02:00
22534c4c64 unlockDialog: Show auth prompt on tap 2019-10-15 15:39:07 +02:00
cd1c45731d fixup! sessonMode: Remove 'lock-screen' mode 2019-10-15 15:38:56 +02:00
5380b06eb5 fixup! unlockDialog: Add UnlockDialogLayout 2019-10-15 15:37:46 +02:00
be714f7401 fixup! screenShield: Blur background 2019-10-14 18:29:31 +02:00
e71c249ea5 authPrompt: Refine entry width
The current entry has a hardcoded size of 320px,
which doesn't really fit the lock screen mockups.

Remove this hardcoded size from AuthPrompt entries
and make them horizontally expand.
2019-10-12 21:33:41 -03:00
5b6deff977 authPrompt: Iconize the cancel button
Replace the "Cancel" label in the cancel button
by an arrow icon, and adjust the theme to make
it circular.
2019-10-12 21:12:45 -03:00
6cd0c3f965 authPrompt: Move cancel button and cog to a single row
Move the cancel button and the user well actors (the cog
menu and the spinner) to a single row.

Ultimately the user well will be splitted out into a different
place, but moving it now at least gives some visual consistency.
2019-10-12 17:58:55 -03:00
d529e222d7 unlockDialog: Add UnlockDialogLayout
This is a specialized layout manager to implement the
UI description of the new lock screen.
2019-10-12 17:49:40 -03:00
2e23a0e6b8 authPrompt: Remove next button 2019-10-12 17:49:40 -03:00
64aaa46333 unlockDialog: Adjust notification style
I think I can flip the development table and
become a designer now -- what else is needed
beyond figuring out spacing anyway?!
2019-10-12 17:49:40 -03:00
d1f61e884d sessonMode: Remove 'lock-screen' mode
As per the latest mockups, the only session mode
related to locked screens will be the unlock dialog.
2019-10-12 17:49:40 -03:00
fe3d55eb80 screenShield: Cleanup unused parameters 2019-10-12 17:49:40 -03:00
7a90b2d908 screenShield: Remove _lockScreenGroup
Now, _lockDialogGroup will be responsible for being
the actual screenshield.
2019-10-12 17:49:40 -03:00
137df4bc26 screenShield: Cleanup lock screen handling 2019-10-12 17:49:40 -03:00
23abe4eb22 screenShield: Translate the dialog group
Instead of the screen lock group, which is now
empty and soon will be removed.
2019-10-12 17:49:40 -03:00
b7feb71490 screenShield: Move notification box to UnlockDialog 2019-10-12 17:49:40 -03:00
9aa9431a32 theme: Adjust unlock screen clock fonts
Designers plz help
2019-10-12 17:49:40 -03:00
c9e2afcf65 screenShield: Move Clock to UnlockDialog
Move the clock to UnlockDialog, as per the latest mockups.
2019-10-12 17:49:40 -03:00
be5ab24e97 screenShield: Remove arrows
They're not used anywhere in the new dialog
2019-10-12 17:49:40 -03:00
caf0c8dd7d screenShield: Blur background
This is a moderately fast two-pass gaussian blur
implementation. It downscales the framebuffer by
half before applying the gaussian shader, which
cuts down rendering time quite considerably.

The blur shader takes 3 uniforms as input: the blur
radius; whether to blur vertically or horizontally;
and a brightness value.

The blur radius is treated as an integer in C land
to simplify calculations. The vertical parameter is
treated as an integer by the shader simply due to
Cogl not having proper boolean support in snippets.
At last, brightness is also added to avoid needing
to use an extra effect to achieve that.
2019-10-12 17:49:40 -03:00
10a194e6ed screenShield: Move background to _screenDialogGroup 2019-10-09 19:42:40 -03:00
254 changed files with 10008 additions and 35235 deletions

6
.eslintrc.json Normal file
View File

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

View File

@ -1,3 +0,0 @@
extends:
- ./lint/eslintrc-gjs.yml
- ./lint/eslintrc-shell.yml

View File

@ -14,7 +14,7 @@ variables:
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: review
variables:
GIT_DEPTH: "100"
@ -47,7 +47,7 @@ eslint:
when: always
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
@ -65,15 +65,14 @@ build:
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
NO_AT_BRIDGE: "1"
before_script:
- ninja -C mutter/build install
script:
- dbus-run-session -- xvfb-run meson test -C build --no-rebuild
- xvfb-run meson test -C build --no-rebuild
<<: *only_default
artifacts:
expire_in: 1 day
@ -82,7 +81,7 @@ test:
when: on_failure
test-pot:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: test
before_script:
- ninja -C mutter/build install

View File

@ -1,5 +1,6 @@
#!/usr/bin/bash
shell_branch=$(git describe --contains --all HEAD)
mutter_target=
git clone https://gitlab.gnome.org/GNOME/mutter.git
@ -25,7 +26,8 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
fi
if [ -z "$mutter_target" ]; then
mutter_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
mutter_target=$(git branch -r -l origin/$shell_branch)
mutter_target=${mutter_target:-$(git branch -r -l ${shell_branch#remotes/})}
mutter_target=${mutter_target:-origin/master}
echo Using $mutter_target instead
fi

View File

@ -13,17 +13,11 @@ is_empty() {
}
run_eslint() {
ARGS_LEGACY='--config lint/eslintrc-legacy.yml'
ARGS_LEGACY='--config lint/eslintrc-legacy.json'
local extra_args=ARGS_$1
local output_var=OUTPUT_$1
local output=${!output_var}
# ensure output exists even if eslint doesn't report any errors
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js
local output=OUTPUT_$1
eslint -f unix ${!extra_args} -o ${!output} js
}
list_commit_range_additions() {
@ -76,13 +70,10 @@ create_common() {
# non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
REMOTE=${1:-$CI_MERGE_REQUEST_PROJECT_URL.git}
BRANCH_NAME=${2:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
if [ "$BRANCH_NAME" ]; then
git fetch $REMOTE $BRANCH_NAME
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commit_range=$branch_point...HEAD
commit_range=$branch_point...$CI_COMMIT_SHA
list_commit_range_additions $commit_range > $LINE_CHANGES
@ -105,7 +96,7 @@ if ! is_empty $OUTPUT_FINAL; then
fi
# Just show the report and succeed when not testing a MR
if [ -z "$BRANCH_NAME" ]; then
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
exit 0
fi

View File

@ -163,17 +163,11 @@ you to inherit from a type to use it, you can do so:
return [100, 100];
}
vfunc_paint(paintContext) {
let framebuffer = paintContext.get_framebuffer();
let coglContext = framebuffer.get_context();
vfunc_paint() {
let alloc = this.get_allocation_box();
let pipeline = new Cogl.Pipeline(coglContext);
pipeline.set_color4ub(255, 0, 0, 255);
framebuffer.draw_rectangle(pipeline,
alloc.x1, alloc.y1,
alloc.x2, alloc.y2);
Cogl.set_source_color4ub(255, 0, 0, 255);
Cogl.rectangle(alloc.x1, alloc.y1,
alloc.x2, alloc.y2);
}
});
```
@ -192,27 +186,15 @@ and "double quotes" for strings that the user may see. This allows us to
quickly find untranslated or mistranslated strings by grepping through the
sources for double quotes without a gettext call around them.
## `actor` (deprecated) and `_delegate`
## `actor` and `_delegate`
gjs allows us to set so-called "expando properties" on introspected objects,
allowing us to treat them like any other. Because the Shell was built before
you could inherit from GTypes natively in JS, in some cases we have a wrapper
class that has a property called `actor` (now deprecated). We call this
wrapper class the "delegate".
you could inherit from GTypes natively in JS, we usually have a wrapper class
that has a property called `actor`. We call this wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on
the actor itself:
```javascript
var MyActor = GObject.registerClass(
class MyActor extends Clutter.Actor {
_init(params) {
super._init(params);
this._delegate = this;
}
});
```
Or using the deprecated `actor`:
```javascript
var MyClass = class {
constructor() {
@ -233,7 +215,6 @@ delegate object from an associated actor. For instance, the drag and drop
system calls the `handleDragOver` function on the delegate of a "drop target"
when the user drags an item over it. If you do not set the `_delegate`
property, your actor will not be able to be dropped onto.
In case the class is an actor itself, the `_delegate` can be just set to `this`.
## Functional style

72
NEWS
View File

@ -1,75 +1,3 @@
3.35.2
======
* Fix unredirection after cancelled animations [Florian; #1788]
* Include shadow in window screenshots [Robert; !762]
* Show indicator when microphone is active [Florian; !729]
* Use inheritance instead of delegate pattern [Marco; !559]
* Use cached coordinates for window sorting in overview [Andrew; !763]
* Wiggle login/unlock password entries on failure [Georges; !769]
* Update window titles in app menu [Florian; #1830]
* Fix window animations getting stuck by workspace switches [Jonas D.; !784]
* Fix not-responding dialog size when using geometry scaling [Jonas D.; !783]
* Handle buggy MPRIS clients more gracefully [Philip; #1362]
* Deprecate StBoxLayout's child properties [Florian; !780]
* Remove StBin's align properties [Florian; !803]
* Use correct timezones for events [Milan, Florian; !806, #1895]
* Reduce overhead of tracking stylesheet changes [Carlos; !779]
* Replace action icons in system menu with regular menu items [Florian; #270]
* Refine polkit dialogs [Jonas D.; !788]
* Fix battery icon glitch in "100% but charging" case [Philip; !814]
* Fix windows getting stuck on screen if closed while animating [Florian; !815]
* Use font from interface settings [Florian; #688288]
* Show polkit confirmation dialog for users with no password
[Joaquim, Jonas D.; !829]
* Use better OSK layout fallback for unsupported variants [Florian; #1907]
* Hide stopped spinner in top bar [Joonas; !832]
* Reuse existing icons when updating the app picker grid [Georges; !841]
* Show switcher popups immediately on second key press [Florian; #1928]
* Add position-based animation to page indicators [Alexander; !843]
* Improve modifier-less keyboard navigation of switcher popups [Florian; #1883]
* Improve weather integration [Florian; #1927, #1926]
* Add back sound feedback when scrolling volume indicator [Florian; #53]
* Fix creating app folders with no pre-existing folders [Jonas D.; #1652]
* Improve DND page switching in app picker [Florian, Jonas D.; #1693]
* Fix disable command of gnome-extensions tool [Florian; #1946]
* Tweak styling of notifications/media constrols [Joonas; !855, !865]
* Enable clean session shutdown after gnome-shell failure [Benjamin; !858]
* Also remove scaled keys when texture cache is cleared [Daniel M.; !567]
* Don't show overflow indicator in switchers that fit screen [Florian; #1834]
* Move libcroco dependency in-tree [Federico; !861]
* Move to app folder location when it is created/renamed [Georges; !883]
* Dismiss switcher popups when a system modal dialogs opens [Florian; #1536]
* Fix weather forecasts for automatic location when Weather is not sandboxed
[Florian; #1823]
* Place launched applications into a systemd scope [Benjamin; !863]
* Fixed crashes [Jonas D., Carlos; !787, !813]
* Misc. bug fixes and cleanups [Marco, Georges, Daniel V., Florian, Robert,
Kalev, Philip, Jonas D., Will, Carlos, Jonas Å., cunidev, Joonas, Federico;
!747, !765, !421, !759, !749, !730, !770, #1799, !774, !773, !776, !777,
!782, !794, !778, !792, !790, !190, !796, !795, !797, !798, !800, !804, !808,
!807, !810, !811, !563, !809, !805, !817, !818, !822, !830, !828, !823, !835,
!840, !842, !833, !845, !846, !847, !851, #1916, !862, !866, #1979, !827,
#1976, !884, !873, !885, !799, !887, !891, !816]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Philip Chimento, Milan Crha,
Jonas Dreßler, Carlos Garnacho, Joonas Henriksson, Kalev Lember, Robert Mader,
Alexander Mikhaylenko, Daniel García Moreno, Florian Müllner,
Georges Basile Stavracas Neto, Federico Mena Quintero, Joaquim Rocha,
Will Thompson, Daniel van Vugt, Andrew Watson, cunidev, Jonas Ådahl
Translators:
Daniel Mustieles [es], Goran Vidović [hr], Fabio Tomat [fur],
Danial Behzadi [fa], Andika Triwidada [id], Efstathios Iosifidis [el],
Ricardo Silva Veloso [pt_BR]
3.35.1
======
* Misc. bug fixes and cleanups [Marco; Matthias; !758, #701212]
Contributors:
Marco Trevisan (Treviño)
3.34.1
======
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]

View File

@ -1,12 +1,11 @@
[Unit]
Description=Disable GNOME Shell extensions after failure
# Note that this unit must not conflict with anything, and must
# be able to run in parallel with the gnome-session-shutdown.target.
DefaultDependencies=no
# We want to disable extensions only if gnome-shell has flagged the extensions
# to be a likely cause of trouble.
ConditionPathExists=%t/gnome-shell-disable-extensions
# 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

View File

@ -50,7 +50,7 @@
</description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'org.gnome.Shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<summary>List of desktop file IDs for favorite applications</summary>
<description>
The applications corresponding to these identifiers

View File

@ -36,8 +36,10 @@ $_hover_bg_color: lighten($bg_color,if($variant=='light', 5%, 3%));
$_active_bg_color: if($variant == 'light', darken($bg_color, 14%), darken($bg_color, 9%));
$font-size: 11;
$font-family: Cantarell, Sans-Serif;
stage {
font-family: $font-family;
@include fontsize($font-size);
color: $fg_color;
}
@ -977,7 +979,6 @@ StScrollBar {
spacing-columns: 0.8em;
}
.weather-header-box,
.weather-box {
spacing: 0.4em;
}
@ -1060,9 +1061,9 @@ StScrollBar {
}
.calendar-today {
font-weight: bold;
color: lighten($fg_color,5%);
background-color: darken($bg_color,5%);
// border: 1px solid lighten($_bubble_borders_color,20%);
//color: lighten($fg_color,10%);
//background-color: darken($bg_color,5%);
border: 1px solid $_bubble_borders_color;
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
@ -1152,21 +1153,14 @@ StScrollBar {
padding: 10px;
}
.message-close-button {
color: lighten($fg_color, 15%);
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
}
.message-media-control {
padding: 12px;
color: lighten($fg_color, 15%);
&:last-child:ltr { padding-right: 18px; }
&:last-child:rtl { padding-left: 18px; }
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
&:insensitive { color: if($variant=='light', lighten($fg_color, 50%), darken($fg_color, 40%)); }
&:hover { color: $fg_color; }
&:insensitive { color: darken($fg_color,40%); }
}
.media-message-cover-icon {
@ -1196,8 +1190,7 @@ StScrollBar {
.aggregate-menu {
min-width: 21em;
.popup-menu-icon { padding: 0 4px;
-st-icon-style: symbolic; }
.popup-menu-icon { padding: 0 4px; }
.popup-sub-menu .popup-menu-item > :first-child {
&:ltr { /* 12px spacing + 2*4px padding */
padding-left: 20px; margin-left: 1.09em; }
@ -1206,6 +1199,27 @@ StScrollBar {
}
}
.system-menu-action {
-st-icon-style: symbolic;
color: $fg_color;
border-radius: 32px; /* wish we could do 50% */
padding: 13px;
border: 1px solid $_bubble_borders_color;
&:hover, &:focus {
background-color: $_hover_bg_color;
color: $fg_color;
border: none;
padding: 14px;
}
&:active {
background-color: $selected_bg_color;
color: $selected_fg_color;
}
& > StIcon { icon-size: 16px; }
}
// Activities Ripples
.ripple-box {
width: 52px;
@ -1557,14 +1571,20 @@ StScrollBar {
}
.page-indicator {
padding: 7px 16px;
padding: 15px 20px;
.page-indicator-icon {
width: 12px;
height: 12px;
background-color: white;
border-radius: 6px;
background-color: transparent;
border: 2px solid rgba(255, 255, 255, 0.4);
border-radius: 12px;
}
&:hover .page-indicator-icon { border-color: white; }
&:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
&:checked .page-indicator-icon,
&:checked:active .page-indicator-icon { background-color: white;}
}
.no-frequent-applications-label { @extend %status_text; }
@ -1764,8 +1784,8 @@ StScrollBar {
padding: 4px 4px;
.page-indicator-icon {
width: 8px;
height: 8px;
width: 6px;
height: 6px
}
}
}
@ -1909,6 +1929,7 @@ StScrollBar {
StEntry {
@extend %search_entry;
width: -1px;
border-radius: $button_radius;
@if $variant=='dark' {
$_gdm_entry_bg: transparentize(lighten(desaturate(#241f31, 20%), 2%), 0.5);
@ -1966,6 +1987,15 @@ StScrollBar {
}
}
}
.cancel-button {
padding: 0;
border-radius: 16px;
width: 32px;
height: 32px;
StIcon { icon-size: 16px; }
}
}
.login-dialog-logo-bin { padding: 24px 0px; }
@ -2049,42 +2079,28 @@ StScrollBar {
$_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
.screen-shield-arrows {
padding-bottom: 3em;
}
.screen-shield-arrows Gjs_Arrow {
color: white;
width: 80px;
height: 48px;
-arrow-thickness: 12px;
-arrow-shadow: $_screenshield_shadow;
}
.screen-shield-clock {
color: white;
text-shadow: $_screenshield_shadow;
font-weight: bold;
text-align: center;
padding-bottom: 1.5em;
padding-bottom: 2.5em;
}
.screen-shield-clock-time {
font-size: 72pt;
text-shadow: $_screenshield_shadow;
font-size: 64pt;
font-weight: 200;
padding-bottom: 24px;
font-feature-settings: "tnum";
}
.screen-shield-clock-date {
font-size: 28pt;
font-weight: normal;
font-size: 16pt;
font-weight: bold;
}
.screen-shield-notifications-container {
spacing: 6px;
width: 30em;
background-color: transparent;
max-height: 500px;
padding: 24px 0;
.summary-notification-stack-scrollview {
padding-top: 0;
padding-bottom: 0;
@ -2092,7 +2108,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
.notification,
.screen-shield-notification-source {
padding: 12px 6px;
padding: 12px;
border: 1px solid $osd_outer_borders_color;
background-color: transparentize($osd_bg_color,0.5);
color: $osd_fg_color;

View File

@ -31,34 +31,34 @@ its dependencies to build from tarballs.</description>
<programming-language>JavaScript</programming-language>
<programming-language>C</programming-language>
<author>
<maintainer>
<foaf:Person>
<foaf:name>William Jon McCann</foaf:name>
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
<gnome:userid>mccann</gnome:userid>
</foaf:Person>
</author>
<author>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Owen Taylor</foaf:name>
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
<gnome:userid>otaylor</gnome:userid>
</foaf:Person>
</author>
<author>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Colin Walters</foaf:name>
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
<gnome:userid>walters</gnome:userid>
</foaf:Person>
</author>
<author>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Marina Zhurakhinskaya</foaf:name>
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
<gnome:userid>marinaz</gnome:userid>
</foaf:Person>
</author>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Florian Müllner</foaf:name>

View File

@ -23,13 +23,14 @@ function stripPrefix(string, prefix) {
return string;
}
var Application = GObject.registerClass(
class Application extends Gtk.Application {
var Application = GObject.registerClass({
GTypeName: 'ExtensionPrefs_Application'
}, class Application extends Gtk.Application {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs');
super._init({
application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
});
this._startupUuid = null;
@ -60,12 +61,12 @@ class Application extends Gtk.Application {
let dialog = new Gtk.Window({
modal: !this._skipMainWindow,
type_hint: Gdk.WindowTypeHint.DIALOG,
type_hint: Gdk.WindowTypeHint.DIALOG
});
dialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true,
visible: true
}));
if (this._skipMainWindow) {
@ -88,20 +89,20 @@ class Application extends Gtk.Application {
_buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true,
propagate_natural_height: true
});
let box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
margin_bottom: 60
});
scroll.add(box);
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(_("Somethings gone wrong")),
use_markup: true,
use_markup: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
box.add(label);
@ -109,13 +110,13 @@ class Application extends Gtk.Application {
label = new Gtk.Label({
label: _("Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors."),
justify: Gtk.Justification.CENTER,
wrap: true,
wrap: true
});
box.add(label);
let expander = new Expander({
label: _("Technical Details"),
margin_top: 12,
margin_top: 12
});
box.add(expander);
@ -126,14 +127,14 @@ class Application extends Gtk.Application {
let buffer = new Gtk.TextBuffer({ text: errortext });
let textview = new Gtk.TextView({
buffer,
buffer: buffer,
wrap_mode: Gtk.WrapMode.WORD,
monospace: true,
editable: false,
top_margin: 12,
bottom_margin: 12,
left_margin: 12,
right_margin: 12,
right_margin: 12
});
let toolbar = new Gtk.Toolbar();
@ -149,7 +150,7 @@ class Application extends Gtk.Application {
let copyButton = new Gtk.ToolButton({
icon_name: 'edit-copy-symbolic',
tooltip_text: _("Copy Error"),
tooltip_text: _("Copy Error")
});
toolbar.add(copyButton);
@ -158,15 +159,15 @@ class Application extends Gtk.Application {
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${row.uuid} had an error:`,
'```', // '`' (xgettext throws up on odd number of backticks)
'```',
`${exc}`,
'```', // '`'
'```',
'',
'Stack trace:',
'```', // '`'
'```',
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```', // '`'
'',
'```',
''
];
clipboard.set_text(lines.join('\n'), -1);
});
@ -179,7 +180,7 @@ class Application extends Gtk.Application {
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: row.url != null,
visible: row.url != null
});
toolbar.add(urlButton);
@ -189,7 +190,7 @@ class Application extends Gtk.Application {
});
let expandedBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
orientation: Gtk.Orientation.VERTICAL
});
expandedBox.add(textview);
expandedBox.add(toolbar);
@ -219,7 +220,7 @@ class Application extends Gtk.Application {
Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._mainStack = new Gtk.Stack({
transition_type: Gtk.StackTransitionType.CROSSFADE,
transition_type: Gtk.StackTransitionType.CROSSFADE
});
this._window.add(this._mainStack);
@ -258,15 +259,23 @@ class Application extends Gtk.Application {
}
_onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let extension = ExtensionUtils.deserializeExtension(newState);
let row = this._findExtensionRow(uuid);
if (row) {
if (extension.state === ExtensionState.UNINSTALLED)
let { state } = ExtensionUtils.deserializeExtension(newState);
if (state == ExtensionState.UNINSTALLED)
row.destroy();
return; // we only deal with new and deleted extensions here
}
this._addExtensionRow(extension);
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() {
@ -352,20 +361,20 @@ var Expander = GObject.registerClass({
'label', 'label', 'label',
GObject.ParamFlags.READWRITE,
null
),
},
)
}
}, class Expander extends Gtk.Box {
_init(params = {}) {
this._labelText = null;
super._init(Object.assign(params, {
orientation: Gtk.Orientation.VERTICAL,
spacing: 0,
spacing: 0
}));
this._frame = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
hexpand: true,
hexpand: true
});
let eventBox = new Gtk.EventBox();
@ -373,12 +382,12 @@ var Expander = GObject.registerClass({
let hbox = new Gtk.Box({
spacing: 6,
margin: 12,
margin: 12
});
eventBox.add(hbox);
this._arrow = new Gtk.Image({
icon_name: 'pan-end-symbolic',
icon_name: 'pan-end-symbolic'
});
hbox.add(this._arrow);
@ -388,7 +397,7 @@ var Expander = GObject.registerClass({
this._revealer = new Gtk.Revealer();
this._childBin = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
shadow_type: Gtk.ShadowType.IN
});
this._revealer.add(this._childBin);
@ -406,7 +415,7 @@ var Expander = GObject.registerClass({
this._gesture = new Gtk.GestureMultiPress({
widget: this._frame,
button: 0,
exclusive: true,
exclusive: true
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress == 1)
@ -451,7 +460,7 @@ class EmptyPlaceholder extends Gtk.Box {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 6,
margin: 32,
margin: 32
});
let image = new Gtk.Image({
@ -459,15 +468,15 @@ class EmptyPlaceholder extends Gtk.Box {
pixel_size: 96,
visible: true,
vexpand: true,
valign: Gtk.Align.END,
valign: Gtk.Align.END
});
image.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(image);
let label = new Gtk.Label({
label: `<b><span size="x-large">${_("No Extensions Installed")}</span></b>`,
label: `<b><span size="x-large">${_("No Extensions Installed" )}</span></b>`,
use_markup: true,
visible: true,
visible: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
@ -482,9 +491,9 @@ class EmptyPlaceholder extends Gtk.Box {
visible: true,
max_width_chars: 50,
hexpand: true,
vexpand: appInfo == null,
vexpand: (appInfo == null),
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
valign: Gtk.Align.START
});
this.add(desc);
@ -492,14 +501,14 @@ class EmptyPlaceholder extends Gtk.Box {
let button = new Gtk.Button({
label: _("Browse in Software"),
image: new Gtk.Image({
icon_name: "org.gnome.Software-symbolic",
icon_name: "org.gnome.Software-symbolic"
}),
always_show_image: true,
margin_top: 12,
visible: true,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
vexpand: true,
vexpand: true
});
this.add(button);
@ -518,13 +527,13 @@ class NoShellPlaceholder extends Gtk.Box {
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
margin_bottom: 60
});
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(
_("Somethings gone wrong")),
use_markup: true,
use_markup: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
@ -532,7 +541,7 @@ class NoShellPlaceholder extends Gtk.Box {
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,
wrap: true
});
this.add(label);
@ -569,11 +578,11 @@ class ExtensionRow extends Gtk.ListBoxRow {
return;
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = this._extension.state == ExtensionState.ENABLED;
let state = (this._extension.state == ExtensionState.ENABLED);
this._switch.block_signal_handler(this._notifyActiveId);
GObject.signal_handler_block(this._switch, this._notifyActiveId);
this._switch.state = state;
this._switch.unblock_signal_handler(this._notifyActiveId);
GObject.signal_handler_unblock(this._switch, this._notifyActiveId);
this._switch.sensitive = this._canToggle();
});
@ -640,7 +649,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._switch = new Gtk.Switch({
valign: Gtk.Align.CENTER,
sensitive: this._canToggle(),
state: this._extension.state === ExtensionState.ENABLED,
state: this._extension.state === ExtensionState.ENABLED
});
this._notifyActiveId = this._switch.connect('notify::active', () => {
if (this._switch.active)
@ -657,12 +666,12 @@ class ExtensionRow extends Gtk.ListBoxRow {
}
get prefsModule() {
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
@ -683,7 +692,7 @@ function initEnvironment() {
log(`ERROR: ${s}`);
},
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']),
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
};
String.prototype.format = Format.format;

View File

@ -1,12 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AuthPrompt */
const { Clutter, GObject, Pango, Shell, St } = imports.gi;
const { Clutter, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Animation = imports.ui.animation;
const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
const Util = imports.misc.util;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
@ -23,36 +22,23 @@ const N_WIGGLES = 3;
var AuthPromptMode = {
UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1,
UNLOCK_OR_LOG_IN: 1
};
var AuthPromptStatus = {
NOT_VERIFYING: 0,
VERIFYING: 1,
VERIFICATION_FAILED: 2,
VERIFICATION_SUCCEEDED: 3,
VERIFICATION_SUCCEEDED: 3
};
var BeginRequestType = {
PROVIDE_USERNAME: 0,
DONT_PROVIDE_USERNAME: 1,
DONT_PROVIDE_USERNAME: 1
};
var AuthPrompt = GObject.registerClass({
Signals: {
'cancelled': {},
'failed': {},
'next': {},
'prompted': {},
'reset': { param_types: [GObject.TYPE_UINT] },
},
}, class AuthPrompt extends St.BoxLayout {
_init(gdmClient, mode) {
super._init({
style_class: 'login-dialog-prompt-layout',
vertical: true,
});
var AuthPrompt = class {
constructor(gdmClient, mode) {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient;
@ -64,7 +50,7 @@ var AuthPrompt = GObject.registerClass({
else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN)
reauthenticationOnly = false;
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly });
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: reauthenticationOnly });
this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this));
this._userVerifier.connect('show-message', this._onShowMessage.bind(this));
@ -78,68 +64,44 @@ var AuthPrompt = GObject.registerClass({
this.connect('next', () => {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService)
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
else
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.connect('destroy', this._onDestroy.bind(this));
this._userWell = new St.Bin({
x_expand: true,
y_expand: true,
});
this.add_child(this._userWell);
this._label = new St.Label({
style_class: 'login-dialog-prompt-label',
x_expand: false,
y_expand: true,
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;
});
this.add_child(this._label);
this._entry = new St.Entry({
style_class: 'login-dialog-prompt-entry',
can_focus: true,
x_expand: false,
y_expand: true,
});
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
this._userWell = new St.Bin({ x_fill: true,
x_align: St.Align.START });
this.actor.add(this._userWell,
{ x_align: St.Align.START,
x_fill: true,
y_fill: true,
expand: true });
this._label = new St.Label({ style_class: 'login-dialog-prompt-label' });
this.add_child(this._entry);
this.actor.add(this._label,
{ expand: true,
x_fill: false,
y_fill: true,
x_align: St.Align.START });
this._entry.grab_key_focus();
this._initEntryRow();
this._message = new St.Label({
opacity: 0,
styleClass: 'login-dialog-message',
x_expand: false,
y_expand: true,
y_align: Clutter.ActorAlign.START,
});
this._message = new St.Label({ opacity: 0,
styleClass: 'login-dialog-message' });
this._message.clutter_text.line_wrap = true;
this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.add_child(this._message);
this._buttonBox = new St.BoxLayout({
style_class: 'login-dialog-button-box',
vertical: false,
y_align: Clutter.ActorAlign.END,
});
this.add_child(this._buttonBox);
this._defaultButtonWell = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
this._initButtons();
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.opacity = 0;
this._spinner.show();
this._defaultButtonWell.add_child(this._spinner);
this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
}
_onDestroy() {
@ -147,52 +109,47 @@ var AuthPrompt = GObject.registerClass({
this._userVerifier = null;
}
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
}
_initEntryRow() {
let mainBox = new St.BoxLayout({
style_class: 'login-dialog-button-box',
vertical: false,
});
this.actor.add_child(mainBox);
_initButtons() {
this.cancelButton = new St.Button({
style_class: 'modal-dialog-button button',
style_class: 'modal-dialog-button button cancel-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
label: _("Cancel"),
x_expand: true,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
child: new St.Icon({ icon_name: 'go-previous-symbolic' }),
});
this.cancelButton.connect('clicked', () => this.cancel());
this._buttonBox.add_child(this.cancelButton);
mainBox.add_child(this.cancelButton);
this._buttonBox.add_child(this._defaultButtonWell);
this.nextButton = new St.Button({
style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
this._entry = new St.Entry({
style_class: 'login-dialog-prompt-entry',
can_focus: true,
label: _("Next"),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
});
this.nextButton.connect('clicked', () => this.emit('next'));
this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add_child(this.nextButton);
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
this._updateNextButtonSensitivity(this._entry.text.length > 0);
mainBox.add_child(this._entry);
this._entry.grab_key_focus();
this._entry.clutter_text.connect('activate', () => this.emit('next'));
this._entry.clutter_text.connect('text-changed', () => {
if (!this._userVerifier.hasPendingMessages)
this._fadeOutMessage();
});
this._updateNextButtonSensitivity(this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING);
});
this._entry.clutter_text.connect('activate', () => {
if (this.nextButton.reactive)
this.emit('next');
});
this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._defaultButtonWellActor = null;
mainBox.add_child(this._defaultButtonWell);
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0;
this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner.actor);
}
_onAskQuestion(verifier, serviceName, question, passwordChar) {
@ -207,16 +164,6 @@ var AuthPrompt = GObject.registerClass({
}
this.setPasswordChar(passwordChar);
this.setQuestion(question);
if (passwordChar) {
if (this._userVerifier.reauthenticating)
this.nextButton.label = _("Unlock");
else
this.nextButton.label = C_("button", "Sign In");
} else {
this.nextButton.label = _("Next");
}
this.updateSensitivity(true);
this.emit('prompted');
}
@ -258,10 +205,33 @@ var AuthPrompt = GObject.registerClass({
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
Util.wiggle(this._entry, {
offset: WIGGLE_OFFSET,
this._wiggle();
}
_wiggle() {
// Accelerate before wiggling
this._entry.ease({
translation_x: -WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
wiggleCount: N_WIGGLES,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
// Wiggle
this._entry.ease({
translation_x: WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
mode: Clutter.AnimationMode.LINEAR,
repeat_count: N_WIGGLES,
auto_reverse: true,
onComplete: () => {
// Decelerate and return to the original position
this._entry.ease({
translation_x: 0,
duration: WIGGLE_DURATION,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
});
}
});
}
});
}
@ -291,13 +261,13 @@ var AuthPrompt = GObject.registerClass({
oldActor.remove_all_transitions();
let wasSpinner;
if (oldActor == this._spinner)
if (oldActor == this._spinner.actor)
wasSpinner = true;
else
wasSpinner = false;
let isSpinner;
if (actor == this._spinner)
if (actor == this._spinner.actor)
isSpinner = true;
else
isSpinner = false;
@ -321,7 +291,7 @@ var AuthPrompt = GObject.registerClass({
if (this._spinner)
this._spinner.stop();
}
},
}
});
}
}
@ -330,23 +300,22 @@ var AuthPrompt = GObject.registerClass({
if (isSpinner)
this._spinner.play();
if (!animate) {
if (!animate)
actor.opacity = 255;
} else {
else
actor.ease({
opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR,
mode: Clutter.AnimationMode.LINEAR
});
}
}
this._defaultButtonWellActor = actor;
}
startSpinning() {
this.setActorInDefaultButtonWell(this._spinner, true);
this.setActorInDefaultButtonWell(this._spinner.actor, true);
}
stopSpinning() {
@ -392,7 +361,7 @@ var AuthPrompt = GObject.registerClass({
this._message.ease({
opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -416,20 +385,14 @@ var AuthPrompt = GObject.registerClass({
}
}
_updateNextButtonSensitivity(sensitive) {
this.nextButton.reactive = sensitive;
this.nextButton.can_focus = sensitive;
}
updateSensitivity(sensitive) {
this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
}
vfunc_hide() {
hide() {
this.setActorInDefaultButtonWell(null, true);
super.vfunc_hide();
this.actor.hide();
this._message.opacity = 0;
this.setUser(null);
@ -445,8 +408,7 @@ var AuthPrompt = GObject.registerClass({
if (user) {
let userWidget = new UserWidget.UserWidget(user);
userWidget.x_align = Clutter.ActorAlign.START;
this._userWell.set_child(userWidget);
this._userWell.set_child(userWidget.actor);
}
}
@ -454,7 +416,6 @@ var AuthPrompt = GObject.registerClass({
let oldStatus = this.verificationStatus;
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
this.nextButton.label = _("Next");
this._preemptiveAnswer = null;
if (this._userVerifier)
@ -525,10 +486,11 @@ var AuthPrompt = GObject.registerClass({
}
cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED)
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return;
}
this.reset();
this.emit('cancelled');
}
});
};
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@ -112,12 +112,13 @@ var Batch = class extends Task {
for (let i = 0; i < tasks.length; i++) {
let task;
if (tasks[i] instanceof Task)
if (tasks[i] instanceof Task) {
task = tasks[i];
else if (typeof tasks[i] == 'function')
} else if (typeof tasks[i] == 'function') {
task = new Task(scope, tasks[i]);
else
} else {
throw new Error('Batch tasks must be functions or Task, Hold or Batch objects');
}
this.tasks.push(task);
}
@ -128,8 +129,9 @@ var Batch = class extends Task {
}
runTask() {
if (!(this._currentTaskIndex in this.tasks))
if (!(this._currentTaskIndex in this.tasks)) {
return null;
}
return this.tasks[this._currentTaskIndex].run();
}
@ -177,8 +179,9 @@ var ConcurrentBatch = class extends Batch {
process() {
let hold = this.runTask();
if (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

View File

@ -20,7 +20,7 @@ function FprintManager() {
g_interface_info: FprintManagerInfo,
g_name: 'net.reactivated.Fprint',
g_object_path: '/net/reactivated/Fprint/Manager',
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
try {
self.init(null);

View File

@ -19,6 +19,7 @@
const { AccountsService, Atk, Clutter, Gdm, Gio,
GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const AuthPrompt = imports.gdm.authPrompt;
const Batch = imports.gdm.batch;
@ -38,81 +39,72 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5;
var UserListItem = GObject.registerClass({
Signals: { 'activate': {} },
}, class UserListItem extends St.Button {
_init(user) {
let layout = new St.BoxLayout({
vertical: true,
x_align: Clutter.ActorAlign.START,
});
super._init({
style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
x_expand: true,
child: layout,
reactive: true,
});
var UserListItem = class {
constructor(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
this._onUserChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this.connect('notify::hover', () => {
this._setSelected(this.hover);
let layout = new St.BoxLayout({ vertical: true });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('key-focus-in', () => {
this._setSelected(true);
});
this.actor.connect('key-focus-out', () => {
this._setSelected(false);
});
this.actor.connect('notify::hover', () => {
this._setSelected(this.actor.hover);
});
this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget);
layout.add(this._userWidget.actor);
this._userWidget.bind_property('label-actor', this, 'label-actor',
GObject.BindingFlags.SYNC_CREATE);
this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor',
GObject.BindingFlags.SYNC_CREATE);
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
scale_x: 0,
visible: false });
layout.add(this._timedLoginIndicator);
this.actor.connect('clicked', this._onClicked.bind(this));
this._onUserChanged();
}
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._setSelected(true);
}
vfunc_key_focus_out() {
super.vfunc_key_focus_out();
this._setSelected(false);
}
_onUserChanged() {
this._updateLoggedIn();
}
_updateLoggedIn() {
if (this.user.is_logged_in())
this.add_style_pseudo_class('logged-in');
this.actor.add_style_pseudo_class('logged-in');
else
this.remove_style_pseudo_class('logged-in');
this.actor.remove_style_pseudo_class('logged-in');
}
_onDestroy() {
this.user.disconnect(this._userChangedId);
}
vfunc_clicked() {
_onClicked() {
this.emit('activate');
}
_setSelected(selected) {
if (selected) {
this.add_style_pseudo_class('selected');
this.grab_key_focus();
this.actor.add_style_pseudo_class('selected');
this.actor.grab_key_focus();
} else {
this.remove_style_pseudo_class('selected');
this.actor.remove_style_pseudo_class('selected');
}
}
@ -125,7 +117,7 @@ var UserListItem = GObject.registerClass({
let startTime = GLib.get_monotonic_time();
this._timedLoginTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 33,
this._timedLoginTimeoutId = GLib.timeout_add (GLib.PRIORITY_DEFAULT, 33,
() => {
let currentTime = GLib.get_monotonic_time();
let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC;
@ -153,33 +145,23 @@ var UserListItem = GObject.registerClass({
this._timedLoginIndicator.visible = false;
this._timedLoginIndicator.scale_x = 0.;
}
});
};
Signals.addSignalMethods(UserListItem.prototype);
var UserList = GObject.registerClass({
Signals: {
'activate': { param_types: [UserListItem.$gtype] },
'item-added': { param_types: [UserListItem.$gtype] },
},
}, class UserList extends St.ScrollView {
_init() {
super._init({
style_class: 'login-dialog-user-list-view',
x_expand: true,
y_expand: true,
});
this.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
var UserList = class {
constructor() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
this.actor.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
this._box = new St.BoxLayout({ vertical: true,
style_class: 'login-dialog-user-list',
pseudo_class: 'expanded' });
this.add_actor(this._box);
this.actor.add_actor(this._box);
this._items = {};
}
vfunc_key_focus_in() {
this._moveFocusToItems();
this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
}
_moveFocusToItems() {
@ -188,10 +170,10 @@ var UserList = GObject.registerClass({
if (!hasItems)
return;
if (global.stage.get_key_focus() != this)
if (global.stage.get_key_focus() != this.actor)
return;
let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
if (!focusSet) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._moveFocusToItems();
@ -212,26 +194,26 @@ var UserList = GObject.registerClass({
for (let userName in this._items) {
let item = this._items[userName];
item.sync_hover();
item.actor.sync_hover();
}
}
scrollToItem(item) {
let box = item.get_allocation_box();
let box = item.actor.get_allocation_box();
let adjustment = this.get_vscroll_bar().get_adjustment();
let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: _SCROLL_ANIMATION_TIME,
duration: _SCROLL_ANIMATION_TIME
});
}
jumpToItem(item) {
let box = item.get_allocation_box();
let box = item.actor.get_allocation_box();
let adjustment = this.get_vscroll_bar().get_adjustment();
let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
@ -269,14 +251,14 @@ var UserList = GObject.registerClass({
this.removeUser(user);
let item = new UserListItem(user);
this._box.add_child(item);
this._box.add(item.actor, { x_fill: true });
this._items[userName] = item;
item.connect('activate', this._onItemActivated.bind(this));
// Try to keep the focused item front-and-center
item.connect('key-focus-in', () => this.scrollToItem(item));
item.actor.connect('key-focus-in', () => this.scrollToItem(item));
this._moveFocusToItems();
@ -297,37 +279,33 @@ var UserList = GObject.registerClass({
if (!item)
return;
item.destroy();
item.actor.destroy();
delete this._items[userName];
}
numItems() {
return Object.keys(this._items).length;
}
});
};
Signals.addSignalMethods(UserList.prototype);
var SessionMenuButton = GObject.registerClass({
Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } },
}, class SessionMenuButton extends St.Bin {
_init() {
var SessionMenuButton = class {
constructor() {
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
let button = new St.Button({
style_class: 'login-dialog-session-list-button',
reactive: true,
track_hover: true,
can_focus: true,
accessible_name: _("Choose Session"),
accessible_role: Atk.Role.MENU,
child: gearIcon,
});
this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
reactive: true,
track_hover: true,
can_focus: true,
accessible_name: _("Choose Session"),
accessible_role: Atk.Role.MENU,
child: gearIcon });
super._init({ child: button });
this._button = button;
this.actor = new St.Bin({ child: this._button });
let side = St.Side.TOP;
let align = 0;
if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
if (this.text_direction == Clutter.TextDirection.RTL)
if (this.actor.text_direction == Clutter.TextDirection.RTL)
side = St.Side.RIGHT;
else
side = St.Side.LEFT;
@ -406,13 +384,15 @@ var SessionMenuButton = GObject.registerClass({
});
}
}
});
};
Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = GObject.registerClass({
Signals: { 'failed': {} },
}, class LoginDialog extends St.Widget {
_init(parentActor) {
super._init({ style_class: 'login-dialog', visible: false });
super._init({ style_class: 'login-dialog',
visible: false });
this.get_accessible().set_role(Atk.Role.WINDOW);
@ -446,35 +426,38 @@ var LoginDialog = GObject.registerClass({
this.add_child(this._userSelectionBox);
this._userList = new UserList();
this._userSelectionBox.add_child(this._userList);
this._userSelectionBox.add(this._userList.actor,
{ expand: true,
x_fill: true,
y_fill: true });
this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
this._authPrompt.connect('prompted', this._onPrompted.bind(this));
this._authPrompt.connect('reset', this._onReset.bind(this));
this._authPrompt.hide();
this.add_child(this._authPrompt);
this.add_child(this._authPrompt.actor);
// translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for
// manually entering the username.
let notListedLabel = new St.Label({
text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label',
x_align: Clutter.ActorAlign.START,
});
this._notListedButton = new St.Button({
style_class: 'login-dialog-not-listed-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: notListedLabel,
reactive: true,
});
let notListedLabel = new St.Label({ text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label' });
this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: notListedLabel,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this));
this._notListedButton.hide();
this._userSelectionBox.add_child(this._notListedButton);
this._userSelectionBox.add(this._notListedButton,
{ expand: false,
x_align: St.Align.START,
x_fill: true });
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
opacity: 0,
@ -509,11 +492,11 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton = new SessionMenuButton();
this._sessionMenuButton.connect('session-activated',
(list, sessionId) => {
this._greeter.call_select_session_sync(sessionId, null);
this._greeter.call_select_session_sync (sessionId, null);
});
this._sessionMenuButton.opacity = 0;
this._sessionMenuButton.show();
this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton);
this._sessionMenuButton.actor.opacity = 0;
this._sessionMenuButton.actor.show();
this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
this._disableUserList = undefined;
this._userListLoaded = false;
@ -596,8 +579,8 @@ var LoginDialog = GObject.registerClass({
let authPromptAllocation = null;
let authPromptWidth = 0;
if (this._authPrompt.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt);
if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
}
@ -702,11 +685,12 @@ var LoginDialog = GObject.registerClass({
}
// Finally hand out the allocations
if (bannerAllocation)
if (bannerAllocation) {
this._bannerView.allocate(bannerAllocation, flags);
}
if (authPromptAllocation)
this._authPrompt.allocate(authPromptAllocation, flags);
this._authPrompt.actor.allocate(authPromptAllocation, flags);
if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation, flags);
@ -776,7 +760,7 @@ var LoginDialog = GObject.registerClass({
this._bannerView.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -810,7 +794,7 @@ var LoginDialog = GObject.registerClass({
_onPrompted() {
if (this._shouldShowSessionMenuButton()) {
this._sessionMenuButton.updateSensitivity(true);
this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton);
this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
} else {
this._sessionMenuButton.updateSensitivity(false);
}
@ -819,9 +803,9 @@ var LoginDialog = GObject.registerClass({
_resetGreeterProxy() {
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
if (this._greeter)
if (this._greeter) {
this._greeter.run_dispose();
}
this._greeter = this._gdmClient.get_greeter_sync(null);
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed',
@ -870,14 +854,14 @@ var LoginDialog = GObject.registerClass({
}
_showPrompt() {
if (this._authPrompt.visible)
if (this._authPrompt.actor.visible)
return;
this._authPrompt.opacity = 0;
this._authPrompt.show();
this._authPrompt.ease({
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,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._fadeInBannerView();
}
@ -945,7 +929,7 @@ var LoginDialog = GObject.registerClass({
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
this._unbindOpacity();
},
}
});
}
@ -967,7 +951,7 @@ var LoginDialog = GObject.registerClass({
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
this._unbindOpacity();
},
}
});
}
@ -984,7 +968,7 @@ var LoginDialog = GObject.registerClass({
let hold = new Batch.Hold();
let signalId = this._userList.connect('item-added',
() => {
item = this._userList.getItemFromUserName(userName);
let item = this._userList.getItemFromUserName(userName);
if (item)
hold.release();
@ -1038,8 +1022,9 @@ var LoginDialog = GObject.registerClass({
() => {
// If we're just starting out, start on the right item.
if (!this._userManager.is_loaded)
if (!this._userManager.is_loaded) {
this._userList.jumpToItem(loginItem);
}
},
() => {
@ -1060,12 +1045,12 @@ var LoginDialog = GObject.registerClass({
() => {
// If idle timeout is done, make sure the timed login indicator is shown
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
this._authPrompt.visible)
this._authPrompt.actor.visible)
this._authPrompt.cancel();
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
this._userList.scrollToItem(loginItem);
loginItem.grab_key_focus();
loginItem.actor.grab_key_focus();
}
},
@ -1090,8 +1075,9 @@ var LoginDialog = GObject.registerClass({
// Restart timed login on user interaction
global.stage.connect('captured-event', (actor, event) => {
if (event.type() == Clutter.EventType.KEY_PRESS ||
event.type() == Clutter.EventType.BUTTON_PRESS)
event.type() == Clutter.EventType.BUTTON_PRESS) {
this._startTimedLogin(userName, seconds);
}
return Clutter.EVENT_PROPAGATE;
});
@ -1125,7 +1111,7 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton.close();
this._setUserListExpanded(true);
this._notListedButton.show();
this._userList.grab_key_focus();
this._userList.actor.grab_key_focus();
}
_beginVerificationForItem(item) {
@ -1134,7 +1120,8 @@ var LoginDialog = GObject.registerClass({
let userName = item.user.get_user_name();
let hold = new Batch.Hold();
this._authPrompt.begin({ userName, hold });
this._authPrompt.begin({ userName: userName,
hold: hold });
return hold;
}
@ -1197,8 +1184,9 @@ var LoginDialog = GObject.registerClass({
let users = this._userManager.list_users();
for (let i = 0; i < users.length; i++)
for (let i = 0; i < users.length; i++) {
this._userList.addUser(users[i]);
}
this._updateDisableUserList();
@ -1231,7 +1219,7 @@ var LoginDialog = GObject.registerClass({
_("Login Window"),
'dialog-password-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
this._userList.grab_key_focus();
this._userList.actor.grab_key_focus();
this.show();
this.opacity = 0;
@ -1240,7 +1228,7 @@ var LoginDialog = GObject.registerClass({
this.ease({
opacity: 255,
duration: 1000,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
return true;

View File

@ -23,7 +23,7 @@ function OVirtCredentials() {
g_interface_info: OVirtCredentialsInfo,
g_name: 'org.ovirt.vdsm.Credentials',
g_object_path: '/org/ovirt/vdsm/Credentials',
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null);
return self;
}

View File

@ -37,7 +37,7 @@ var MessageType = {
NONE: 0,
ERROR: 1,
INFO: 2,
HINT: 3,
HINT: 3
};
function fadeInActor(actor) {
@ -58,7 +58,7 @@ function fadeInActor(actor) {
onComplete: () => {
this.set_height(-1);
hold.release();
},
}
});
return hold;
@ -81,7 +81,7 @@ function fadeOutActor(actor) {
this.hide();
this.set_height(-1);
hold.release();
},
}
});
return hold;
}
@ -109,7 +109,7 @@ function cloneAndFadeOutActor(actor) {
onComplete: () => {
clone.destroy();
hold.release();
},
}
});
return hold;
}
@ -272,7 +272,7 @@ var ShellUserVerifier = class {
let interval = this._getIntervalForMessage(message);
this.hasPendingMessages = true;
this._messageQueue.push({ text: message, type: messageType, interval });
this._messageQueue.push({ text: message, type: messageType, interval: interval });
this._queueMessageTimeout();
}
@ -544,7 +544,6 @@ var ShellUserVerifier = class {
});
}
} else {
// eslint-disable-next-line no-lonely-if
if (!this.hasPendingMessages) {
this._cancelAndReset();
} else {
@ -572,8 +571,9 @@ var ShellUserVerifier = class {
// if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed
if (this.serviceIsForeground(serviceName))
if (this.serviceIsForeground(serviceName)) {
this._verificationFailed(true);
}
}
};
Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@ -15,7 +15,7 @@ const Config = imports.misc.config;
var ExtensionType = {
SYSTEM: 1,
PER_USER: 2,
PER_USER: 2
};
var ExtensionState = {
@ -28,7 +28,7 @@ var ExtensionState = {
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99,
UNINSTALLED: 99
};
const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange'];
@ -36,11 +36,10 @@ const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'ca
/**
* getCurrentExtension:
*
* @returns {?object} - The current extension, or null if not called from
* an extension.
* Returns the current extension, or null if not called from an extension.
*/
function getCurrentExtension() {
let stack = new Error().stack.split('\n');
let stack = (new Error()).stack.split('\n');
let extensionStackLine;
// Search for an occurrence of an extension stack frame
@ -85,7 +84,7 @@ function getCurrentExtension() {
/**
* initTranslations:
* @param {string=} domain - the gettext domain to use
* @domain: (optional): the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
@ -109,8 +108,7 @@ function initTranslations(domain) {
/**
* getSettings:
* @param {string=} schema - the GSettings schema id
* @returns {Gio.Settings} - a new settings object for @schema
* @schema: (optional): the GSettings schema id
*
* Builds and returns a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is omitted, it is taken from
@ -130,13 +128,12 @@ function getSettings(schema) {
// SYSTEM extension that has been installed in the same prefix as the shell
let schemaDir = extension.dir.get_child('schemas');
let schemaSource;
if (schemaDir.query_exists(null)) {
if (schemaDir.query_exists(null))
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
} else {
else
schemaSource = GioSSS.get_default();
}
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
@ -147,9 +144,8 @@ function getSettings(schema) {
/**
* versionCheck:
* @param {string[]} required - an array of versions we're compatible with
* @param {string} current - the version we have
* @returns {bool} - true if @current is compatible with @required
* @required: an array of versions we're compatible with
* @current: the version we have
*
* Check if a component is compatible for an extension.
* @required is an array, and at least one version must match.

View File

@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported collectFromDatadirs, recursivelyDeleteDir,
/* exported collectFromDatadirs, deleteGFile, recursivelyDeleteDir,
recursivelyMoveDir, loadInterfaceXML */
const { Gio, GLib } = imports.gi;
@ -29,6 +29,11 @@ function collectFromDatadirs(subdir, includeUserDir, processFile) {
}
}
function deleteGFile(file) {
// Work around 'delete' being a keyword in JS.
return file['delete'](null);
}
function recursivelyDeleteDir(dir, deleteParent) {
let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
@ -38,13 +43,13 @@ function recursivelyDeleteDir(dir, deleteParent) {
let type = info.get_file_type();
let child = dir.get_child(info.get_name());
if (type == Gio.FileType.REGULAR)
child.delete(null);
deleteGFile(child);
else if (type == Gio.FileType.DIRECTORY)
recursivelyDeleteDir(child, true);
}
if (deleteParent)
dir.delete(null);
deleteGFile(dir);
}
function recursivelyMoveDir(srcDir, destDir) {
@ -70,14 +75,14 @@ let _ifaceResource = null;
function loadInterfaceXML(iface) {
if (!_ifaceResource) {
// don't use global.datadir so the method is usable from tests/tools
let dir = GLib.getenv('GNOME_SHELL_DATADIR') || Config.PKGDATADIR;
let path = `${dir}/gnome-shell-dbus-interfaces.gresource`;
let dir = GLib.getenv ('GNOME_SHELL_DATADIR') || Config.PKGDATADIR;
let path = dir + '/gnome-shell-dbus-interfaces.gresource';
_ifaceResource = Gio.Resource.load(path);
_ifaceResource._register();
}
let xml = null;
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
let uri = 'resource:///org/gnome/shell/dbus-interfaces/' + iface + '.xml';
let f = Gio.File.new_for_uri(uri);
try {

View File

@ -11,7 +11,7 @@ var PresenceStatus = {
AVAILABLE: 0,
INVISIBLE: 1,
BUSY: 2,
IDLE: 3,
IDLE: 3
};
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);

View File

@ -82,11 +82,11 @@ var HistoryManager = class {
_onEntryKeyPress(entry, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Up)
if (symbol == Clutter.KEY_Up) {
return this._setPrevItem(entry.get_text());
else if (symbol == Clutter.KEY_Down)
} else if (symbol == Clutter.KEY_Down) {
return this._setNextItem(entry.get_text());
}
return Clutter.EVENT_PROPAGATE;
}

View File

@ -142,7 +142,7 @@ var IBusManager = class {
});
this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in');
this.emit ('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
@ -157,10 +157,10 @@ var IBusManager = class {
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch (e) {

View File

@ -48,7 +48,7 @@ class InputMethod extends Clutter.InputMethod {
_onConnected() {
this._cancellable = new Gio.Cancellable();
this._ibus.create_input_context_async('gnome-shell', -1,
this._ibus.create_input_context_async ('gnome-shell', -1,
this._cancellable, this._setContext.bind(this));
}
@ -69,7 +69,6 @@ class InputMethod extends Clutter.InputMethod {
this._context.connect('show-preedit-text', this._onShowPreeditText.bind(this));
this._context.connect('hide-preedit-text', this._onHidePreeditText.bind(this));
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._context.connect('destroy', this._clear.bind(this));
this._updateCapabilities();
}
@ -129,7 +128,7 @@ class InputMethod extends Clutter.InputMethod {
_onForwardKeyEvent(_context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~IBus.ModifierType.RELEASE_MASK;
state &= ~(IBus.ModifierType.RELEASE_MASK);
let curEvent = Clutter.get_current_event();
let time;
@ -265,9 +264,6 @@ class InputMethod extends Clutter.InputMethod {
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, this._cancellable,
(context, res) => {
if (context != this._context)
return;
try {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);

View File

@ -40,15 +40,6 @@ var IntrospectService = class {
});
this._syncRunningApplications();
this._whitelistMap = new Map();
APP_WHITELIST.forEach(appName => {
Gio.DBus.watch_name(Gio.BusType.SESSION,
appName,
Gio.BusNameWatcherFlags.NONE,
(conn, name, owner) => this._whitelistMap.set(name, owner),
(conn, name) => this._whitelistMap.delete(name));
});
}
_isStandaloneApp(app) {
@ -60,7 +51,7 @@ var IntrospectService = class {
}
_isSenderWhitelisted(sender) {
return [...this._whitelistMap.values()].includes(sender);
return APP_WHITELIST.includes(sender);
}
_getSandboxedAppId(app) {
@ -79,7 +70,7 @@ var IntrospectService = class {
for (let app of apps) {
let appInfo = {};
let isAppActive = focusedApp == app;
let isAppActive = (focusedApp == app);
if (!this._isStandaloneApp(app))
continue;
@ -113,10 +104,10 @@ var IntrospectService = class {
return false;
let type = window.get_window_type();
return type == Meta.WindowType.NORMAL ||
return (type == Meta.WindowType.NORMAL ||
type == Meta.WindowType.DIALOG ||
type == Meta.WindowType.MODAL_DIALOG ||
type == Meta.WindowType.UTILITY;
type == Meta.WindowType.UTILITY);
}
GetRunningApplicationsAsync(params, invocation) {
@ -161,9 +152,9 @@ var IntrospectService = class {
'app-id': GLib.Variant.new('s', app.get_id()),
'client-type': GLib.Variant.new('u', window.get_client_type()),
'is-hidden': GLib.Variant.new('b', window.is_hidden()),
'has-focus': GLib.Variant.new('b', window == focusWindow),
'has-focus': GLib.Variant.new('b', (window == focusWindow)),
'width': GLib.Variant.new('u', frameRect.width),
'height': GLib.Variant.new('u', frameRect.height),
'height': GLib.Variant.new('u', frameRect.height)
};
// These properties may not be available for all windows:
@ -173,10 +164,9 @@ var IntrospectService = class {
if (wmClass != null)
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
if (sandboxedAppId != null) {
if (sandboxedAppId != null)
windowsList[windowId]['sandboxed-app-id'] =
GLib.Variant.new('s', sandboxedAppId);
}
}
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));

View File

@ -11,8 +11,9 @@ function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr_, base;
let attrHead = '';
if (globalCompletionList == null)
if (globalCompletionList == null) {
globalCompletionList = [];
}
let offset = getExpressionOffset(text, text.length - 1);
if (offset >= 0) {
@ -58,8 +59,9 @@ function isStopChar(c) {
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;
}
}
return -1;
}
@ -67,8 +69,9 @@ 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;
}
}
return -1;
}
@ -79,30 +82,31 @@ function findMatchingSlash(expr, offset) {
// findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset);
let openBrace = { ')': '(', ']': '[' }[closeBrace];
let openBrace = ({ ')': '(', ']': '[' })[closeBrace];
return findTheBrace(expr, offset - 1, openBrace, closeBrace);
}
function findTheBrace(expr, offset) {
if (offset < 0) {
return -1;
}
function findTheBrace(expr, offset, ...braces) {
let [openBrace, closeBrace] = braces;
if (expr.charAt(offset) == openBrace) {
return offset;
}
if (expr.charAt(offset).match(/['"]/)) {
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
}
if (expr.charAt(offset) == '/') {
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
}
if (expr.charAt(offset) == closeBrace) {
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
}
if (offset < 0)
return -1;
return findTheBrace(expr, offset - 1);
if (expr.charAt(offset) == openBrace)
return offset;
}
if (expr.charAt(offset).match(/['"]/))
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == '/')
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == closeBrace)
return findTheBrace(expr, findTheBrace(expr, offset - 1, ...braces) - 1, ...braces);
return findTheBrace(expr, offset - 1, ...braces);
return findTheBrace(expr, offset - 1);
}
// Walk expr backwards from offset looking for the beginning of an
@ -114,11 +118,13 @@ 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);
}
--offset;
}
@ -135,10 +141,10 @@ function isValidPropertyName(w) {
// To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves
function getAllProps(obj) {
if (obj === null || obj === undefined)
if (obj === null || obj === undefined) {
return [];
return Object.getOwnPropertyNames(obj).concat(getAllProps(Object.getPrototypeOf(obj)));
}
return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
}
// Given a string _expr_, returns all methods
@ -162,7 +168,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
if (typeof obj === 'object') {
let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.'
allProps = allProps.filter(isValidPropertyName);
allProps = allProps.filter( isValidPropertyName );
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
@ -183,26 +189,24 @@ function getCommonPrefix(words) {
return word;
}
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0)
return '';
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(
str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(
str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Returns true if there is reason to think that eval(str)
// will modify the global scope
function isUnsafeExpression(str) {
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0) {
return '';
}
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Check for any sort of assignment
// The strategy used is dumb: remove any quotes
@ -210,8 +214,8 @@ function isUnsafeExpression(str) {
// If there is, it might be an unsafe assignment.
let prunedStr = removeLiterals(str);
prunedStr = prunedStr.replace(/[=!]==/g, ''); // replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); // replace ==, <=, >=, != with nothing
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/[=]/)) {
return true;

View File

@ -74,9 +74,8 @@ function registerSessionWithGDM() {
let _loginManager = null;
/**
* getLoginManager:
* LoginManager:
* An abstraction over systemd/logind and ConsoleKit.
* @returns {object} - the LoginManager singleton
*
*/
function getLoginManager() {
@ -104,21 +103,21 @@ var LoginManagerSystemd = class {
getCurrentSessionProxy(callback) {
if (this._currentSession) {
callback(this._currentSession);
callback (this._currentSession);
return;
}
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;
} else {
log('Failed to find "Display" session; are we the greeter?');
for ([session, objectPath] of this._userProxy.Sessions) {
for (let [session, objectPath] of this._userProxy.Sessions) {
let sessionProxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
objectPath);
@ -186,7 +185,7 @@ var LoginManagerSystemd = class {
try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd }));
callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) {
logError(e, "Error getting systemd inhibitor");
callback(null);

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModemBase, ModemGsm, ModemCdma, BroadbandModem */
const { Gio, GObject, NM, NMA } = imports.gi;
const { Gio, NMA } = imports.gi;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils;
@ -98,46 +98,21 @@ const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInter
const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma');
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
var ModemBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'operator-name': GObject.ParamSpec.string(
'operator-name', 'operator-name', 'operator-name',
GObject.ParamFlags.READABLE,
null),
'signal-quality': GObject.ParamSpec.int(
'signal-quality', 'signal-quality', 'signal-quality',
GObject.ParamFlags.READABLE,
0, 100, 0),
},
}, class ModemBase extends GObject.Object {
_setOperatorName(operatorName) {
if (this.operator_name == operatorName)
return;
this.operator_name = operatorName;
this.notify('operator-name');
}
_setSignalQuality(signalQuality) {
if (this.signal_quality == signalQuality)
return;
this.signal_quality = signalQuality;
this.notify('signal-quality');
}
});
var ModemGsm = GObject.registerClass(
class ModemGsm extends ModemBase {
_init(path) {
super._init();
var ModemGsm = class {
constructor(path) {
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
// Code is duplicated because the function have different signatures
this._proxy.connectSignal('SignalQuality', (proxy, sender, [quality]) => {
this._setSignalQuality(quality);
this.signal_quality = quality;
this.emit('notify::signal-quality');
});
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [_status, code, name]) => {
this._setOperatorName(_findProviderForMccMnc(name, code));
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
this._proxy.GetRegistrationInfoRemote(([result], err) => {
if (err) {
@ -146,28 +121,32 @@ class ModemGsm extends ModemBase {
}
let [status_, code, name] = result;
this._setOperatorName(_findProviderForMccMnc(name, code));
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
this._proxy.GetSignalQualityRemote((result, err) => {
if (err) {
// it will return an error if the device is not connected
this._setSignalQuality(0);
this.signal_quality = 0;
} else {
let [quality] = result;
this._setSignalQuality(quality);
this.signal_quality = quality;
}
this.emit('notify::signal-quality');
});
}
});
};
Signals.addSignalMethods(ModemGsm.prototype);
var ModemCdma = GObject.registerClass(
class ModemCdma extends ModemBase {
_init(path) {
super._init();
var ModemCdma = class {
constructor(path) {
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
this._proxy.connectSignal('SignalQuality', (proxy, sender, params) => {
this._setSignalQuality(params[0]);
this.signal_quality = params[0];
this.emit('notify::signal-quality');
// receiving this signal means the device got activated
// and we can finally call GetServingSystem
@ -177,11 +156,12 @@ class ModemCdma extends ModemBase {
this._proxy.GetSignalQualityRemote((result, err) => {
if (err) {
// it will return an error if the device is not connected
this._setSignalQuality(0);
this.signal_quality = 0;
} else {
let [quality] = result;
this._setSignalQuality(quality);
this.signal_quality = quality;
}
this.emit('notify::signal-quality');
});
}
@ -189,14 +169,17 @@ class ModemCdma extends ModemBase {
this._proxy.GetServingSystemRemote(([result], err) => {
if (err) {
// it will return an error if the device is not connected
this._setOperatorName(null);
this.operator_name = null;
} else {
let [bandClass_, band_, sid] = result;
this._setOperatorName(_findProviderForSid(sid));
this.operator_name = _findProviderForSid(sid);
}
this.emit('notify::operator-name');
});
}
});
};
Signals.addSignalMethods(ModemCdma.prototype);
// ------------------------------------------------------- //
@ -212,20 +195,12 @@ const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gp
const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma');
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
var BroadbandModem = GObject.registerClass({
Properties: {
'capabilities': GObject.ParamSpec.flags(
'capabilities', 'capabilities', 'capabilities',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
NM.DeviceModemCapabilities.$gtype,
NM.DeviceModemCapabilities.NONE),
},
}, class BroadbandModem extends ModemBase {
_init(path, capabilities) {
super._init({ capabilities });
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
var BroadbandModem = class {
constructor(path, capabilities) {
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._capabilities = capabilities;
this._proxy.connect('g-properties-changed', (proxy, properties) => {
if ('SignalQuality' in properties.deep_unpack())
@ -249,8 +224,9 @@ var BroadbandModem = GObject.registerClass({
}
_reloadSignalQuality() {
let [quality, recent_] = this.SignalQuality;
this._setSignalQuality(quality);
let [quality, recent_] = this._proxy.SignalQuality;
this.signal_quality = quality;
this.emit('notify::signal-quality');
}
_reloadOperatorName() {
@ -264,7 +240,8 @@ var BroadbandModem = GObject.registerClass({
newName += this.operator_name_cdma;
}
this._setOperatorName(newName);
this.operator_name = newName;
this.emit('notify::operator-name');
}
_reload3gppOperatorName() {
@ -279,4 +256,5 @@ var BroadbandModem = GObject.registerClass({
this.operator_name_cdma = _findProviderForSid(sid);
this._reloadOperatorName();
}
});
};
Signals.addSignalMethods(BroadbandModem.prototype);

View File

@ -192,8 +192,9 @@ var ObjectManager = class {
_onNameAppeared() {
this._managerProxy.GetManagedObjectsRemote((result, error) => {
if (!result) {
if (error)
if (error) {
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
}
this._tryToCompleteLoad();
return;

View File

@ -17,10 +17,9 @@
// @params and @defaults
function parse(params = {}, defaults, allowExtras) {
if (!allowExtras) {
for (let prop in params) {
for (let prop in params)
if (!(prop in defaults))
throw new Error(`Unrecognized parameter "${prop}"`);
}
}
let defaultsCopy = Object.assign({}, defaults);

View File

@ -72,10 +72,11 @@ var SmartcardManager = class {
if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token);
if (token.IsInserted)
if (token.IsInserted) {
this.emit('smartcard-inserted', token);
else
} else {
this.emit('smartcard-removed', token);
}
}
});

View File

@ -74,8 +74,8 @@ const SystemActions = GObject.registerClass({
'orientation-lock-icon',
'orientation-lock-icon',
GObject.ParamFlags.READWRITE,
null),
},
null)
}
}, class SystemActions extends GObject.Object {
_init() {
super._init();
@ -90,7 +90,7 @@ const SystemActions = GObject.registerClass({
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,
available: false
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
// Translators: The name of the lock screen action in search
@ -98,7 +98,7 @@ const SystemActions = GObject.registerClass({
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,
available: false
});
this._actions.set(LOGOUT_ACTION_ID, {
// Translators: The name of the logout action in search
@ -106,7 +106,7 @@ const SystemActions = GObject.registerClass({
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,
available: false
});
this._actions.set(SUSPEND_ACTION_ID, {
// Translators: The name of the suspend action in search
@ -114,7 +114,7 @@ const SystemActions = GObject.registerClass({
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
available: false,
available: false
});
this._actions.set(SWITCH_USER_ACTION_ID, {
// Translators: The name of the switch user action in search
@ -122,7 +122,7 @@ const SystemActions = GObject.registerClass({
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,
available: false
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
// Translators: The name of the lock orientation action in search
@ -130,7 +130,7 @@ const SystemActions = GObject.registerClass({
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
available: false,
available: false
});
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
@ -233,10 +233,9 @@ const SystemActions = GObject.registerClass({
_updateOrientationLock() {
let available = false;
if (this._sensorProxy.g_name_owner) {
if (this._sensorProxy.g_name_owner)
available = this._sensorProxy.HasAccelerometer &&
this._monitorManager.get_is_builtin_display_on();
}
this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
@ -274,10 +273,9 @@ const SystemActions = GObject.registerClass({
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);
}
return results;
}

View File

@ -1,9 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView, wiggle */
makeCloseButton, ensureActorVisibleInScrollView */
const { Clutter, Gio, GLib, GObject, Shell, St, GnomeDesktop } = imports.gi;
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const Main = imports.ui.main;
@ -121,15 +121,12 @@ function trySpawn(argv) {
// We are only interested in the part in the parentheses. (And
// we can't pattern match the text, since it gets localized.)
let message = err.message.replace(/.*\((.+)\)/, '$1');
throw new err.constructor({ code: err.code, message });
throw new (err.constructor)({ code: err.code,
message: message });
} else {
throw err;
}
}
// Async call, we don't need the reply though
GnomeDesktop.start_systemd_scope(argv[0], pid, null, null, null, () => {});
// Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
@ -175,28 +172,23 @@ function formatTimeSpan(date) {
if (minutesAgo < 5)
return _("Just now");
if (hoursAgo < 1) {
if (hoursAgo < 1)
return Gettext.ngettext("%d minute ago",
"%d minutes ago", minutesAgo).format(minutesAgo);
}
if (daysAgo < 1) {
if (daysAgo < 1)
return Gettext.ngettext("%d hour ago",
"%d hours ago", hoursAgo).format(hoursAgo);
}
if (daysAgo < 2)
return _("Yesterday");
if (daysAgo < 15) {
if (daysAgo < 15)
return Gettext.ngettext("%d day ago",
"%d days ago", daysAgo).format(daysAgo);
}
if (weeksAgo < 8) {
if (weeksAgo < 8)
return Gettext.ngettext("%d week ago",
"%d weeks ago", weeksAgo).format(weeksAgo);
}
if (yearsAgo < 1) {
if (yearsAgo < 1)
return Gettext.ngettext("%d month ago",
"%d months ago", monthsAgo).format(monthsAgo);
}
return Gettext.ngettext("%d year ago",
"%d years ago", yearsAgo).format(yearsAgo);
}
@ -221,10 +213,7 @@ function formatTime(time, params) {
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
let clockFormat = _desktopSettings.get_string('clock-format');
params = Params.parse(params, {
timeOnly: false,
ampm: true,
});
params = Params.parse(params, { timeOnly: false });
if (clockFormat == '24h') {
// Show only the time if date is on today
@ -257,7 +246,7 @@ function formatTime(time, params) {
format = N_("%B %-d %Y, %H\u2236%M");
} else {
// Show only the time if date is on today
if (daysAgo < 1 || params.timeOnly) // eslint-disable-line no-lonely-if
if (daysAgo < 1 || params.timeOnly)
/* Translators: Time in 12h format */
format = N_("%l\u2236%M %p");
// Show the word "Yesterday" and time if date is on yesterday
@ -286,11 +275,6 @@ function formatTime(time, params) {
format = N_("%B %-d %Y, %l\u2236%M %p");
}
// Time in short 12h format, without the equivalent of "AM" or "PM"; used
// when it is clear from the context
if (!params.ampm)
format = format.replace(/\s*%p/g, '');
let formattedTime = date.format(Shell.util_translate_time_string(format));
// prepend LTR-mark to colon/ratio to force a text direction on times
return formattedTime.replace(/([:\u2236])/g, '\u200e$1');
@ -341,7 +325,7 @@ function lowerBound(array, val, cmp) {
max = mid;
}
return min == max || cmp(array[min], val) < 0 ? max : min;
return (min == max || cmp(array[min], val) < 0) ? max : min;
}
// insertSorted:
@ -362,13 +346,19 @@ function insertSorted(array, val, cmp) {
var CloseButton = GObject.registerClass(
class CloseButton extends St.Button {
_init(boxpointer) {
super._init({
style_class: 'notification-close',
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START,
});
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
// Clutter 2.0. Since St.Bin doesn't define its own setters, the
// setters are a workaround to get Clutter's version.
this.set_x_align(Clutter.ActorAlign.END);
this.set_y_align(Clutter.ActorAlign.START);
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
// to respect the alignments.
this.set_x_expand(true);
this.set_y_expand(true);
this._boxPointer = boxpointer;
if (boxpointer)
@ -421,7 +411,7 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
if (!parent)
throw new Error("actor not in scroll view");
box = parent.get_allocation_box();
let box = parent.get_allocation_box();
y1 += box.y1;
y2 += box.y1;
parent = parent.get_parent();
@ -436,40 +426,6 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SCROLL_TIME,
});
}
function wiggle(actor, params) {
params = Params.parse(params, {
offset: 0,
duration: 0,
wiggleCount: 0,
});
actor.translation_x = 0;
// Accelerate before wiggling
actor.ease({
translation_x: -params.offset,
duration: params.duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
// Wiggle
actor.ease({
translation_x: params.offset,
duration: params.duration,
mode: Clutter.AnimationMode.LINEAR,
repeatCount: params.wiggleCount,
autoReverse: true,
onComplete: () => {
// Decelerate and return to the original position
actor.ease({
translation_x: 0,
duration: params.duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
});
},
});
},
duration: SCROLL_TIME
});
}

View File

@ -32,7 +32,6 @@ var WeatherClient = class {
this._gclueStarting = false;
this._gclueLocationChangedId = 0;
this._needsAuth = true;
this._weatherAuthorized = false;
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) {
@ -48,11 +47,11 @@ var WeatherClient = class {
return;
}
this._permStore.LookupRemote('gnome', 'geolocation', (res, err) => {
if (err)
log(`Error looking up permission: ${err.message}`);
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error)
log(`Error looking up permission: ${error.message}`);
let [perms, data] = err ? [{}, null] : res;
let [perms, data] = error ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms];
this._onPermStoreChanged(this._permStore, '', params);
});
@ -91,7 +90,7 @@ var WeatherClient = class {
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather',
schema_id: 'org.gnome.shell.weather'
});
this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this));
@ -143,7 +142,7 @@ var WeatherClient = class {
get _useAutoLocation() {
return this._autoLocationRequested &&
this._locationSettings.get_boolean('enabled') &&
(!this._needsAuth || this._weatherAuthorized);
this._weatherAuthorized;
}
_onWeatherProxyReady(o, res) {
@ -170,19 +169,12 @@ var WeatherClient = class {
}
_onInstalledChanged() {
let hadApp = this._weatherApp != null;
let hadApp = (this._weatherApp != null);
this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
let haveApp = this._weatherApp != null;
let haveApp = (this._weatherApp != null);
if (hadApp !== haveApp)
this.emit('changed');
let neededAuth = this._needsAuth;
this._needsAuth = this._weatherApp === null ||
this._weatherApp.app_info.has_key('X-Flatpak');
if (neededAuth !== this._needsAuth)
this._updateAutoLocation();
}
_loadInfo() {
@ -213,7 +205,7 @@ var WeatherClient = class {
this._weatherInfo.abort();
this._weatherInfo.set_location(location);
this._locationValid = location != null;
this._locationValid = (location != null);
this._weatherInfo.set_enabled_providers(location ? this._providers : 0);

View File

@ -57,7 +57,7 @@ var METRICS = {
units: "us" },
applicationsShowTimeSubsequent:
{ description: "Time to switch to applications view, second time",
units: "us" },
units: "us" }
};
let WINDOW_CONFIGS = [
@ -67,7 +67,7 @@ let WINDOW_CONFIGS = [
{ width: 640, height: 480, alpha: false, maximized: true, count: 5, metric: 'overviewFps5Maximized' },
{ width: 640, height: 480, alpha: false, maximized: true, count: 10, metric: 'overviewFps10Maximized' },
{ width: 640, height: 480, alpha: true, maximized: false, count: 5, metric: 'overviewFps5Alpha' },
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' },
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }
];
function *run() {
@ -94,12 +94,11 @@ function *run() {
let config = WINDOW_CONFIGS[i / 2];
yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++) {
for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow({ width: config.width,
height: config.height,
alpha: config.alpha,
maximized: config.maximized });
}
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
@ -128,11 +127,11 @@ function *run() {
for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview.dash.showAppsButton.checked = true;
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;
Main.overview._dash.showAppsButton.checked = false;
yield Scripting.waitLeisure();
}
}
@ -175,10 +174,11 @@ function script_applicationsShowDone(time) {
}
function script_afterShowHide(_time) {
if (overviewShowCount == 1)
if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize;
else
} else {
METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
}
}
function malloc_usedSize(time, bytes) {

View File

@ -114,7 +114,7 @@ function *run() {
Scripting.scriptEvent('desktopShown');
let interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface',
schema_id: 'org.gnome.desktop.interface'
});
interfaceSettings.set_boolean('enable-animations', false);
@ -127,7 +127,7 @@ function *run() {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview.dash.showAppsButton.checked = true;
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');

View File

@ -11,17 +11,17 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
const PortalHelperResult = {
CANCELLED: 0,
COMPLETED: 1,
RECHECK: 2,
RECHECK: 2
};
const PortalHelperSecurityLevel = {
NOT_YET_DETERMINED: 0,
SECURE: 1,
INSECURE: 2,
INSECURE: 2
};
const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
const CONNECTIVITY_CHECK_URI = `http://${CONNECTIVITY_CHECK_HOST}`;
const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
@ -92,7 +92,7 @@ class PortalHeaderBar extends Gtk.HeaderBar {
var PortalWindow = GObject.registerClass(
class PortalWindow extends Gtk.ApplicationWindow {
_init(application, url, timestamp, doneCallback) {
super._init({ application });
super._init({ application: application });
this.connect('delete-event', this.destroyWindow.bind(this));
this._headerBar = new PortalHeaderBar();
@ -287,7 +287,7 @@ class WebPortalHelper extends Gtk.Application {
}
Authenticate(connection, url, timestamp) {
this._queue.push({ connection, url, timestamp });
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue();
}

View File

@ -13,7 +13,7 @@ const AccessIface = loadInterfaceXML('org.freedesktop.impl.portal.Access');
var DialogResponse = {
OK: 0,
CANCEL: 1,
CLOSED: 2,
CLOSED: 2
};
var AccessDialog = GObject.registerClass(
@ -35,7 +35,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
_buildLayout(title, subtitle, body, options) {
// No support for non-modal system dialogs, so ignore the option
// let modal = options['modal'] || true;
//let modal = options['modal'] || true;
let denyLabel = options['deny_label'] || _("Deny Access");
let grantLabel = options['grant_label'] || _("Grant Access");
let iconName = options['icon'] || null;
@ -56,8 +56,8 @@ class AccessDialog extends ModalDialog.ModalDialog {
let check = new CheckBox.CheckBox();
check.getLabelActor().text = name;
check.checked = selected == "true";
content.insertBeforeBody(check);
check.actor.checked = selected == "true";
content.insertBeforeBody(check.actor);
this._choices.set(id, check);
}
@ -99,7 +99,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
let results = {};
if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) {
let checked = check.checked ? 'true' : 'false';
let checked = check.actor.checked ? 'true' : 'false';
results[id] = new GLib.Variant('s', checked);
}
}

View File

@ -62,7 +62,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this.thumbnailsVisible = false;
let apps = Shell.AppSystem.get_default().get_running();
let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0)
return;
@ -111,12 +111,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_initialSelection(backward, binding) {
if (binding == 'switch-group') {
if (backward)
if (backward) {
this._select(0, this._items[0].cachedWindows.length - 1);
else if (this._items[0].cachedWindows.length > 1)
this._select(0, 1);
else
this._select(0, 0);
} else {
if (this._items[0].cachedWindows.length > 1)
this._select(0, 1);
else
this._select(0, 0);
}
} else if (binding == 'switch-group-backward') {
this._select(0, this._items[0].cachedWindows.length - 1);
} else if (binding == 'switch-applications-backward') {
@ -178,27 +180,28 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous());
} else if (keysym === Clutter.KEY_q) {
} else if (keysym == Clutter.q) {
this._quitApplication(this._selectedIndex);
} else if (this._thumbnailsFocused) {
if (keysym === Clutter.KEY_Left)
if (keysym == Clutter.Left)
this._select(this._selectedIndex, this._previousWindow());
else if (keysym === Clutter.KEY_Right)
else if (keysym == Clutter.Right)
this._select(this._selectedIndex, this._nextWindow());
else if (keysym === Clutter.KEY_Up)
else if (keysym == Clutter.Up)
this._select(this._selectedIndex, null, true);
else if (keysym === Clutter.KEY_w || keysym === Clutter.KEY_F4)
else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeAppWindow(this._selectedIndex, this._currentWindow);
else
return Clutter.EVENT_PROPAGATE;
} else if (keysym == Clutter.KEY_Left) {
this._select(this._previous());
} else if (keysym == Clutter.KEY_Right) {
this._select(this._next());
} else if (keysym == Clutter.KEY_Down) {
this._select(this._selectedIndex, 0);
} else {
return Clutter.EVENT_PROPAGATE;
if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
else if (keysym == Clutter.Down)
this._select(this._selectedIndex, 0);
else
return Clutter.EVENT_PROPAGATE;
}
return Clutter.EVENT_STOP;
@ -293,9 +296,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
/**
* _select:
* @param {number} app: index of the app to select
* @param {number=} window: index of which of @app's windows to select
* @param {bool} forceAppFocus: optional flag, see below
* @app: index of the app to select
* @window: (optional) index of which of @app's windows to select
* @forceAppFocus: optional flag, see below
*
* Selects the indicated @app, and optional @window, and sets
* this._thumbnailsFocused appropriately to indicate whether the
@ -365,15 +368,15 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
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);
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
}
_createThumbnails() {
this._thumbnails = new ThumbnailList(this._items[this._selectedIndex].cachedWindows);
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
this._thumbnails.connect('item-activated', this._windowActivated.bind(this));
this._thumbnails.connect('item-entered', this._windowEntered.bind(this));
this._thumbnails.connect('item-removed', this._windowRemoved.bind(this));
@ -395,33 +398,34 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this.thumbnailsVisible = true;
},
}
});
this._switcherList._items[this._selectedIndex].add_accessible_state(Atk.StateType.EXPANDED);
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
}
});
var CyclerHighlight = GObject.registerClass(
class CyclerHighlight extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
class CyclerHighlight {
constructor() {
this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._clone = new Clutter.Clone();
this.add_actor(this._clone);
this.actor.add_actor(this._clone);
this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
this.add_actor(this._highlight);
this.actor.add_actor(this._highlight);
let coordinate = Clutter.BindCoordinate.ALL;
let constraint = new Clutter.BindConstraint({ coordinate });
let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
this._clone.bind_property('source', constraint, 'source', 0);
this.add_constraint(constraint);
this.actor.add_constraint(constraint);
this.connect('notify::allocation', this._onAllocationChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::allocation',
this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
}
set window(w) {
@ -447,7 +451,7 @@ class CyclerHighlight extends St.Widget {
this._highlight.set_size(0, 0);
this._highlight.hide();
} else {
let [x, y] = this.allocation.get_origin();
let [x, y] = this.actor.allocation.get_origin();
let rect = this._window.get_frame_rect();
this._highlight.set_size(rect.width, rect.height);
this._highlight.set_position(rect.x - x, rect.y - y);
@ -458,7 +462,7 @@ class CyclerHighlight extends St.Widget {
_onDestroy() {
this.window = null;
}
});
}
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
@ -474,7 +478,7 @@ var CyclerList = GObject.registerClass({
});
var CyclerPopup = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
GTypeFlags: GObject.TypeFlags.ABSTRACT
}, class CyclerPopup extends SwitcherPopup.SwitcherPopup {
_init() {
super._init();
@ -485,7 +489,7 @@ var CyclerPopup = GObject.registerClass({
return;
this._highlight = new CyclerHighlight();
global.window_group.add_actor(this._highlight);
global.window_group.add_actor(this._highlight.actor);
this._switcherList = new CyclerList();
this._switcherList.connect('item-highlighted', (list, index) => {
@ -495,7 +499,7 @@ var CyclerPopup = GObject.registerClass({
_highlightItem(index, _justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight, null);
global.window_group.set_child_above_sibling(this._highlight.actor, null);
}
_finish() {
@ -525,7 +529,7 @@ var CyclerPopup = GObject.registerClass({
}
_onDestroy() {
this._highlight.destroy();
this._highlight.actor.destroy();
super._onDestroy();
}
@ -588,18 +592,20 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS)
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD)
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous());
else if (keysym == Clutter.KEY_Left)
this._select(this._previous());
else if (keysym == Clutter.KEY_Right)
this._select(this._next());
else if (keysym == Clutter.KEY_w || keysym == Clutter.KEY_F4)
this._closeWindow(this._selectedIndex);
else
return Clutter.EVENT_PROPAGATE;
} else {
if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeWindow(this._selectedIndex);
else
return Clutter.EVENT_PROPAGATE;
}
return Clutter.EVENT_STOP;
}
@ -642,22 +648,20 @@ class WindowCyclerPopup extends CyclerPopup {
}
});
var AppIcon = GObject.registerClass(
class AppIcon extends St.BoxLayout {
var AppIcon = GObject.registerClass({
GTypeName: 'AltTab_AppIcon'
}, class AppIcon extends St.BoxLayout {
_init(app) {
super._init({ style_class: 'alt-tab-app',
vertical: true });
this.app = app;
this.icon = null;
this._iconBin = new St.Bin();
this._iconBin = new St.Bin({ x_fill: true, y_fill: true });
this.add_child(this._iconBin);
this.label = new St.Label({
text: this.app.get_name(),
x_align: Clutter.ActorAlign.CENTER,
});
this.add_child(this.label);
this.add(this._iconBin, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: this.app.get_name() });
this.add(this.label, { x_fill: false });
}
// eslint-disable-next-line camelcase
@ -693,7 +697,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it
appIcon.cachedWindows = allWindows.filter(
w => windowTracker.get_window_app(w) == appIcon.app
w => windowTracker.get_window_app (w) == appIcon.app
);
if (appIcon.cachedWindows.length > 0)
this._addIcon(appIcon);
@ -717,9 +721,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_setIconSize() {
let j = 0;
while (this._items.length > 1 && this._items[j].style_class != 'item-box')
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();
@ -853,7 +857,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
if (appIcon.cachedWindows.length == 1)
arrow.hide();
else
item.add_accessible_state(Atk.StateType.EXPANDABLE);
item.add_accessible_state (Atk.StateType.EXPANDABLE);
}
_removeIcon(app) {
@ -889,13 +893,12 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
let title = windows[i].get_title();
if (title) {
let name = new St.Label({
text: title,
// St.Label doesn't support text-align
x_align: Clutter.ActorAlign.CENTER,
});
this._labels.push(name);
box.add_actor(name);
let name = new St.Label({ text: title });
// St.Label doesn't support text-align so use a Bin
let bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._labels.push(bin);
bin.add_actor(name);
box.add_actor(bin);
this.addItem(box, name);
} else {
@ -974,7 +977,7 @@ class WindowIcon extends St.BoxLayout {
this._icon = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.add_child(this._icon);
this.add(this._icon, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: window.get_title() });
let tracker = Shell.WindowTracker.get_default();
@ -997,10 +1000,9 @@ class WindowIcon extends St.BoxLayout {
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
if (this.app) {
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL));
}
break;
case AppIconMode.APP_ICON_ONLY:

View File

@ -1,20 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
const { Clutter, GLib, GObject, Gio, St } = imports.gi;
const Params = imports.misc.params;
const { Clutter, GLib, Gio, St } = imports.gi;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
var Animation = GObject.registerClass(
class Animation extends St.Bin {
_init(file, width, height, speed) {
super._init({ width, height });
this.connect('destroy', this._onDestroy.bind(this));
this.connect('resource-scale-changed',
var Animation = class {
constructor(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.set_size(width, height);
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
this.actor.connect('resource-scale-changed',
this._loadFile.bind(this, file, width, height));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
@ -53,14 +52,14 @@ class Animation extends St.Bin {
}
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.get_resource_scale();
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false;
this.destroy_all_children();
this.actor.destroy_all_children();
if (!validResourceScale) {
if (wasPlaying)
@ -73,11 +72,7 @@ class Animation extends St.Bin {
this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this._animations.set({
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
this.set_child(this._animations);
this.actor.set_child(this._animations);
if (wasPlaying)
this.play();
@ -88,7 +83,7 @@ class Animation extends St.Bin {
if (oldFrameActor)
oldFrameActor.hide();
this._frame = frame % this._animations.get_n_children();
this._frame = (frame % this._animations.get_n_children());
let newFrameActor = this._animations.get_child_at_index(this._frame);
if (newFrameActor)
@ -104,7 +99,7 @@ class Animation extends St.Bin {
if (!this._isLoaded)
return;
let [width, height] = this.get_size();
let [width, height] = this.actor.get_size();
for (let i = 0; i < this._animations.get_n_children(); ++i)
this._animations.get_child_at_index(i).set_size(width, height);
@ -127,29 +122,21 @@ class Animation extends St.Bin {
themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0;
}
});
};
var AnimatedIcon = GObject.registerClass(
class AnimatedIcon extends Animation {
_init(file, size) {
super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
var AnimatedIcon = class extends Animation {
constructor(file, size) {
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});
};
var Spinner = GObject.registerClass(
class Spinner extends AnimatedIcon {
_init(size, params) {
params = Params.parse(params, {
animate: false,
hideOnStop: false,
});
var Spinner = class extends AnimatedIcon {
constructor(size, animate = false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super._init(file, size);
super(file, size);
this.opacity = 0;
this._animate = params.animate;
this._hideOnStop = params.hideOnStop;
this.visible = !this._hideOnStop;
this.actor.opacity = 0;
this._animate = animate;
}
_onDestroy() {
@ -158,43 +145,35 @@ class Spinner extends AnimatedIcon {
}
play() {
this.remove_all_transitions();
this.show();
this.actor.remove_all_transitions();
if (this._animate) {
super.play();
this.ease({
this.actor.ease({
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
mode: Clutter.AnimationMode.LINEAR
});
} else {
this.opacity = 255;
this.actor.opacity = 255;
super.play();
}
}
stop() {
this.remove_all_transitions();
this.actor.remove_all_transitions();
if (this._animate) {
this.ease({
this.actor.ease({
opacity: 0,
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
super.stop();
if (this._hideOnStop)
this.hide();
},
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => super.stop()
});
} else {
this.opacity = 0;
this.actor.opacity = 0;
super.stop();
if (this._hideOnStop)
this.hide();
}
}
});
};

File diff suppressed because it is too large Load Diff

View File

@ -55,7 +55,6 @@ const RENAMED_DESKTOP_IDS = {
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'shotwell.desktop': 'org.gnome.Shotwell.desktop',
'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop',

View File

@ -9,13 +9,13 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
var AudioDevice = {
HEADPHONES: 1 << 0,
HEADSET: 1 << 1,
MICROPHONE: 1 << 2,
MICROPHONE: 1 << 2
};
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
var AudioDeviceSelectionDialog = GObject.registerClass({
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } },
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } }
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
_init(devices) {
super._init({ styleClass: 'audio-device-selection-dialog' });
@ -43,19 +43,15 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
this.contentLayout.style_class = 'audio-selection-content';
this.contentLayout.add(title);
this._selectionBox = new St.BoxLayout({
style_class: 'audio-selection-box',
x_expand: true,
});
this.contentLayout.add_child(this._selectionBox);
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
this.contentLayout.add(this._selectionBox, { expand: true });
if (Main.sessionMode.allowSettings) {
if (Main.sessionMode.allowSettings)
this.addButton({ action: this._openSettings.bind(this),
label: _("Sound Settings") });
}
this.addButton({ action: this.close.bind(this),
label: _("Cancel"),
key: Clutter.KEY_Escape });
key: Clutter.Escape });
}
_getDeviceLabel(device) {

View File

@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SystemBackground */
// READ THIS FIRST
// Background handling is a maze of objects, both objects in this file, and
@ -94,7 +93,7 @@
// MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage
const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi;
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi;
const Signals = imports.signals;
const LoginManager = imports.misc.loginManager;
@ -145,7 +144,7 @@ var BackgroundCache = class BackgroundCache {
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed',
(obj, theFile, otherFile, eventType) => {
(obj, file, otherFile, eventType) => {
// Ignore CHANGED and CREATED events, since in both cases
// we'll get a CHANGES_DONE_HINT event when done.
if (eventType != Gio.FileMonitorEvent.CHANGED &&
@ -221,17 +220,16 @@ function getBackgroundCache() {
return _backgroundCache;
}
var Background = GObject.registerClass({
Signals: { 'loaded': {}, 'bg-changed': {} },
}, class Background extends Meta.Background {
_init(params) {
var Background = class Background {
constructor(params) {
params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager,
settings: null,
file: null,
style: null });
super._init({ meta_display: global.display });
this.background = new Meta.Background({ meta_display: global.display });
this.background._delegate = this;
this._settings = params.settings;
this._file = params.file;
@ -264,14 +262,16 @@ var Background = GObject.registerClass({
}
destroy() {
this.background = null;
this._cancellable.cancel();
this._removeAnimationTimeout();
let i;
let keys = Object.keys(this._fileWatches);
for (i = 0; i < keys.length; i++)
for (i = 0; i < keys.length; i++) {
this._cache.disconnect(this._fileWatches[keys[i]]);
}
this._fileWatches = null;
if (this._timezoneChangedId != 0)
@ -300,11 +300,9 @@ var Background = GObject.registerClass({
this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._changedIdleId = 0;
this.emit('bg-changed');
this.emit('changed');
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._changedIdleId,
'[gnome-shell] Background._emitChangedSignal');
}
updateResolution() {
@ -330,7 +328,7 @@ var Background = GObject.registerClass({
this.emit('loaded');
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] Background._setLoaded Idle');
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
}
_loadPattern() {
@ -344,9 +342,9 @@ var Background = GObject.registerClass({
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
if (shadingType == GDesktopEnums.BackgroundShading.SOLID)
this.set_color(color);
this.background.set_color(color);
else
this.set_gradient(shadingType, color, secondColor);
this.background.set_gradient(shadingType, color, secondColor);
}
_watchFile(file) {
@ -382,13 +380,13 @@ var Background = GObject.registerClass({
let finish = () => {
this._setLoaded();
if (files.length > 1) {
this.set_blend(files[0], files[1],
this._animation.transitionProgress,
this._style);
this.background.set_blend(files[0], files[1],
this._animation.transitionProgress,
this._style);
} else if (files.length > 0) {
this.set_file(files[0], this._style);
this.background.set_file(files[0], this._style);
} else {
this.set_file(null, this._style);
this.background.set_file(null, this._style);
}
this._queueUpdateAnimation();
};
@ -403,7 +401,6 @@ var Background = GObject.registerClass({
if (numPendingImages == 0)
finish();
} else {
// eslint-disable-next-line no-loop-func
let id = image.connect('loaded', () => {
image.disconnect(id);
numPendingImages--;
@ -445,7 +442,7 @@ var Background = GObject.registerClass({
_loadAnimation(file) {
this._cache.getAnimation({
file,
file: file,
settingsSchema: this._settings.schema_id,
onLoaded: animation => {
this._animation = animation;
@ -457,12 +454,12 @@ var Background = GObject.registerClass({
this._updateAnimation();
this._watchFile(file);
},
}
});
}
_loadImage(file) {
this.set_file(file, this._style);
this.background.set_file(file, this._style);
this._watchFile(file);
let cache = Meta.BackgroundImageCache.get_default();
@ -496,14 +493,13 @@ var Background = GObject.registerClass({
this._loadFile(this._file);
}
});
};
Signals.addSignalMethods(Background.prototype);
let _systemBackground;
var SystemBackground = GObject.registerClass({
Signals: { 'loaded': {} },
}, class SystemBackground extends Meta.BackgroundActor {
_init() {
var SystemBackground = class SystemBackground {
constructor() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) {
@ -512,11 +508,9 @@ var SystemBackground = GObject.registerClass({
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
}
super._init({
meta_display: global.display,
monitor: 0,
background: _systemBackground,
});
this.actor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: 0,
background: _systemBackground });
let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file);
@ -535,7 +529,8 @@ var SystemBackground = GObject.registerClass({
});
}
}
});
};
Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = class BackgroundSource {
constructor(layoutManager, settingsSchema) {
@ -571,7 +566,7 @@ var BackgroundSource = class BackgroundSource {
// We don't watch changes to settings here,
// instead we rely on Background to watch those
// and emit 'bg-changed' at the right time
// and emit 'changed' at the right time
if (this._overrideImage != null) {
file = Gio.File.new_for_path(this._overrideImage);
@ -593,14 +588,14 @@ var BackgroundSource = class BackgroundSource {
if (!(monitorIndex in this._backgrounds)) {
let background = new Background({
monitorIndex,
monitorIndex: monitorIndex,
layoutManager: this._layoutManager,
settings: this._settings,
file,
style,
file: file,
style: style
});
background._changedId = background.connect('bg-changed', () => {
background._changedId = background.connect('changed', () => {
background.disconnect(background._changedId);
background.destroy();
delete this._backgrounds[monitorIndex];
@ -626,11 +621,11 @@ var BackgroundSource = class BackgroundSource {
}
};
var Animation = GObject.registerClass(
class Animation extends GnomeDesktop.BGSlideShow {
_init(params) {
super._init(params);
var Animation = class Animation {
constructor(params) {
params = Params.parse(params, { file: null });
this.file = params.file;
this.keyFrameFiles = [];
this.transitionProgress = 0.0;
this.transitionDuration = 0.0;
@ -638,7 +633,9 @@ class Animation extends GnomeDesktop.BGSlideShow {
}
load(callback) {
this.load_async(null, () => {
this._show = new GnomeDesktop.BGSlideShow({ file: this.file });
this._show.load_async(null, () => {
this.loaded = true;
if (callback)
callback();
@ -648,11 +645,13 @@ class Animation extends GnomeDesktop.BGSlideShow {
update(monitor) {
this.keyFrameFiles = [];
if (this.get_num_slides() < 1)
if (!this._show)
return;
let [progress, duration, isFixed_, filename1, filename2] =
this.get_current_slide(monitor.width, monitor.height);
if (this._show.get_num_slides() < 1)
return;
let [progress, duration, isFixed_, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
this.transitionDuration = duration;
this.transitionProgress = progress;
@ -663,7 +662,8 @@ class Animation extends GnomeDesktop.BGSlideShow {
if (filename2)
this.keyFrameFiles.push(Gio.File.new_for_path(filename2));
}
});
};
Signals.addSignalMethods(Animation.prototype);
var BackgroundManager = class BackgroundManager {
constructor(params) {
@ -714,7 +714,7 @@ var BackgroundManager = class BackgroundManager {
opacity: 0,
duration: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => oldBackgroundActor.destroy(),
onComplete: () => oldBackgroundActor.destroy()
});
}
@ -732,7 +732,7 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = newBackgroundActor;
let background = newBackgroundActor.background;
let background = newBackgroundActor.background._delegate;
if (background.isLoaded) {
this._swapBackgroundActor();
@ -752,7 +752,7 @@ var BackgroundManager = class BackgroundManager {
let backgroundActor = new Meta.BackgroundActor({
meta_display: global.display,
monitor: this._monitorIndex,
background,
background: background.background,
vignette: this._vignette,
vignette_sharpness: 0.5,
brightness: 0.5,
@ -763,10 +763,10 @@ var BackgroundManager = class BackgroundManager {
if (this._controlPosition) {
let monitor = this._layoutManager.monitors[this._monitorIndex];
backgroundActor.set_position(monitor.x, monitor.y);
this._container.set_child_below_sibling(backgroundActor, null);
backgroundActor.lower_bottom();
}
let changeSignalId = background.connect('bg-changed', () => {
let changeSignalId = background.connect('changed', () => {
background.disconnect(changeSignalId);
changeSignalId = null;
this._updateBackgroundActor();

View File

@ -35,12 +35,11 @@ function addBackgroundMenu(actor, layoutManager) {
}
let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', (action, theActor, state) => {
if (state == Clutter.LongPressState.QUERY) {
return (action.get_button() == 0 ||
clickAction.connect('long-press', (action, actor, state) => {
if (state == Clutter.LongPressState.QUERY)
return ((action.get_button() == 0 ||
action.get_button() == 1) &&
!actor._backgroundMenu.isOpen;
}
!actor._backgroundMenu.isOpen);
if (state == Clutter.LongPressState.ACTIVATE) {
let [x, y] = action.get_coords();
openMenu(x, y);

View File

@ -16,8 +16,8 @@ var BarLevel = GObject.registerClass({
'overdrive-start': GObject.ParamSpec.double(
'overdrive-start', 'overdrive-start', 'overdrive-start',
GObject.ParamFlags.READWRITE,
1, 2, 1),
},
1, 2, 1)
}
}, class BarLevel extends St.DrawingArea {
_init(params) {
this._maxValue = 1;
@ -27,7 +27,7 @@ var BarLevel = GObject.registerClass({
let defaultParams = {
style_class: 'barlevel',
accessible_role: Atk.Role.LEVEL_BAR,
accessible_role: Atk.Role.LEVEL_BAR
};
super._init(Object.assign(defaultParams, params));
this.connect('allocation-changed', (actor, box) => {
@ -88,10 +88,9 @@ var BarLevel = GObject.registerClass({
if (this._overdriveStart == value)
return;
if (value > this._maxValue) {
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');

View File

@ -44,20 +44,14 @@ var BoxPointer = GObject.registerClass({
this._border = new St.DrawingArea();
this._border.connect('repaint', this._drawBorder.bind(this));
this.add_actor(this._border);
this.set_child_above_sibling(this.bin, this._border);
this.bin.raise(this._border);
this._sourceAlignment = 0.5;
this._muteInput = true;
this._capturedEventId = 0;
this._muteInput();
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_captured_event() {
if (this._muteInput)
return Clutter.EVENT_STOP;
return Clutter.EVENT_PROPAGATE;
}
_onDestroy() {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
@ -69,10 +63,23 @@ var BoxPointer = GObject.registerClass({
return this._arrowSide;
}
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP);
}
_unmuteInput() {
if (this._capturedEventId != 0) {
this.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
}
open(animate, onComplete) {
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let animationTime = animate & PopupAnimation.FULL ? POPUP_ANIMATION_TIME : 0;
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate & PopupAnimation.FADE)
this.opacity = 0;
@ -105,10 +112,10 @@ var BoxPointer = GObject.registerClass({
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._muteInput = false;
this._unmuteInput();
if (onComplete)
onComplete();
},
}
});
}
@ -120,8 +127,8 @@ var BoxPointer = GObject.registerClass({
let translationY = 0;
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let fade = animate & PopupAnimation.FADE;
let animationTime = animate & PopupAnimation.FULL ? POPUP_ANIMATION_TIME : 0;
let fade = (animate & PopupAnimation.FADE);
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
@ -140,7 +147,7 @@ var BoxPointer = GObject.registerClass({
}
}
this._muteInput = true;
this._muteInput();
this.remove_all_transitions();
this.ease({
@ -156,7 +163,7 @@ var BoxPointer = GObject.registerClass({
this.translation_y = 0;
if (onComplete)
onComplete();
},
}
});
}
@ -247,10 +254,11 @@ var BoxPointer = GObject.registerClass({
let [absX, absY] = this.get_transformed_position();
if (this._arrowSide == St.Side.TOP ||
this._arrowSide == St.Side.BOTTOM)
this._arrowSide == St.Side.BOTTOM) {
this._arrowOrigin = sourceX - absX + sourceWidth / 2;
else
} else {
this._arrowOrigin = sourceY - absY + sourceHeight / 2;
}
}
let borderWidth = themeNode.get_length('-arrow-border-width');
@ -265,19 +273,20 @@ var BoxPointer = GObject.registerClass({
let [width, height] = area.get_surface_size();
let [boxWidth, boxHeight] = [width, height];
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
boxHeight -= rise;
else
} else {
boxWidth -= rise;
}
let cr = area.get_context();
// Translate so that box goes from 0,0 to boxWidth,boxHeight,
// with the arrow poking out of that
if (this._arrowSide == St.Side.TOP)
if (this._arrowSide == St.Side.TOP) {
cr.translate(0, rise);
else if (this._arrowSide == St.Side.LEFT)
} else if (this._arrowSide == St.Side.LEFT) {
cr.translate(rise, 0);
}
let [x1, y1] = [halfBorder, halfBorder];
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
@ -473,7 +482,7 @@ var BoxPointer = GObject.registerClass({
let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base');
let borderRadius = themeNode.get_length('-arrow-border-radius');
let margin = 4 * borderRadius + borderWidth + arrowBase;
let margin = (4 * borderRadius + borderWidth + arrowBase);
let gap = themeNode.get_length('-boxpointer-gap');
let padding = themeNode.get_length('-arrow-rise');
@ -524,11 +533,11 @@ var BoxPointer = GObject.registerClass({
arrowOrigin = sourceCenterX - resX;
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
if (arrowOrigin > x1)
resX += arrowOrigin - x1;
resX += (arrowOrigin - x1);
arrowOrigin = x1;
} else if (arrowOrigin >= (x2 - (borderRadius + halfBase))) {
if (arrowOrigin < x2)
resX -= x2 - arrowOrigin;
resX -= (x2 - arrowOrigin);
arrowOrigin = x2;
}
break;
@ -543,11 +552,11 @@ var BoxPointer = GObject.registerClass({
arrowOrigin = sourceCenterY - resY;
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
if (arrowOrigin > y1)
resY += arrowOrigin - y1;
resY += (arrowOrigin - y1);
arrowOrigin = y1;
} else if (arrowOrigin >= (y2 - (borderRadius + halfBase))) {
if (arrowOrigin < y2)
resX -= y2 - arrowOrigin;
resX -= (y2 - arrowOrigin);
arrowOrigin = y2;
}
break;

View File

@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList, DBusEventSource */
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
const MessageList = imports.ui.messageList;
@ -20,7 +21,7 @@ var MESSAGE_ICON_SIZE = -1; // pick up from CSS
var NC_ = (context, str) => `${context}\u0004${str}`;
function sameYear(dateA, dateB) {
return dateA.getYear() == dateB.getYear();
return (dateA.getYear() == dateB.getYear());
}
function sameMonth(dateA, dateB) {
@ -78,7 +79,7 @@ function _getCalendarDayAbbreviation(dayNumber) {
/* Translators: Calendar grid abbreviation for Friday */
NC_("grid friday", "F"),
/* Translators: Calendar grid abbreviation for Saturday */
NC_("grid saturday", "S"),
NC_("grid saturday", "S")
];
return Shell.util_translate_time_string(abbreviations[dayNumber]);
}
@ -98,54 +99,17 @@ var CalendarEvent = class CalendarEvent {
// Interface for appointments/events - e.g. the contents of a calendar
//
var EventSourceBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'has-calendars': GObject.ParamSpec.boolean(
'has-calendars', 'has-calendars', 'has-calendars',
GObject.ParamFlags.READABLE,
false),
'is-loading': GObject.ParamSpec.boolean(
'is-loading', 'is-loading', 'is-loading',
GObject.ParamFlags.READABLE,
false),
},
Signals: { 'changed': {} },
}, class EventSourceBase extends GObject.Object {
get isLoading() {
throw new GObject.NotImplementedError(`isLoading in ${this.constructor.name}`);
}
get hasCalendars() {
throw new GObject.NotImplementedError(`hasCalendars in ${this.constructor.name}`);
// First, an implementation with no events
var EmptyEventSource = class EmptyEventSource {
constructor() {
this.isLoading = false;
this.isDummy = true;
this.hasCalendars = false;
}
destroy() {
}
requestRange(_begin, _end) {
throw new GObject.NotImplementedError(`requestRange in ${this.constructor.name}`);
}
getEvents(_begin, _end) {
throw new GObject.NotImplementedError(`getEvents in ${this.constructor.name}`);
}
hasEvents(_day) {
throw new GObject.NotImplementedError(`hasEvents in ${this.constructor.name}`);
}
});
var EmptyEventSource = GObject.registerClass(
class EmptyEventSource extends EventSourceBase {
get isLoading() {
return false;
}
get hasCalendars() {
return false;
}
requestRange(_begin, _end) {
}
@ -157,7 +121,8 @@ class EmptyEventSource extends EventSourceBase {
hasEvents(_day) {
return false;
}
});
};
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = loadInterfaceXML('org.gnome.Shell.CalendarServer');
@ -189,12 +154,11 @@ function _dateIntervalsOverlap(a0, a1, b0, b1) {
}
// an implementation that reads data from a session bus service
var DBusEventSource = GObject.registerClass(
class DBusEventSource extends EventSourceBase {
_init() {
super._init();
var DBusEventSource = class DBusEventSource {
constructor() {
this._resetCache();
this._isLoading = false;
this.isLoading = false;
this.isDummy = false;
this._initialized = false;
this._dbusProxy = new CalendarServer();
@ -229,12 +193,12 @@ class DBusEventSource extends EventSourceBase {
});
this._dbusProxy.connect('g-properties-changed', () => {
this.notify('has-calendars');
this.emit('notify::has-calendars');
});
this._initialized = loaded;
if (loaded) {
this.notify('has-calendars');
this.emit('notify::has-calendars');
this._onNameAppeared();
}
});
@ -251,10 +215,6 @@ class DBusEventSource extends EventSourceBase {
return false;
}
get isLoading() {
return this._isLoading;
}
_resetCache() {
this._events = [];
this._lastRequestBegin = null;
@ -292,7 +252,7 @@ class DBusEventSource extends EventSourceBase {
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
this._events = newEvents;
this._isLoading = false;
this.isLoading = false;
this.emit('changed');
}
@ -312,7 +272,7 @@ class DBusEventSource extends EventSourceBase {
requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
this._isLoading = true;
this.isLoading = true;
this._lastRequestBegin = begin;
this._lastRequestEnd = end;
this._curRequestBegin = begin;
@ -326,8 +286,9 @@ class DBusEventSource extends EventSourceBase {
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
result.push(event);
}
}
result.sort((event1, event2) => {
// sort events by end time on ending day
@ -349,12 +310,11 @@ class DBusEventSource extends EventSourceBase {
return true;
}
});
};
Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = GObject.registerClass({
Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } },
}, class Calendar extends St.Widget {
_init() {
var Calendar = class Calendar {
constructor() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
@ -384,19 +344,19 @@ var Calendar = GObject.registerClass({
this._shouldDateGrabFocus = false;
super._init({
style_class: 'calendar',
layout_manager: new Clutter.GridLayout(),
reactive: true,
});
this.actor = new St.Widget({ style_class: 'calendar',
layout_manager: new Clutter.TableLayout(),
reactive: true });
this._buildHeader();
this.actor.connect('scroll-event',
this._onScroll.bind(this));
this._buildHeader ();
}
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
setEventSource(eventSource) {
if (!(eventSource instanceof EventSourceBase))
throw new Error('Event source is not valid type');
this._eventSource = eventSource;
this._eventSource.connect('changed', () => {
this._rebuildCalendar();
@ -413,10 +373,7 @@ var Calendar = GObject.registerClass({
this._selectedDate = date;
this._update();
let datetime = GLib.DateTime.new_from_unix_local(
this._selectedDate.getTime() / 1000);
this.emit('selected-date-changed', datetime);
this.emit('selected-date-changed', new Date(this._selectedDate));
}
updateTimeZone() {
@ -427,13 +384,14 @@ var Calendar = GObject.registerClass({
}
_buildHeader() {
let layout = this.layout_manager;
let layout = this.actor.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0;
this.destroy_all_children();
this.actor.destroy_all_children();
// Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout();
layout.attach(this._topBox, 0, 0, offsetCols + 7, 1);
layout.pack(this._topBox, 0, 0);
layout.set_span(this._topBox, offsetCols + 7, 1);
this._backButton = new St.Button({ style_class: 'calendar-change-month-back pager-button',
accessible_name: _("Previous month"),
@ -442,13 +400,9 @@ var Calendar = GObject.registerClass({
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,
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
});
this._topBox.add_child(this._monthLabel);
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',
accessible_name: _("Next month"),
@ -474,20 +428,20 @@ var Calendar = GObject.registerClass({
can_focus: true });
label.accessible_name = iter.toLocaleFormat('%A');
let col;
if (this.get_text_direction() == Clutter.TextDirection.RTL)
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(label, col, 1, 1, 1);
layout.pack(label, col, 1);
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
// All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.get_n_children();
this._firstDayIndex = this.actor.get_n_children();
}
vfunc_scroll_event(scrollEvent) {
switch (scrollEvent.direction) {
_onScroll(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT:
this._onPrevMonthButtonClicked();
@ -557,7 +511,7 @@ var Calendar = GObject.registerClass({
let now = new Date();
// Remove everything but the topBox and the weekday labels
let children = this.get_children();
let children = this.actor.get_children();
for (let i = this._firstDayIndex; i < children.length; i++)
children[i].destroy();
@ -594,7 +548,7 @@ var Calendar = GObject.registerClass({
beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY);
let layout = this.layout_manager;
let layout = this.actor.layout_manager;
let iter = new Date(beginDate);
let row = 2;
// nRows here means 6 weeks + one header + one navbar
@ -605,7 +559,7 @@ var Calendar = GObject.registerClass({
can_focus: true });
let rtl = button.get_text_direction() == Clutter.TextDirection.RTL;
if (this._eventSource instanceof EmptyEventSource)
if (this._eventSource.isDummy)
button.reactive = false;
button._date = new Date(iter);
@ -649,7 +603,7 @@ var Calendar = GObject.registerClass({
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(button, col, row, 1, 1);
layout.pack(button, col, row);
this._buttons.push(button);
@ -659,7 +613,7 @@ var Calendar = GObject.registerClass({
can_focus: true });
let weekFormat = Shell.util_translate_time_string(N_("Week %V"));
label.accessible_name = iter.toLocaleFormat(weekFormat);
layout.attach(label, rtl ? 7 : 0, row, 1, 1);
layout.pack(label, rtl ? 7 : 0, row);
}
iter.setTime(iter.getTime() + MSECS_IN_DAY);
@ -694,12 +648,12 @@ var Calendar = GObject.registerClass({
}
});
}
});
};
Signals.addSignalMethods(Calendar.prototype);
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', event.summary);
var EventMessage = class EventMessage extends MessageList.Message {
constructor(event, date) {
super('', event.summary);
this._event = event;
this._date = date;
@ -708,19 +662,18 @@ class EventMessage extends MessageList.Message {
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
}
vfunc_style_changed() {
let iconVisible = this.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = iconVisible ? 255 : 0;
super.vfunc_style_changed();
this.actor.connect('style-changed', () => {
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0);
});
}
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
let allDay = this._event.allDay || (this._event.date <= periodBegin &&
this._event.end >= periodEnd);
let allDay = (this._event.allDay || (this._event.date <= periodBegin &&
this._event.end >= periodEnd));
let title;
if (allDay) {
/* Translators: Shown in calendar event list for all day events
@ -749,12 +702,12 @@ class EventMessage extends MessageList.Message {
}
return title;
}
});
};
var NotificationMessage = GObject.registerClass(
var NotificationMessage =
class NotificationMessage extends MessageList.Message {
_init(notification) {
super._init(notification.title, notification.bannerBodyText);
constructor(notification) {
super(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup);
this.notification = notification;
@ -777,12 +730,11 @@ class NotificationMessage extends MessageList.Message {
}
_getIcon() {
if (this.notification.gicon) {
if (this.notification.gicon)
return new St.Icon({ gicon: this.notification.gicon,
icon_size: MESSAGE_ICON_SIZE });
} else {
else
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
}
}
_onUpdated(n, _clear) {
@ -792,7 +744,7 @@ class NotificationMessage extends MessageList.Message {
this.setUseBodyMarkup(n.bannerBodyMarkup);
}
vfunc_clicked() {
_onClicked() {
this.notification.activate();
}
@ -814,12 +766,11 @@ class NotificationMessage extends MessageList.Message {
canClose() {
return true;
}
});
};
var EventsSection = GObject.registerClass(
class EventsSection extends MessageList.MessageListSection {
_init() {
super._init();
var EventsSection = class EventsSection extends MessageList.MessageListSection {
constructor() {
super();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
@ -829,9 +780,9 @@ class EventsSection extends MessageList.MessageListSection {
this._title = new St.Button({ style_class: 'events-section-title',
label: '',
x_align: St.Align.START,
can_focus: true });
this._title.child.x_align = Clutter.ActorAlign.START;
this.insert_child_below(this._title, null);
this.actor.insert_child_below(this._title, null);
this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
@ -842,9 +793,6 @@ class EventsSection extends MessageList.MessageListSection {
}
setEventSource(eventSource) {
if (!(eventSource instanceof EventSourceBase))
throw new Error('Event source is not valid type');
this._eventSource = eventSource;
this._eventSource.connect('changed', this._reloadEvents.bind(this));
}
@ -861,15 +809,14 @@ class EventsSection extends MessageList.MessageListSection {
let dayFormat;
let now = new Date();
if (sameYear(this._date, now)) {
if (sameYear(this._date, now))
/* Translators: Shown on calendar heading when selected day occurs on current year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %-d"));
} else {
else
/* Translators: Shown on calendar heading when selected day occurs on different year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %-d, %Y"));
}
this._title.label = this._date.toLocaleFormat(dayFormat);
}
@ -910,7 +857,7 @@ class EventsSection extends MessageList.MessageListSection {
_appInstalledChanged() {
this._calendarApp = undefined;
this._title.reactive = this._getCalendarApp() != null;
this._title.reactive = (this._getCalendarApp() != null);
}
_getCalendarApp() {
@ -954,29 +901,12 @@ class EventsSection extends MessageList.MessageListSection {
super._sync();
}
});
};
var TimeLabel = GObject.registerClass(
class NotificationTimeLabel extends St.Label {
_init(datetime) {
super._init({
style_class: 'event-time',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
});
this._datetime = datetime;
}
vfunc_map() {
this.text = Util.formatTimeSpan(this._datetime);
super.vfunc_map();
}
});
var NotificationSection = GObject.registerClass(
var NotificationSection =
class NotificationSection extends MessageList.MessageListSection {
_init() {
super._init();
constructor() {
super();
this._sources = new Map();
this._nUrgent = 0;
@ -985,6 +915,8 @@ class NotificationSection extends MessageList.MessageListSection {
Main.messageTray.getSources().forEach(source => {
this._sourceAdded(Main.messageTray, source);
});
this.actor.connect('notify::mapped', this._onMapped.bind(this));
}
get allowed() {
@ -992,13 +924,24 @@ class NotificationSection extends MessageList.MessageListSection {
!Main.sessionMode.isGreeter;
}
_createTimeLabel(datetime) {
let label = new St.Label({ style_class: 'event-time',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END });
label.connect('notify::mapped', () => {
if (label.mapped)
label.text = Util.formatTimeSpan(datetime);
});
return label;
}
_sourceAdded(tray, source) {
let obj = {
destroyId: 0,
notificationAddedId: 0,
};
obj.destroyId = source.connect('destroy', () => {
obj.destroyId = source.connect('destroy', source => {
this._onSourceDestroy(source, obj);
});
obj.notificationAddedId = source.connect('notification-added',
@ -1009,13 +952,13 @@ class NotificationSection extends MessageList.MessageListSection {
_onNotificationAdded(source, notification) {
let message = new NotificationMessage(notification);
message.setSecondaryActor(new TimeLabel(notification.datetime));
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL;
let updatedId = notification.connect('updated', () => {
message.setSecondaryActor(new TimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.mapped);
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped);
});
let destroyId = notification.connect('destroy', () => {
notification.disconnect(destroyId);
@ -1035,7 +978,7 @@ class NotificationSection extends MessageList.MessageListSection {
}
let index = isUrgent ? 0 : this._nUrgent;
this.addMessageAtIndex(message, index, this.mapped);
this.addMessageAtIndex(message, index, this.actor.mapped);
}
_onSourceDestroy(source, obj) {
@ -1045,23 +988,25 @@ class NotificationSection extends MessageList.MessageListSection {
this._sources.delete(source);
}
vfunc_map() {
this._messages.forEach(message => {
_onMapped() {
if (!this.actor.mapped)
return;
for (let message of this._messages.keys())
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
message.notification.acknowledged = true;
});
super.vfunc_map();
}
_shouldShow() {
return !this.empty && isToday(this._date);
}
});
};
var Placeholder = class Placeholder {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
vertical: true });
var Placeholder = GObject.registerClass(
class Placeholder extends St.BoxLayout {
_init() {
super._init({ style_class: 'message-list-placeholder', vertical: true });
this._date = new Date();
let todayFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/no-notifications.svg');
@ -1070,10 +1015,10 @@ class Placeholder extends St.BoxLayout {
this._otherIcon = new Gio.FileIcon({ file: otherFile });
this._icon = new St.Icon();
this.add_actor(this._icon);
this.actor.add_actor(this._icon);
this._label = new St.Label();
this.add_actor(this._label);
this.actor.add_actor(this._label);
this._sync();
}
@ -1100,56 +1045,48 @@ class Placeholder extends St.BoxLayout {
this._label.text = _("No Events");
}
}
});
};
var CalendarMessageList = GObject.registerClass(
class CalendarMessageList extends St.Widget {
_init() {
super._init({
style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
var CalendarMessageList = class CalendarMessageList {
constructor() {
this.actor = new St.Widget({ style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
this._placeholder = new Placeholder();
this.add_actor(this._placeholder);
this.actor.add_actor(this._placeholder.actor);
let box = new St.BoxLayout({ vertical: true,
x_expand: true, y_expand: true });
this.add_actor(box);
this.actor.add_actor(box);
this._scrollView = new St.ScrollView({
style_class: 'vfade',
overlay_scrollbars: true,
x_expand: true, y_expand: true,
});
this._scrollView = new St.ScrollView({ style_class: 'vfade',
overlay_scrollbars: true,
x_expand: true, y_expand: true,
x_fill: true, y_fill: true });
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
box.add_actor(this._scrollView);
this._clearButton = new St.Button({
style_class: 'message-list-clear-button button',
label: _('Clear'),
can_focus: true,
x_align: Clutter.ActorAlign.END,
});
this._clearButton = new St.Button({ style_class: 'message-list-clear-button button',
label: _("Clear"),
can_focus: true });
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
this._sectionList.get_children().forEach(s => s.clear());
let sections = [...this._sections.keys()];
sections.forEach(s => s.clear());
});
box.add_actor(this._clearButton);
this._placeholder.bind_property('visible',
this._placeholder.actor.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true,
x_expand: true,
y_expand: true,
y_align: Clutter.ActorAlign.START });
this._sectionList.connect('actor-added', this._sync.bind(this));
this._sectionList.connect('actor-removed', this._sync.bind(this));
this._scrollView.add_actor(this._sectionList);
this._sections = new Map();
this._mediaSection = new Mpris.MediaSection();
this._addSection(this._mediaSection);
@ -1164,35 +1101,58 @@ class CalendarMessageList extends St.Widget {
}
_addSection(section) {
let connectionsIds = [];
let obj = {
destroyId: 0,
visibleId: 0,
emptyChangedId: 0,
canClearChangedId: 0,
keyFocusId: 0
};
obj.destroyId = section.actor.connect('destroy', () => {
this._removeSection(section);
});
obj.visibleId = section.actor.connect('notify::visible',
this._sync.bind(this));
obj.emptyChangedId = section.connect('empty-changed',
this._sync.bind(this));
obj.canClearChangedId = section.connect('can-clear-changed',
this._sync.bind(this));
obj.keyFocusId = section.connect('key-focus-in',
this._onKeyFocusIn.bind(this));
for (let prop of ['visible', 'empty', 'can-clear']) {
connectionsIds.push(
section.connect(`notify::${prop}`, this._sync.bind(this)));
}
connectionsIds.push(section.connect('message-focused', (_s, messageActor) => {
Util.ensureActorVisibleInScrollView(this._scrollView, messageActor);
}));
this._sections.set(section, obj);
this._sectionList.add_actor(section.actor);
this._sync();
}
connectionsIds.push(section.connect('destroy', () => {
connectionsIds.forEach(id => section.disconnect(id));
this._sectionList.remove_actor(section);
}));
_removeSection(section) {
let obj = this._sections.get(section);
section.actor.disconnect(obj.destroyId);
section.actor.disconnect(obj.visibleId);
section.disconnect(obj.emptyChangedId);
section.disconnect(obj.canClearChangedId);
section.disconnect(obj.keyFocusId);
this._sectionList.add_actor(section);
this._sections.delete(section);
this._sectionList.remove_actor(section.actor);
this._sync();
}
_onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
}
_sync() {
let sections = this._sectionList.get_children();
let sections = [...this._sections.keys()];
let visible = sections.some(s => s.allowed);
this.visible = visible;
this.actor.visible = visible;
if (!visible)
return;
let empty = sections.every(s => s.empty || !s.visible);
this._placeholder.visible = empty;
let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty;
let canClear = sections.some(s => s.canClear && s.visible);
let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear;
}
@ -1201,7 +1161,8 @@ class CalendarMessageList extends St.Widget {
}
setDate(date) {
this._sectionList.get_children().forEach(s => s.setDate(date));
for (let section of this._sections.keys())
section.setDate(date);
this._placeholder.setDate(date);
}
});
};

View File

@ -1,22 +1,19 @@
/* exported CheckBox */
const { Clutter, GObject, Pango, St } = imports.gi;
const { Clutter, Pango, St } = imports.gi;
var CheckBox = GObject.registerClass(
class CheckBox extends St.Button {
_init(label) {
let container = new St.BoxLayout({
x_expand: true,
y_expand: true,
});
super._init({
style_class: 'check-box',
child: container,
button_mask: St.ButtonMask.ONE,
toggle_mode: true,
can_focus: true,
});
var CheckBox = class CheckBox {
constructor(label) {
let container = new St.BoxLayout();
this.actor = new St.Button({ style_class: 'check-box',
child: container,
button_mask: St.ButtonMask.ONE,
toggle_mode: true,
can_focus: true,
x_fill: true,
y_fill: true });
this._box = new St.Bin({ y_align: Clutter.ActorAlign.START });
this._box = new St.Bin();
this._box.set_y_align(Clutter.ActorAlign.START);
container.add_actor(this._box);
this._label = new St.Label();
@ -35,4 +32,4 @@ class CheckBox extends St.Button {
getLabelActor() {
return this._label;
}
});
};

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
@ -13,7 +13,7 @@ var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({
Implements: [Meta.CloseDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog),
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
},
}, class CloseDialog extends GObject.Object {
_init(window) {
@ -46,18 +46,6 @@ var CloseDialog = GObject.registerClass({
return new Dialog.MessageDialogContent({ icon, title, subtitle });
}
_updateScale() {
// Since this is a child of MetaWindowActor (which, for Wayland clients,
// applies the geometry scale factor to its children itself, see
// meta_window_actor_set_geometry_scale()), make sure we don't apply
// the factor twice in the end.
if (this._window.get_client_type() !== Meta.WindowClientType.WAYLAND)
return;
let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
this._dialog.set_scale(1 / scaleFactor, 1 / scaleFactor);
}
_initDialog() {
if (this._dialog)
return;
@ -73,14 +61,9 @@ var CloseDialog = GObject.registerClass({
default: true });
this._dialog.addButton({ label: _('Wait'),
action: this._onWait.bind(this),
key: Clutter.KEY_Escape });
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
let themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.connect('notify::scale-factor', this._updateScale.bind(this));
this._updateScale();
}
_addWindowEffect() {
@ -124,12 +107,11 @@ var CloseDialog = GObject.registerClass({
if (this._tracked === shouldTrack)
return;
if (shouldTrack) {
if (shouldTrack)
Main.layoutManager.trackChrome(this._dialog,
{ affectsInputRegion: true });
} else {
else
Main.layoutManager.untrackChrome(this._dialog);
}
// The buttons are broken when they aren't added to the input region,
// so disable them properly in that case
@ -163,14 +145,14 @@ var CloseDialog = GObject.registerClass({
this._addWindowEffect();
this._initDialog();
this._dialog._dialog.scale_y = 0;
this._dialog._dialog.set_pivot_point(0.5, 0.5);
this._dialog.scale_y = 0;
this._dialog.set_pivot_point(0.5, 0.5);
this._dialog._dialog.ease({
this._dialog.ease({
scale_y: 1,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this),
onComplete: this._onFocusChanged.bind(this)
});
}
@ -193,11 +175,11 @@ var CloseDialog = GObject.registerClass({
this._dialog = null;
this._removeWindowEffect();
dialog._dialog.ease({
dialog.ease({
scale_y: 0,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
onComplete: () => dialog.destroy(),
onComplete: () => dialog.destroy()
});
}

View File

@ -58,8 +58,9 @@ var AutomountManager = class {
_InhibitorsChanged(_object, _senderName, [_inhibitor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
(result, error) => {
if (!error)
if (!error) {
this._inhibited = result[0];
}
});
}
@ -109,7 +110,7 @@ var AutomountManager = class {
// mount operation object
if (drive.can_stop()) {
drive.stop(Gio.MountUnmountFlags.FORCE, null, null,
(o, res) => {
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
@ -118,7 +119,7 @@ var AutomountManager = class {
});
} else if (drive.can_eject()) {
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE, null, null,
(o, res) => {
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
@ -222,7 +223,7 @@ var AutomountManager = class {
delete volume._allowAutorunExpireId;
}
this._volumeQueue =
this._volumeQueue.filter(element => element != volume);
this._volumeQueue.filter(element => (element != volume));
}
_reaskPassword(volume) {
@ -230,7 +231,7 @@ var AutomountManager = class {
let existingDialog = prevOperation ? prevOperation.borrowDialog() : null;
let operation =
new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog });
{ existingDialog: existingDialog });
this._mountVolume(volume, operation);
}

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GObject, St } = imports.gi;
const { Gio, St } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
@ -20,7 +20,7 @@ var AutorunSetting = {
RUN: 0,
IGNORE: 1,
FILES: 2,
ASK: 3,
ASK: 3
};
// misc utils
@ -41,7 +41,7 @@ function isMountRootHidden(root) {
let path = root.get_path();
// skip any mounts in hidden directory hierarchies
return path.includes('/.');
return (path.includes('/.'));
}
function isMountNonLocal(mount) {
@ -52,7 +52,7 @@ function isMountNonLocal(mount) {
if (volume == null)
return true;
return volume.get_identifier("class") == "network";
return (volume.get_identifier("class") == "network");
}
function startAppForMount(app, mount) {
@ -115,8 +115,7 @@ var ContentTypeDiscoverer = class {
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(),
result => {
[contentTypes] = result;
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
});
}
@ -125,7 +124,7 @@ var ContentTypeDiscoverer = class {
_emitCallback(mount, contentTypes = []) {
// we're not interested in win32 software content types here
contentTypes = contentTypes.filter(
type => type != 'x-content/win32-software'
type => (type != 'x-content/win32-software')
);
let apps = [];
@ -167,7 +166,7 @@ var AutorunManager = class {
if (!this._session.SessionIsActive)
return;
let discoverer = new ContentTypeDiscoverer((m, apps, contentTypes) => {
let discoverer = new ContentTypeDiscoverer((mount, apps, contentTypes) => {
this._dispatcher.addMount(mount, apps, contentTypes);
});
discoverer.guessContentTypes(mount);
@ -202,7 +201,7 @@ var AutorunDispatcher = class {
}
_getSourceForMount(mount) {
let filtered = this._sources.filter(source => source.mount == mount);
let filtered = this._sources.filter(source => (source.mount == mount));
// we always make sure not to add two sources for the same
// mount in addMount(), so it's safe to assume filtered.length
@ -246,10 +245,11 @@ var AutorunDispatcher = class {
let success = false;
let app = null;
if (setting == AutorunSetting.RUN)
if (setting == AutorunSetting.RUN) {
app = Gio.app_info_get_default_for_type(contentTypes[0], false);
else if (setting == AutorunSetting.FILES)
} else if (setting == AutorunSetting.FILES) {
app = Gio.app_info_get_default_for_type('inode/directory', false);
}
if (app)
success = startAppForMount(app, mount);
@ -272,10 +272,9 @@ var AutorunDispatcher = class {
}
};
var AutorunSource = GObject.registerClass(
class AutorunSource extends MessageTray.Source {
_init(manager, mount, apps) {
super._init(mount.get_name());
var AutorunSource = class extends MessageTray.Source {
constructor(manager, mount, apps) {
super(mount.get_name());
this._manager = manager;
this.mount = mount;
@ -285,7 +284,7 @@ class AutorunSource extends MessageTray.Source {
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
this.showNotification(this._notification);
this.notify(this._notification);
}
getIcon() {
@ -295,12 +294,11 @@ class AutorunSource extends MessageTray.Source {
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
});
};
var AutorunNotification = GObject.registerClass(
class AutorunNotification extends MessageTray.Notification {
_init(manager, source) {
super._init(source, source.title);
var AutorunNotification = class extends MessageTray.Notification {
constructor(manager, source) {
super(source, source.title);
this._manager = manager;
this._mount = source.mount;
@ -320,23 +318,20 @@ class AutorunNotification extends MessageTray.Notification {
}
_buttonForApp(app) {
let box = new St.BoxLayout({
x_expand: true,
x_align: Clutter.ActorAlign.START,
});
let box = new St.BoxLayout();
let icon = new St.Icon({ gicon: app.get_icon(),
style_class: 'hotplug-notification-item-icon' });
box.add(icon);
let label = new St.Bin({
child: new St.Label({
text: _("Open with %s").format(app.get_name()),
y_align: Clutter.ActorAlign.CENTER,
}),
y_align: St.Align.MIDDLE,
child: new St.Label({ text: _("Open with %s").format(app.get_name()) }),
});
box.add(label);
let button = new St.Button({ child: box,
x_fill: true,
x_align: St.Align.START,
x_expand: true,
button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item button' });
@ -355,6 +350,6 @@ class AutorunNotification extends MessageTray.Notification {
let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount);
}
});
};
var Component = AutorunManager;

View File

@ -33,7 +33,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._cancelButton = this.addButton({ label: '',
action: this._onCancelButton.bind(this),
key: Clutter.KEY_Escape });
key: Clutter.Escape });
this._continueButton = this.addButton({ label: '',
action: this._onContinueButton.bind(this),
default: true });
@ -54,12 +54,8 @@ class KeyringDialog extends ModalDialog.ModalDialog {
_buildControlTable() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
let table = new St.Widget({
style_class: 'keyring-dialog-control-table',
layout_manager: layout,
x_expand: true,
y_expand: true,
});
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout });
layout.hookup_style(table);
let rtl = table.get_text_direction() == Clutter.TextDirection.RTL;
let row = 0;
@ -78,18 +74,16 @@ class KeyringDialog extends ModalDialog.ModalDialog {
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true,
});
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
if (rtl) {
layout.attach(this._workSpinner, 0, row, 1, 1);
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(label, 2, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(this._workSpinner, 2, row, 1, 1);
layout.attach(this._workSpinner.actor, 2, row, 1, 1);
}
row++;
} else {
@ -98,9 +92,9 @@ class KeyringDialog extends ModalDialog.ModalDialog {
}
if (this.prompt.confirm_visible) {
var label = new St.Label({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
var label = new St.Label(({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER }));
label.set_text(_("Type again:"));
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
@ -127,8 +121,8 @@ class KeyringDialog extends ModalDialog.ModalDialog {
if (this.prompt.choice_visible) {
let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice, rtl ? 0 : 1, row, 1, 1);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1);
row++;
}
@ -146,7 +140,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
}
this._controlTable = table;
this._content.messageBox.add_child(table);
this._content.messageBox.add(table, { x_fill: true, y_fill: true });
}
_updateSensitivity(sensitive) {
@ -234,11 +228,10 @@ var KeyringDummyDialog = class {
}
};
var KeyringPrompter = GObject.registerClass(
class KeyringPrompter extends Gcr.SystemPrompter {
_init() {
super._init();
this.connect('new-prompt', () => {
var KeyringPrompter = class {
constructor() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => {
let dialog = this._enabled
? new KeyringDialog()
: new KeyringDummyDialog();
@ -253,7 +246,7 @@ class KeyringPrompter extends Gcr.SystemPrompter {
enable() {
if (!this._registered) {
this.register(Gio.DBus.session);
this._prompter.register(Gio.DBus.session);
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
this._registered = true;
@ -264,10 +257,10 @@ class KeyringPrompter extends Gcr.SystemPrompter {
disable() {
this._enabled = false;
if (this.prompting)
if (this._prompter.prompting)
this._currentPrompt.cancel();
this._currentPrompt = null;
}
});
};
var Component = KeyringPrompter;

View File

@ -56,7 +56,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive,
reactive,
reactive: reactive,
x_expand: true });
ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password });
@ -106,7 +106,10 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
descriptionLabel.clutter_text.line_wrap = true;
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add_child(descriptionLabel);
contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
}
this._okButton = {
@ -169,7 +172,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
return true;
}
return value.length >= 8 && value.length <= 63;
return (value.length >= 8 && value.length <= 63);
}
_validateStaticWep(secret) {
@ -222,12 +225,11 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
validate: this._validateStaticWep, password: true });
break;
case 'ieee8021x':
if (wirelessSecuritySetting.auth_alg == 'leap') { // Cisco LEAP
if (wirelessSecuritySetting.auth_alg == 'leap') // Cisco LEAP
secrets.push({ label: _("Password: "), key: 'leap-password',
value: wirelessSecuritySetting.leap_password || '', password: true });
} else { // Dynamic (IEEE 802.1x) WEP
else // Dynamic (IEEE 802.1x) WEP
this._get8021xSecrets(secrets);
}
break;
case 'wpa-eap':
this._get8021xSecrets(secrets);
@ -242,18 +244,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
/* If hints were given we know exactly what we need to ask */
if (this._settingName == "802-1x" && this._hints.length) {
if (this._hints.includes('identity')) {
if (this._hints.includes('identity'))
secrets.push({ label: _("Username: "), key: 'identity',
value: ieee8021xSetting.identity || '', password: false });
}
if (this._hints.includes('password')) {
if (this._hints.includes('password'))
secrets.push({ label: _("Password: "), key: 'password',
value: ieee8021xSetting.password || '', password: true });
}
if (this._hints.includes('private-key-password')) {
if (this._hints.includes('private-key-password'))
secrets.push({ label: _("Private key password: "), key: 'private-key-password',
value: ieee8021xSetting.private_key_password || '', password: true });
}
return;
}
@ -557,7 +556,7 @@ var VPNRequestHandler = class {
contentOverride.secrets.push({
label: keyfile.get_string(groups[i], 'Label'),
key: groups[i],
value,
value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret'),
});
} else {
@ -735,7 +734,7 @@ var NetworkAgent = class {
});
Main.messageTray.add(source);
source.showNotification(notification);
source.notify(notification);
}
_newRequest(agent, requestId, connection, settingName, hints, flags) {

View File

@ -11,19 +11,12 @@ const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
const DialogMode = {
AUTH: 0,
CONFIRM: 1,
};
var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16;
const DELAYED_RESET_TIMEOUT = 200;
var AuthenticationDialog = GObject.registerClass({
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } },
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }
}, class AuthenticationDialog extends ModalDialog.ModalDialog {
_init(actionId, body, cookie, userNames) {
super._init({ styleClass: 'prompt-dialog' });
@ -31,6 +24,7 @@ var AuthenticationDialog = GObject.registerClass({
this.actionId = actionId;
this.message = body;
this.userNames = userNames;
this._wasDismissed = false;
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
this.visible = !Main.sessionMode.isLocked;
@ -57,63 +51,70 @@ var AuthenticationDialog = GObject.registerClass({
userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
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',
this._onUserChanged.bind(this));
let userBox = new St.BoxLayout({
style_class: 'polkit-dialog-user-layout',
vertical: false,
});
content.messageBox.add(userBox);
// Special case 'root'
let userIsRoot = false;
if (userName == 'root') {
userIsRoot = true;
userRealName = _("Administrator");
}
this._userAvatar = new UserWidget.Avatar(this._user, {
iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon',
});
userBox.add_child(this._userAvatar);
if (userIsRoot) {
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
text: userRealName }));
content.messageBox.add(userLabel, { x_fill: false,
x_align: St.Align.START });
} else {
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
vertical: false });
content.messageBox.add(userBox);
this._userAvatar = new UserWidget.Avatar(this._user,
{ iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
{ 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_align: St.Align.END,
y_align: St.Align.MIDDLE });
}
this._userLabel = new St.Label({
style_class: userName === 'root'
? 'polkit-dialog-user-root-label'
: 'polkit-dialog-user-label',
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
if (userName === 'root')
this._userLabel.text = _('Administrator');
userBox.add_child(this._userLabel);
this._onUserChanged();
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
content.messageBox.add(this._passwordBox);
this._passwordLabel = new St.Label({
style_class: 'prompt-dialog-password-label',
y_align: Clutter.ActorAlign.CENTER,
});
this._passwordBox.add_child(this._passwordLabel);
this._passwordEntry = new St.Entry({
style_class: 'prompt-dialog-password-entry',
text: "",
can_focus: true,
x_expand: true,
});
this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
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 });
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordEntry.bind_property('reactive',
this._passwordEntry.clutter_text, 'editable',
GObject.BindingFlags.SYNC_CREATE);
this._passwordBox.add_child(this._passwordEntry);
this._passwordBox.add(this._passwordEntry,
{ expand: true });
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true,
});
this._passwordBox.add(this._workSpinner);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry);
this._passwordBox.hide();
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._errorMessageLabel.clutter_text.line_wrap = true;
content.messageBox.add_child(this._errorMessageLabel);
content.messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START });
this._errorMessageLabel.hide();
this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' });
@ -136,30 +137,15 @@ var AuthenticationDialog = GObject.registerClass({
this._cancelButton = this.addButton({ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape });
key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"),
action: this._onAuthenticateButtonPressed.bind(this),
reactive: false });
this._okButton.bind_property('reactive',
this._okButton, 'can-focus',
GObject.BindingFlags.SYNC_CREATE);
this._passwordEntry.clutter_text.connect('text-changed', text => {
this._okButton.reactive = text.get_text().length > 0;
});
default: true });
this._doneEmitted = false;
this._mode = -1;
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie;
this._userLoadedId = this._user.connect('notify::is-loaded',
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
this._onUserChanged.bind(this));
this._onUserChanged();
}
_setWorking(working) {
@ -169,9 +155,8 @@ var AuthenticationDialog = GObject.registerClass({
this._workSpinner.stop();
}
_initiateSession() {
this._destroySession(DELAYED_RESET_TIMEOUT);
performAuthentication() {
this._destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie });
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this));
@ -210,15 +195,18 @@ var AuthenticationDialog = GObject.registerClass({
}
}
_updateSensitivity(sensitive) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive;
this._setWorking(!sensitive);
}
_onEntryActivate() {
let response = this._passwordEntry.get_text();
if (response.length === 0)
return;
this._passwordEntry.reactive = false;
this._okButton.reactive = false;
this._setWorking(true);
this._updateSensitivity(false);
this._session.response(response);
// When the user responds, dismiss already shown info and
// error texts (if any)
@ -228,10 +216,7 @@ var AuthenticationDialog = GObject.registerClass({
}
_onAuthenticateButtonPressed() {
if (this._mode === DialogMode.CONFIRM)
this._initiateSession();
else
this._onEntryActivate();
this._onEntryActivate();
}
_onSessionCompleted(session, gainedAuthorization) {
@ -250,7 +235,7 @@ var AuthenticationDialog = GObject.registerClass({
* error providing authentication-method specific information),
* show "Sorry, that didn't work. Please try again."
*/
if (!this._errorMessageLabel.visible) {
if (!this._errorMessageLabel.visible && !this._wasDismissed) {
/* Translators: "that didn't work" refers to the fact that the
* requested authentication was not gained; this can happen
* because of an authentication error (like invalid password),
@ -262,16 +247,11 @@ var AuthenticationDialog = GObject.registerClass({
}
/* Try and authenticate again */
this._initiateSession();
this.performAuthentication();
}
}
_onSessionRequest(session, request, echoOn) {
if (this._sessionRequestTimeoutId) {
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
}
// Cheap localization trick
if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:"));
@ -285,12 +265,9 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.show();
this._passwordEntry.set_text('');
this._passwordEntry.reactive = true;
this._okButton.reactive = false;
this._setWorking(false);
this._ensureOpen();
this._passwordEntry.grab_key_focus();
this._updateSensitivity(true);
this._ensureOpen();
}
_onSessionShowError(session, text) {
@ -311,78 +288,29 @@ var AuthenticationDialog = GObject.registerClass({
this._ensureOpen();
}
_destroySession(delay = 0) {
_destroySession() {
if (this._session) {
if (!this._completed)
this._session.cancel();
this._completed = false;
this._session.disconnect(this._sessionCompletedId);
this._session.disconnect(this._sessionRequestId);
this._session.disconnect(this._sessionShowErrorId);
this._session.disconnect(this._sessionShowInfoId);
if (!this._completed)
this._session.cancel();
this._completed = false;
this._session = null;
}
if (this._sessionRequestTimeoutId) {
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
}
let resetDialog = () => {
if (this.state != ModalDialog.State.OPENED)
return;
this._passwordBox.hide();
this._cancelButton.grab_key_focus();
this._okButton.reactive = false;
};
if (delay) {
this._sessionRequestTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, resetDialog);
GLib.Source.set_name_by_id(this._sessionRequestTimeoutId, '[gnome-shell] this._sessionRequestTimeoutId');
} else {
resetDialog();
}
}
_onUserChanged() {
if (!this._user.is_loaded)
return;
let userName = this._user.get_user_name();
let realName = this._user.get_real_name();
if (userName !== 'root')
this._userLabel.set_text(realName);
this._userAvatar.update();
if (this._user.get_password_mode() === AccountsService.UserPasswordMode.NONE) {
if (this._mode === DialogMode.CONFIRM)
return;
this._mode = DialogMode.CONFIRM;
this._destroySession();
this._okButton.reactive = true;
/* We normally open the dialog when we get a "request" signal, but
* since in this case initiating a session would perform the
* authentication, only open the dialog and initiate the session
* when the user confirmed. */
this._ensureOpen();
} else {
if (this._mode === DialogMode.AUTH)
return;
this._mode = DialogMode.AUTH;
this._initiateSession();
if (this._user.is_loaded && this._userAvatar) {
this._userAvatar.update();
this._userAvatar.actor.show();
}
}
cancel() {
this._wasDismissed = true;
this.close(global.get_current_time());
this._emitDone(true);
}
@ -390,10 +318,7 @@ var AuthenticationDialog = GObject.registerClass({
_onDialogClosed() {
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
if (this._sessionRequestTimeoutId)
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
this._sessionUpdatedId = 0;
if (this._user) {
this._user.disconnect(this._userLoadedId);
@ -405,20 +330,19 @@ var AuthenticationDialog = GObject.registerClass({
}
});
var AuthenticationAgent = GObject.registerClass(
class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
_init() {
super._init();
var AuthenticationAgent = class {
constructor() {
this._currentDialog = null;
this.connect('initiate', this._onInitiate.bind(this));
this.connect('cancel', this._onCancel.bind(this));
this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', this._onInitiate.bind(this));
this._native.connect('cancel', this._onCancel.bind(this));
this._sessionUpdatedId = 0;
}
enable() {
try {
this.register();
this._native.register();
} catch (e) {
log('Failed to register AuthenticationAgent');
}
@ -426,7 +350,7 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
disable() {
try {
this.unregister();
this._native.unregister();
} catch (e) {
log('Failed to unregister AuthenticationAgent');
}
@ -445,7 +369,19 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
}
this._currentDialog = new AuthenticationDialog(actionId, message, cookie, userNames);
// We actually don't want to open the dialog until we know for
// sure that we're going to interact with the user. For
// example, if the password for the identity to auth is blank
// (which it will be on a live CD) then there will be no
// conversation at all... of course, we don't *know* that
// until we actually try it.
//
// See https://bugzilla.gnome.org/show_bug.cgi?id=643062 for more
// discussion.
this._currentDialog.connect('done', this._onDialogDone.bind(this));
this._currentDialog.performAuthentication();
}
_onCancel(_nativeAgent) {
@ -464,8 +400,8 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
this.complete(dismissed);
this._native.complete(dismissed);
}
});
};
var Component = AuthenticationAgent;

View File

@ -19,7 +19,7 @@ const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
const Util = imports.misc.util;
const HAVE_TP = Tp != null && Tpl != null;
const HAVE_TP = (Tp != null && Tpl != null);
// See Notification.appendMessage
var SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes
@ -37,7 +37,7 @@ var CHAT_EXPAND_LINES = 12;
var NotificationDirection = {
SENT: 'chat-sent',
RECEIVED: 'chat-received',
RECEIVED: 'chat-received'
};
function makeMessageFromTpMessage(tpMessage, direction) {
@ -49,10 +49,10 @@ function makeMessageFromTpMessage(tpMessage, direction) {
return {
messageType: tpMessage.get_message_type(),
text,
text: text,
sender: tpMessage.sender.alias,
timestamp,
direction,
timestamp: timestamp,
direction: direction
};
}
@ -66,7 +66,7 @@ function makeMessageFromTplEvent(event) {
text: event.get_message(),
sender: event.get_sender().get_alias(),
timestamp: event.get_timestamp(),
direction,
direction: direction
};
}
@ -158,7 +158,7 @@ class TelepathyClient extends Tp.BaseClient {
continue;
/* Only observe contact text channels */
if (!(channel instanceof Tp.TextChannel) ||
if ((!(channel instanceof Tp.TextChannel)) ||
targetHandleType != Tp.HandleType.CONTACT)
continue;
@ -215,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
// We are already handling the channel, display the source
let source = this._chatSources[channel.get_object_path()];
if (source)
source.showNotification();
source.notify();
}
}
}
@ -231,12 +231,11 @@ class TelepathyClient extends Tp.BaseClient {
return;
}
if (chanType == Tp.IFACE_CHANNEL_TYPE_TEXT) {
if (chanType == Tp.IFACE_CHANNEL_TYPE_TEXT)
this._approveTextChannel(account, conn, channel, dispatchOp, context);
} else {
else
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Unsupported channel type' }));
}
}
_approveTextChannel(account, conn, channel, dispatchOp, context) {
@ -249,7 +248,7 @@ class TelepathyClient extends Tp.BaseClient {
}
// Approve private text channels right away as we are going to handle it
dispatchOp.claim_with_async(this, (o, result) => {
dispatchOp.claim_with_async(this, (dispatchOp, result) => {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
@ -267,10 +266,9 @@ class TelepathyClient extends Tp.BaseClient {
}
}) : null;
var ChatSource = HAVE_TP ? GObject.registerClass(
class ChatSource extends MessageTray.Source {
_init(account, conn, channel, contact, client) {
super._init(contact.get_alias());
var ChatSource = class extends MessageTray.Source {
constructor(account, conn, channel, contact, client) {
super(contact.get_alias());
this._account = account;
this._contact = contact;
@ -328,7 +326,7 @@ class ChatSource extends MessageTray.Source {
// We ack messages when the user expands the new notification
let id = this._banner.connect('expanded', this._ackMessages.bind(this));
this._banner.connect('destroy', () => {
this._banner.actor.connect('destroy', () => {
this._banner.disconnect(id);
this._banner = null;
});
@ -350,10 +348,11 @@ class ChatSource extends MessageTray.Source {
getIcon() {
let file = this._contact.get_avatar_file();
if (file)
return new Gio.FileIcon({ file });
else
if (file) {
return new Gio.FileIcon({ file: file });
} else {
return new Gio.ThemedIcon({ name: 'avatar-default' });
}
}
getSecondaryIcon() {
@ -387,11 +386,10 @@ class ChatSource extends MessageTray.Source {
_updateAvatarIcon() {
this.iconUpdated();
if (this._notifiction) {
if (this._notifiction)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ gicon: this.getIcon() });
}
}
open() {
@ -478,7 +476,7 @@ class ChatSource extends MessageTray.Source {
this._notification.appendMessage(pendingMessages[i], true);
if (pendingMessages.length > 0)
this.showNotification();
this.notify();
}
destroy(reason) {
@ -555,7 +553,7 @@ class ChatSource extends MessageTray.Source {
_notifyTimeout() {
if (this._pendingMessages.length != 0)
this.showNotification();
this.notify();
this._notifyTimeoutId = 0;
@ -570,8 +568,8 @@ class ChatSource extends MessageTray.Source {
this._notification.appendMessage(message);
}
showNotification() {
super.showNotification(this._notification);
notify() {
super.notify(this._notification);
}
respond(text) {
@ -603,11 +601,10 @@ class ChatSource extends MessageTray.Source {
}
_presenceChanged(_contact, _presence, _status, _message) {
if (this._notification) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ secondaryGIcon: this.getSecondaryIcon() });
}
}
_pendingRemoved(channel, message) {
@ -628,18 +625,12 @@ class ChatSource extends MessageTray.Source {
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
}
}) : null;
};
var ChatNotification = HAVE_TP ? GObject.registerClass({
Signals: {
'message-removed': { param_types: [Tp.Message.$gtype] },
'message-added': { param_types: [Tp.Message.$gtype] },
'timestamp-changed': { param_types: [Tp.Message.$gtype] },
},
}, class ChatNotification extends MessageTray.Notification {
_init(source) {
super._init(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
var ChatNotification = class extends MessageTray.Notification {
constructor(source) {
super(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true);
@ -656,16 +647,16 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
/**
* appendMessage:
* @param {Object} message: An object with the properties
* {string} message.text: the body of the message,
* {Tp.ChannelTextMessageType} message.messageType: the type
* {string} message.sender: the name of the sender,
* {number} message.timestamp: the time the message was sent
* {NotificationDirection} message.direction: a #NotificationDirection
* @message: An object with the properties:
* text: the body of the message,
* messageType: a #Tp.ChannelTextMessageType,
* sender: the name of the sender,
* timestamp: the time the message was sent
* direction: a #NotificationDirection
*
* @param {bool} noTimestamp: Whether to add a timestamp. If %true,
* no timestamp will be added, regardless of the difference since
* the last timestamp
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp
* will be added, regardless of the difference since the
* last timestamp
*/
appendMessage(message, noTimestamp) {
let messageBody = GLib.markup_escape_text(message.text, -1);
@ -677,20 +668,19 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
styles.push('chat-action');
}
if (message.direction == NotificationDirection.RECEIVED) {
if (message.direction == NotificationDirection.RECEIVED)
this.update(this.source.title, messageBody,
{ datetime: GLib.DateTime.new_from_unix_local(message.timestamp),
{ datetime: GLib.DateTime.new_from_unix_local (message.timestamp),
bannerMarkup: true });
}
let group = message.direction == NotificationDirection.RECEIVED
? 'received' : 'sent';
let group = (message.direction == NotificationDirection.RECEIVED
? 'received' : 'sent');
this._append({ body: messageBody,
group,
styles,
group: group,
styles: styles,
timestamp: message.timestamp,
noTimestamp });
noTimestamp: noTimestamp });
}
_filterMessages() {
@ -698,7 +688,7 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
return;
let lastMessageTime = this.messages[0].timestamp;
let currentTime = Date.now() / 1000;
let currentTime = (Date.now() / 1000);
// Keep the scrollback from growing too long. If the most
// recent message (before the one we just added) is within
@ -706,7 +696,7 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
// we'll keep SCROLLBACK_IDLE_LENGTH messages.
let maxLength = lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME)
? SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(item => item.realMessage);
@ -720,16 +710,16 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
/**
* _append:
* @param {Object} props: An object with the properties:
* {string} props.body: The text of the message.
* {string} props.group: The group of the message, one of:
* @props: An object with the properties:
* body: The text of the message.
* group: The group of the message, one of:
* 'received', 'sent', 'meta'.
* {string[]} props.styles: Style class names for the message to have.
* {number} props.timestamp: The timestamp of the message.
* {bool} props.noTimestamp: suppress timestamp signal?
* styles: Style class names for the message to have.
* timestamp: The timestamp of the message.
* noTimestamp: suppress timestamp signal?
*/
_append(props) {
let currentTime = Date.now() / 1000;
let currentTime = (Date.now() / 1000);
props = Params.parse(props, { body: null,
group: null,
styles: [],
@ -792,7 +782,7 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
this._filterMessages();
}
}) : null;
};
var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
@ -802,10 +792,9 @@ class ChatLineBox extends St.BoxLayout {
}
});
var ChatNotificationBanner = GObject.registerClass(
class ChatNotificationBanner extends MessageTray.NotificationBanner {
_init(notification) {
super._init(notification);
var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
constructor(notification) {
super(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true,
@ -890,7 +879,8 @@ class ChatNotificationBanner extends MessageTray.NotificationBanner {
}
_addMessage(message) {
let body = new MessageList.URLHighlighter(message.body, true, true);
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
let body = highlighter.actor;
let styles = message.styles;
for (let i = 0; i < styles.length; i++)
@ -978,6 +968,6 @@ class ChatNotificationBanner extends MessageTray.NotificationBanner {
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
}
}
});
};
var Component = TelepathyComponent;

View File

@ -12,7 +12,7 @@ var POPUP_APPICON_SIZE = 96;
var SortGroup = {
TOP: 0,
MIDDLE: 1,
BOTTOM: 2,
BOTTOM: 2
};
var CtrlAltTabManager = class CtrlAltTabManager {
@ -86,26 +86,25 @@ var CtrlAltTabManager = class CtrlAltTabManager {
for (let i = 0; i < windows.length; i++) {
let icon = null;
let iconName = null;
if (windows[i].get_window_type() == Meta.WindowType.DESKTOP) {
if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) {
iconName = 'video-display-symbolic';
} else {
let app = windowTracker.get_window_app(windows[i]);
if (app) {
if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
} else {
else
icon = textureCache.bind_cairo_surface_property(windows[i],
'icon',
POPUP_APPICON_SIZE);
}
}
items.push({ name: windows[i].title,
proxy: windows[i].get_compositor_private(),
focusCallback: timestamp => {
Main.activateWindow(windows[i], timestamp);
},
focusCallback: function(timestamp) {
Main.activateWindow(this, timestamp);
}.bind(windows[i]),
iconActor: icon,
iconName,
iconName: iconName,
sortGroup: SortGroup.MIDDLE });
}
}
@ -144,9 +143,9 @@ class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(this._previous());
else if (keysym == Clutter.KEY_Left)
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.KEY_Right)
else if (keysym == Clutter.Right)
this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
@ -178,13 +177,10 @@ class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
icon = new St.Icon({ icon_name: item.iconName,
icon_size: POPUP_APPICON_SIZE });
}
box.add_child(icon);
box.add(icon, { x_fill: false, y_fill: false } );
let text = new St.Label({
text: item.name,
x_align: Clutter.ActorAlign.CENTER,
});
box.add_child(text);
let text = new St.Label({ text: item.name });
box.add(text, { x_fill: false });
this.addItem(box, text);
}

View File

@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
const { Clutter, GLib, GObject,
Graphene, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites;
@ -16,18 +16,18 @@ var DASH_ITEM_LABEL_HIDE_TIME = 100;
var DASH_ITEM_HOVER_TIMEOUT = 300;
function getAppFromSource(source) {
if (source instanceof AppDisplay.AppIcon)
if (source instanceof AppDisplay.AppIcon) {
return source.app;
else
} else {
return null;
}
}
var DashIcon = GObject.registerClass(
class DashIcon extends AppDisplay.AppIcon {
_init(app) {
super._init(app, {
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
constructor(app) {
super(app, {
setSizeManually: true,
showLabel: false,
showLabel: false
});
}
@ -45,7 +45,7 @@ class DashIcon extends AppDisplay.AppIcon {
acceptDrop() {
return false;
}
});
};
// A container like StBin, but taking the child's scale into account
// when requesting a size
@ -53,7 +53,7 @@ var DashItemContainer = GObject.registerClass(
class DashItemContainer extends St.Widget {
_init() {
super._init({ style_class: 'dash-item-container',
pivot_point: new Graphene.Point({ x: .5, y: .5 }),
pivot_point: new Clutter.Point({ x: .5, y: .5 }),
scale_x: 0,
scale_y: 0,
opacity: 0,
@ -125,7 +125,7 @@ class DashItemContainer extends St.Widget {
this.label.ease({
opacity: 255,
duration: DASH_ITEM_LABEL_SHOW_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -139,7 +139,7 @@ class DashItemContainer extends St.Widget {
opacity: 0,
duration: DASH_ITEM_LABEL_HIDE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.label.hide(),
onComplete: () => this.label.hide()
});
}
@ -163,7 +163,7 @@ class DashItemContainer extends St.Widget {
scale_y: 1,
opacity: 255,
duration: time,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -182,7 +182,7 @@ class DashItemContainer extends St.Widget {
opacity: 0,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.destroy(),
onComplete: () => this.destroy()
});
}
});
@ -284,12 +284,9 @@ var DashActor = GObject.registerClass(
class DashActor extends St.Widget {
_init() {
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
super._init({
name: 'dash',
layout_manager: layout,
clip_to_allocation: true,
y_align: Clutter.ActorAlign.CENTER,
});
super._init({ name: 'dash',
layout_manager: layout,
clip_to_allocation: true });
}
vfunc_allocate(box, flags) {
@ -333,10 +330,8 @@ class DashActor extends St.Widget {
const baseIconSizes = [16, 22, 24, 32, 48, 64];
var Dash = GObject.registerClass({
Signals: { 'icon-size-changed': {} },
}, class Dash extends St.Bin {
_init() {
var Dash = class Dash {
constructor() {
this._maxHeight = -1;
this.iconSize = 64;
this._shownInitially = false;
@ -364,11 +359,11 @@ var Dash = GObject.registerClass({
this._container.add_actor(this._showAppsIcon);
super._init({ child: this._container });
this.connect('notify::height', () => {
if (this._maxHeight != this.height)
this.actor = new St.Bin({ child: this._container });
this.actor.connect('notify::height', () => {
if (this._maxHeight != this.actor.height)
this._queueRedisplay();
this._maxHeight = this.height;
this._maxHeight = this.actor.height;
});
this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
@ -391,13 +386,13 @@ var Dash = GObject.registerClass({
// Translators: this is the name of the dock/favorites area on
// the left of the overview
Main.ctrlAltTabManager.addGroup(this, _("Dash"), 'user-bookmarks-symbolic');
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
}
_onDragBegin() {
this._dragCancelled = false;
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
dragMotion: this._onDragMotion.bind(this)
};
DND.addDragMonitor(this._dragMonitor);
@ -481,16 +476,16 @@ var Dash = GObject.registerClass({
let appIcon = new DashIcon(app);
appIcon.connect('menu-state-changed',
(o, opened) => {
(appIcon, opened) => {
this._itemMenuStateChanged(item, opened);
});
let item = new DashItemContainer();
item.setChild(appIcon);
item.setChild(appIcon.actor);
// Override default AppIcon label_actor, now the
// accessible_name is set at DashItemContainer.setLabelText
appIcon.label_actor = null;
appIcon.actor.label_actor = null;
item.setLabelText(app.get_name());
appIcon.icon.setIconSize(this.iconSize);
@ -628,8 +623,8 @@ var Dash = GObject.registerClass({
icon.icon.ease({
width: targetWidth,
height: targetHeight,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
time: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@ -728,10 +723,9 @@ var Dash = GObject.registerClass({
}
}
for (let i = 0; i < addedItems.length; i++) {
for (let i = 0; i < addedItems.length; i++)
this._box.insert_child_at_index(addedItems[i].item,
addedItems[i].pos);
}
for (let i = 0; i < removedActors.length; i++) {
let item = removedActors[i];
@ -755,8 +749,9 @@ var Dash = GObject.registerClass({
if (!this._shownInitially)
this._shownInitially = true;
for (let i = 0; i < addedItems.length; i++)
for (let i = 0; i < addedItems.length; i++) {
addedItems[i].item.show(animate);
}
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
// Without it, StBoxLayout may use a stale size cache
@ -836,8 +831,8 @@ var Dash = GObject.registerClass({
}
this._dragPlaceholder = new DragPlaceholderItem();
this._dragPlaceholder.child.set_width(this.iconSize);
this._dragPlaceholder.child.set_height(this.iconSize / 2);
this._dragPlaceholder.child.set_width (this.iconSize);
this._dragPlaceholder.child.set_height (this.iconSize / 2);
this._box.insert_child_at_index(this._dragPlaceholder,
this._dragPlaceholderPos);
this._dragPlaceholder.show(fadeIn);
@ -851,7 +846,7 @@ var Dash = GObject.registerClass({
if (!this._dragPlaceholder)
return DND.DragMotionResult.NO_DROP;
let srcIsFavorite = favPos != -1;
let srcIsFavorite = (favPos != -1);
if (srcIsFavorite)
return DND.DragMotionResult.MOVE_DROP;
@ -864,8 +859,9 @@ var Dash = GObject.registerClass({
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps
if (app == null || app.is_window_backed())
if (app == null || app.is_window_backed()) {
return false;
}
if (!global.settings.is_writable('favorite-apps'))
return false;
@ -874,7 +870,7 @@ var Dash = GObject.registerClass({
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
let srcIsFavorite = id in favorites;
let srcIsFavorite = (id in favorites);
let favPos = 0;
let children = this._box.get_children();
@ -906,4 +902,5 @@ var Dash = GObject.registerClass({
return true;
}
});
};
Signals.addSignalMethods(Dash.prototype);

View File

@ -2,7 +2,7 @@
/* exported DateMenuButton */
const { Clutter, Gio, GLib, GnomeDesktop,
GObject, GWeather, Pango, Shell, St } = imports.gi;
GObject, GWeather, Shell, St } = imports.gi;
const Util = imports.misc.util;
const Main = imports.ui.main;
@ -25,25 +25,24 @@ function _isToday(date) {
now.getDate() == date.getDate();
}
function _gDateTimeToDate(datetime) {
return new Date(datetime.to_unix() * 1000 + datetime.get_microsecond() / 1000);
}
var TodayButton = GObject.registerClass(
class TodayButton extends St.Button {
_init(calendar) {
var TodayButton = class TodayButton {
constructor(calendar) {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
super._init({
this.actor = new St.Button({
style_class: 'datemenu-today-button',
x_align: St.Align.START,
x_expand: true,
can_focus: true,
reactive: false,
});
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
});
let hbox = new St.BoxLayout({ vertical: true });
this.add_actor(hbox);
this.actor.add_actor(hbox);
this._dayLabel = new St.Label({ style_class: 'day-label',
x_align: Clutter.ActorAlign.START });
@ -53,17 +52,13 @@ class TodayButton extends St.Button {
hbox.add_actor(this._dateLabel);
this._calendar = calendar;
this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
this._calendar.connect('selected-date-changed', (calendar, date) => {
// Make the button reactive only if the selected date is not the
// current date.
this.reactive = !_isToday(_gDateTimeToDate(datetime));
this.actor.reactive = !_isToday(date);
});
}
vfunc_clicked() {
this._calendar.setDate(new Date(), false);
}
setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A'));
@ -72,38 +67,42 @@ class TodayButton extends St.Button {
* "Tue 9:29 AM"). The string itself should become a full date, e.g.,
* "February 17 2015".
*/
let dateFormat = Shell.util_translate_time_string(N_("%B %-d %Y"));
let dateFormat = Shell.util_translate_time_string (N_("%B %-d %Y"));
this._dateLabel.set_text(date.toLocaleFormat(dateFormat));
/* Translators: This is the accessible name of the date button shown
* below the time in the shell; it should combine the weekday and the
* date, e.g. "Tuesday February 17 2015".
*/
dateFormat = Shell.util_translate_time_string(N_("%A %B %e %Y"));
this.accessible_name = date.toLocaleFormat(dateFormat);
dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
this.actor.accessible_name = date.toLocaleFormat(dateFormat);
}
});
};
var WorldClocksSection = GObject.registerClass(
class WorldClocksSection extends St.Button {
_init() {
super._init({
style_class: 'world-clocks-button',
can_focus: true,
x_expand: true,
});
var WorldClocksSection = class WorldClocksSection {
constructor() {
this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0;
this._locations = [];
this.actor = new St.Button({ style_class: 'world-clocks-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
});
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._grid = new St.Widget({ style_class: 'world-clocks-grid',
x_expand: true,
layout_manager: layout });
layout.hookup_style(this._grid);
this.child = this._grid;
this.actor.child = this._grid;
this._clocksApp = null;
this._clocksProxy = new ClocksProxy(
@ -115,7 +114,7 @@ class WorldClocksSection extends St.Button {
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES);
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.world-clocks',
schema_id: 'org.gnome.shell.world-clocks'
});
this._settings.connect('changed', this._clocksChanged.bind(this));
this._clocksChanged();
@ -126,17 +125,9 @@ class WorldClocksSection extends St.Button {
this._sync();
}
vfunc_clicked() {
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
}
_sync() {
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
this.visible = this._clocksApp != null;
this.actor.visible = this._clocksApp != null;
}
_clocksChanged() {
@ -157,14 +148,14 @@ class WorldClocksSection extends St.Button {
});
let layout = this._grid.layout_manager;
let title = this._locations.length == 0
let title = (this._locations.length == 0)
? _("Add world clocks…")
: _("World Clocks");
let header = new St.Label({ style_class: 'world-clocks-header',
x_align: Clutter.ActorAlign.START,
text: title });
layout.attach(header, 0, 0, 2, 1);
this.label_actor = header;
this.actor.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
@ -182,8 +173,8 @@ class WorldClocksSection extends St.Button {
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let fmt = Math.trunc(offset) == offset ? '%s%.0f' : '%s%.1f';
let prefix = offset >= 0 ? '+' : '-';
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
let prefix = (offset >= 0) ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
text: fmt.format(prefix, Math.abs(offset)),
x_align: Clutter.ActorAlign.END,
@ -203,10 +194,9 @@ class WorldClocksSection extends St.Button {
}
if (this._grid.get_n_children() > 1) {
if (!this._clockNotifyId) {
if (!this._clockNotifyId)
this._clockNotifyId =
this._clock.connect('notify::clock', this._updateLabels.bind(this));
}
this._updateLabels();
} else {
if (this._clockNotifyId)
@ -246,49 +236,45 @@ class WorldClocksSection extends St.Button {
this._settings.set_value('locations',
new GLib.Variant('av', this._clocksProxy.Locations));
}
});
var WeatherSection = GObject.registerClass(
class WeatherSection extends St.Button {
_init() {
super._init({
style_class: 'weather-button',
can_focus: true,
x_expand: true,
});
};
var WeatherSection = class WeatherSection {
constructor() {
this._weatherClient = new Weather.WeatherClient();
let box = new St.BoxLayout({
style_class: 'weather-box',
vertical: true,
x_expand: true,
this.actor = new St.Button({ style_class: 'weather-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
this._weatherClient.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
});
this.actor.connect('notify::mapped', () => {
if (this.actor.mapped)
this._weatherClient.update();
});
this.child = box;
let box = new St.BoxLayout({ style_class: 'weather-box',
vertical: true });
let titleBox = new St.BoxLayout({ style_class: 'weather-header-box' });
titleBox.add_child(new St.Label({
style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_align: Clutter.ActorAlign.END,
text: _('Weather'),
}));
this.actor.child = box;
let titleBox = new St.BoxLayout();
titleBox.add_child(new St.Label({ style_class: 'weather-header',
x_align: Clutter.ActorAlign.START,
x_expand: true,
text: _("Weather") }));
box.add_child(titleBox);
this._titleLocation = new St.Label({
style_class: 'weather-header location',
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
});
this._titleLocation = new St.Label({ style_class: 'weather-header location',
x_align: Clutter.ActorAlign.END });
titleBox.add_child(this._titleLocation);
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._forecastGrid = new St.Widget({
style_class: 'weather-grid',
layout_manager: layout,
});
this._forecastGrid = new St.Widget({ style_class: 'weather-grid',
layout_manager: layout });
layout.hookup_style(this._forecastGrid);
box.add_child(this._forecastGrid);
@ -296,40 +282,26 @@ class WeatherSection extends St.Button {
this._sync();
}
vfunc_map() {
this._weatherClient.update();
super.vfunc_map();
}
vfunc_clicked() {
this._weatherClient.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
}
_getInfos() {
let forecasts = this._weatherClient.info.get_forecast_list();
let info = this._weatherClient.info;
let forecasts = info.get_forecast_list();
let now = GLib.DateTime.new_now_local();
let current = GLib.DateTime.new_from_unix_local(0);
let infos = [];
let current = info;
let infos = [info];
for (let i = 0; i < forecasts.length; i++) {
const [valid, timestamp] = forecasts[i].get_value_update();
if (!valid || timestamp === 0)
continue; // 0 means 'never updated'
let [ok_, timestamp] = forecasts[i].get_value_update();
let datetime = new Date(timestamp * 1000);
if (!_isToday(datetime))
continue; // Ignore forecasts from other days
const datetime = GLib.DateTime.new_from_unix_local(timestamp);
if (now.difference(datetime) > 0)
continue; // Ignore earlier forecasts
if (datetime.difference(current) < GLib.TIME_SPAN_HOUR)
[ok_, timestamp] = current.get_value_update();
let currenttime = new Date(timestamp * 1000);
if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h
if (infos.push(forecasts[i]) == MAX_FORECASTS)
current = forecasts[i];
if (infos.push(current) == MAX_FORECASTS)
break; // Use a maximum of five forecasts
current = datetime;
}
return infos;
}
@ -343,31 +315,21 @@ class WeatherSection extends St.Button {
let col = 0;
infos.forEach(fc => {
const [valid_, timestamp] = fc.get_value_update();
let [ok_, timestamp] = fc.get_value_update();
let timeStr = Util.formatTime(new Date(timestamp * 1000), {
timeOnly: true,
ampm: false,
timeOnly: true
});
let icon = new St.Icon({
style_class: 'weather-forecast-icon',
icon_name: fc.get_symbolic_icon_name(),
x_align: Clutter.ActorAlign.CENTER,
x_expand: true,
});
let temp = new St.Label({
style_class: 'weather-forecast-temp',
text: fc.get_temp_summary(),
x_align: Clutter.ActorAlign.CENTER,
});
let time = new St.Label({
style_class: 'weather-forecast-time',
text: timeStr,
x_align: Clutter.ActorAlign.CENTER,
});
temp.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
time.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let icon = new St.Icon({ style_class: 'weather-forecast-icon',
icon_name: fc.get_symbolic_icon_name(),
x_align: Clutter.ActorAlign.CENTER,
x_expand: true });
let temp = new St.Label({ style_class: 'weather-forecast-temp',
text: fc.get_temp_summary(),
x_align: Clutter.ActorAlign.CENTER });
let time = new St.Label({ style_class: 'weather-forecast-time',
text: timeStr,
x_align: Clutter.ActorAlign.CENTER });
layout.attach(icon, col, 0, 1, 1);
layout.attach(temp, col, 1, 1, 1);
@ -391,12 +353,7 @@ class WeatherSection extends St.Button {
}
let info = this._weatherClient.info;
let loc = info.get_location();
if (loc.get_level() !== GWeather.LocationLevel.CITY && loc.has_coords()) {
let world = GWeather.Location.get_world();
loc = world.find_nearest_city(...loc.get_coords());
}
this._titleLocation.text = loc.get_name();
this._titleLocation.text = info.get_location().get_name();
if (this._weatherClient.loading) {
this._setStatusLabel(_("Loading…"));
@ -415,27 +372,23 @@ class WeatherSection extends St.Button {
}
_sync() {
this.visible = this._weatherClient.available;
this.actor.visible = this._weatherClient.available;
if (!this.visible)
if (!this.actor.visible)
return;
this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts();
}
});
};
var MessagesIndicator = GObject.registerClass(
class MessagesIndicator extends St.Icon {
_init() {
super._init({
icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
var MessagesIndicator = class MessagesIndicator {
constructor() {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false, y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this._sources = [];
@ -448,7 +401,7 @@ class MessagesIndicator extends St.Icon {
}
_onSourceAdded(tray, source) {
source.connect('notify::count', this._updateCount.bind(this));
source.connect('count-updated', this._updateCount.bind(this));
this._sources.push(source);
this._updateCount();
}
@ -463,9 +416,9 @@ class MessagesIndicator extends St.Icon {
this._sources.forEach(source => (count += source.unseenCount));
count -= Main.messageTray.queueCount;
this.visible = count > 0;
this.actor.visible = (count > 0);
}
});
};
var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
@ -558,13 +511,13 @@ class DateMenuButton extends PanelMenu.Button {
this._indicator = new MessagesIndicator();
let box = new St.BoxLayout();
box.add_actor(new IndicatorPad(this._indicator));
box.add_actor(new IndicatorPad(this._indicator.actor));
box.add_actor(this._clockDisplay);
box.add_actor(this._indicator);
box.add_actor(this._indicator.actor);
this.label_actor = this._clockDisplay;
this.add_actor(box);
this.add_style_class_name('clock-display');
this.add_style_class_name ('clock-display');
let layout = new FreezableBinLayout();
let bin = new St.Widget({ layout_manager: layout });
@ -576,11 +529,11 @@ class DateMenuButton extends PanelMenu.Button {
bin.add_actor(hbox);
this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
let date = _gDateTimeToDate(datetime);
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
});
this._calendar.connect('selected-date-changed',
(calendar, date) => {
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
});
this.menu.connect('open-state-changed', (menu, isOpen) => {
// Whenever the menu is opened, select today
@ -594,36 +547,35 @@ class DateMenuButton extends PanelMenu.Button {
// Fill up the first column
this._messageList = new Calendar.CalendarMessageList();
hbox.add_child(this._messageList);
hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
// Fill up the second column
let boxLayout = new CalendarColumnLayout(this._calendar);
let boxLayout = new CalendarColumnLayout(this._calendar.actor);
vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
layout_manager: boxLayout });
boxLayout.hookup_style(vbox);
hbox.add(vbox);
this._date = new TodayButton(this._calendar);
vbox.add_actor(this._date);
vbox.add_actor(this._date.actor);
vbox.add_actor(this._calendar);
vbox.add_actor(this._calendar.actor);
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true,
x_expand: true, x_fill: true,
overlay_scrollbars: true });
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
vbox.add_actor(this._displaysSection);
let displaysBox = new St.BoxLayout({ vertical: true,
x_expand: true,
style_class: 'datemenu-displays-box' });
this._displaysSection.add_actor(displaysBox);
this._clocksItem = new WorldClocksSection();
displaysBox.add_child(this._clocksItem);
displaysBox.add(this._clocksItem.actor, { x_fill: true });
this._weatherItem = new WeatherSection();
displaysBox.add_child(this._weatherItem);
displaysBox.add(this._weatherItem.actor, { x_fill: true });
// Done with hbox for calendar and event list
@ -661,11 +613,11 @@ class DateMenuButton extends PanelMenu.Button {
_sessionUpdated() {
let eventSource;
let showEvents = Main.sessionMode.showCalendarEvents;
if (showEvents)
if (showEvents) {
eventSource = this._getEventSource();
else
} else {
eventSource = new Calendar.EmptyEventSource();
}
this._setEventSource(eventSource);
// Displays are not actually expected to launch Settings when activated

View File

@ -36,15 +36,19 @@ class Dialog extends St.Widget {
this._dialog.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
this._dialog.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this.contentLayout = new St.BoxLayout({
vertical: true,
style_class: 'modal-dialog-content-box',
y_expand: true,
});
this._dialog.add_child(this.contentLayout);
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,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this.buttonLayout = new St.Widget({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
this._dialog.add_child(this.buttonLayout);
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE,
y_align: St.Align.START });
}
_onDestroy() {
@ -96,7 +100,7 @@ class Dialog extends St.Widget {
}
addContent(actor) {
this.contentLayout.add(actor, { expand: true });
this.contentLayout.add (actor, { expand: true });
}
addButton(buttonInfo) {
@ -117,7 +121,7 @@ class Dialog extends St.Widget {
can_focus: true,
x_expand: true,
y_expand: true,
label });
label: label });
button.connect('clicked', action);
buttonInfo['button'] = button;
@ -159,8 +163,8 @@ var MessageDialogContent = GObject.registerClass({
'body': GObject.ParamSpec.string('body', 'body', 'body',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT,
null),
},
null)
}
}, class MessageDialogContent extends St.BoxLayout {
_init(params) {
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
@ -211,7 +215,7 @@ var MessageDialogContent = GObject.registerClass({
set icon(icon) {
this._icon.set({
gicon: icon,
visible: icon != null,
visible: icon != null
});
this.notify('icon');
}
@ -231,7 +235,7 @@ var MessageDialogContent = GObject.registerClass({
_setLabel(label, prop, value) {
label.set({
text: value || '',
visible: value != null,
visible: value != null
});
this.notify(prop);
}

View File

@ -18,7 +18,7 @@ var DragMotionResult = {
NO_DROP: 0,
COPY_DROP: 1,
MOVE_DROP: 2,
CONTINUE: 3,
CONTINUE: 3
};
var DragState = {
@ -30,13 +30,13 @@ var DragState = {
var DRAG_CURSOR_MAP = {
0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
1: Meta.Cursor.DND_COPY,
2: Meta.Cursor.DND_MOVE,
2: Meta.Cursor.DND_MOVE
};
var DragDropResult = {
FAILURE: 0,
SUCCESS: 1,
CONTINUE: 2,
CONTINUE: 2
};
var dragMonitors = [];
@ -61,12 +61,11 @@ function addDragMonitor(monitor) {
}
function removeDragMonitor(monitor) {
for (let i = 0; i < dragMonitors.length; i++) {
for (let i = 0; i < dragMonitors.length; i++)
if (dragMonitors[i] == monitor) {
dragMonitors.splice(i, 1);
return;
}
}
}
var _Draggable = class _Draggable {
@ -151,12 +150,12 @@ var _Draggable = class _Draggable {
if (touchSequence)
pointer.sequence_grab(touchSequence, actor);
else if (pointer)
pointer.grab(actor);
pointer.grab (actor);
this._grabbedDevice = pointer;
this._touchSequence = touchSequence;
this._capturedEventId = global.stage.connect('captured-event', (o, event) => {
this._capturedEventId = global.stage.connect('captured-event', (actor, event) => {
let device = event.get_device();
if (device != this._grabbedDevice &&
device.get_device_type() != Clutter.InputDeviceType.KEYBOARD_DEVICE)
@ -172,7 +171,7 @@ var _Draggable = class _Draggable {
}
if (this._touchSequence)
this._grabbedDevice.sequence_ungrab(this._touchSequence);
this._grabbedDevice.sequence_ungrab (this._touchSequence);
else
this._grabbedDevice.ungrab();
@ -213,9 +212,9 @@ var _Draggable = class _Draggable {
_eventIsRelease(event) {
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
let buttonMask = Clutter.ModifierType.BUTTON1_MASK |
let buttonMask = (Clutter.ModifierType.BUTTON1_MASK |
Clutter.ModifierType.BUTTON2_MASK |
Clutter.ModifierType.BUTTON3_MASK;
Clutter.ModifierType.BUTTON3_MASK);
/* We only obey the last button release from the device,
* other buttons may get pressed/released during the DnD op.
*/
@ -259,16 +258,16 @@ var _Draggable = class _Draggable {
} else if (event.type() == Clutter.EventType.MOTION ||
(event.type() == Clutter.EventType.TOUCH_UPDATE &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
if (this._dragActor && this._dragState == DragState.DRAGGING)
if (this._dragActor && this._dragState == DragState.DRAGGING) {
return this._updateDragPosition(event);
else if (this._dragActor == null && this._dragState != DragState.CANCELLED)
} else if (this._dragActor == null && this._dragState != DragState.CANCELLED) {
return this._maybeStartDrag(event);
}
// We intercept KEY_PRESS event so that we can process Esc key press to cancel
// dragging and ignore all other key presses.
} else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragState == DragState.DRAGGING) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Escape) {
if (symbol == Clutter.Escape) {
this._cancelDrag(event.get_time());
return Clutter.EVENT_STOP;
}
@ -292,11 +291,9 @@ var _Draggable = class _Draggable {
/**
* startDrag:
* @param {number} stageX: X coordinate of event
* @param {number} stageY: Y coordinate of event
* @param {number} time: Event timestamp
* @param {Clutter.EventSequence=} sequence: Event sequence
* @param {Clutter.InputDevice=} device: device that originated the event
* @stageX: X coordinate of event
* @stageY: Y coordinate of event
* @time: Event timestamp
*
* Directly initiate a drag and drop operation from the given actor.
* This function is useful to call if you've specified manualMode
@ -341,7 +338,7 @@ var _Draggable = class _Draggable {
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor();
Main.uiGroup.add_child(this._dragActor);
Main.uiGroup.set_child_above_sibling(this._dragActor, null);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
// Drag actor does not always have to be the same as actor. For example drag actor
@ -391,7 +388,7 @@ var _Draggable = class _Draggable {
this._dragOrigParent.remove_actor(this._dragActor);
Main.uiGroup.add_child(this._dragActor);
Main.uiGroup.set_child_above_sibling(this._dragActor, null);
this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true);
}
@ -430,7 +427,7 @@ var _Draggable = class _Draggable {
scale_x: scale * origScale,
scale_y: scale * origScale,
duration: SCALE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._dragActor.get_transition('scale-x').connect('new-frame', () => {
@ -475,7 +472,7 @@ var _Draggable = class _Draggable {
y: this._dragY,
dragActor: this._dragActor,
source: this.actor._delegate,
targetActor: target,
targetActor: target
};
let targetActorDestroyHandlerId;
@ -554,11 +551,11 @@ var _Draggable = class _Draggable {
let dropEvent = {
dropActor: this._dragActor,
targetActor: target,
clutterEvent: event,
clutterEvent: event
};
for (let i = 0; i < dragMonitors.length; i++) {
let dropFunc = dragMonitors[i].dragDrop;
if (dropFunc) {
if (dropFunc)
switch (dropFunc(dropEvent)) {
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
@ -566,7 +563,6 @@ var _Draggable = class _Draggable {
case DragDropResult.CONTINUE:
continue;
}
}
}
// At this point it is too late to cancel a drag by destroying
@ -577,15 +573,11 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
let accepted = false;
try {
accepted = target._delegate.acceptDrop(this.actor._delegate,
this._dragActor, targX, targY, event.get_time());
} catch (e) {
// On error, skip this target
logError(e, "Skipping drag target");
}
if (accepted) {
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time())) {
// If it accepted the drop without taking the actor,
// handle it ourselves.
if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {
@ -646,7 +638,7 @@ var _Draggable = class _Draggable {
_cancelDrag(eventTime) {
this.emit('drag-cancelled', eventTime);
let wasCancelled = this._dragState == DragState.CANCELLED;
let wasCancelled = (this._dragState == DragState.CANCELLED);
this._dragState = DragState.CANCELLED;
if (this._actorDestroyed || wasCancelled) {
@ -667,7 +659,7 @@ var _Draggable = class _Draggable {
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
duration: SNAP_BACK_ANIMATION_TIME,
duration: SNAP_BACK_ANIMATION_TIME
});
}
@ -681,7 +673,7 @@ var _Draggable = class _Draggable {
this._dragActor.opacity = 0;
this._animateDragEnd(eventTime, {
duration: REVERT_ANIMATION_TIME,
duration: REVERT_ANIMATION_TIME
});
}
@ -694,7 +686,7 @@ var _Draggable = class _Draggable {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._onAnimationComplete(this._dragActor, eventTime);
},
}
}));
}
@ -748,9 +740,8 @@ Signals.addSignalMethods(_Draggable.prototype);
/**
* makeDraggable:
* @param {Clutter.Actor} actor: Source actor
* @param {Object=} params: Additional parameters
* @returns {Object} a new Draggable
* @actor: Source actor
* @params: (optional) Additional parameters
*
* Create an object which controls drag and drop for the given actor.
*

View File

@ -37,17 +37,17 @@ var EdgeDragAction = GObject.registerClass({
let [x, y] = this.get_press_coords(0);
let monitorRect = this._getMonitorRect(x, y);
return (this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD);
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
}
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);
let offsetY = Math.abs(y - startY);
let offsetX = Math.abs (x - startX);
let offsetY = Math.abs (y - startY);
if (offsetX < EDGE_THRESHOLD && offsetY < EDGE_THRESHOLD)
return true;

View File

@ -128,7 +128,7 @@ const DialogType = {
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3,
UPGRADE_RESTART: 4,
UPGRADE_RESTART: 4
};
const DialogContent = {
@ -136,7 +136,7 @@ const DialogContent = {
1 /* DialogType.SHUTDOWN */: shutdownDialogContent,
2 /* DialogType.RESTART */: restartDialogContent,
3 /* DialogType.UPDATE_RESTART */: restartUpdateDialogContent,
4 /* DialogType.UPGRADE_RESTART */: restartUpgradeDialogContent,
4 /* DialogType.UPGRADE_RESTART */: restartUpgradeDialogContent
};
var MAX_USERS_IN_SESSION_DIALOG = 5;
@ -207,10 +207,10 @@ function _setCheckBoxLabel(checkBox, text) {
if (text) {
label.set_text(text);
checkBox.show();
checkBox.actor.show();
} else {
label.set_text('');
checkBox.hide();
checkBox.actor.hide();
}
}
@ -218,7 +218,7 @@ function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
new EndSessionDialog();
(new EndSessionDialog());
}
var EndSessionDialog = GObject.registerClass(
@ -263,39 +263,42 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._userLoadedId = this._user.connect('notify::is_loaded', this._sync.bind(this));
this._userChangedId = this._user.connect('changed', this._sync.bind(this));
let mainContentLayout = new St.BoxLayout({
vertical: false,
x_expand: true,
y_expand: false,
});
this.contentLayout.add_child(mainContentLayout);
let mainContentLayout = new St.BoxLayout({ vertical: false });
this.contentLayout.add(mainContentLayout,
{ x_fill: true,
y_fill: false });
this._iconBin = new St.Bin({
x_expand: true,
x_align: Clutter.ActorAlign.END,
});
mainContentLayout.add_child(this._iconBin);
this._iconBin = new St.Bin();
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
let messageLayout = new St.BoxLayout({ vertical: true,
style_class: 'end-session-dialog-layout' });
mainContentLayout.add_child(messageLayout);
mainContentLayout.add(messageLayout,
{ y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' });
messageLayout.add_child(this._subjectLabel);
messageLayout.add(this._subjectLabel,
{ x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._descriptionLabel = new St.Label({
style_class: 'end-session-dialog-description',
y_expand: true,
});
this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' });
this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add_child(this._descriptionLabel);
messageLayout.add(this._descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
this._checkBox = new CheckBox.CheckBox();
this._checkBox.connect('clicked', this._sync.bind(this));
messageLayout.add(this._checkBox);
this._checkBox.actor.connect('clicked', this._sync.bind(this));
messageLayout.add(this._checkBox.actor);
this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning',
text: _("Running on battery power: please plug in before installing updates.") });
@ -303,13 +306,11 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._batteryWarning.clutter_text.line_wrap = true;
messageLayout.add(this._batteryWarning);
this._scrollView = new St.ScrollView({
style_class: 'end-session-dialog-list',
x_expand: true,
y_expand: true,
});
this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
this.contentLayout.add_child(this._scrollView);
this.contentLayout.add(this._scrollView,
{ x_fill: true,
y_fill: true });
this._scrollView.hide();
this._inhibitorSection = new St.BoxLayout({ vertical: true,
@ -366,7 +367,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}
_sync() {
let open = this.state == ModalDialog.State.OPENING || this.state == ModalDialog.State.OPENED;
let open = (this.state == ModalDialog.State.OPENING || this.state == ModalDialog.State.OPENED);
if (!open)
return;
@ -375,12 +376,12 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let subject = dialogContent.subject;
// Use different title when we are installing updates
if (dialogContent.subjectWithUpdates && this._checkBox.checked)
if (dialogContent.subjectWithUpdates && this._checkBox.actor.checked)
subject = dialogContent.subjectWithUpdates;
if (dialogContent.showBatteryWarning) {
// Warn when running on battery power
if (this._powerProxy.OnBattery && this._checkBox.checked)
if (this._powerProxy.OnBattery && this._checkBox.actor.checked)
this._batteryWarning.opacity = 255;
else
this._batteryWarning.opacity = 0;
@ -428,7 +429,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let avatarWidget = new UserWidget.Avatar(this._user,
{ iconSize: _DIALOG_ICON_SIZE,
styleClass: dialogContent.iconStyleClass });
this._iconBin.child = avatarWidget;
this._iconBin.child = avatarWidget.actor;
avatarWidget.update();
}
@ -443,7 +444,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let dialogContent = DialogContent[this._type];
let buttons = [{ action: this.cancel.bind(this),
label: _("Cancel"),
key: Clutter.KEY_Escape }];
key: Clutter.Escape }];
for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
let signal = dialogContent.confirmButtons[i].signal;
@ -456,7 +457,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._confirm(signal);
});
},
label,
label: label,
});
}
@ -484,13 +485,13 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
};
// Offline update not available; just emit the signal
if (!this._checkBox.visible) {
if (!this._checkBox.actor.visible) {
callback();
return;
}
// Trigger the offline update as requested
if (this._checkBox.checked) {
if (this._checkBox.actor.checked) {
switch (signal) {
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
@ -566,7 +567,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => {
let currentTime = GLib.get_monotonic_time();
let secondsElapsed = (currentTime - startTime) / 1000000;
let secondsElapsed = ((currentTime - startTime) / 1000000);
this._secondsLeft = this._totalSecondsToStayOpen - secondsElapsed;
if (this._secondsLeft > 0) {
@ -655,7 +656,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item',
can_focus: true });
actor.add(avatar);
actor.add(avatar.actor);
let nameLabel = new St.Label({ text: userLabelText,
style_class: 'end-session-dialog-session-list-item-name',
@ -681,12 +682,11 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
continue;
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) {
if (!sessionId)
this._loginManager.getCurrentSessionProxy(currentSessionProxy => {
sessionId = currentSessionProxy.Id;
log(`endSessionDialog: No XDG_SESSION_ID, fetched from logind: ${sessionId}`);
});
}
if (proxy.Id == sessionId)
continue;
@ -754,14 +754,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.visible = dialogContent.checkBoxText && updatePrepared && updatesAllowed;
this._checkBox.checked = updatePrepared && updateTriggered;
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateTriggered);
// We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have
// enough permissions to cancel them.
this._batteryWarning.visible = dialogContent.showBatteryWarning &&
(this._checkBox.visible || updatePrepared && updateTriggered && !updatesAllowed);
this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
(this._checkBox.actor.visible || updatePrepared && updateTriggered && !updatesAllowed));
this._updateButtons();

View File

@ -10,7 +10,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have
@ -23,7 +23,7 @@ const Gettext = imports.gettext;
// of interfaces in Javascript
function _patchContainerClass(containerClass) {
// This one is a straightforward mapping of the C method
containerClass.prototype.child_set = function (actor, props) {
containerClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor);
for (let prop in props)
meta[prop] = props[prop];
@ -32,7 +32,7 @@ function _patchContainerClass(containerClass) {
// clutter_container_add() actually is a an add-many-actors
// method. We conveniently, but somewhat dubiously, take the
// this opportunity to make it do something more useful.
containerClass.prototype.add = function (actor, props) {
containerClass.prototype.add = function(actor, props) {
this.add_actor(actor);
if (props)
this.child_set(actor, props);
@ -40,8 +40,8 @@ function _patchContainerClass(containerClass) {
}
function _patchLayoutClass(layoutClass, styleProps) {
if (styleProps) {
layoutClass.prototype.hookup_style = function (container) {
if (styleProps)
layoutClass.prototype.hookup_style = function(container) {
container.connect('style-changed', () => {
let node = container.get_theme_node();
for (let prop in styleProps) {
@ -51,7 +51,11 @@ function _patchLayoutClass(layoutClass, styleProps) {
}
});
};
}
layoutClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor.get_parent(), actor);
for (let prop in props)
meta[prop] = props[prop];
};
}
function _makeEaseCallback(params, cleanup) {
@ -101,20 +105,22 @@ function _easeActor(actor, params) {
actor.set_easing_delay(params.delay);
delete params.delay;
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let repeat_count = 0;
if (params.repeat_count != undefined)
repeat_count = params.repeat_count;
delete params.repeat_count;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
let auto_reverse = false;
if (params.auto_reverse != undefined)
auto_reverse = params.auto_reverse;
delete params.auto_reverse;
if (params.mode != undefined)
actor.set_easing_mode(params.mode);
delete params.mode;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
@ -128,13 +134,10 @@ function _easeActor(actor, params) {
let transition = animatedProps.map(p => actor.get_transition(p))
.find(t => t !== null);
if (transition && transition.delay)
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
else
Meta.disable_unredirect_for_display(global.display);
if (transition) {
transition.set({ repeatCount, autoReverse });
transition.repeat_count = repeat_count;
transition.auto_reverse = auto_reverse;
transition.connect('stopped', (t, finished) => callback(finished));
} else {
callback(true);
@ -151,21 +154,23 @@ function _easeActorProperty(actor, propName, target, params) {
params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0);
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let repeat_count = 0;
if (params.repeat_count != undefined)
repeat_count = params.repeat_count;
delete params.repeat_count;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
let auto_reverse = false;
if (params.auto_reverse != undefined)
auto_reverse = params.auto_reverse;
delete params.auto_reverse;
// Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
@ -176,7 +181,6 @@ function _easeActorProperty(actor, propName, target, params) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
Meta.disable_unredirect_for_display(global.display);
callback(true);
return;
@ -187,18 +191,13 @@ function _easeActorProperty(actor, propName, target, params) {
property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true,
repeat_count: repeatCount,
auto_reverse: autoReverse,
repeat_count: repeat_count,
auto_reverse: auto_reverse,
}, params));
actor.add_transition(propName, transition);
transition.set_to(target);
if (transition.delay)
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
else
Meta.disable_unredirect_for_display(global.display);
transition.connect('stopped', (t, finished) => callback(finished));
}
@ -229,37 +228,37 @@ function init() {
window.ngettext = Gettext.ngettext;
window.N_ = s => s;
GObject.gtypeNameBasedOnJSPath = true;
// Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout);
_patchLayoutClass(Clutter.TableLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
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) {
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) {
Clutter.Actor.prototype.set_easing_delay = function(msecs) {
origSetEasingDelay.call(this, adjustAnimationTime(msecs));
};
Clutter.Actor.prototype.ease = function (props, easingParams) {
Clutter.Actor.prototype.ease = function(props, easingParams) {
_easeActor(this, props, easingParams);
};
Clutter.Actor.prototype.ease_property = function (propName, target, params) {
Clutter.Actor.prototype.ease_property = function(propName, target, params) {
_easeActorProperty(this, propName, target, params);
};
St.Adjustment.prototype.ease = function (target, params) {
St.Adjustment.prototype.ease = function(target, params) {
// we're not an actor of course, but we implement the same
// transition API as Clutter.Actor, so this works anyway
_easeActorProperty(this, 'value', target, params);
};
Clutter.Actor.prototype.toString = function () {
Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this);
};
// Deprecation warning for former JS classes turned into an actor subclass
@ -269,17 +268,17 @@ function init() {
let { stack } = new Error();
log(`Usage of object.actor is deprecated for ${klass}\n${stack}`);
return this;
},
}
});
St.set_slow_down_factor = function (factor) {
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 () {
Object.prototype.toString = function() {
let base = origToString.call(this);
try {
if ('actor' in this && this.actor instanceof Clutter.Actor)
@ -292,9 +291,8 @@ function init() {
};
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
Date.prototype.toLocaleFormat = function (format) {
let dt = GLib.DateTime.new_from_unix_local(this.getTime() / 1000);
return dt ? dt.format(format) : '';
Date.prototype.toLocaleFormat = function(format) {
return Shell.util_format_date(format, this.getTime());
};
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');

View File

@ -19,12 +19,12 @@ var REPOSITORY_URL_UPDATE = `${REPOSITORY_URL_BASE}/update-info/`;
let _httpSession;
function installExtension(uuid, invocation) {
let params = { uuid,
let params = { uuid: uuid,
shell_version: Config.PACKAGE_VERSION };
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
_httpSession.queue_message(message, () => {
_httpSession.queue_message(message, (session, message) => {
if (message.status_code != Soup.KnownStatusCode.OK) {
Main.extensionManager.logExtensionError(uuid, `downloading info: ${message.status_code}`);
invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
@ -90,7 +90,7 @@ function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
return;
}
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, (o, status) => {
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, (pid, status) => {
GLib.spawn_close_pid(pid);
if (status != 0)
@ -113,7 +113,7 @@ function updateExtension(uuid) {
let url = REPOSITORY_URL_DOWNLOAD.format(uuid);
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, session => {
_httpSession.queue_message(message, (session, message) => {
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => {
let oldExtension = Main.extensionManager.lookup(uuid);
let extensionDir = oldExtension.dir;
@ -145,8 +145,8 @@ function updateExtension(uuid) {
}
FileUtils.recursivelyDeleteDir(oldExtensionTmpDir, true);
}, (code, msg) => {
log(`Error while updating extension ${uuid}: ${code} (${msg})`);
}, (code, message) => {
log('Error while updating extension %s: %s (%s)'.format(uuid, code, message ? message : ''));
});
});
}
@ -162,7 +162,7 @@ function checkForUpdates() {
let url = REPOSITORY_URL_UPDATE;
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, () => {
_httpSession.queue_message(message, (session, message) => {
if (message.status_code != Soup.KnownStatusCode.OK)
return;
@ -189,7 +189,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.setButtons([{
label: _("Cancel"),
action: this._onCancelButtonPressed.bind(this),
key: Clutter.KEY_Escape,
key: Clutter.Escape,
}, {
label: _("Install"),
action: this._onInstallButtonPressed.bind(this),
@ -199,8 +199,8 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
let content = new Dialog.MessageDialogContent({
title: _("Download and install “%s” from extensions.gnome.org?").format(info.name),
icon: new Gio.FileIcon({
file: Gio.File.new_for_uri(`${REPOSITORY_URL_BASE}${info.icon}`),
}),
file: Gio.File.new_for_uri(`${REPOSITORY_URL_BASE}${info.icon}`)
})
});
this.contentLayout.add(content);
@ -220,9 +220,10 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
let uuid = this._uuid;
let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
let invocation = this._invocation;
function errback(code, msg) {
log(`Error while installing ${uuid}: ${code} (${msg})`);
invocation.return_dbus_error(`org.gnome.Shell.${code}`, msg || '');
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);
}
function callback() {
@ -240,7 +241,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
invocation.return_value(GLib.Variant.new('(s)', ['successful']));
}
_httpSession.queue_message(message, session => {
_httpSession.queue_message(message, (session, message) => {
gotExtensionZipFile(session, message, uuid, dir, callback, errback);
});

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
const { GLib, Gio, St } = imports.gi;
const { Gio, St } = imports.gi;
const Signals = imports.signals;
const ExtensionUtils = imports.misc.extensionUtils;
@ -28,23 +28,6 @@ var ExtensionManager = class {
}
init() {
// The following file should exist for a period of time when extensions
// are enabled after start. If it exists, then the systemd unit will
// disable extensions should gnome-shell crash.
// Should the file already exist from a previous login, then this is OK.
let disableFilename = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gnome-shell-disable-extensions']);
let disableFile = Gio.File.new_for_path(disableFilename);
try {
disableFile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, null);
} catch (e) {
log(`Failed to create file ${disableFilename}: ${e.message}`);
}
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
disableFile.delete(null);
return GLib.SOURCE_REMOVE;
});
this._sessionUpdated();
}
@ -77,11 +60,11 @@ var ExtensionManager = class {
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let otherUuid = orderReversed[i];
let uuid = orderReversed[i];
try {
this.lookup(otherUuid).stateObj.disable();
this.lookup(uuid).stateObj.disable();
} catch (e) {
this.logExtensionError(otherUuid, e);
this.logExtensionError(uuid, e);
}
}
@ -98,11 +81,11 @@ var ExtensionManager = class {
}
for (let i = 0; i < order.length; i++) {
let otherUuid = order[i];
let uuid = order[i];
try {
this.lookup(otherUuid).stateObj.enable();
this.lookup(uuid).stateObj.enable();
} catch (e) {
this.logExtensionError(otherUuid, e);
this.logExtensionError(uuid, e);
}
}
@ -217,8 +200,9 @@ var ExtensionManager = class {
createExtensionObject(uuid, dir, type) {
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null))
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
let metadataContents, success_;
try {
@ -238,12 +222,14 @@ var ExtensionManager = class {
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i];
if (!meta[prop])
if (!meta[prop]) {
throw new Error(`missing "${prop}" property in metadata.json`);
}
}
if (uuid != meta.uuid)
if (uuid != meta.uuid) {
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
}
let extension = {
metadata: meta,
@ -253,7 +239,7 @@ var ExtensionManager = class {
path: dir.get_path(),
error: '',
hasPrefs: dir.get_child('prefs.js').query_exists(null),
canChange: false,
canChange: false
};
this._extensions.set(uuid, extension);

View File

@ -195,7 +195,7 @@ var GrabHelper = class GrabHelper {
}
_takeModalGrab() {
let firstGrab = this._modalCount == 0;
let firstGrab = (this._modalCount == 0);
if (firstGrab) {
if (!Main.pushModal(this._owner, this._modalParams))
return false;
@ -292,7 +292,7 @@ var GrabHelper = class GrabHelper {
let touchEnd = type == Clutter.EventType.TOUCH_END;
let touch = touchUpdate || touchBegin || touchEnd;
if (touch && !global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
if (touch && !global.display.is_pointer_emulating_sequence (event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (this._ignoreUntilRelease && (motion || release || touch)) {

View File

@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
const { Clutter, GObject, IBus, St } = imports.gi;
const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
@ -11,23 +12,11 @@ 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 CandidateArea = GObject.registerClass({
Signals: {
'candidate-clicked': { param_types: [GObject.TYPE_UINT,
GObject.TYPE_UINT,
Clutter.ModifierType.$gtype] },
'cursor-down': {},
'cursor-up': {},
'next-page': {},
'previous-page': {},
},
}, class CandidateArea extends St.BoxLayout {
_init() {
super._init({
vertical: true,
reactive: true,
visible: false,
});
var CandidateArea = class CandidateArea {
constructor() {
this.actor = new St.BoxLayout({ vertical: true,
reactive: true,
visible: false });
this._candidateBoxes = [];
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
let box = new St.BoxLayout({ style_class: 'candidate-box',
@ -35,10 +24,10 @@ var CandidateArea = GObject.registerClass({
track_hover: true });
box._indexLabel = new St.Label({ style_class: 'candidate-index' });
box._candidateLabel = new St.Label({ style_class: 'candidate-label' });
box.add_child(box._indexLabel);
box.add_child(box._candidateLabel);
box.add(box._indexLabel, { y_fill: false });
box.add(box._candidateLabel, { y_fill: false });
this._candidateBoxes.push(box);
this.add(box);
this.actor.add(box);
let j = i;
box.connect('button-release-event', (actor, event) => {
@ -47,23 +36,30 @@ var CandidateArea = GObject.registerClass({
});
}
this.actor.connect('scroll-event', (actor, event) => {
let direction = event.get_scroll_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;
});
this._buttonBox = new St.BoxLayout({ style_class: 'candidate-page-button-box' });
this._previousButton = new St.Button({
style_class: 'candidate-page-button candidate-page-button-previous button',
x_expand: true,
});
this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous button' });
this._previousButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
this._buttonBox.add_child(this._previousButton);
this._buttonBox.add(this._previousButton, { expand: true });
this._nextButton = new St.Button({
style_class: 'candidate-page-button candidate-page-button-next button',
x_expand: true,
});
this._nextButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-next button' });
this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
this._buttonBox.add_child(this._nextButton);
this._buttonBox.add(this._nextButton, { expand: true });
this.add(this._buttonBox);
this.actor.add(this._buttonBox);
this._previousButton.connect('clicked', () => {
this.emit('previous-page');
@ -76,18 +72,6 @@ var CandidateArea = GObject.registerClass({
this._cursorPosition = 0;
}
vfunc_scroll_event(scrollEvent) {
switch (scrollEvent.direction) {
case Clutter.ScrollDirection.UP:
this.emit('cursor-up');
break;
case Clutter.ScrollDirection.DOWN:
this.emit('cursor-down');
break;
}
return Clutter.EVENT_PROPAGATE;
}
setOrientation(orientation) {
if (this._orientation == orientation)
return;
@ -95,15 +79,15 @@ var CandidateArea = GObject.registerClass({
this._orientation = orientation;
if (this._orientation == IBus.Orientation.HORIZONTAL) {
this.vertical = false;
this.remove_style_class_name('vertical');
this.add_style_class_name('horizontal');
this.actor.vertical = false;
this.actor.remove_style_class_name('vertical');
this.actor.add_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-previous-symbolic';
this._nextButton.child.icon_name = 'go-next-symbolic';
} else { // VERTICAL || SYSTEM
this.vertical = true;
this.add_style_class_name('vertical');
this.remove_style_class_name('horizontal');
this.actor.vertical = true;
this.actor.add_style_class_name('vertical');
this.actor.remove_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-up-symbolic';
this._nextButton.child.icon_name = 'go-down-symbolic';
}
@ -118,7 +102,7 @@ var CandidateArea = GObject.registerClass({
if (!visible)
continue;
box._indexLabel.text = indexes && indexes[i] ? indexes[i] : DEFAULT_INDEX_LABELS[i];
box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : DEFAULT_INDEX_LABELS[i]);
box._candidateLabel.text = candidates[i];
}
@ -137,23 +121,22 @@ var CandidateArea = GObject.registerClass({
this._previousButton.reactive = wrapsAround || page > 0;
this._nextButton.reactive = wrapsAround || page < nPages - 1;
}
});
var CandidatePopup = GObject.registerClass(
class IbusCandidatePopup extends BoxPointer.BoxPointer {
_init() {
super._init(St.Side.TOP);
this.visible = false;
this.style_class = 'candidate-popup-boxpointer';
};
Signals.addSignalMethods(CandidateArea.prototype);
var CandidatePopup = class CandidatePopup {
constructor() {
this._dummyCursor = new St.Widget({ opacity: 0 });
Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
Main.layoutManager.addChrome(this);
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer';
Main.layoutManager.addChrome(this._boxPointer);
let box = new St.BoxLayout({ style_class: 'candidate-popup-content',
vertical: true });
this.bin.set_child(box);
this._boxPointer.bin.set_child(box);
this._preeditText = new St.Label({ style_class: 'candidate-popup-text',
visible: false });
@ -164,7 +147,7 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
box.add(this._auxText);
this._candidateArea = new CandidateArea();
box.add(this._candidateArea);
box.add(this._candidateArea.actor);
this._candidateArea.connect('previous-page', () => {
this._panelService.page_up();
@ -215,10 +198,9 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
this._preeditText.text = text.get_text();
let attrs = text.get_attributes();
if (attrs) {
if (attrs)
this._setTextAttributes(this._preeditText.clutter_text,
attrs);
}
});
panelService.connect('show-preedit-text', () => {
this._preeditText.show();
@ -243,14 +225,14 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
this._updateVisibility();
});
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
this._candidateArea.visible = visible;
this._candidateArea.actor.visible = visible;
this._updateVisibility();
let nCandidates = lookupTable.get_number_of_candidates();
let cursorPos = lookupTable.get_cursor_pos();
let pageSize = lookupTable.get_page_size();
let nPages = Math.ceil(nCandidates / pageSize);
let page = cursorPos == 0 ? 0 : Math.floor(cursorPos / pageSize);
let page = ((cursorPos == 0) ? 0 : Math.floor(cursorPos / pageSize));
let startIndex = page * pageSize;
let endIndex = Math.min((page + 1) * pageSize, nCandidates);
@ -279,15 +261,15 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
});
panelService.connect('show-lookup-table', () => {
this._candidateArea.show();
this._candidateArea.actor.show();
this._updateVisibility();
});
panelService.connect('hide-lookup-table', () => {
this._candidateArea.hide();
this._candidateArea.actor.hide();
this._updateVisibility();
});
panelService.connect('focus-out', () => {
this.close(BoxPointer.PopupAnimation.NONE);
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});
}
@ -296,30 +278,29 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
this._dummyCursor.set_position(Math.round(x), Math.round(y));
this._dummyCursor.set_size(Math.round(w), Math.round(h));
if (this.visible)
this.setPosition(this._dummyCursor, 0);
if (this._boxPointer.visible)
this._boxPointer.setPosition(this._dummyCursor, 0);
}
_updateVisibility() {
let isVisible = !Main.keyboard.visible &&
let isVisible = (!Main.keyboard.visible &&
(this._preeditText.visible ||
this._auxText.visible ||
this._candidateArea.visible);
this._candidateArea.actor.visible));
if (isVisible) {
this.setPosition(this._dummyCursor, 0);
this.open(BoxPointer.PopupAnimation.NONE);
this.get_parent().set_child_above_sibling(this, null);
this._boxPointer.setPosition(this._dummyCursor, 0);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.raise_top();
} else {
this.close(BoxPointer.PopupAnimation.NONE);
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
}
}
_setTextAttributes(clutterText, ibusAttrList) {
let attr;
for (let i = 0; (attr = ibusAttrList.get(i)); ++i) {
for (let i = 0; (attr = ibusAttrList.get(i)); ++i)
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
}
}
});
};

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, PaginatedIconGrid */
const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Params = imports.misc.params;
const Main = imports.ui.main;
@ -22,7 +22,7 @@ var ANIMATION_BOUNCE_ICON_SCALE = 1.1;
var AnimationDirection = {
IN: 0,
OUT: 1,
OUT: 1
};
var APPICON_ANIMATION_OUT_SCALE = 3;
@ -39,19 +39,18 @@ class BaseIcon extends St.Bin {
if (params.showLabel)
styleClass += ' overview-icon-with-label';
super._init({ style_class: styleClass });
super._init({ style_class: styleClass,
x_fill: true,
y_fill: true });
this.connect('destroy', this._onDestroy.bind(this));
this._box = new St.BoxLayout({
vertical: true,
x_expand: true,
y_expand: true,
});
this._box = new St.BoxLayout({ vertical: true });
this.set_child(this._box);
this.iconSize = ICON_SIZE;
this._iconBin = new St.Bin();
this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._box.add_actor(this._iconBin);
@ -59,7 +58,7 @@ class BaseIcon extends St.Bin {
this.label = new St.Label({ text: label });
this.label.clutter_text.set({
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER
});
this._box.add_actor(this.label);
} else {
@ -190,7 +189,7 @@ function zoomOutActorAtPos(actor, x, y) {
opacity: 0,
duration: APPICON_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => actorClone.destroy(),
onComplete: () => actorClone.destroy()
});
}
@ -232,21 +231,21 @@ var IconGrid = GObject.registerClass({
this._fixedHItemSize = this._fixedVItemSize = undefined;
this.connect('style-changed', this._onStyleChanged.bind(this));
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
this.connect('notify::mapped', () => {
if (!this.mapped)
this._resetAnimationActors();
});
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_unmap() {
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
this._resetAnimationActors();
super.vfunc_unmap();
}
_onDestroy() {
if (this._updateIconSizesLaterId) {
Meta.later_remove(this._updateIconSizesLaterId);
Meta.later_remove (this._updateIconSizesLaterId);
this._updateIconSizesLaterId = 0;
}
}
@ -403,7 +402,7 @@ var IconGrid = GObject.registerClass({
let allocationBox = this.get_allocation_box();
let paintBox = themeNode.get_paint_box(allocationBox);
let origin = new Graphene.Point3D();
let origin = new Clutter.Vertex();
origin.x = paintBox.x1 - allocationBox.x1;
origin.y = paintBox.y1 - allocationBox.y1;
origin.z = 0.0;
@ -432,7 +431,7 @@ var IconGrid = GObject.registerClass({
return true;
}
/*
/**
* Intended to be override by subclasses if they need a different
* set of items to be animated.
*/
@ -455,10 +454,9 @@ var IconGrid = GObject.registerClass({
}
animatePulse(animationDirection) {
if (animationDirection != AnimationDirection.IN) {
if (animationDirection != AnimationDirection.IN)
throw new GObject.NotImplementedError("Pulse animation only implements " +
"'in' animation direction");
}
this._resetAnimationActors();
@ -488,7 +486,7 @@ var IconGrid = GObject.registerClass({
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
duration: bounceUpTime,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
delay: delay,
onComplete: () => {
let duration = ANIMATION_TIME_IN - bounceUpTime;
actor.ease({
@ -500,9 +498,9 @@ var IconGrid = GObject.registerClass({
if (isLastItem)
this._animationDone();
actor.reactive = true;
},
}
});
},
}
});
}
}
@ -569,7 +567,7 @@ var IconGrid = GObject.registerClass({
scale_y: 1,
duration: ANIMATION_TIME_IN,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
delay
};
if (isLastItem)
@ -579,7 +577,7 @@ var IconGrid = GObject.registerClass({
opacity: 255,
duration: ANIMATION_FADE_IN_TIME_FOR_ITEM,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
delay
};
} else {
let isLastItem = actor._distance == maxDist;
@ -595,7 +593,7 @@ var IconGrid = GObject.registerClass({
scale_y: scaleY,
duration: ANIMATION_TIME_OUT,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay,
delay
};
if (isLastItem)
@ -605,7 +603,7 @@ var IconGrid = GObject.registerClass({
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,
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM
};
}
@ -678,8 +676,8 @@ var IconGrid = GObject.registerClass({
nRows(forWidth) {
let children = this._getVisibleChildren();
let nColumns = forWidth < 0 ? children.length : this._computeLayout(forWidth)[0];
let nRows = nColumns > 0 ? Math.ceil(children.length / nColumns) : 0;
let nColumns = (forWidth < 0) ? children.length : this._computeLayout(forWidth)[0];
let nRows = (nColumns > 0) ? Math.ceil(children.length / nColumns) : 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
return nRows;
@ -719,13 +717,13 @@ var IconGrid = GObject.registerClass({
this._items.push(item);
if (index !== undefined)
this.insert_child_at_index(item, index);
this.insert_child_at_index(item.actor, index);
else
this.add_actor(item);
this.add_actor(item.actor);
}
removeItem(item) {
this.remove_child(item);
this.remove_child(item.actor);
}
getItemAtIndex(index) {
@ -785,7 +783,7 @@ var IconGrid = GObject.registerClass({
this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
}
/*
/**
* This function must to be called before iconGrid allocation,
* to know how much spacing can the grid has
*/
@ -798,7 +796,7 @@ var IconGrid = GObject.registerClass({
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededSpacePerItem = neededWidth > neededHeight
let neededSpacePerItem = (neededWidth > neededHeight)
? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
@ -806,10 +804,9 @@ var IconGrid = GObject.registerClass({
this._updateSpacingForSize(availWidth, availHeight);
}
if (!this._updateIconSizesLaterId) {
if (!this._updateIconSizesLaterId)
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
}
}
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
@ -817,9 +814,9 @@ var IconGrid = GObject.registerClass({
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)
for (let i in this._items) {
this._items[i].icon.setIconSize(newIconSize);
}
return GLib.SOURCE_REMOVE;
}
});
@ -881,9 +878,9 @@ var PaginatedIconGrid = GObject.registerClass({
children[i].show();
columnIndex++;
if (columnIndex == nColumns)
if (columnIndex == nColumns) {
columnIndex = 0;
}
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage == 0)
@ -958,16 +955,15 @@ var PaginatedIconGrid = GObject.registerClass({
/**
* openExtraSpace:
* @param {Clutter.Actor} sourceItem: item for which to create extra space
* @param {St.Side} side: where @sourceItem should be located relative to
* the created space
* @param {number} nRows: the amount of space to create
* @sourceItem: the item for which to create extra space
* @side: where @sourceItem should be located relative to the created space
* @nRows: the amount of space to create
*
* Pan view to create extra space for @nRows above or below @sourceItem.
*/
openExtraSpace(sourceItem, side, nRows) {
let children = this._getVisibleChildren();
let index = children.indexOf(sourceItem);
let index = children.indexOf(sourceItem.actor);
if (index == -1)
throw new Error('Item not found.');
@ -977,7 +973,7 @@ var PaginatedIconGrid = GObject.registerClass({
let childrenPerRow = this._childrenPerPage / this._rowsPerPage;
let sourceRow = Math.floor((index - pageOffset) / childrenPerRow);
let nRowsAbove = side == St.Side.TOP ? sourceRow + 1 : sourceRow;
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 : sourceRow;
let nRowsBelow = this._rowsPerPage - nRowsAbove;
let nRowsUp, nRowsDown;
@ -1020,7 +1016,7 @@ var PaginatedIconGrid = GObject.registerClass({
let params = {
translation_y: translationY,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD
};
if (i == (children.length - 1))
params.onComplete = () => this.emit('space-opened');
@ -1041,7 +1037,7 @@ var PaginatedIconGrid = GObject.registerClass({
translation_y: 0,
duration: EXTRA_SPACE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
onComplete: () => this.emit('space-closed'),
onComplete: () => this.emit('space-closed')
});
}
}

View File

@ -18,8 +18,8 @@ var DialogResponse = Meta.InhibitShortcutsDialogResponse;
var InhibitShortcutsDialog = GObject.registerClass({
Implements: [Meta.InhibitShortcutsDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog),
},
'window': GObject.ParamSpec.override('window', Meta.InhibitShortcutsDialog)
}
}, class InhibitShortcutsDialog extends GObject.Object {
_init(window) {
super._init();
@ -84,11 +84,10 @@ var InhibitShortcutsDialog = GObject.registerClass({
let contentParams = { icon, title };
let restoreAccel = this._getRestoreAccel();
if (restoreAccel) {
if (restoreAccel)
contentParams.subtitle =
/* Translators: %s is a keyboard shortcut like "Super+x" */
_("You can restore shortcuts by pressing %s.").format(restoreAccel);
}
let content = new Dialog.MessageDialogContent(contentParams);
this._dialog.contentLayout.add_actor(content);
@ -135,10 +134,10 @@ var InhibitShortcutsDialog = GObject.registerClass({
this._permStore.LookupRemote(APP_PERMISSIONS_TABLE,
APP_PERMISSIONS_ID,
(res, err) => {
if (err) {
(res, error) => {
if (error) {
this._dialog.open();
log(err.message);
log(error.message);
return;
}

View File

@ -61,7 +61,7 @@ class KbdA11yDialog extends GObject.Object {
dialog.close();
},
default: enabled,
key: !enabled ? Clutter.KEY_Escape : null });
key: !enabled ? Clutter.Escape : null });
dialog.addButton({ label: enabled ? _("Turn Off") : _("Leave Off"),
action: () => {
@ -69,7 +69,7 @@ class KbdA11yDialog extends GObject.Object {
dialog.close();
},
default: !enabled,
key: enabled ? Clutter.KEY_Escape : null });
key: enabled ? Clutter.Escape : null });
dialog.open();
}

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ var MonitorConstraint = GObject.registerClass({
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
false)
},
}, class MonitorConstraint extends Clutter.Constraint {
_init(props) {
@ -167,12 +167,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];
}
@ -181,7 +181,7 @@ class UiActor extends St.Widget {
const defaultParams = {
trackFullscreen: false,
affectsStruts: false,
affectsInputRegion: true,
affectsInputRegion: true
};
var LayoutManager = GObject.registerClass({
@ -189,13 +189,12 @@ var LayoutManager = GObject.registerClass({
'startup-complete': {},
'startup-prepared': {},
'monitors-changed': {},
'system-modal-opened': {},
'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
}, class LayoutManager extends GObject.Object {
_init() {
super._init();
this._rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
this.monitors = [];
this.primaryMonitor = null;
this.primaryIndex = -1;
@ -213,6 +212,11 @@ var LayoutManager = GObject.registerClass({
this._startingUp = true;
this._pendingLoadBackground = false;
// We don't want to paint the stage background color because either
// the SystemBackground we create or the MetaBackgroundActor inside
// global.window_group covers the entirety of the screen.
global.stage.no_clear_hint = true;
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new UiActor({ name: 'uiGroup' });
this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
@ -270,11 +274,11 @@ var LayoutManager = GObject.registerClass({
this._backgroundGroup = new Meta.BackgroundGroup();
global.window_group.add_child(this._backgroundGroup);
global.window_group.set_child_below_sibling(this._backgroundGroup, null);
this._backgroundGroup.lower_bottom();
this._bgManagers = [];
this._interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface',
schema_id: 'org.gnome.desktop.interface'
});
this._interfaceSettings.connect('changed::enable-hot-corners',
@ -340,11 +344,10 @@ var LayoutManager = GObject.registerClass({
this.monitors = [];
let nMonitors = display.get_n_monitors();
for (let i = 0; i < nMonitors; i++) {
for (let i = 0; i < nMonitors; i++)
this.monitors.push(new Monitor(i,
display.get_monitor_geometry(i),
display.get_monitor_scale(i)));
}
if (nMonitors == 0) {
this.primaryIndex = this.bottomIndex = -1;
@ -447,7 +450,7 @@ var LayoutManager = GObject.registerClass({
_createBackgroundManager(monitorIndex) {
let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
layoutManager: this,
monitorIndex });
monitorIndex: monitorIndex });
bgManager.connect('changed', this._addBackgroundMenu.bind(this));
this._addBackgroundMenu(bgManager);
@ -464,14 +467,15 @@ var LayoutManager = GObject.registerClass({
backgroundActor.ease({
opacity: 255,
duration: BACKGROUND_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
}
_updateBackgrounds() {
for (let i = 0; i < this._bgManagers.length; i++)
let i;
for (i = 0; i < this._bgManagers.length; i++)
this._bgManagers[i].destroy();
this._bgManagers = [];
@ -602,17 +606,17 @@ var LayoutManager = GObject.registerClass({
return;
}
this._systemBackground = new Background.SystemBackground();
this._systemBackground.hide();
this._systemBackground.actor.hide();
global.stage.insert_child_below(this._systemBackground, null);
global.stage.insert_child_below(this._systemBackground.actor, null);
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this._systemBackground.add_constraint(constraint);
this._systemBackground.actor.add_constraint(constraint);
let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId);
this._systemBackground.show();
this._systemBackground.actor.show();
global.stage.show();
this._prepareStartupAnimation();
@ -699,7 +703,7 @@ var LayoutManager = GObject.registerClass({
translation_y: 0,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete(),
onComplete: () => this._startupAnimationComplete()
});
}
@ -710,7 +714,7 @@ var LayoutManager = GObject.registerClass({
opacity: 255,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._startupAnimationComplete(),
onComplete: () => this._startupAnimationComplete()
});
}
@ -718,7 +722,7 @@ var LayoutManager = GObject.registerClass({
this._coverPane.destroy();
this._coverPane = null;
this._systemBackground.destroy();
this._systemBackground.actor.destroy();
this._systemBackground = null;
this._startingUp = false;
@ -744,7 +748,7 @@ var LayoutManager = GObject.registerClass({
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._showKeyboardComplete();
},
}
});
this.emit('keyboard-visible-changed', true);
}
@ -771,7 +775,7 @@ var LayoutManager = GObject.registerClass({
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._hideKeyboardComplete();
},
}
});
this.emit('keyboard-visible-changed', false);
@ -957,7 +961,7 @@ var LayoutManager = GObject.registerClass({
findIndexForActor(actor) {
let [x, y] = actor.get_transformed_position();
let [w, h] = actor.get_transformed_size();
let rect = new Meta.Rectangle({ x, y, width: w, height: h });
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h });
return global.display.get_monitor_index_for_rect(rect);
}
@ -972,10 +976,9 @@ var LayoutManager = GObject.registerClass({
if (this._startingUp)
return;
if (!this._updateRegionIdle) {
if (!this._updateRegionIdle)
this._updateRegionIdle = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateRegions.bind(this));
}
}
_getWindowActorsForWorkspace(workspace) {
@ -1029,7 +1032,7 @@ var LayoutManager = GObject.registerClass({
h = Math.round(h);
if (actorData.affectsInputRegion && wantsInputRegion && actorData.actor.get_paint_visibility())
rects.push(new Meta.Rectangle({ x, y, width: w, height: h }));
rects.push(new Meta.Rectangle({ x: x, y: y, width: w, height: h }));
let monitor = null;
if (actorData.affectsStruts)
@ -1080,7 +1083,7 @@ var LayoutManager = GObject.registerClass({
}
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 });
let strut = new Meta.Strut({ rect: strutRect, side });
let strut = new Meta.Strut({ rect: strutRect, side: side });
struts.push(strut);
}
}
@ -1109,11 +1112,8 @@ var LayoutManager = GObject.registerClass({
//
// This class manages a "hot corner" that can toggle switching to
// overview.
var HotCorner = GObject.registerClass(
class HotCorner extends Clutter.Actor {
_init(layoutManager, monitor, x, y) {
super._init();
var HotCorner = class HotCorner {
constructor(layoutManager, monitor, x, y) {
// We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding
// guard area (the "environs"). This avoids triggering the hot corner
@ -1142,8 +1142,6 @@ class HotCorner extends Clutter.Actor {
this._ripples = new Ripples.Ripples(px, py, 'ripple-box');
this._ripples.addTo(layoutManager.uiGroup);
this.connect('destroy', this._onDestroy.bind(this));
}
setBarrierSize(size) {
@ -1183,14 +1181,11 @@ class HotCorner extends Clutter.Actor {
_setupFallbackCornerIfNeeded(layoutManager) {
if (!global.display.supports_extended_barriers()) {
this.set({
name: 'hot-corner-environs',
x: this._x,
y: this._y,
width: 3,
height: 3,
reactive: true,
});
this.actor = new Clutter.Actor({ name: 'hot-corner-environs',
x: this._x, y: this._y,
width: 3,
height: 3,
reactive: true });
this._corner = new Clutter.Actor({ name: 'hot-corner',
width: 1,
@ -1199,16 +1194,19 @@ class HotCorner extends Clutter.Actor {
reactive: true });
this._corner._delegate = this;
this.add_child(this._corner);
layoutManager.addChrome(this);
this.actor.add_child(this._corner);
layoutManager.addChrome(this.actor);
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
this._corner.set_position(this.width - this._corner.width, 0);
this.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
this._corner.set_position(this.actor.width - this._corner.width, 0);
this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
} else {
this._corner.set_position(0, 0);
}
this.actor.connect('leave-event',
this._onEnvironsLeft.bind(this));
this._corner.connect('enter-event',
this._onCornerEntered.bind(this));
this._corner.connect('leave-event',
@ -1216,11 +1214,14 @@ class HotCorner extends Clutter.Actor {
}
}
_onDestroy() {
destroy() {
this.setBarrierSize(0);
this._pressureBarrier.destroy();
this._pressureBarrier = null;
if (this.actor)
this.actor.destroy();
this._ripples.destroy();
}
@ -1252,18 +1253,18 @@ class HotCorner extends Clutter.Actor {
}
_onCornerLeft(actor, event) {
if (event.get_related() != this)
if (event.get_related() != this.actor)
this._entered = false;
// Consume event, otherwise this will confuse onEnvironsLeft
return Clutter.EVENT_STOP;
}
vfunc_leave_event(crossingEvent) {
if (crossingEvent.related != this._corner)
_onEnvironsLeft(actor, event) {
if (event.get_related() != this._corner)
this._entered = false;
return Clutter.EVENT_PROPAGATE;
}
});
};
var PressureBarrier = class PressureBarrier {
constructor(threshold, timeout, actionMode) {

View File

@ -2,6 +2,7 @@
/* exported Lightbox */
const { Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Params = imports.misc.params;
@ -33,8 +34,8 @@ var RadialShaderEffect = GObject.registerClass({
'sharpness', 'sharpness', 'sharpness',
GObject.ParamFlags.READWRITE,
0, 1, 0
),
},
)
}
}, class RadialShaderEffect extends Shell.GLSLEffect {
_init(params) {
this._brightness = undefined;
@ -88,8 +89,8 @@ var RadialShaderEffect = GObject.registerClass({
* - inhibitEvents: whether to inhibit events for @container
* - width: shade actor width
* - height: shade actor height
* - fadeFactor: fading opacity factor
* - radialEffect: whether to enable the GLSL radial effect
* - fadeInTime: milliseconds used to fade in
* - fadeOutTime: milliseconds used to fade out
*
* Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors
@ -105,13 +106,8 @@ var RadialShaderEffect = GObject.registerClass({
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height in @params.
*/
var Lightbox = GObject.registerClass({
Properties: {
'active': GObject.ParamSpec.boolean(
'active', 'active', 'active', GObject.ParamFlags.READABLE, false),
},
}, class Lightbox extends St.Bin {
_init(container, params) {
var Lightbox = class Lightbox {
constructor(container, params) {
params = Params.parse(params, {
inhibitEvents: false,
width: null,
@ -120,34 +116,32 @@ var Lightbox = GObject.registerClass({
radialEffect: false,
});
super._init({
reactive: params.inhibitEvents,
width: params.width,
height: params.height,
visible: false,
});
this._active = false;
this._container = container;
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.add_effect(new RadialShaderEffect({ name: 'radial' }));
this.actor.add_effect(new RadialShaderEffect({ name: 'radial' }));
else
this.set({ opacity: 0, style_class: 'lightbox' });
this.actor.set({ opacity: 0, style_class: 'lightbox' });
container.add_actor(this);
container.set_child_above_sibling(this, null);
container.add_actor(this.actor);
this.actor.raise_top();
this.actor.hide();
this.shown = false;
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
if (!params.width || !params.height) {
this.add_constraint(new Clutter.BindConstraint({
source: container,
coordinate: Clutter.BindCoordinate.ALL,
}));
if (params.width && params.height) {
this.actor.width = params.width;
this.actor.height = params.height;
} else {
let constraint = new Clutter.BindConstraint({ source: container,
coordinate: Clutter.BindCoordinate.ALL });
this.actor.add_constraint(constraint);
}
this._actorAddedSignalId = container.connect('actor-added', this._actorAdded.bind(this));
@ -156,20 +150,16 @@ var Lightbox = GObject.registerClass({
this._highlighted = null;
}
get active() {
return this._active;
}
_actorAdded(container, newChild) {
let children = this._container.get_children();
let myIndex = children.indexOf(this);
let myIndex = children.indexOf(this.actor);
let newChildIndex = children.indexOf(newChild);
if (newChildIndex > myIndex) {
// The child was added above the shade (presumably it was
// made the new top-most child). Move it below the shade,
// and add it to this._children as the new topmost actor.
this._container.set_child_above_sibling(this, newChild);
newChild.lower(this.actor);
this._children.push(newChild);
} else if (newChildIndex == 0) {
// Bottom of stack
@ -182,55 +172,53 @@ var Lightbox = GObject.registerClass({
}
}
lightOn(fadeInTime) {
this.remove_all_transitions();
show(fadeInTime) {
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeInTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => {
this._active = true;
this.notify('active');
this.shown = true;
this.emit('shown');
};
this.show();
this.actor.show();
if (this._radialEffect) {
this.ease_property(
this.actor.ease_property(
'@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps);
this.ease_property(
this.actor.ease_property(
'@effects.radial.sharpness', VIGNETTE_SHARPNESS,
Object.assign({ onComplete }, easeProps));
} else {
this.ease(Object.assign(easeProps, {
this.actor.ease(Object.assign(easeProps, {
opacity: 255 * this._fadeFactor,
onComplete,
onComplete
}));
}
}
lightOff(fadeOutTime) {
this.remove_all_transitions();
this._active = false;
this.notify('active');
hide(fadeOutTime) {
this.shown = false;
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeOutTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => this.hide();
let onComplete = () => this.actor.hide();
if (this._radialEffect) {
this.ease_property(
this.actor.ease_property(
'@effects.radial.brightness', 1.0, easeProps);
this.ease_property(
this.actor.ease_property(
'@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps));
} else {
this.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
}
}
@ -245,7 +233,7 @@ var Lightbox = GObject.registerClass({
/**
* highlight:
* @param {Clutter.Actor=} window: actor to highlight
* @window: actor to highlight
*
* Highlights the indicated actor and unhighlights any other
* currently-highlighted actor. With no arguments or a false/null
@ -261,12 +249,12 @@ var Lightbox = GObject.registerClass({
// case we may need to indicate some *other* actor as the new
// sibling of the to-be-lowered one.
let below = this;
let below = this.actor;
for (let i = this._children.length - 1; i >= 0; i--) {
if (this._children[i] == window)
this._container.set_child_above_sibling(this._children[i], null);
this._children[i].raise_top();
else if (this._children[i] == this._highlighted)
this._container.set_child_below_sibling(this._children[i], below);
this._children[i].lower(below);
else
below = this._children[i];
}
@ -274,6 +262,15 @@ var Lightbox = GObject.registerClass({
this._highlighted = window;
}
/**
* destroy:
*
* Destroys the lightbox.
*/
destroy() {
this.actor.destroy();
}
/**
* _onDestroy:
*
@ -281,15 +278,10 @@ var Lightbox = GObject.registerClass({
* by destroying its container or by explicitly calling this.destroy().
*/
_onDestroy() {
if (this._actorAddedSignalId) {
this._container.disconnect(this._actorAddedSignalId);
this._actorAddedSignalId = 0;
}
if (this._actorRemovedSignalId) {
this._container.disconnect(this._actorRemovedSignalId);
this._actorRemovedSignalId = 0;
}
this._container.disconnect(this._actorAddedSignalId);
this._container.disconnect(this._actorRemovedSignalId);
this.highlight(null);
}
});
};
Signals.addSignalMethods(Lightbox.prototype);

View File

@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */
const { Clutter, Cogl, Gio, GLib, GObject,
Graphene, Meta, Pango, Shell, St } = imports.gi;
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const System = imports.system;
@ -54,9 +54,9 @@ var AutoComplete = class AutoComplete {
}
_processCompletionRequest(event) {
if (event.completions.length == 0)
if (event.completions.length == 0) {
return;
}
// Unique match = go ahead and complete; multiple matches + single tab = complete the common starting string;
// multiple matches + double tab = emit a suggest event with all possible options
if (event.completions.length == 1) {
@ -78,20 +78,20 @@ var AutoComplete = class AutoComplete {
_entryKeyPressEvent(actor, event) {
let cursorPos = this._entry.clutter_text.get_cursor_position();
let text = this._entry.get_text();
if (cursorPos != -1)
if (cursorPos != -1) {
text = text.slice(0, cursorPos);
if (event.get_key_symbol() == Clutter.KEY_Tab) {
}
if (event.get_key_symbol() == Clutter.Tab) {
let [completions, attrHead] = JsParse.getCompletions(text, commandHeader, AUTO_COMPLETE_GLOBAL_KEYWORDS);
let currTime = global.get_current_time();
if ((currTime - this._lastTabTime) < AUTO_COMPLETE_DOUBLE_TAB_DELAY) {
this._processCompletionRequest({ tabType: 'double',
completions,
attrHead });
completions: completions,
attrHead: attrHead });
} else {
this._processCompletionRequest({ tabType: 'single',
completions,
attrHead });
completions: completions,
attrHead: attrHead });
}
this._lastTabTime = currTime;
}
@ -110,14 +110,9 @@ var AutoComplete = class AutoComplete {
Signals.addSignalMethods(AutoComplete.prototype);
var Notebook = GObject.registerClass({
Signals: { 'selection': { param_types: [Clutter.Actor.$gtype] } },
}, class Notebook extends St.BoxLayout {
_init() {
super._init({
vertical: true,
y_expand: true,
});
var Notebook = class Notebook {
constructor() {
this.actor = new St.BoxLayout({ vertical: true });
this.tabControls = new St.BoxLayout({ style_class: 'labels' });
@ -134,21 +129,21 @@ var Notebook = GObject.registerClass({
this.selectChild(child);
return true;
});
labelBox.add_child(label);
labelBox.add(label, { expand: true });
this.tabControls.add(labelBox);
let scrollview = new St.ScrollView({ y_expand: true });
let scrollview = new St.ScrollView({ x_fill: true, y_fill: true });
scrollview.get_hscroll_bar().hide();
scrollview.add_actor(child);
let tabData = { child,
labelBox,
label,
let tabData = { child: child,
labelBox: labelBox,
label: label,
scrollView: scrollview,
_scrollToBottom: false };
this._tabs.push(tabData);
scrollview.hide();
this.add_child(scrollview);
this.actor.add(scrollview, { expand: true });
let vAdjust = scrollview.vscroll.adjustment;
vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData));
@ -179,7 +174,7 @@ var Notebook = GObject.registerClass({
// Focus the new tab before unmapping the old one
let tabData = this._tabs[index];
if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
this.grab_key_focus();
this.actor.grab_key_focus();
this._unselect();
@ -224,20 +219,23 @@ var Notebook = GObject.registerClass({
nextTab() {
let nextIndex = this._selectedIndex;
if (nextIndex < this._tabs.length - 1)
if (nextIndex < this._tabs.length - 1) {
++nextIndex;
}
this.selectIndex(nextIndex);
}
prevTab() {
let prevIndex = this._selectedIndex;
if (prevIndex > 0)
if (prevIndex > 0) {
--prevIndex;
}
this.selectIndex(prevIndex);
}
});
};
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
if (typeof o == typeof objectToString) {
@ -248,63 +246,57 @@ function objectToString(o) {
}
}
var ObjLink = GObject.registerClass(
class ObjLink extends St.Button {
_init(lookingGlass, o, title) {
var ObjLink = class ObjLink {
constructor(lookingGlass, o, title) {
let text;
if (title)
text = title;
else
text = objectToString(o);
text = GLib.markup_escape_text(text, -1);
super._init({
reactive: true,
track_hover: true,
style_class: 'shell-link',
label: text,
x_align: Clutter.ActorAlign.START,
});
this.get_child().single_line_mode = true;
this._obj = o;
this.actor = new St.Button({ reactive: true,
track_hover: true,
style_class: 'shell-link',
label: text });
this.actor.get_child().single_line_mode = true;
this.actor.connect('clicked', this._onClicked.bind(this));
this._lookingGlass = lookingGlass;
}
vfunc_clicked() {
this._lookingGlass.inspectObject(this._obj, this);
_onClicked() {
this._lookingGlass.inspectObject(this._obj, this.actor);
}
});
var Result = GObject.registerClass(
class Result extends St.BoxLayout {
_init(lookingGlass, command, o, index) {
super._init({ vertical: true });
};
var Result = class Result {
constructor(lookingGlass, command, o, index) {
this.index = index;
this.o = o;
this.actor = new St.BoxLayout({ vertical: true });
this._lookingGlass = lookingGlass;
let cmdTxt = new St.Label({ text: command });
cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
this.add(cmdTxt);
this.actor.add(cmdTxt);
let box = new St.BoxLayout({});
this.add(box);
this.actor.add(box);
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);
box.add(objLink);
box.add(objLink.actor);
}
});
};
var WindowList = GObject.registerClass({
}, class WindowList extends St.BoxLayout {
_init(lookingGlass) {
super._init({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
var WindowList = class WindowList {
constructor(lookingGlass) {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default();
this._updateId = Main.initializeDeferredWork(this, this._updateWindowList.bind(this));
this._updateId = Main.initializeDeferredWork(this.actor, this._updateWindowList.bind(this));
global.display.connect('window-created', this._updateWindowList.bind(this));
tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this));
@ -315,7 +307,7 @@ var WindowList = GObject.registerClass({
if (!this._lookingGlass.isOpen)
return;
this.destroy_all_children();
this.actor.destroy_all_children();
let windows = global.get_window_actors();
let tracker = Shell.WindowTracker.get_default();
for (let i = 0; i < windows.length; i++) {
@ -326,9 +318,9 @@ var WindowList = GObject.registerClass({
metaWindow._lookingGlassManaged = true;
}
let box = new St.BoxLayout({ vertical: true });
this.add(box);
this.actor.add(box);
let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title);
box.add_child(windowLink);
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()}` }));
@ -337,10 +329,10 @@ var WindowList = GObject.registerClass({
let icon = app.create_icon_texture(22);
let propBox = new St.BoxLayout({ style: 'spacing: 6px; ' });
propsBox.add(propBox);
propBox.add_child(new St.Label({ text: 'app: ' }));
propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false });
let appLink = new ObjLink(this._lookingGlass, app, app.get_id());
propBox.add_child(appLink);
propBox.add_child(icon);
propBox.add(appLink.actor, { y_fill: false });
propBox.add(icon, { y_fill: false });
} else {
propsBox.add(new St.Label({ text: '<untracked>' }));
}
@ -350,29 +342,23 @@ var WindowList = GObject.registerClass({
update() {
this._updateWindowList();
}
});
var ObjInspector = GObject.registerClass(
class ObjInspector extends St.ScrollView {
_init(lookingGlass) {
super._init({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
};
Signals.addSignalMethods(WindowList.prototype);
var ObjInspector = class ObjInspector {
constructor(lookingGlass) {
this._obj = null;
this._previousObj = null;
this._parentList = [];
this.get_hscroll_bar().hide();
this._container = new St.BoxLayout({
name: 'LookingGlassPropertyInspector',
style_class: 'lg-dialog',
vertical: true,
x_expand: true,
y_expand: true,
});
this.add_actor(this._container);
this.actor = new St.ScrollView({ pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
x_fill: true, y_fill: true });
this.actor.get_hscroll_bar().hide();
this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector',
style_class: 'lg-dialog',
vertical: true });
this.actor.add_actor(this._container);
this._lookingGlass = lookingGlass;
}
@ -388,12 +374,10 @@ class ObjInspector extends St.ScrollView {
let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
this._container.add_actor(hbox);
let label = new St.Label({
text: 'Inspecting: %s: %s'.format(typeof obj, objectToString(obj)),
x_expand: true,
});
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof obj,
objectToString(obj)) });
label.single_line_mode = true;
hbox.add_child(label);
hbox.add(label, { expand: true, y_fill: false });
let button = new St.Button({ label: 'Insert', style_class: 'lg-obj-inspector-button' });
button.connect('clicked', this._onInsert.bind(this));
hbox.add(button);
@ -410,8 +394,9 @@ class ObjInspector extends St.ScrollView {
hbox.add(button);
if (typeof obj == typeof {}) {
let properties = [];
for (let propName in obj)
for (let propName in obj) {
properties.push(propName);
}
properties.sort();
for (let i = 0; i < properties.length; i++) {
@ -419,14 +404,14 @@ class ObjInspector extends St.ScrollView {
let link;
try {
let prop = obj[propName];
link = new ObjLink(this._lookingGlass, prop);
link = new ObjLink(this._lookingGlass, prop).actor;
} catch (e) {
link = new St.Label({ text: '<error>' });
}
let box = new St.BoxLayout();
box.add(new St.Label({ text: `${propName}: ` }));
box.add(link);
this._container.add_actor(box);
let hbox = new St.BoxLayout();
hbox.add(new St.Label({ text: `${propName}: ` }));
hbox.add(link);
this._container.add_actor(hbox);
}
}
}
@ -436,17 +421,17 @@ class ObjInspector extends St.ScrollView {
return;
this._previousObj = null;
this._open = true;
this.show();
this.actor.show();
if (sourceActor) {
this.set_scale(0, 0);
this.ease({
this.actor.set_scale(0, 0);
this.actor.ease({
scale_x: 1,
scale_y: 1,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: 200,
time: 200
});
} else {
this.set_scale(1, 1);
this.actor.set_scale(1, 1);
}
}
@ -454,7 +439,7 @@ class ObjInspector extends St.ScrollView {
if (!this._open)
return;
this._open = false;
this.hide();
this.actor.hide();
this._previousObj = null;
this._obj = null;
}
@ -468,44 +453,29 @@ class ObjInspector extends St.ScrollView {
_onBack() {
this.selectObject(this._previousObj, true);
}
});
};
var RedBorderEffect = GObject.registerClass(
class RedBorderEffect extends Clutter.Effect {
_init() {
super._init();
this._pipeline = null;
}
vfunc_paint(paintContext) {
let framebuffer = paintContext.get_framebuffer();
let coglContext = framebuffer.get_context();
vfunc_paint() {
let actor = this.get_actor();
actor.continue_paint(paintContext);
actor.continue_paint();
if (!this._pipeline) {
let color = new Cogl.Color();
color.init_from_4ub(0xff, 0, 0, 0xc4);
let color = new Cogl.Color();
color.init_from_4ub(0xff, 0, 0, 0xc4);
Cogl.set_source_color(color);
this._pipeline = new Cogl.Pipeline(coglContext);
this._pipeline.set_color(color);
}
let alloc = actor.get_allocation_box();
let geom = actor.get_allocation_geometry();
let width = 2;
// clockwise order
framebuffer.draw_rectangle(this._pipeline,
0, 0, alloc.get_width(), width);
framebuffer.draw_rectangle(this._pipeline,
alloc.get_width() - width, width,
alloc.get_width(), alloc.get_height());
framebuffer.draw_rectangle(this._pipeline,
0, alloc.get_height(),
alloc.get_width() - width, alloc.get_height() - width);
framebuffer.draw_rectangle(this._pipeline,
0, alloc.get_height() - width,
width, width);
Cogl.rectangle(0, 0, geom.width, width);
Cogl.rectangle(geom.width - width, width,
geom.width, geom.height);
Cogl.rectangle(0, geom.height,
geom.width - width, geom.height - width);
Cogl.rectangle(0, geom.height - width,
width, width);
}
});
@ -514,7 +484,8 @@ var Inspector = GObject.registerClass({
'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
}, class Inspector extends Clutter.Actor {
_init(lookingGlass) {
super._init({ width: 0, height: 0 });
super._init({ width: 0,
height: 0 });
Main.uiGroup.add_actor(this);
@ -523,8 +494,8 @@ var Inspector = GObject.registerClass({
reactive: true });
this._eventHandler = eventHandler;
this.add_actor(eventHandler);
this._displayText = new St.Label({ x_expand: true });
eventHandler.add_child(this._displayText);
this._displayText = new St.Label();
eventHandler.add(this._displayText, { expand: true });
eventHandler.connect('key-press-event', this._onKeyPressEvent.bind(this));
eventHandler.connect('button-press-event', this._onButtonPressEvent.bind(this));
@ -577,7 +548,7 @@ var Inspector = GObject.registerClass({
}
_onKeyPressEvent(actor, event) {
if (event.get_key_symbol() === Clutter.KEY_Escape)
if (event.get_key_symbol() == Clutter.Escape)
this._close();
return Clutter.EVENT_STOP;
}
@ -649,19 +620,18 @@ var Inspector = GObject.registerClass({
}
});
var Extensions = GObject.registerClass({
}, class Extensions extends St.BoxLayout {
_init(lookingGlass) {
super._init({ vertical: true, name: 'lookingGlassExtensions' });
var Extensions = class Extensions {
constructor(lookingGlass) {
this._lookingGlass = lookingGlass;
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
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.add(this._extensionsList);
this.actor.add(this._extensionsList);
Main.extensionManager.getUuids().forEach(uuid => {
this._loadExtension(null, uuid);
@ -682,7 +652,7 @@ var Extensions = GObject.registerClass({
if (this._numExtensions == 0)
this._extensionsList.remove_actor(this._noExtensions);
this._numExtensions++;
this._numExtensions ++;
this._extensionsList.add(extensionDisplay);
}
@ -707,7 +677,7 @@ var Extensions = GObject.registerClass({
let errors = extension.errors;
let errorDisplay = new St.BoxLayout({ vertical: true });
if (errors && errors.length) {
for (let i = 0; i < errors.length; i++)
for (let i = 0; i < errors.length; i ++)
errorDisplay.add(new St.Label({ text: errors[i] }));
} else {
/* Translators: argument is an extension UUID. */
@ -746,18 +716,12 @@ var Extensions = GObject.registerClass({
_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,
x_expand: true,
});
box.add_child(name);
let description = new St.Label({
style_class: 'lg-extension-description',
text: extension.metadata.description || 'No description',
x_expand: true,
});
box.add_child(description);
let name = new St.Label({ style_class: 'lg-extension-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' });
box.add(description, { expand: true });
let metaBox = new St.BoxLayout({ style_class: 'lg-extension-meta' });
box.add(metaBox);
@ -795,19 +759,10 @@ var Extensions = GObject.registerClass({
return box;
}
});
var LookingGlass = GObject.registerClass(
class LookingGlass extends St.BoxLayout {
_init() {
super._init({
name: 'LookingGlassDialog',
style_class: 'lg-dialog',
vertical: true,
visible: false,
reactive: true,
});
};
var LookingGlass = class LookingGlass {
constructor() {
this._borderPaintTarget = null;
this._redBorderEffect = new RedBorderEffect();
@ -815,18 +770,26 @@ class LookingGlass extends St.BoxLayout {
this._it = null;
this._offset = 0;
this._results = [];
// Sort of magic, but...eh.
this._maxItems = 150;
this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
style_class: 'lg-dialog',
vertical: true,
visible: false,
reactive: true });
this.actor.connect('key-press-event', this._globalKeyPressEvent.bind(this));
this._interfaceSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._interfaceSettings.connect('changed::monospace-font-name',
this._updateFont.bind(this));
this._updateFont();
// We want it to appear to slide out from underneath the panel
Main.uiGroup.add_actor(this);
Main.uiGroup.set_child_below_sibling(this,
Main.uiGroup.add_actor(this.actor);
Main.uiGroup.set_child_below_sibling(this.actor,
Main.layoutManager.panelBox);
Main.layoutManager.panelBox.connect('allocation-changed',
this._queueResize.bind(this));
@ -834,11 +797,11 @@ class LookingGlass extends St.BoxLayout {
this._queueResize.bind(this));
this._objInspector = new ObjInspector(this);
Main.uiGroup.add_actor(this._objInspector);
this._objInspector.hide();
Main.uiGroup.add_actor(this._objInspector.actor);
this._objInspector.actor.hide();
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
this.add_actor(toolbar);
this.actor.add_actor(toolbar);
let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker',
icon_size: 24 });
toolbar.add_actor(inspectIcon);
@ -849,10 +812,10 @@ class LookingGlass extends St.BoxLayout {
this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
});
inspector.connect('closed', () => {
this.show();
this.actor.show();
global.stage.set_key_focus(this._entry);
});
this.hide();
this.actor.hide();
return Clutter.EVENT_STOP;
});
@ -874,43 +837,33 @@ class LookingGlass extends St.BoxLayout {
let notebook = new Notebook();
this._notebook = notebook;
this.add_child(notebook);
this.actor.add(notebook.actor, { expand: true });
let emptyBox = new St.Bin({ x_expand: true });
toolbar.add_child(emptyBox);
let emptyBox = new St.Bin();
toolbar.add(emptyBox, { expand: true });
toolbar.add_actor(notebook.tabControls);
this._evalBox = new St.BoxLayout({ name: 'EvalBox', vertical: true });
notebook.appendPage('Evaluator', this._evalBox);
this._resultsArea = new St.BoxLayout({
name: 'ResultsArea',
vertical: true,
y_expand: true,
});
this._evalBox.add_child(this._resultsArea);
this._resultsArea = new St.BoxLayout({ name: 'ResultsArea', vertical: true });
this._evalBox.add(this._resultsArea, { expand: true });
this._entryArea = new St.BoxLayout({
name: 'EntryArea',
y_align: Clutter.ActorAlign.END,
});
this._entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(this._entryArea);
let label = new St.Label({ text: CHEVRON });
this._entryArea.add(label);
this._entry = new St.Entry({
can_focus: true,
x_expand: true,
});
this._entry = new St.Entry({ can_focus: true });
ShellEntry.addContextMenu(this._entry);
this._entryArea.add_child(this._entry);
this._entryArea.add(this._entry, { expand: true });
this._windowList = new WindowList(this);
notebook.appendPage('Windows', this._windowList);
notebook.appendPage('Windows', this._windowList.actor);
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions);
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', (o, _e) => {
// Hide any completions we are currently showing
@ -952,7 +905,7 @@ class LookingGlass extends St.BoxLayout {
// 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.style = `
this.actor.style = `
font-size: ${size}${unit};
font-family: "${fontDesc.get_family()}";`;
}
@ -966,14 +919,17 @@ class LookingGlass extends St.BoxLayout {
}
_pushResult(command, obj) {
let index = this._resultsArea.get_n_children() + this._offset;
let index = this._results.length + this._offset;
let result = new Result(this, CHEVRON + command, obj, index);
this._resultsArea.add(result);
this._results.push(result);
this._resultsArea.add(result.actor);
if (obj instanceof Clutter.Actor)
this.setBorderPaintTarget(obj);
if (this._resultsArea.get_n_children() > this._maxItems) {
this._resultsArea.get_first_child().destroy();
let children = this._resultsArea.get_children();
if (children.length > this._maxItems) {
this._results.shift();
children[0].destroy();
this._offset++;
}
this._it = obj;
@ -1009,7 +965,7 @@ class LookingGlass extends St.BoxLayout {
height: naturalHeight,
opacity: 255,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@ -1026,7 +982,7 @@ class LookingGlass extends St.BoxLayout {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._completionActor.hide();
},
}
});
}
}
@ -1060,7 +1016,7 @@ class LookingGlass extends St.BoxLayout {
getResult(idx) {
try {
return this._resultsArea.get_child_at_index(idx - this._offset).o;
return this._results[idx - this._offset].o;
} catch (e) {
throw new Error(`Unknown result at index ${idx}`);
}
@ -1085,15 +1041,15 @@ class LookingGlass extends St.BoxLayout {
let myWidth = primary.width * 0.7;
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.x = primary.x + (primary.width - myWidth) / 2;
this.actor.x = primary.x + (primary.width - myWidth) / 2;
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight;
this._targetY = this._hiddenY + myHeight;
this.y = this._hiddenY;
this.width = myWidth;
this.height = myHeight;
this._objInspector.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
this._objInspector.set_position(this.x + Math.floor(myWidth * 0.1),
this._targetY + Math.floor(myHeight * 0.1));
this.actor.y = this._hiddenY;
this.actor.width = myWidth;
this.actor.height = myHeight;
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
this._targetY + Math.floor(myHeight * 0.1));
}
insertObject(obj) {
@ -1106,21 +1062,24 @@ class LookingGlass extends St.BoxLayout {
}
// Handle key events which are relevant for all tabs of the LookingGlass
vfunc_key_press_event(keyPressEvent) {
let symbol = keyPressEvent.keyval;
if (symbol == Clutter.KEY_Escape) {
if (this._objInspector.visible)
_globalKeyPressEvent(actor, event) {
let symbol = event.get_key_symbol();
let modifierState = event.get_state();
if (symbol == Clutter.Escape) {
if (this._objInspector.actor.visible) {
this._objInspector.close();
else
} else {
this.close();
}
return Clutter.EVENT_STOP;
}
// Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
if (keyPressEvent.modifier_state & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.KEY_Page_Up)
if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.KEY_Page_Up) {
this._notebook.prevTab();
else if (symbol == Clutter.KEY_Page_Down)
} else if (symbol == Clutter.KEY_Page_Down) {
this._notebook.nextTab();
}
}
return Clutter.EVENT_PROPAGATE;
}
@ -1133,19 +1092,19 @@ class LookingGlass extends St.BoxLayout {
return;
this._notebook.selectIndex(0);
this.show();
this.actor.show();
this._open = true;
this._history.lastItem();
this.remove_all_transitions();
this.actor.remove_all_transitions();
// 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.ease({
this.actor.ease({
y: this._targetY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._windowList.update();
@ -1155,10 +1114,10 @@ class LookingGlass extends St.BoxLayout {
if (!this._open)
return;
this._objInspector.hide();
this._objInspector.actor.hide();
this._open = false;
this.remove_all_transitions();
this.actor.remove_all_transitions();
this.setBorderPaintTarget(null);
@ -1167,15 +1126,16 @@ class LookingGlass extends St.BoxLayout {
let settings = St.Settings.get();
let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
LG_ANIMATION_TIME);
this.ease({
this.actor.ease({
y: this._hiddenY,
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.hide(),
onComplete: () => this.actor.hide()
});
}
get isOpen() {
return this._open;
}
});
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -55,7 +55,7 @@ var MouseSpriteContent = GObject.registerClass({
return [true, this._texture.get_width(), this._texture.get_height()];
}
vfunc_paint_content(actor, node, _paintContext) {
vfunc_paint_content(actor, node) {
if (!this._texture)
return;
@ -118,7 +118,7 @@ var Magnifier = class Magnifier {
});
// Export to dbus.
new MagnifierDBus.ShellMagnifier();
(new MagnifierDBus.ShellMagnifier());
this.setActive(St.Settings.get().magnifier_active);
}
@ -141,7 +141,7 @@ var Magnifier = class Magnifier {
/**
* setActive:
* Show/hide all the zoom regions.
* @param {bool} activate: Boolean to activate or de-activate the magnifier.
* @activate: Boolean to activate or de-activate the magnifier.
*/
setActive(activate) {
let isActive = this.isActive();
@ -177,7 +177,7 @@ var Magnifier = class Magnifier {
/**
* isActive:
* @returns {bool} Whether the magnifier is active.
* @return Whether the magnifier is active (boolean).
*/
isActive() {
// Sufficient to check one ZoomRegion since Magnifier's active
@ -212,7 +212,7 @@ var Magnifier = class Magnifier {
/**
* isTrackingMouse:
* @returns {bool} whether the magnifier is currently tracking the mouse
* Is the magnifier tracking the mouse currently?
*/
isTrackingMouse() {
return !!this._mouseTrackingId;
@ -222,7 +222,7 @@ var Magnifier = class Magnifier {
* scrollToMousePos:
* Position all zoom regions' ROI relative to the current location of the
* system pointer.
* @returns {bool} true.
* @return true.
*/
scrollToMousePos() {
let [xMouse, yMouse] = global.get_pointer();
@ -247,17 +247,17 @@ var Magnifier = class Magnifier {
/**
* createZoomRegion:
* Create a ZoomRegion instance with the given properties.
* @param {number} xMagFactor:
* The power to set horizontal magnification of the ZoomRegion. A value
* of 1.0 means no magnification, a value of 2.0 doubles the size.
* @param {number} yMagFactor:
* The power to set the vertical magnification of the ZoomRegion.
* @param {{x: number, y: number, width: number, height: number}} roi:
* The reg Object that defines the region to magnify, given in
* unmagnified coordinates.
* @param {{x: number, y: number, width: number, height: number}} viewPort:
* Object that defines the position of the ZoomRegion on screen.
* @returns {ZoomRegion} the newly created ZoomRegion.
* @xMagFactor: The power to set horizontal magnification of the
* ZoomRegion. A value of 1.0 means no magnification. A
* value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification of the
* ZoomRegion.
* @roi Object in the form { x, y, width, height } that
* defines the region to magnify. Given in unmagnified
* coordinates.
* @viewPort Object in the form { x, y, width, height } that defines
* the position of the ZoomRegion on screen.
* @return The newly created ZoomRegion.
*/
createZoomRegion(xMagFactor, yMagFactor, roi, viewPort) {
let zoomRegion = new ZoomRegion(this, this._cursorRoot);
@ -277,7 +277,7 @@ var Magnifier = class Magnifier {
* addZoomRegion:
* Append the given ZoomRegion to the list of currently defined ZoomRegions
* for this Magnifier instance.
* @param {ZoomRegion} zoomRegion: The zoomRegion to add.
* @zoomRegion: The zoomRegion to add.
*/
addZoomRegion(zoomRegion) {
if (zoomRegion) {
@ -290,7 +290,7 @@ var Magnifier = class Magnifier {
/**
* getZoomRegions:
* Return a list of ZoomRegion's for this Magnifier.
* @returns {number[]} The Magnifier's zoom region list.
* @return: The Magnifier's zoom region list (array).
*/
getZoomRegions() {
return this._zoomRegions;
@ -330,7 +330,7 @@ var Magnifier = class Magnifier {
this.setCrosshairsClip(clip);
let theCrossHairs = this._crossHairs;
this._zoomRegions.forEach(zoomRegion => {
this._zoomRegions.forEach (zoomRegion => {
zoomRegion.addCrosshairs(theCrossHairs);
});
}
@ -338,7 +338,7 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsVisible:
* Show or hide the cross hair.
* @param {bool} visible: Flag that indicates show (true) or hide (false).
* @visible Flag that indicates show (true) or hide (false).
*/
setCrosshairsVisible(visible) {
if (visible) {
@ -346,7 +346,6 @@ var Magnifier = class Magnifier {
this.addCrosshairs();
this._crossHairs.show();
} else {
// eslint-disable-next-line no-lonely-if
if (this._crossHairs)
this._crossHairs.hide();
}
@ -355,7 +354,7 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsColor:
* Set the color of the crosshairs for all ZoomRegions.
* @param {string} color: The color as a string, e.g. '#ff0000ff' or 'red'.
* @color: The color as a string, e.g. '#ff0000ff' or 'red'.
*/
setCrosshairsColor(color) {
if (this._crossHairs) {
@ -367,7 +366,7 @@ var Magnifier = class Magnifier {
/**
* getCrosshairsColor:
* Get the color of the crosshairs.
* @returns {string} The color as a string, e.g. '#0000ffff' or 'blue'.
* @return: The color as a string, e.g. '#0000ffff' or 'blue'.
*/
getCrosshairsColor() {
if (this._crossHairs) {
@ -381,8 +380,8 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsThickness:
* Set the crosshairs thickness for all ZoomRegions.
* @param {number} thickness: The width of the vertical and
* horizontal lines of the crosshairs.
* @thickness: The width of the vertical and horizontal lines of the
* crosshairs.
*/
setCrosshairsThickness(thickness) {
if (this._crossHairs)
@ -392,8 +391,8 @@ var Magnifier = class Magnifier {
/**
* getCrosshairsThickness:
* Get the crosshairs thickness.
* @returns {number} The width of the vertical and horizontal
* lines of the crosshairs.
* @return: The width of the vertical and horizontal lines of the
* crosshairs.
*/
getCrosshairsThickness() {
if (this._crossHairs)
@ -404,8 +403,7 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsOpacity:
* @param {number} opacity: Value between 0.0 (transparent)
* and 1.0 (fully opaque).
* @opacity: Value between 0.0 (transparent) and 1.0 (fully opaque).
*/
setCrosshairsOpacity(opacity) {
if (this._crossHairs)
@ -414,7 +412,7 @@ var Magnifier = class Magnifier {
/**
* getCrosshairsOpacity:
* @returns {number} Value between 0.0 (transparent) and 1.0 (fully opaque).
* @return: Value between 0.0 (transparent) and 1.0 (fully opaque).
*/
getCrosshairsOpacity() {
if (this._crossHairs)
@ -426,8 +424,8 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsLength:
* Set the crosshairs length for all ZoomRegions.
* @param {number} length: The length of the vertical and horizontal
* lines making up the crosshairs.
* @length: The length of the vertical and horizontal lines making up the
* crosshairs.
*/
setCrosshairsLength(length) {
if (this._crossHairs)
@ -437,8 +435,8 @@ var Magnifier = class Magnifier {
/**
* getCrosshairsLength:
* Get the crosshairs length.
* @returns {number} The length of the vertical and horizontal
* lines making up the crosshairs.
* @return: The length of the vertical and horizontal lines making up the
* crosshairs.
*/
getCrosshairsLength() {
if (this._crossHairs)
@ -450,7 +448,7 @@ var Magnifier = class Magnifier {
/**
* setCrosshairsClip:
* Set whether the crosshairs are clipped at their intersection.
* @param {bool} clip: Flag to indicate whether to clip the crosshairs.
* @clip: Flag to indicate whether to clip the crosshairs.
*/
setCrosshairsClip(clip) {
if (!this._crossHairs)
@ -463,18 +461,18 @@ var Magnifier = class Magnifier {
/**
* getCrosshairsClip:
* Get whether the crosshairs are clipped by the mouse image.
* @returns {bool} Whether the crosshairs are clipped.
* @return: Whether the crosshairs are clipped.
*/
getCrosshairsClip() {
if (this._crossHairs) {
let [clipWidth, clipHeight] = this._crossHairs.getClip();
return clipWidth > 0 && clipHeight > 0;
return (clipWidth > 0 && clipHeight > 0);
} else {
return false;
}
}
// Private methods //
//// Private methods ////
_updateMouseSprite() {
this._updateSpriteTexture();
@ -625,8 +623,9 @@ var Magnifier = class Magnifier {
_updateLensMode() {
// Applies only to the first zoom region.
if (this._zoomRegions.length)
if (this._zoomRegions.length) {
this._zoomRegions[0].setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
}
}
_updateClampMode() {
@ -773,16 +772,15 @@ var ZoomRegion = class ZoomRegion {
}
_updateScreenPosition() {
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE) {
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
this._setViewPort({
x: this._viewPortX,
y: this._viewPortY,
width: this._viewPortWidth,
height: this._viewPortHeight,
height: this._viewPortHeight
});
} else {
else
this.setScreenPosition(this._screenPosition);
}
}
_updateFocus(caller, event) {
@ -820,7 +818,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setActive:
* @param {bool} activate: Boolean to show/hide the ZoomRegion.
* @activate: Boolean to show/hide the ZoomRegion.
*/
setActive(activate) {
if (activate == this.isActive())
@ -846,7 +844,7 @@ var ZoomRegion = class ZoomRegion {
/**
* isActive:
* @returns {bool} Whether this ZoomRegion is active
* @return Whether this ZoomRegion is active (boolean).
*/
isActive() {
return this._magView != null;
@ -854,24 +852,24 @@ var ZoomRegion = class ZoomRegion {
/**
* setMagFactor:
* @param {number} xMagFactor: The power to set the horizontal
* magnification factor to of the magnified view. A value of 1.0
* means no magnification. A value of 2.0 doubles the size.
* @param {number} yMagFactor: The power to set the vertical
* magnification factor to of the magnified view.
* @xMagFactor: The power to set the horizontal magnification factor to
* of the magnified view. A value of 1.0 means no
* magnification. A value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification factor to
* of the magnified view.
*/
setMagFactor(xMagFactor, yMagFactor) {
this._changeROI({ xMagFactor,
yMagFactor,
this._changeROI({ xMagFactor: xMagFactor,
yMagFactor: yMagFactor,
redoCursorTracking: this._followingCursor });
}
/**
* getMagFactor:
* @returns {number[]} an array, [xMagFactor, yMagFactor], containing
* the horizontal and vertical magnification powers. A value of
* 1.0 means no magnification. A value of 2.0 means the contents
* are doubled in size, and so on.
* @return an array, [xMagFactor, yMagFactor], containing the horizontal
* and vertical magnification powers. A value of 1.0 means no
* magnification. A value of 2.0 means the contents are doubled
* in size, and so on.
*/
getMagFactor() {
return [this._xMagFactor, this._yMagFactor];
@ -879,7 +877,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setMouseTrackingMode
* @param {GDesktopEnums.MagnifierMouseTrackingMode} mode: the new mode
* @mode: One of the enum MouseTrackingMode values.
*/
setMouseTrackingMode(mode) {
if (mode >= GDesktopEnums.MagnifierMouseTrackingMode.NONE &&
@ -889,7 +887,7 @@ var ZoomRegion = class ZoomRegion {
/**
* getMouseTrackingMode
* @returns {GDesktopEnums.MagnifierMouseTrackingMode} the current mode
* @return: One of the enum MouseTrackingMode values.
*/
getMouseTrackingMode() {
return this._mouseTrackingMode;
@ -897,7 +895,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setFocusTrackingMode
* @param {GDesktopEnums.MagnifierFocusTrackingMode} mode: the new mode
* @mode: One of the enum FocusTrackingMode values.
*/
setFocusTrackingMode(mode) {
this._focusTrackingMode = mode;
@ -906,7 +904,7 @@ var ZoomRegion = class ZoomRegion {
/**
* setCaretTrackingMode
* @param {GDesktopEnums.MagnifierCaretTrackingMode} mode: the new mode
* @mode: One of the enum CaretTrackingMode values.
*/
setCaretTrackingMode(mode) {
this._caretTrackingMode = mode;
@ -936,9 +934,9 @@ var ZoomRegion = class ZoomRegion {
/**
* setViewPort
* Sets the position and size of the ZoomRegion on screen.
* @param {{x: number, y: number, width: number, height: number}} viewPort:
* Object defining the position and size of the view port.
* The values are in stage coordinate space.
* @viewPort: Object defining the position and size of the view port.
* It has members x, y, width, height. The values are in
* stage coordinate space.
*/
setViewPort(viewPort) {
this._setViewPort(viewPort);
@ -948,9 +946,9 @@ var ZoomRegion = class ZoomRegion {
/**
* setROI
* Sets the "region of interest" that the ZoomRegion is magnifying.
* @param {{x: number, y: number, width: number, height: number}} roi:
* Object that defines the region of the screen to magnify.
* The values are in screen (unmagnified) coordinate space.
* @roi: Object that defines the region of the screen to magnify. It
* has members x, y, width, height. The values are in
* screen (unmagnified) coordinate space.
*/
setROI(roi) {
if (roi.width <= 0 || roi.height <= 0)
@ -968,8 +966,8 @@ var ZoomRegion = class ZoomRegion {
* Retrieves the "region of interest" -- the rectangular bounds of that part
* of the desktop that the magnified view is showing (x, y, width, height).
* The bounds are given in non-magnified coordinates.
* @returns {number[]} an array, [x, y, width, height], representing
* the bounding rectangle of what is shown in the magnified view.
* @return an array, [x, y, width, height], representing the bounding
* rectangle of what is shown in the magnified view.
*/
getROI() {
let roiWidth = this._viewPortWidth / this._xMagFactor;
@ -984,18 +982,18 @@ var ZoomRegion = class ZoomRegion {
* setLensMode:
* Turn lens mode on/off. In full screen mode, lens mode does nothing since
* a lens the size of the screen is pointless.
* @param {bool} lensMode: Whether lensMode should be active
* @lensMode: A boolean to set the sense of lens mode.
*/
setLensMode(lensMode) {
this._lensMode = lensMode;
if (!this._lensMode)
this.setScreenPosition(this._screenPosition);
this.setScreenPosition (this._screenPosition);
}
/**
* isLensMode:
* Is lens mode on or off?
* @returns {bool} The lens mode state.
* @return The lens mode state as a boolean.
*/
isLensMode() {
return this._lensMode;
@ -1005,7 +1003,7 @@ var ZoomRegion = class ZoomRegion {
* setClampScrollingAtEdges:
* Stop vs. allow scrolling of the magnified contents when it scroll beyond
* the edges of the screen.
* @param {bool} clamp: Boolean to turn on/off clamping.
* @clamp: Boolean to turn on/off clamping.
*/
setClampScrollingAtEdges(clamp) {
this._clampScrollingAtEdges = clamp;
@ -1089,7 +1087,9 @@ var ZoomRegion = class ZoomRegion {
* setScreenPosition:
* Positions the zoom region to one of the enumerated positions on the
* screen.
* @param {GDesktopEnums.MagnifierScreenPosition} inPosition: the position
* @position: one of Magnifier.FULL_SCREEN, Magnifier.TOP_HALF,
* Magnifier.BOTTOM_HALF,Magnifier.LEFT_HALF, or
* Magnifier.RIGHT_HALF.
*/
setScreenPosition(inPosition) {
switch (inPosition) {
@ -1115,7 +1115,7 @@ var ZoomRegion = class ZoomRegion {
* getScreenPosition:
* Tell the outside world what the current mode is -- magnifiying the
* top half, bottom half, etc.
* @returns {GDesktopEnums.MagnifierScreenPosition}: the current position.
* @return: the current mode.
*/
getScreenPosition() {
return this._screenPosition;
@ -1124,8 +1124,7 @@ var ZoomRegion = class ZoomRegion {
/**
* scrollToMousePos:
* Set the region of interest based on the position of the system pointer.
* @returns {bool}: Whether the system mouse pointer is over the
* magnified view.
* @return: Whether the system mouse pointer is over the magnified view.
*/
scrollToMousePos() {
this._followingCursor = true;
@ -1162,8 +1161,8 @@ var ZoomRegion = class ZoomRegion {
* scrollContentsTo:
* Shift the contents of the magnified view such it is centered on the given
* coordinate.
* @param {number} x: The x-coord of the point to center on.
* @param {number} y: The y-coord of the point to center on.
* @x: The x-coord of the point to center on.
* @y: The y-coord of the point to center on.
*/
scrollContentsTo(x, y) {
this._clearScrollContentsTimer();
@ -1176,21 +1175,22 @@ var ZoomRegion = class ZoomRegion {
/**
* addCrosshairs:
* Add crosshairs centered on the magnified mouse.
* @param {Crosshairs} crossHairs: Crosshairs instance
* @crossHairs: Crosshairs instance
*/
addCrosshairs(crossHairs) {
this._crossHairs = crossHairs;
// If the crossHairs is not already within a larger container, add it
// to this zoom region. Otherwise, add a clone.
if (crossHairs && this.isActive())
if (crossHairs && this.isActive()) {
this._crossHairsActor = crossHairs.addToZoomRegion(this, this._mouseActor);
}
}
/**
* setInvertLightness:
* Set whether to invert the lightness of the magnified view.
* @param {bool} flag: whether brightness should be inverted
* @flag Boolean to either invert brightness (true), or not (false).
*/
setInvertLightness(flag) {
this._invertLightness = flag;
@ -1201,7 +1201,7 @@ var ZoomRegion = class ZoomRegion {
/**
* getInvertLightness:
* Retrieve whether the lightness is inverted.
* @returns {bool} whether brightness should be inverted
* @return Boolean indicating inversion (true), or not (false).
*/
getInvertLightness() {
return this._invertLightness;
@ -1210,9 +1210,9 @@ var ZoomRegion = class ZoomRegion {
/**
* setColorSaturation:
* Set the color saturation of the magnified view.
* @param {number} saturation: A value from 0.0 to 1.0 that defines
* the color saturation, with 0.0 defining no color (grayscale),
* and 1.0 defining full color.
* @sauration A value from 0.0 to 1.0 that defines the color
* saturation, with 0.0 defining no color (grayscale),
* and 1.0 defining full color.
*/
setColorSaturation(saturation) {
this._colorSaturation = saturation;
@ -1223,7 +1223,6 @@ var ZoomRegion = class ZoomRegion {
/**
* getColorSaturation:
* Retrieve the color saturation of the magnified view.
* @returns {number} the color saturation
*/
getColorSaturation() {
return this._colorSaturation;
@ -1232,14 +1231,10 @@ var ZoomRegion = class ZoomRegion {
/**
* setBrightness:
* Alter the brightness of the magnified view.
* @param {Object} brightness: Object containing the contrast for the
* red, green, and blue channels. Values of 0.0 represent "standard"
* brightness (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed brightness, respectively.
*
* {number} brightness.r - the red component
* {number} brightness.g - the green component
* {number} brightness.b - the blue component
* @brightness Object containing the contrast for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* brightness (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed brightness, respectively.
*/
setBrightness(brightness) {
this._brightness.r = brightness.r;
@ -1252,14 +1247,10 @@ var ZoomRegion = class ZoomRegion {
/**
* setContrast:
* Alter the contrast of the magnified view.
* @param {Object} contrast: Object containing the contrast for the
* red, green, and blue channels. Values of 0.0 represent "standard"
* contrast (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed contrast, respectively.
*
* {number} contrast.r - the red component
* {number} contrast.g - the green component
* {number} contrast.b - the blue component
* @contrast Object containing the contrast for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* contrast (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed contrast, respectively.
*/
setContrast(contrast) {
this._contrast.r = contrast.r;
@ -1272,8 +1263,8 @@ var ZoomRegion = class ZoomRegion {
/**
* getContrast:
* Retrieve the contrast of the magnified view.
* @returns {{r: number, g: number, b: number}}: Object containing
* the contrast for the red, green, and blue channels.
* @return Object containing the contrast for the red, green,
* and blue channels.
*/
getContrast() {
let contrast = {};
@ -1283,15 +1274,15 @@ var ZoomRegion = class ZoomRegion {
return contrast;
}
// Private methods //
//// Private methods ////
_createActors() {
// The root actor for the zoom region
this._magView = new St.Bin({ style_class: 'magnifier-zoom-region' });
this._magView = new St.Bin({ style_class: 'magnifier-zoom-region', x_fill: true, y_fill: true });
global.stage.add_actor(this._magView);
// hide the magnified region from CLUTTER_PICK_ALL
Shell.util_set_hidden_from_pick(this._magView, true);
Shell.util_set_hidden_from_pick (this._magView, true);
// Add a group to clip the contents of the magnified view.
let mainGroup = new Clutter.Actor({ clip_to_allocation: true });
@ -1299,7 +1290,7 @@ var ZoomRegion = class ZoomRegion {
// Add a background for when the magnified uiGroup is scrolled
// out of view (don't want to see desktop showing through).
this._background = new Background.SystemBackground();
this._background = (new Background.SystemBackground()).actor;
mainGroup.add_actor(this._background);
// Clone the group that contains all of UI on the screen. This is the
@ -1331,7 +1322,7 @@ var ZoomRegion = class ZoomRegion {
_destroyActors() {
if (this._mouseActor == this._mouseSourceActor)
this._mouseActor.get_parent().remove_actor(this._mouseActor);
this._mouseActor.get_parent().remove_actor (this._mouseActor);
if (this._crossHairs)
this._crossHairs.removeFromParent(this._crossHairsActor);
@ -1411,12 +1402,11 @@ var ZoomRegion = class ZoomRegion {
// If in lens mode, move the magnified view such that it is centered
// over the actual mouse. However, in full screen mode, the "lens" is
// the size of the screen -- pointless to move such a large lens around.
if (this._lensMode && !this._isFullScreen()) {
if (this._lensMode && !this._isFullScreen())
this._setViewPort({ x: this._xCenter - this._viewPortWidth / 2,
y: this._yCenter - this._viewPortHeight / 2,
width: this._viewPortWidth,
height: this._viewPortHeight }, true);
}
this._updateCloneGeometry();
this._updateMousePosition();
@ -1430,9 +1420,10 @@ var ZoomRegion = class ZoomRegion {
let xMouse = this._magnifier.xMouse;
let yMouse = this._magnifier.yMouse;
mouseIsOver =
mouseIsOver = (
xMouse >= this._viewPortX && xMouse < (this._viewPortX + this._viewPortWidth) &&
yMouse >= this._viewPortY && yMouse < (this._viewPortY + this._viewPortHeight);
yMouse >= this._viewPortY && yMouse < (this._viewPortY + this._viewPortHeight)
);
}
return mouseIsOver;
}
@ -1457,12 +1448,13 @@ var ZoomRegion = class ZoomRegion {
let xMouse = this._magnifier.xMouse;
let yMouse = this._magnifier.yMouse;
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL)
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);
}
return null; // Should never be hit
}
@ -1504,14 +1496,14 @@ var ZoomRegion = class ZoomRegion {
let yRoiBottom = yRoi + heightRoi - cursorHeight;
if (xPoint < xRoi)
xPos -= xRoi - xPoint;
xPos -= (xRoi - xPoint);
else if (xPoint > xRoiRight)
xPos += xPoint - xRoiRight;
xPos += (xPoint - xRoiRight);
if (yPoint < yRoi)
yPos -= yRoi - yPoint;
yPos -= (yRoi - yPoint);
else if (yPoint > yRoiBottom)
yPos += yPoint - yRoiBottom;
yPos += (yPoint - yRoiBottom);
return [xPos, yPos];
}
@ -1595,9 +1587,8 @@ var ZoomRegion = class ZoomRegion {
}
};
var Crosshairs = GObject.registerClass(
class Crosshairs extends Clutter.Actor {
_init() {
var Crosshairs = class Crosshairs {
constructor() {
// Set the group containing the crosshairs to three times the desktop
// size in case the crosshairs need to appear to be infinite in
@ -1605,19 +1596,19 @@ class Crosshairs extends Clutter.Actor {
let groupWidth = global.screen_width * 3;
let groupHeight = global.screen_height * 3;
super._init({
this._actor = new Clutter.Actor({
clip_to_allocation: false,
width: groupWidth,
height: groupHeight,
height: groupHeight
});
this._horizLeftHair = new Clutter.Actor();
this._horizRightHair = new Clutter.Actor();
this._vertTopHair = new Clutter.Actor();
this._vertBottomHair = new Clutter.Actor();
this.add_actor(this._horizLeftHair);
this.add_actor(this._horizRightHair);
this.add_actor(this._vertTopHair);
this.add_actor(this._vertBottomHair);
this._actor.add_actor(this._horizLeftHair);
this._actor.add_actor(this._horizRightHair);
this._actor.add_actor(this._vertTopHair);
this._actor.add_actor(this._vertBottomHair);
this._clipSize = [0, 0];
this._clones = [];
this.reCenter();
@ -1627,7 +1618,7 @@ class Crosshairs extends Clutter.Actor {
}
_monitorsChanged() {
this.set_size(global.screen_width * 3, global.screen_height * 3);
this._actor.set_size(global.screen_width * 3, global.screen_height * 3);
this.reCenter();
}
@ -1637,30 +1628,26 @@ class Crosshairs extends Clutter.Actor {
* already part of some other ZoomRegion, create a clone of the crosshairs
* actor, and add the clone instead. Returns either the original or the
* clone.
* @param {ZoomRegion} zoomRegion: The container to add the crosshairs
* group to.
* @param {Clutter.Actor} magnifiedMouse: The mouse actor for the
* zoom region -- used to position the crosshairs and properly
* layer them below the mouse.
* @returns {Clutter.Actor} The crosshairs actor, or its clone.
* @zoomRegion: The container to add the crosshairs group to.
* @magnifiedMouse: The mouse actor for the zoom region -- used to
* position the crosshairs and properly layer them below
* the mouse.
* @return The crosshairs actor, or its clone.
*/
addToZoomRegion(zoomRegion, magnifiedMouse) {
let crosshairsActor = null;
if (zoomRegion && magnifiedMouse) {
let container = magnifiedMouse.get_parent();
if (container) {
crosshairsActor = this;
if (this.get_parent() != null) {
crosshairsActor = new Clutter.Clone({ source: this });
crosshairsActor = this._actor;
if (this._actor.get_parent() != null) {
crosshairsActor = new Clutter.Clone({ source: this._actor });
this._clones.push(crosshairsActor);
// Clones don't share visibility.
this.bind_property('visible', crosshairsActor, 'visible',
GObject.BindingFlags.SYNC_CREATE);
}
crosshairsActor.visible = this._actor.visible;
container.add_actor(crosshairsActor);
container.set_child_above_sibling(magnifiedMouse, crosshairsActor);
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);
@ -1671,13 +1658,12 @@ class Crosshairs extends Clutter.Actor {
/**
* removeFromParent:
* @param {Clutter.Actor} childActor: the actor returned from
* addToZoomRegion
* @childActor: the actor returned from addToZoomRegion
* Remove the crosshairs actor from its parent container, or destroy the
* child actor if it was just a clone of the crosshairs actor.
*/
removeFromParent(childActor) {
if (childActor == this)
if (childActor == this._actor)
childActor.get_parent().remove_actor(childActor);
else
childActor.destroy();
@ -1686,7 +1672,7 @@ class Crosshairs extends Clutter.Actor {
/**
* setColor:
* Set the color of the crosshairs.
* @param {Clutter.Color} clutterColor: The color
* @clutterColor: The color as a Clutter.Color.
*/
setColor(clutterColor) {
this._horizLeftHair.background_color = clutterColor;
@ -1698,7 +1684,7 @@ class Crosshairs extends Clutter.Actor {
/**
* getColor:
* Get the color of the crosshairs.
* @returns {ClutterColor} the crosshairs color
* @color: The color as a Clutter.Color.
*/
getColor() {
return this._horizLeftHair.get_color();
@ -1707,7 +1693,7 @@ class Crosshairs extends Clutter.Actor {
/**
* setThickness:
* Set the width of the vertical and horizontal lines of the crosshairs.
* @param {number} thickness: the new thickness value
* @thickness
*/
setThickness(thickness) {
this._horizLeftHair.set_height(thickness);
@ -1720,7 +1706,7 @@ class Crosshairs extends Clutter.Actor {
/**
* getThickness:
* Get the width of the vertical and horizontal lines of the crosshairs.
* @returns {number} The thickness of the crosshairs.
* @return: The thickness of the crosshairs.
*/
getThickness() {
return this._horizLeftHair.get_height();
@ -1729,8 +1715,7 @@ class Crosshairs extends Clutter.Actor {
/**
* setOpacity:
* Set how opaque the crosshairs are.
* @param {number} opacity: Value between 0 (fully transparent)
* and 255 (full opaque).
* @opacity: Value between 0 (fully transparent) and 255 (full opaque).
*/
setOpacity(opacity) {
// set_opacity() throws an exception for values outside the range
@ -1749,7 +1734,7 @@ class Crosshairs extends Clutter.Actor {
/**
* setLength:
* Set the length of the vertical and horizontal lines in the crosshairs.
* @param {number} length: The length of the crosshairs.
* @length: The length of the crosshairs.
*/
setLength(length) {
this._horizLeftHair.set_width(length);
@ -1762,7 +1747,7 @@ class Crosshairs extends Clutter.Actor {
/**
* getLength:
* Get the length of the vertical and horizontal lines in the crosshairs.
* @returns {number} The length of the crosshairs.
* @return: The length of the crosshairs.
*/
getLength() {
return this._horizLeftHair.get_width();
@ -1772,8 +1757,8 @@ class Crosshairs extends Clutter.Actor {
* setClip:
* Set the width and height of the rectangle that clips the crosshairs at
* their intersection
* @param {number[]} size: Array of [width, height] defining the size
* of the clip rectangle.
* @size: Array of [width, height] defining the size of the clip
* rectangle.
*/
setClip(size) {
if (size) {
@ -1788,15 +1773,37 @@ class Crosshairs extends Clutter.Actor {
}
}
/**
* show:
* Show the crosshairs.
*/
show() {
this._actor.show();
// Clones don't share visibility.
for (let i = 0; i < this._clones.length; i++)
this._clones[i].show();
}
/**
* hide:
* Hide the crosshairs.
*/
hide() {
this._actor.hide();
// Clones don't share visibility.
for (let i = 0; i < this._clones.length; i++)
this._clones[i].hide();
}
/**
* reCenter:
* Reposition the horizontal and vertical hairs such that they cross at
* the center of crosshairs group. If called with the dimensions of
* the clip rectangle, these are used to update the size of the clip.
* @param {number[]=} clipSize: If present, the clip's [width, height].
* @clipSize: Optional. If present, an array of the form [width, height].
*/
reCenter(clipSize) {
let [groupWidth, groupHeight] = this.get_size();
let [groupWidth, groupHeight] = this._actor.get_size();
let leftLength = this._horizLeftHair.get_width();
let topLength = this._vertTopHair.get_height();
let thickness = this._horizLeftHair.get_height();
@ -1818,7 +1825,7 @@ class Crosshairs extends Clutter.Actor {
this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
}
});
};
var MagShaderEffects = class MagShaderEffects {
constructor(uiGroupClone) {
@ -1851,7 +1858,7 @@ var MagShaderEffects = class MagShaderEffects {
/**
* setInvertLightness:
* Enable/disable invert lightness effect.
* @param {bool} invertFlag: Enabled flag.
* @invertFlag: Enabled flag.
*/
setInvertLightness(invertFlag) {
this._inverse.set_enabled(invertFlag);
@ -1864,14 +1871,11 @@ var MagShaderEffects = class MagShaderEffects {
/**
* setBrightness:
* Set the brightness of the magnified view.
* @param {Object} brightness: Object containing the contrast for the
* red, green, and blue channels. Values of 0.0 represent "standard"
* brightness (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed brightness, respectively.
*
* {number} brightness.r - the red component
* {number} brightness.g - the green component
* {number} brightness.b - the blue component
* @brightness: Object containing the brightness for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* brightness (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed brightness,
* respectively.
*/
setBrightness(brightness) {
let bRed = brightness.r;
@ -1883,21 +1887,17 @@ var MagShaderEffects = class MagShaderEffects {
// it modifies the brightness and/or contrast.
let [cRed, cGreen, cBlue] = this._brightnessContrast.get_contrast();
this._brightnessContrast.set_enabled(
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 ||
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE)
);
}
/**
* Set the contrast of the magnified view.
* @param {Object} contrast: Object containing the contrast for the
* red, green, and blue channels. Values of 0.0 represent "standard"
* contrast (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed contrast, respectively.
*
* {number} contrast.r - the red component
* {number} contrast.g - the green component
* {number} contrast.b - the blue component
* @contrast: Object containing the contrast for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* contrast (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed contrast, respectively.
*/
setContrast(contrast) {
let cRed = contrast.r;

View File

@ -32,7 +32,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* setActive:
* @param {bool} activate: activate or de-activate the magnifier.
* @activate: Boolean to activate or de-activate the magnifier.
*/
setActive(activate) {
Main.magnifier.setActive(activate);
@ -40,7 +40,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* isActive:
* @returns {bool} Whether the magnifier is active.
* @return Whether the magnifier is active (boolean).
*/
isActive() {
return Main.magnifier.isActive();
@ -65,25 +65,22 @@ var ShellMagnifier = class ShellMagnifier {
/**
* createZoomRegion:
* Create a new ZoomRegion and return its object path.
* @param {number} xMagFactor:
* The power to set horizontal magnification of the ZoomRegion.
* A value of 1.0 means no magnification. A value of 2.0 doubles
* the size.
* @param {number} yMagFactor:
* The power to set the vertical magnification of the
* ZoomRegion.
* @param {number[]} roi
* Array of integers defining the region of the screen/desktop
* to magnify. The array has the form [left, top, right, bottom].
* @param {number[]} viewPort
* Array of integers, [left, top, right, bottom] that defines
* the position of the ZoomRegion on screen.
* @xMagFactor: The power to set horizontal magnification of the
* ZoomRegion. A value of 1.0 means no magnification. A
* value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification of the
* ZoomRegion.
* @roi Array of integers defining the region of the
* screen/desktop to magnify. The array has the form
* [left, top, right, bottom].
* @viewPort Array of integers, [left, top, right, bottom] that defines
* the position of the ZoomRegion on screen.
*
* FIXME: The arguments here are redundant, since the width and height of
* the ROI are determined by the viewport and magnification factors.
* We ignore the passed in width and height.
*
* @returns {ZoomRegion} The newly created ZoomRegion.
* @return The newly created ZoomRegion.
*/
createZoomRegion(xMagFactor, yMagFactor, roi, viewPort) {
let ROI = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
@ -103,9 +100,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* addZoomRegion:
* Append the given ZoomRegion to the magnifier's list of ZoomRegions.
* @param {string} zoomerObjectPath: The object path for the zoom
* region proxy.
* @returns {bool} whether the region was added successfully
* @zoomerObjectPath: The object path for the zoom region proxy.
*/
addZoomRegion(zoomerObjectPath) {
let proxyAndZoomRegion = this._zoomers[zoomerObjectPath];
@ -120,8 +115,8 @@ var ShellMagnifier = class ShellMagnifier {
/**
* getZoomRegions:
* Return a list of ZoomRegion object paths for this Magnifier.
* @returns {string[]}: The Magnifier's zoom region list as an array
* of DBus object paths.
* @return: The Magnifier's zoom region list as an array of DBus object
* paths.
*/
getZoomRegions() {
// There may be more ZoomRegions in the magnifier itself than have
@ -130,7 +125,7 @@ var ShellMagnifier = class ShellMagnifier {
let zoomRegions = Main.magnifier.getZoomRegions();
let objectPaths = [];
let thoseZoomers = this._zoomers;
zoomRegions.forEach(aZoomRegion => {
zoomRegions.forEach (aZoomRegion => {
let found = false;
for (let objectPath in thoseZoomers) {
let proxyAndZoomRegion = thoseZoomers[objectPath];
@ -142,7 +137,7 @@ var ShellMagnifier = class ShellMagnifier {
}
if (!found) {
// Got a ZoomRegion with no DBus proxy, make one.
let newPath = `${ZOOM_SERVICE_PATH}/zoomer${_zoomRegionInstanceCount}`;
let newPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
_zoomRegionInstanceCount++;
let zoomRegionProxy = new ShellMagnifierZoomRegion(newPath, aZoomRegion);
let proxyAndZoomer = {};
@ -174,7 +169,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* fullScreenCapable:
* Consult if the Magnifier can magnify in full-screen mode.
* @returns {bool} Always return true.
* @return Always return true.
*/
fullScreenCapable() {
return true;
@ -183,7 +178,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* setCrosswireSize:
* Set the crosswire size of all ZoomRegions.
* @param {number} size: The thickness of each line in the cross wire.
* @size: The thickness of each line in the cross wire.
*/
setCrosswireSize(size) {
Main.magnifier.setCrosshairsThickness(size);
@ -192,7 +187,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* getCrosswireSize:
* Get the crosswire size of all ZoomRegions.
* @returns {number}: The thickness of each line in the cross wire.
* @return: The thickness of each line in the cross wire.
*/
getCrosswireSize() {
return Main.magnifier.getCrosshairsThickness();
@ -201,16 +196,16 @@ var ShellMagnifier = class ShellMagnifier {
/**
* setCrosswireLength:
* Set the crosswire length of all zoom-regions..
* @param {number} length: The length of each line in the cross wire.
* @size: The length of each line in the cross wire.
*/
setCrosswireLength(length) {
Main.magnifier.setCrosshairsLength(length);
}
/**
* getCrosswireSize:
* Get the crosswire length of all zoom-regions.
* @returns {number} size: The length of each line in the cross wire.
* setCrosswireSize:
* Set the crosswire size of all zoom-regions.
* @size: The thickness of each line in the cross wire.
*/
getCrosswireLength() {
return Main.magnifier.getCrosshairsLength();
@ -219,7 +214,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* setCrosswireClip:
* Set if the crosswire will be clipped by the cursor image..
* @param {bool} clip: Flag to indicate whether to clip the crosswire.
* @clip: Flag to indicate whether to clip the crosswire.
*/
setCrosswireClip(clip) {
Main.magnifier.setCrosshairsClip(clip);
@ -228,7 +223,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* getCrosswireClip:
* Get the crosswire clip value.
* @returns {bool}: Whether the crosswire is clipped by the cursor image.
* @return: Whether the crosswire is clipped by the cursor image.
*/
getCrosswireClip() {
return Main.magnifier.getCrosshairsClip();
@ -237,7 +232,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* setCrosswireColor:
* Set the crosswire color of all ZoomRegions.
* @param {number} color: Unsigned int of the form rrggbbaa.
* @color: Unsigned int of the form rrggbbaa.
*/
setCrosswireColor(color) {
Main.magnifier.setCrosshairsColor('#%08x'.format(color));
@ -246,8 +241,7 @@ var ShellMagnifier = class ShellMagnifier {
/**
* getCrosswireClip:
* Get the crosswire color of all ZoomRegions.
* @returns {number}: The crosswire color as an unsigned int in
* the form rrggbbaa.
* @return: The crosswire color as an unsigned int in the form rrggbbaa.
*/
getCrosswireColor() {
let colorString = Main.magnifier.getCrosshairsColor();
@ -272,11 +266,11 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
/**
* setMagFactor:
* @param {number} xMagFactor: The power to set the horizontal
* magnification factor to of the magnified view. A value of
* 1.0 means no magnification. A value of 2.0 doubles the size.
* @param {number} yMagFactor: The power to set the vertical
* magnification factor to of the magnified view.
* @xMagFactor: The power to set the horizontal magnification factor to
* of the magnified view. A value of 1.0 means no
* magnification. A value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification factor to
* of the magnified view.
*/
setMagFactor(xMagFactor, yMagFactor) {
this._zoomRegion.setMagFactor(xMagFactor, yMagFactor);
@ -284,7 +278,7 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
/**
* getMagFactor:
* @returns {number[]}: [xMagFactor, yMagFactor], containing the horizontal
* @return an array, [xMagFactor, yMagFactor], containing the horizontal
* and vertical magnification powers. A value of 1.0 means no
* magnification. A value of 2.0 means the contents are doubled
* in size, and so on.
@ -296,9 +290,9 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
/**
* setRoi:
* Sets the "region of interest" that the ZoomRegion is magnifying.
* @param {number[]} roi: [left, top, right, bottom], defining the
* region of the screen to magnify.
* The values are in screen (unmagnified) coordinate space.
* @roi Array, [left, top, right, bottom], defining the region of the
* screen to magnify. The values are in screen (unmagnified)
* coordinate space.
*/
setRoi(roi) {
let roiObject = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
@ -310,7 +304,7 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
* Retrieves the "region of interest" -- the rectangular bounds of that part
* of the desktop that the magnified view is showing (x, y, width, height).
* The bounds are given in non-magnified coordinates.
* @returns {Array}: [left, top, right, bottom], representing the bounding
* @return an array, [left, top, right, bottom], representing the bounding
* rectangle of what is shown in the magnified view.
*/
getRoi() {
@ -323,11 +317,10 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
/**
* Set the "region of interest" by centering the given screen coordinate
* within the zoom region.
* @param {number} x: The x-coord of the point to place at the
* center of the zoom region.
* @param {number} y: The y-coord.
* @returns {bool} Whether the shift was successful (for GS-mag, this
* is always true).
* @x The x-coord of the point to place at the center of the zoom region.
* @y The y-coord.
* @return Whether the shift was successful (for GS-mag, this is always
* true).
*/
shiftContentsTo(x, y) {
this._zoomRegion.scrollContentsTo(x, y);
@ -337,8 +330,8 @@ var ShellMagnifierZoomRegion = class ShellMagnifierZoomRegion {
/**
* moveResize
* Sets the position and size of the ZoomRegion on screen.
* @param {number[]} viewPort: [left, top, right, bottom], defining
* the position and size on screen to place the zoom region.
* @viewPort Array, [left, top, right, bottom], defining the position and
* size on screen to place the zoom region.
*/
moveResize(viewPort) {
let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };

View File

@ -189,7 +189,7 @@ function _initializeUI() {
messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel();
keyboard = new Keyboard.KeyboardManager();
keyboard = new Keyboard.Keyboard();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
@ -199,12 +199,12 @@ function _initializeUI() {
layoutManager.init();
overview.init();
new PointerA11yTimeout.PointerA11yTimeout();
(new PointerA11yTimeout.PointerA11yTimeout());
_a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
global.display.connect('overlay-key', () => {
if (!_a11ySettings.get_boolean(STICKY_KEYS_ENABLE))
if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE))
overview.toggle();
});
@ -248,33 +248,20 @@ function _initializeUI() {
}
layoutManager.connect('startup-complete', () => {
if (actionMode == Shell.ActionMode.NONE)
if (actionMode == Shell.ActionMode.NONE) {
actionMode = Shell.ActionMode.NORMAL;
if (screenShield)
}
if (screenShield) {
screenShield.lockIfWasLocked();
}
if (sessionMode.currentMode != 'gdm' &&
sessionMode.currentMode != 'initial-setup') {
GLib.log_structured(LOG_DOMAIN, GLib.LogLevelFlags.LEVEL_MESSAGE, {
'MESSAGE': `GNOME Shell started at ${_startDate}`,
'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID,
'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID
});
}
let credentials = new Gio.Credentials();
if (credentials.get_unix_user() === 0) {
notify(_('Logged in as a privileged user'),
_('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
}
if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup' &&
screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
@ -289,19 +276,19 @@ function _initializeUI() {
function _getStylesheet(name) {
let stylesheet;
stylesheet = Gio.File.new_for_uri(`resource:///org/gnome/shell/theme/${name}`);
stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + name);
if (stylesheet.query_exists(null))
return stylesheet;
let dataDirs = GLib.get_system_data_dirs();
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'theme', name]);
stylesheet = Gio.file_new_for_path(path);
let stylesheet = Gio.file_new_for_path(path);
if (stylesheet.query_exists(null))
return stylesheet;
}
stylesheet = Gio.File.new_for_path(`${global.datadir}/theme/${name}`);
stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + name);
if (stylesheet.query_exists(null))
return stylesheet;
@ -337,7 +324,7 @@ function _loadDefaultStylesheet() {
*
* Get the theme CSS file that the shell will load
*
* @returns {?Gio.File}: A #GFile that contains the theme CSS,
* Returns: A #GFile that contains the theme CSS,
* null if using the default
*/
function getThemeStylesheet() {
@ -346,8 +333,8 @@ function getThemeStylesheet() {
/**
* setThemeStylesheet:
* @param {string=} cssStylesheet: A file path that contains the theme CSS,
* set it to null to use the default
* @cssStylesheet: A file path that contains the theme CSS,
* set it to null to use the default
*
* Set the theme CSS file that the shell will load
*/
@ -359,12 +346,12 @@ function reloadThemeResource() {
if (_themeResource)
_themeResource._unregister();
_themeResource = Gio.Resource.load(`${global.datadir}/gnome-shell-theme.gresource`);
_themeResource = Gio.Resource.load(global.datadir + '/gnome-shell-theme.gresource');
_themeResource._register();
}
function _loadOskLayouts() {
_oskResource = Gio.Resource.load(`${global.datadir}/gnome-shell-osk-layouts.gresource`);
_oskResource = Gio.Resource.load(global.datadir + '/gnome-shell-osk-layouts.gresource');
_oskResource._register();
}
@ -374,13 +361,11 @@ function _loadOskLayouts() {
* Reloads the theme CSS file
*/
function loadTheme() {
let themeContext = St.ThemeContext.get_for_stage(global.stage);
let themeContext = St.ThemeContext.get_for_stage (global.stage);
let previousTheme = themeContext.get_theme();
let theme = new St.Theme({
application_stylesheet: _cssStylesheet,
default_stylesheet: _defaultCssStylesheet,
});
let theme = new St.Theme ({ application_stylesheet: _cssStylesheet,
default_stylesheet: _defaultCssStylesheet });
if (theme.default_stylesheet == null)
throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
@ -392,26 +377,26 @@ function loadTheme() {
theme.load_stylesheet(customStylesheets[i]);
}
themeContext.set_theme(theme);
themeContext.set_theme (theme);
}
/**
* notify:
* @param {string} msg: A message
* @param {string} details: Additional information
* @msg: A message
* @details: Additional information
*/
function notify(msg, details) {
let source = new MessageTray.SystemNotificationSource();
messageTray.add(source);
let notification = new MessageTray.Notification(source, msg, details);
notification.setTransient(true);
source.showNotification(notification);
source.notify(notification);
}
/**
* notifyError:
* @param {string} msg: An error message
* @param {string} details: Additional information
* @msg: An error message
* @details: Additional information
*
* See shell_global_notify_problem().
*/
@ -435,8 +420,8 @@ function _findModal(actor) {
/**
* pushModal:
* @param {Clutter.Actor} actor: actor which will be given keyboard focus
* @param {Object=} params: optional parameters
* @actor: #ClutterActor which will be given keyboard focus
* @params: optional parameters
*
* Ensure we are in a mode where all keyboard and mouse input goes to
* the stage, and focus @actor. Multiple calls to this function act in
@ -459,7 +444,7 @@ function _findModal(actor) {
* global keybindings; the default of NONE will filter
* out all keybindings
*
* @returns {bool}: true iff we successfully acquired a grab or already had one
* Returns: true iff we successfully acquired a grab or already had one
*/
function pushModal(actor, params) {
params = Params.parse(params, { timestamp: global.get_current_time(),
@ -490,11 +475,11 @@ function pushModal(actor, params) {
modalActorFocusStack[index].prevFocus = null;
});
}
modalActorFocusStack.push({ actor,
modalActorFocusStack.push({ actor: actor,
destroyId: actorDestroyId,
prevFocus,
prevFocusDestroyId,
actionMode });
prevFocus: prevFocus,
prevFocusDestroyId: prevFocusDestroyId,
actionMode: actionMode });
actionMode = params.actionMode;
global.stage.set_key_focus(actor);
@ -503,9 +488,8 @@ function pushModal(actor, params) {
/**
* popModal:
* @param {Clutter.Actor} actor: the actor passed to original invocation
* of pushModal()
* @param {number=} timestamp: optional timestamp
* @actor: #ClutterActor passed to original invocation of pushModal()
* @timestamp: optional timestamp
*
* Reverse the effect of pushModal(). If this invocation is undoing
* the topmost invocation, then the focus will be restored to the
@ -576,24 +560,24 @@ function popModal(actor, timestamp) {
}
function createLookingGlass() {
if (lookingGlass == null)
if (lookingGlass == null) {
lookingGlass = new LookingGlass.LookingGlass();
}
return lookingGlass;
}
function openRunDialog() {
if (runDialog == null)
if (runDialog == null) {
runDialog = new RunDialog.RunDialog();
}
runDialog.open();
}
/**
* activateWindow:
* @param {Meta.Window} window: the window to activate
* @param {number=} time: current event time
* @param {number=} workspaceNum: window's workspace number
* @window: the Meta.Window to activate
* @time: (optional) current event time
* @workspaceNum: (optional) window's workspace number
*
* Activates @window, switching to its workspace first if necessary,
* and switching out of the overview if it's currently active
@ -601,7 +585,7 @@ function openRunDialog() {
function activateWindow(window, time, workspaceNum) {
let workspaceManager = global.workspace_manager;
let activeWorkspaceNum = workspaceManager.get_active_workspace_index();
let windowWorkspaceNum = workspaceNum !== undefined ? workspaceNum : window.get_workspace().index();
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
if (!time)
time = global.get_current_time();
@ -669,8 +653,8 @@ function _queueBeforeRedraw(workId) {
/**
* initializeDeferredWork:
* @param {Clutter.Actor} actor: an actor
* @param {callback} callback: Function to invoke to perform work
* @actor: A #ClutterActor
* @callback: Function to invoke to perform work
*
* This function sets up a callback to be invoked when either the
* given actor is mapped, or after some period of time when the machine
@ -683,13 +667,13 @@ function _queueBeforeRedraw(workId) {
* initialization as well, under the assumption that new actors
* will need it.
*
* @returns {string}: A string work identifier
* Returns: A string work identifier
*/
function initializeDeferredWork(actor, callback) {
// Turn into a string so we can use as an object property
let workId = `${++_deferredWorkSequence}`;
_deferredWorkData[workId] = { actor,
callback };
let workId = `${(++_deferredWorkSequence)}`;
_deferredWorkData[workId] = { 'actor': actor,
'callback': callback };
actor.connect('notify::mapped', () => {
if (!(actor.mapped && _deferredWorkQueue.includes(workId)))
return;
@ -707,7 +691,7 @@ function initializeDeferredWork(actor, callback) {
/**
* queueDeferredWork:
* @param {string} workId: work identifier
* @workId: work identifier
*
* Ensure that the work identified by @workId will be
* run on map or timeout. You should call this function
@ -743,13 +727,12 @@ class RestartMessage extends ModalDialog.ModalDialog {
shouldFadeIn: false,
destroyOnClose: true });
let label = new St.Label({
text: message,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
let label = new St.Label({ text: message });
this.contentLayout.add_child(label);
this.contentLayout.add(label, { x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.buttonLayout.hide();
}
});

View File

@ -1,8 +1,7 @@
/* exported MessageListSection */
const { Atk, Clutter, Gio, GLib,
GObject, Graphene, Meta, Pango, St } = imports.gi;
const { Atk, Clutter, Gio, GLib, GObject, Meta, Pango, St } = imports.gi;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
const Util = imports.misc.util;
@ -32,18 +31,13 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1);
}
var URLHighlighter = GObject.registerClass(
class URLHighlighter extends St.Label {
_init(text = '', lineWrap, allowMarkup) {
super._init({
reactive: true,
style_class: 'url-highlighter',
x_expand: true,
x_align: Clutter.ActorAlign.START,
});
var URLHighlighter = class URLHighlighter {
constructor(text = '', lineWrap, allowMarkup) {
this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter',
x_expand: true, x_align: Clutter.ActorAlign.START });
this._linkColor = '#ccccff';
this.connect('style-changed', () => {
let [hasColor, color] = this.get_theme_node().lookup_color('link-color', false);
this.actor.connect('style-changed', () => {
let [hasColor, color] = this.actor.get_theme_node().lookup_color('link-color', false);
if (hasColor) {
let linkColor = color.to_string().substr(0, 7);
if (linkColor != this._linkColor) {
@ -52,75 +46,70 @@ class URLHighlighter extends St.Label {
}
}
});
this.clutter_text.line_wrap = lineWrap;
this.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
this.actor.clutter_text.line_wrap = lineWrap;
this.actor.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
this.setMarkup(text, allowMarkup);
}
this.actor.connect('button-press-event', (actor, event) => {
// Don't try to URL highlight when invisible.
// The MessageTray doesn't actually hide us, so
// we need to check for paint opacities as well.
if (!actor.visible || actor.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE;
vfunc_button_press_event(buttonEvent) {
// Don't try to URL highlight when invisible.
// The MessageTray doesn't actually hide us, so
// we need to check for paint opacities as well.
if (!this.visible || this.get_paint_opacity() == 0)
// Keep Notification.actor from seeing this and taking
// a pointer grab, which would block our button-release-event
// handler, if an URL is clicked
return this._findUrlAtPos(event) != -1;
});
this.actor.connect('button-release-event', (actor, event) => {
if (!actor.visible || actor.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE;
let urlId = this._findUrlAtPos(event);
if (urlId != -1) {
let url = this._urls[urlId].url;
if (!url.includes(':'))
url = 'http://' + url;
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1));
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
});
this.actor.connect('motion-event', (actor, event) => {
if (!actor.visible || actor.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE;
// Keep Notification from seeing this and taking
// a pointer grab, which would block our button-release-event
// handler, if an URL is clicked
return this._findUrlAtPos(buttonEvent) != -1;
}
vfunc_button_release_event(buttonEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
let urlId = this._findUrlAtPos(event);
if (urlId != -1 && !this._cursorChanged) {
global.display.set_cursor(Meta.Cursor.POINTING_HAND);
this._cursorChanged = true;
} else if (urlId == -1) {
global.display.set_cursor(Meta.Cursor.DEFAULT);
this._cursorChanged = false;
}
return Clutter.EVENT_PROPAGATE;
});
this.actor.connect('leave-event', () => {
if (!this.actor.visible || this.actor.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE;
let urlId = this._findUrlAtPos(buttonEvent);
if (urlId != -1) {
let url = this._urls[urlId].url;
if (!url.includes(':'))
url = `http://${url}`;
Gio.app_info_launch_default_for_uri(
url, global.create_app_launch_context(0, -1));
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
}
vfunc_motion_event(motionEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
if (this._cursorChanged) {
this._cursorChanged = false;
global.display.set_cursor(Meta.Cursor.DEFAULT);
}
return Clutter.EVENT_PROPAGATE;
let urlId = this._findUrlAtPos(motionEvent);
if (urlId != -1 && !this._cursorChanged) {
global.display.set_cursor(Meta.Cursor.POINTING_HAND);
this._cursorChanged = true;
} else if (urlId == -1) {
global.display.set_cursor(Meta.Cursor.DEFAULT);
this._cursorChanged = false;
}
return Clutter.EVENT_PROPAGATE;
}
vfunc_leave_event(crossingEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE;
if (this._cursorChanged) {
this._cursorChanged = false;
global.display.set_cursor(Meta.Cursor.DEFAULT);
}
return super.vfunc_leave_event(crossingEvent);
});
}
setMarkup(text, allowMarkup) {
text = text ? _fixMarkup(text, allowMarkup) : '';
this._text = text;
this.clutter_text.set_markup(text);
this.actor.clutter_text.set_markup(text);
/* clutter_text.text contain text without markup */
this._urls = Util.findUrls(this.clutter_text.text);
this._urls = Util.findUrls(this.actor.clutter_text.text);
this._highlightUrls();
}
@ -132,33 +121,33 @@ class URLHighlighter extends St.Label {
for (let i = 0; i < urls.length; i++) {
let url = urls[i];
let str = this._text.substr(pos, url.pos - pos);
markup += `${str}<span foreground="${this._linkColor}"><u>${url.url}</u></span>`;
markup += str + '<span foreground="' + this._linkColor + '"><u>' + url.url + '</u></span>';
pos = url.pos + url.url.length;
}
markup += this._text.substr(pos);
this.clutter_text.set_markup(markup);
this.actor.clutter_text.set_markup(markup);
}
_findUrlAtPos(event) {
let { x, y } = event;
[, x, y] = this.transform_stage_point(x, y);
let success_;
let [x, y] = event.get_coords();
[success_, x, y] = this.actor.transform_stage_point(x, y);
let findPos = -1;
for (let i = 0; i < this.clutter_text.text.length; i++) {
let [, px, py, lineHeight] = this.clutter_text.position_to_coords(i);
for (let i = 0; i < this.actor.clutter_text.text.length; i++) {
let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + lineHeight < y || x < px)
continue;
findPos = i;
}
if (findPos != -1) {
for (let i = 0; i < this._urls.length; i++) {
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;
}
}
return -1;
}
});
};
var ScaleLayout = GObject.registerClass(
class ScaleLayout extends Clutter.BinLayout {
@ -171,22 +160,20 @@ class ScaleLayout extends Clutter.BinLayout {
if (this._container == container)
return;
if (this._container) {
if (this._container)
for (let id of this._signals)
this._container.disconnect(id);
}
this._container = container;
this._signals = [];
if (this._container) {
if (this._container)
for (let signal of ['notify::scale-x', 'notify::scale-y']) {
let id = this._container.connect(signal, () => {
this.layout_changed();
});
this._signals.push(id);
}
}
}
vfunc_get_preferred_width(container, forHeight) {
@ -213,7 +200,7 @@ var LabelExpanderLayout = GObject.registerClass({
'Expansion of the layout, between 0 (collapsed) ' +
'and 1 (fully expanded',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
0, 1, 0),
0, 1, 0)
},
}, class LabelExpanderLayout extends Clutter.LayoutManager {
_init(params) {
@ -235,7 +222,7 @@ var LabelExpanderLayout = GObject.registerClass({
let visibleIndex = this._expansion > 0 ? 1 : 0;
for (let i = 0; this._container && i < this._container.get_n_children(); i++)
this._container.get_child_at_index(i).visible = i == visibleIndex;
this._container.get_child_at_index(i).visible = (i == visibleIndex);
this.layout_changed();
}
@ -296,31 +283,21 @@ var LabelExpanderLayout = GObject.registerClass({
}
});
var Message = GObject.registerClass({
Signals: {
'close': {},
'expanded': {},
'unexpanded': {},
},
}, class Message extends St.Button {
_init(title, body) {
super._init({
style_class: 'message',
accessible_role: Atk.Role.NOTIFICATION,
can_focus: true,
x_expand: true,
y_expand: true,
});
var Message = class Message {
constructor(title, body) {
this.expanded = false;
this._useBodyMarkup = false;
let vbox = new St.BoxLayout({
vertical: true,
x_expand: true,
});
this.set_child(vbox);
this.actor = new St.Button({ style_class: 'message',
accessible_role: Atk.Role.NOTIFICATION,
can_focus: true,
x_expand: true, x_fill: true });
this.actor.connect('key-press-event',
this._onKeyPressed.bind(this));
let vbox = new St.BoxLayout({ vertical: true });
this.actor.set_child(vbox);
let hbox = new St.BoxLayout();
vbox.add_actor(hbox);
@ -331,7 +308,7 @@ var Message = GObject.registerClass({
this._iconBin = new St.Bin({ style_class: 'message-icon-bin',
y_expand: true,
y_align: Clutter.ActorAlign.START,
y_align: St.Align.START,
visible: false });
hbox.add_actor(this._iconBin);
@ -349,18 +326,14 @@ var Message = GObject.registerClass({
this.setTitle(title);
titleBox.add_actor(this.titleLabel);
this._secondaryBin = new St.Bin({
style_class: 'message-secondary-bin',
x_expand: true, y_expand: true,
});
this._secondaryBin = new St.Bin({ style_class: 'message-secondary-bin',
x_expand: true, y_expand: true,
x_fill: true, y_fill: true });
titleBox.add_actor(this._secondaryBin);
let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic',
icon_size: 16 });
this._closeButton = new St.Button({
style_class: 'message-close-button',
child: closeIcon, opacity: 0,
});
this._closeButton = new St.Button({ child: closeIcon, opacity: 0 });
titleBox.add_actor(this._closeButton);
this._bodyStack = new St.Widget({ x_expand: true });
@ -368,14 +341,15 @@ var Message = GObject.registerClass({
contentBox.add_actor(this._bodyStack);
this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup);
this.bodyLabel.add_style_class_name('message-body');
this._bodyStack.add_actor(this.bodyLabel);
this.bodyLabel.actor.add_style_class_name('message-body');
this._bodyStack.add_actor(this.bodyLabel.actor);
this.setBody(body);
this._closeButton.connect('clicked', this.close.bind(this));
let actorHoverId = this.connect('notify::hover', this._sync.bind(this));
this._closeButton.connect('destroy', this.disconnect.bind(this, actorHoverId));
this.connect('destroy', this._onDestroy.bind(this));
let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this));
this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId));
this.actor.connect('clicked', this._onClicked.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._sync();
}
@ -385,7 +359,7 @@ var Message = GObject.registerClass({
setIcon(actor) {
this._iconBin.child = actor;
this._iconBin.visible = actor != null;
this._iconBin.visible = (actor != null);
}
setSecondaryActor(actor) {
@ -456,12 +430,12 @@ var Message = GObject.registerClass({
expand(animate) {
this.expanded = true;
this._actionBin.visible = this._actionBin.get_n_children() > 0;
this._actionBin.visible = (this._actionBin.get_n_children() > 0);
if (this._bodyStack.get_n_children() < 2) {
this._expandedLabel = new URLHighlighter(this._bodyText,
true, this._useBodyMarkup);
this.setExpandedBody(this._expandedLabel);
this.setExpandedBody(this._expandedLabel.actor);
}
if (animate) {
@ -474,7 +448,7 @@ var Message = GObject.registerClass({
this._actionBin.ease({
scale_y: 1,
duration: MessageTray.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} else {
this._bodyStack.layout_manager.expansion = 1;
@ -498,7 +472,7 @@ var Message = GObject.registerClass({
onComplete: () => {
this._actionBin.hide();
this.expanded = false;
},
}
});
} else {
this._bodyStack.layout_manager.expansion = 0;
@ -514,16 +488,19 @@ var Message = GObject.registerClass({
}
_sync() {
let visible = this.hover && this.canClose();
let visible = this.actor.hover && this.canClose();
this._closeButton.opacity = visible ? 255 : 0;
this._closeButton.reactive = visible;
}
_onClicked() {
}
_onDestroy() {
}
vfunc_key_press_event(keyEvent) {
let keysym = keyEvent.keyval;
_onKeyPressed(a, event) {
let keysym = event.get_key_symbol();
if (keysym == Clutter.KEY_Delete ||
keysym == Clutter.KEY_KP_Delete) {
@ -532,66 +509,37 @@ var Message = GObject.registerClass({
}
return Clutter.EVENT_PROPAGATE;
}
});
};
Signals.addSignalMethods(Message.prototype);
var MessageListSection = GObject.registerClass({
Properties: {
'can-clear': GObject.ParamSpec.boolean(
'can-clear', 'can-clear', 'can-clear',
GObject.ParamFlags.READABLE,
false),
'empty': GObject.ParamSpec.boolean(
'empty', 'empty', 'empty',
GObject.ParamFlags.READABLE,
true),
},
Signals: {
'can-clear-changed': {},
'empty-changed': {},
'message-focused': { param_types: [Message.$gtype] },
},
}, class MessageListSection extends St.BoxLayout {
_init() {
super._init({
style_class: 'message-list-section',
clip_to_allocation: true,
vertical: true,
x_expand: true,
});
var MessageListSection = class MessageListSection {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'message-list-section',
clip_to_allocation: true,
x_expand: true, vertical: true });
this._list = new St.BoxLayout({ style_class: 'message-list-section-list',
vertical: true });
this.add_actor(this._list);
this.actor.add_actor(this._list);
this._list.connect('actor-added', this._sync.bind(this));
this._list.connect('actor-removed', this._sync.bind(this));
let id = Main.sessionMode.connect('updated',
this._sync.bind(this));
this.connect('destroy', () => {
this.actor.connect('destroy', () => {
Main.sessionMode.disconnect(id);
});
this._messages = new Map();
this._date = new Date();
this._empty = true;
this._canClear = false;
this.empty = true;
this.canClear = false;
this._sync();
}
get empty() {
return this._empty;
}
get canClear() {
return this._canClear;
}
get _messages() {
return this._list.get_children().map(i => i.child);
}
_onKeyFocusIn(messageActor) {
this.emit('message-focused', messageActor);
_onKeyFocusIn(actor) {
this.emit('key-focus-in', actor);
}
get allowed() {
@ -610,94 +558,94 @@ var MessageListSection = GObject.registerClass({
}
addMessageAtIndex(message, index, animate) {
if (this._messages.includes(message))
throw new Error('Message was already added previously');
let listItem = new St.Bin({
child: message,
layout_manager: new ScaleLayout(),
pivot_point: new Graphene.Point({ x: .5, y: .5 }),
let obj = {
container: null,
destroyId: 0,
keyFocusId: 0,
closeId: 0
};
let pivot = new Clutter.Point({ x: .5, y: .5 });
let scale = animate ? 0 : 1;
obj.container = new St.Widget({ layout_manager: new ScaleLayout(),
pivot_point: pivot,
scale_x: scale, scale_y: scale });
obj.keyFocusId = message.actor.connect('key-focus-in',
this._onKeyFocusIn.bind(this));
obj.destroyId = message.actor.connect('destroy', () => {
this.removeMessage(message, false);
});
listItem._connectionsIds = [];
listItem._connectionsIds.push(message.connect('key-focus-in',
this._onKeyFocusIn.bind(this)));
listItem._connectionsIds.push(message.connect('close', () => {
obj.closeId = message.connect('close', () => {
this.removeMessage(message, true);
}));
listItem._connectionsIds.push(message.connect('destroy', () => {
listItem._connectionsIds.forEach(id => message.disconnect(id));
listItem.destroy();
}));
});
this._list.insert_child_at_index(listItem, index);
this._messages.set(message, obj);
obj.container.add_actor(message.actor);
if (animate) {
listItem.set({ scale_x: 0, scale_y: 0 });
listItem.ease({
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,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
moveMessage(message, index, animate) {
if (!this._messages.includes(message))
throw new Error(`Impossible to move untracked message`);
let listItem = message.get_parent();
let obj = this._messages.get(message);
if (!animate) {
this._list.set_child_at_index(listItem, index);
this._list.set_child_at_index(obj.container, index);
return;
}
let onComplete = () => {
this._list.set_child_at_index(listItem, index);
listItem.ease({
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,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
};
listItem.ease({
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete,
onComplete
});
}
removeMessage(message, animate) {
if (!this._messages.includes(message))
throw new Error(`Impossible to remove untracked message`);
let obj = this._messages.get(message);
let listItem = message.get_parent();
listItem._connectionsIds.forEach(id => message.disconnect(id));
message.actor.disconnect(obj.destroyId);
message.actor.disconnect(obj.keyFocusId);
message.disconnect(obj.closeId);
this._messages.delete(message);
if (animate) {
listItem.ease({
obj.container.ease({
scale_x: 0,
scale_y: 0,
duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
listItem.destroy();
obj.container.destroy();
global.sync_pointer();
},
}
});
} else {
listItem.destroy();
obj.container.destroy();
global.sync_pointer();
}
}
clear() {
let messages = this._messages.filter(msg => msg.canClose());
let messages = [...this._messages.keys()].filter(msg => msg.canClose());
// If there are few messages, letting them all zoom out looks OK
if (messages.length < 2) {
@ -710,37 +658,46 @@ var MessageListSection = GObject.registerClass({
let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5);
for (let i = 0; i < messages.length; i++) {
let message = messages[i];
message.get_parent().ease({
translation_x: this._list.width,
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(),
onComplete: () => message.close()
});
}
}
}
_canClear() {
for (let message of this._messages.keys())
if (message.canClose())
return true;
return false;
}
_shouldShow() {
return !this.empty;
}
_sync() {
let messages = this._messages;
let empty = messages.length == 0;
let empty = this._list.get_n_children() == 0;
let changed = this.empty !== empty;
this.empty = empty;
if (this._empty != empty) {
this._empty = empty;
this.notify('empty');
}
if (changed)
this.emit('empty-changed');
let canClear = messages.some(m => m.canClose());
if (this._canClear != canClear) {
this._canClear = canClear;
this.notify('can-clear');
}
let canClear = this._canClear();
changed = this.canClear !== canClear;
this.canClear = canClear;
this.visible = this.allowed && this._shouldShow();
if (changed)
this.emit('can-clear-changed');
this.actor.visible = this.allowed && this._shouldShow();
}
});
};
Signals.addSignalMethods(MessageListSection.prototype);

View File

@ -4,6 +4,7 @@
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
const GnomeSession = imports.misc.gnomeSession;
@ -33,7 +34,7 @@ var State = {
HIDDEN: 0,
SHOWING: 1,
SHOWN: 2,
HIDING: 3,
HIDING: 3
};
// These reasons are useful when we destroy the notifications received through
@ -47,7 +48,7 @@ var NotificationDestroyedReason = {
EXPIRED: 1,
DISMISSED: 2,
SOURCE_CLOSED: 3,
REPLACED: 4,
REPLACED: 4
};
// Message tray has its custom Urgency enumeration. LOW, NORMAL and CRITICAL
@ -58,7 +59,7 @@ var Urgency = {
LOW: 0,
NORMAL: 1,
HIGH: 2,
CRITICAL: 3,
CRITICAL: 3
};
// The privacy of the details of a notification. USER is for notifications which
@ -133,82 +134,72 @@ var FocusGrabber = class FocusGrabber {
// source, such as whether to play sound or honour the critical bit.
//
// A notification without a policy object will inherit the default one.
var NotificationPolicy = GObject.registerClass({
Properties: {
'enable': GObject.ParamSpec.boolean(
'enable', 'enable', 'enable',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'enable-sound': GObject.ParamSpec.boolean(
'enable-sound', 'enable-sound', 'enable-sound',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'show-banners': GObject.ParamSpec.boolean(
'show-banners', 'show-banners', 'show-banners',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'force-expanded': GObject.ParamSpec.boolean(
'force-expanded', 'force-expanded', 'force-expanded',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'show-in-lock-screen': GObject.ParamSpec.boolean(
'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'details-in-lock-screen': GObject.ParamSpec.boolean(
'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
},
}, class NotificationPolicy extends GObject.Object {
var NotificationPolicy = class NotificationPolicy {
constructor(params) {
params = Params.parse(params, {
enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false,
});
Object.getOwnPropertyNames(params).forEach(key => {
let desc = Object.getOwnPropertyDescriptor(params, key);
Object.defineProperty(this, `_${key}`, desc);
});
}
// Do nothing for the default policy. These methods are only useful for the
// GSettings policy.
store() { }
destroy() {
this.run_dispose();
destroy() { }
get enable() {
return this._enable;
}
get enableSound() {
return this.enable_sound;
return this._enableSound;
}
get showBanners() {
return this.show_banners;
return this._showBanners;
}
get forceExpanded() {
return this.force_expanded;
return this._forceExpanded;
}
get showInLockScreen() {
return this.show_in_lock_screen;
return this._showInLockScreen;
}
get detailsInLockScreen() {
return this.details_in_lock_screen;
return this._detailsInLockScreen;
}
});
};
Signals.addSignalMethods(NotificationPolicy.prototype);
var NotificationGenericPolicy = GObject.registerClass({
}, class NotificationGenericPolicy extends NotificationPolicy {
_init() {
super._init();
var NotificationGenericPolicy =
class NotificationGenericPolicy extends NotificationPolicy {
constructor() {
super();
this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', this._changed.bind(this));
}
store() { }
destroy() {
this._masterSettings.run_dispose();
super.destroy();
}
_changed(settings, key) {
if (this.constructor.find_property(key))
this.notify(key);
this.emit('policy-changed', key);
}
get showBanners() {
@ -218,12 +209,12 @@ var NotificationGenericPolicy = GObject.registerClass({
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen');
}
});
};
var NotificationApplicationPolicy = GObject.registerClass({
}, class NotificationApplicationPolicy extends NotificationPolicy {
_init(id) {
super._init();
var NotificationApplicationPolicy =
class NotificationApplicationPolicy extends NotificationPolicy {
constructor(id) {
super();
this.id = id;
this._canonicalId = this._canonicalizeId(id);
@ -249,13 +240,12 @@ var NotificationApplicationPolicy = GObject.registerClass({
destroy() {
this._masterSettings.run_dispose();
this._settings.run_dispose();
super.destroy();
}
_changed(settings, key) {
if (this.constructor.find_property(key))
this.notify(key);
this.emit('policy-changed', key);
if (key == 'enable')
this.emit('enable-changed');
}
_canonicalizeId(id) {
@ -289,7 +279,7 @@ var NotificationApplicationPolicy = GObject.registerClass({
get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen');
}
});
};
// Notification:
// @source: the notification's Source
@ -346,25 +336,12 @@ var NotificationApplicationPolicy = GObject.registerClass({
// @source allows playing sounds).
//
// [1] https://developer.gnome.org/notification-spec/#markup
var Notification = GObject.registerClass({
Properties: {
'acknowledged': GObject.ParamSpec.boolean(
'acknowledged', 'acknowledged', 'acknowledged',
GObject.ParamFlags.READWRITE,
false),
},
Signals: {
'activated': {},
'destroy': { param_types: [GObject.TYPE_UINT] },
'updated': { param_types: [GObject.TYPE_BOOLEAN] },
},
}, class Notification extends GObject.Object {
_init(source, title, banner, params) {
super._init();
var Notification = class Notification {
constructor(source, title, banner, params) {
this.source = source;
this.title = title;
this.urgency = Urgency.NORMAL;
this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
this.isTransient = false;
this.privacyScope = PrivacyScope.USER;
@ -376,7 +353,6 @@ var Notification = GObject.registerClass({
this._soundFile = null;
this._soundPlayed = false;
this.actions = [];
this.setResident(false);
// If called with only one argument we assume the caller
// will call .update() later on. This is the case of
@ -435,7 +411,7 @@ var Notification = GObject.registerClass({
// @label: the label for the action's button
// @callback: the callback for the action
addAction(label, callback) {
this.actions.push({ label, callback });
this.actions.push({ label: label, callback: callback });
}
get acknowledged() {
@ -446,7 +422,7 @@ var Notification = GObject.registerClass({
if (this._acknowledged == v)
return;
this._acknowledged = v;
this.notify('acknowledged');
this.emit('acknowledged-changed');
}
setUrgency(urgency) {
@ -455,15 +431,6 @@ var Notification = GObject.registerClass({
setResident(resident) {
this.resident = resident;
if (this.resident) {
if (this._activatedId) {
this.disconnect(this._activatedId);
this._activatedId = 0;
}
} else if (!this._activatedId) {
this._activatedId = this.connect_after('activated', () => this.destroy());
}
}
setTransient(isTransient) {
@ -505,30 +472,23 @@ var Notification = GObject.registerClass({
activate() {
this.emit('activated');
if (!this.resident)
this.destroy();
}
destroy(reason = NotificationDestroyedReason.DISMISSED) {
if (this._activatedId) {
this.disconnect(this._activatedId);
delete this._activatedId;
}
this.emit('destroy', reason);
this.run_dispose();
}
});
};
Signals.addSignalMethods(Notification.prototype);
var NotificationBanner = GObject.registerClass({
Signals: {
'done-displaying': {},
'unfocused': {},
},
}, class NotificationBanner extends Calendar.NotificationMessage {
_init(notification) {
super._init(notification);
var NotificationBanner =
class NotificationBanner extends Calendar.NotificationMessage {
constructor(notification) {
super(notification);
this.can_focus = false;
this.add_style_class_name('notification-banner');
this.actor.can_focus = false;
this.actor.add_style_class_name('notification-banner');
this._buttonBox = null;
@ -609,13 +569,13 @@ var NotificationBanner = GObject.registerClass({
addAction(label, callback) {
let button = new St.Button({ style_class: 'notification-button',
label,
label: label,
x_expand: true,
can_focus: true });
return this.addButton(button, callback);
}
});
};
var SourceActor = GObject.registerClass(
class SourceActor extends St.Widget {
@ -632,7 +592,8 @@ class SourceActor extends St.Widget {
this._actorDestroyed = false;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._iconBin = new St.Bin({ x_expand: true,
this._iconBin = new St.Bin({ x_fill: true,
x_expand: true,
height: size * scaleFactor,
width: size * scaleFactor });
@ -679,7 +640,7 @@ class SourceActorWithLabel extends SourceActor {
this.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this));
this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this));
this._updateCount();
this.connect('destroy', () => {
@ -727,33 +688,11 @@ class SourceActorWithLabel extends SourceActor {
}
});
var Source = GObject.registerClass({
Properties: {
'count': GObject.ParamSpec.int(
'count', 'count', 'count',
GObject.ParamFlags.READABLE,
0, GLib.MAXINT32, 0),
'policy': GObject.ParamSpec.object(
'policy', 'policy', 'policy',
GObject.ParamFlags.READWRITE,
NotificationPolicy.$gtype),
'title': GObject.ParamSpec.string(
'title', 'title', 'title',
GObject.ParamFlags.READWRITE,
null),
},
Signals: {
'destroy': { param_types: [GObject.TYPE_UINT] },
'icon-updated': {},
'notification-added': { param_types: [Notification.$gtype] },
'notification-show': { param_types: [Notification.$gtype] },
},
}, class Source extends GObject.Object {
_init(title, iconName) {
super._init({ title });
var Source = class Source {
constructor(title, iconName) {
this.SOURCE_ICON_SIZE = 48;
this.title = title;
this.iconName = iconName;
this.isChat = false;
@ -788,7 +727,7 @@ var Source = GObject.registerClass({
}
countUpdated() {
super.notify('count');
this.emit('count-updated');
}
_createPolicy() {
@ -802,11 +741,8 @@ var Source = GObject.registerClass({
}
setTitle(newTitle) {
if (this.title == newTitle)
return;
this.title = newTitle;
this.notify('title');
this.emit('title-changed');
}
createBanner(notification) {
@ -831,10 +767,10 @@ var Source = GObject.registerClass({
return;
this.notifications.splice(index, 1);
this.countUpdated();
if (this.notifications.length == 0)
this.destroy();
this.countUpdated();
}
pushNotification(notification) {
@ -845,36 +781,22 @@ var Source = GObject.registerClass({
this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED);
notification.connect('destroy', this._onNotificationDestroy.bind(this));
notification.connect('notify::acknowledged', this.countUpdated.bind(this));
notification.connect('acknowledged-changed', this.countUpdated.bind(this));
this.notifications.push(notification);
this.emit('notification-added', notification);
this.countUpdated();
}
showNotification(notification) {
notify(notification) {
notification.acknowledged = false;
this.pushNotification(notification);
if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL)
this.emit('notification-show', notification);
else
if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) {
this.emit('notify', notification);
} else {
notification.playSound();
}
notify(propName) {
if (propName instanceof Notification) {
try {
throw new Error('Source.notify() has been moved to Source.showNotification()' +
'this code will break in the future');
} catch (e) {
logError(e);
this.showNotification(propName);
return;
}
}
super.notify(propName);
}
destroy(reason) {
@ -887,8 +809,6 @@ var Source = GObject.registerClass({
notifications[i].destroy(reason);
this.emit('destroy', reason);
this.run_dispose();
}
iconUpdated() {
@ -900,27 +820,17 @@ var Source = GObject.registerClass({
}
destroyNonResidentNotifications() {
for (let i = this.notifications.length - 1; i >= 0; i--) {
for (let i = this.notifications.length - 1; i >= 0; i--)
if (!this.notifications[i].resident)
this.notifications[i].destroy();
}
this.countUpdated();
}
});
var MessageTray = GObject.registerClass({
Signals: {
'queue-changed': {},
'source-added': { param_types: [Source.$gtype] },
'source-removed': { param_types: [Source.$gtype] },
},
}, class MessageTray extends St.Widget {
_init() {
super._init({
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
};
Signals.addSignalMethods(Source.prototype);
var MessageTray = class MessageTray {
constructor() {
this._presence = new GnomeSession.Presence((proxy, _error) => {
this._onStatusChanged(proxy.status);
});
@ -937,15 +847,18 @@ var MessageTray = GObject.registerClass({
// so fix up Clutter's view of the pointer position in
// that case.
let related = ev.get_related();
if (!related || this.contains(related))
if (!related || this.actor.contains(related))
global.sync_pointer();
});
this.actor = new St.Widget({ visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout() });
let constraint = new Layout.MonitorConstraint({ primary: true });
Main.layoutManager.panelBox.bind_property('visible',
constraint, 'work-area',
GObject.BindingFlags.SYNC_CREATE);
this.add_constraint(constraint);
this.actor.add_constraint(constraint);
this._bannerBin = new St.Widget({ name: 'notification-container',
reactive: true,
@ -959,7 +872,7 @@ var MessageTray = GObject.registerClass({
this._onNotificationKeyRelease.bind(this));
this._bannerBin.connect('notify::hover',
this._onNotificationHoverChanged.bind(this));
this.add_actor(this._bannerBin);
this.actor.add_actor(this._bannerBin);
this._notificationFocusGrabber = new FocusGrabber(this._bannerBin);
this._notificationQueue = [];
@ -988,7 +901,7 @@ var MessageTray = GObject.registerClass({
this._notificationTimeoutId = 0;
this._notificationRemoved = false;
Main.layoutManager.addChrome(this, { affectsInputRegion: false });
Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true });
global.display.connect('in-fullscreen-changed', this._updateState.bind(this));
@ -1031,11 +944,11 @@ var MessageTray = GObject.registerClass({
}
_onDragBegin() {
Shell.util_set_hidden_from_pick(this, true);
Shell.util_set_hidden_from_pick(this.actor, true);
}
_onDragEnd() {
Shell.util_set_hidden_from_pick(this, false);
Shell.util_set_hidden_from_pick(this.actor, false);
}
get bannerAlignment() {
@ -1084,22 +997,22 @@ var MessageTray = GObject.registerClass({
// Register that we got a notification for this source
source.policy.store();
source.policy.connect('notify::enable', () => {
source.policy.connect('enable-changed', () => {
this._onSourceEnableChanged(source.policy, source);
});
source.policy.connect('notify', this._updateState.bind(this));
source.policy.connect('policy-changed', this._updateState.bind(this));
this._onSourceEnableChanged(source.policy, source);
}
_addSource(source) {
let obj = {
showId: 0,
notifyId: 0,
destroyId: 0,
};
this._sources.set(source, obj);
obj.showId = source.connect('notification-show', this._onNotificationShow.bind(this));
obj.notifyId = source.connect('notify', this._onNotify.bind(this));
obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this));
this.emit('source-added', source);
@ -1109,7 +1022,7 @@ var MessageTray = GObject.registerClass({
let obj = this._sources.get(source);
this._sources.delete(source);
source.disconnect(obj.showId);
source.disconnect(obj.notifyId);
source.disconnect(obj.destroyId);
this.emit('source-removed', source);
@ -1150,7 +1063,7 @@ var MessageTray = GObject.registerClass({
}
}
_onNotificationShow(_source, notification) {
_onNotify(source, notification) {
if (this._notification == notification) {
// If a notification that is being shown is updated, we update
// how it is shown and extend the time until it auto-hides.
@ -1162,7 +1075,7 @@ var MessageTray = GObject.registerClass({
// indicator in the panel; however do make an exception for CRITICAL
// notifications, as only banner mode allows expansion.
let bannerCount = this._notification ? 1 : 0;
let full = this.queueCount + bannerCount >= MAX_NOTIFICATIONS_IN_QUEUE;
let full = (this.queueCount + bannerCount >= MAX_NOTIFICATIONS_IN_QUEUE);
if (!full || notification.urgency == Urgency.CRITICAL) {
notification.connect('destroy',
this._onNotificationDestroy.bind(this));
@ -1282,7 +1195,7 @@ var MessageTray = GObject.registerClass({
// at the present time.
_updateState() {
let hasMonitor = Main.layoutManager.primaryMonitor != null;
this.visible = !this._bannerBlocked && hasMonitor && this._banner != null;
this.actor.visible = !this._bannerBlocked && hasMonitor && this._banner != null;
if (this._bannerBlocked || !hasMonitor)
return;
@ -1309,7 +1222,7 @@ var MessageTray = GObject.registerClass({
let nextNotification = this._notificationQueue[0] || null;
if (hasNotifications && nextNotification) {
let limited = this._busy || Main.layoutManager.primaryMonitor.inFullscreen;
let showNextNotification = !limited || nextNotification.forFeedback || nextNotification.urgency == Urgency.CRITICAL;
let showNextNotification = (!limited || nextNotification.forFeedback || nextNotification.urgency == Urgency.CRITICAL);
if (showNextNotification)
this._showNotification();
}
@ -1319,7 +1232,7 @@ var MessageTray = GObject.registerClass({
this._notification.urgency != Urgency.CRITICAL &&
!this._banner.focused &&
!this._pointerInNotification) || this._notificationExpired;
let mustClose = this._notificationRemoved || !hasNotifications || expired;
let mustClose = (this._notificationRemoved || !hasNotifications || expired);
if (mustClose) {
let animate = hasNotifications && !this._notificationRemoved;
@ -1362,11 +1275,11 @@ var MessageTray = GObject.registerClass({
this._updateState();
});
this._bannerBin.add_actor(this._banner);
this._bannerBin.add_actor(this._banner.actor);
this._bannerBin.opacity = 0;
this._bannerBin.y = -this._banner.height;
this.show();
this._bannerBin.y = -this._banner.actor.height;
this.actor.show();
Meta.disable_unredirect_for_display(global.display);
this._updateShowingNotification();
@ -1414,7 +1327,7 @@ var MessageTray = GObject.registerClass({
this._bannerBin.ease({
opacity: 255,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
mode: Clutter.AnimationMode.LINEAR
});
this._bannerBin.ease({
y: 0,
@ -1424,7 +1337,7 @@ var MessageTray = GObject.registerClass({
this._notificationState = State.SHOWN;
this._showNotificationCompleted();
this._updateState();
},
}
});
}
@ -1490,7 +1403,7 @@ var MessageTray = GObject.registerClass({
this._bannerBin.ease({
opacity: 0,
duration: ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_BACK,
mode: Clutter.AnimationMode.EASE_OUT_BACK
});
this._bannerBin.ease({
y: -this._bannerBin.height,
@ -1500,7 +1413,7 @@ var MessageTray = GObject.registerClass({
this._notificationState = State.HIDDEN;
this._hideNotificationCompleted();
this._updateState();
},
}
});
} else {
this._bannerBin.y = -this._bannerBin.height;
@ -1513,16 +1426,16 @@ var MessageTray = GObject.registerClass({
_hideNotificationCompleted() {
let notification = this._notification;
this._notification = null;
if (!this._notificationRemoved && notification.isTransient)
if (notification.isTransient)
notification.destroy(NotificationDestroyedReason.EXPIRED);
this._pointerInNotification = false;
this._notificationRemoved = false;
Meta.enable_unredirect_for_display(global.display);
this._banner.destroy();
this._banner.actor.destroy();
this._banner = null;
this.hide();
this.actor.hide();
}
_expandActiveNotification() {
@ -1544,15 +1457,15 @@ var MessageTray = GObject.registerClass({
_ensureBannerFocused() {
this._notificationFocusGrabber.grabFocus();
}
});
};
Signals.addSignalMethods(MessageTray.prototype);
var SystemNotificationSource = GObject.registerClass(
class SystemNotificationSource extends Source {
_init() {
super._init(_("System Information"), 'dialog-information-symbolic');
var SystemNotificationSource = class SystemNotificationSource extends Source {
constructor() {
super(_("System Information"), 'dialog-information-symbolic');
}
open() {
this.destroy();
}
});
};

View File

@ -17,7 +17,7 @@ var State = {
CLOSED: 1,
OPENING: 2,
CLOSING: 3,
FADED_OUT: 4,
FADED_OUT: 4
};
var ModalDialog = GObject.registerClass({
@ -26,9 +26,9 @@ var ModalDialog = GObject.registerClass({
GObject.ParamFlags.READABLE,
Math.min(...Object.values(State)),
Math.max(...Object.values(State)),
State.CLOSED),
State.CLOSED)
},
Signals: { 'opened': {}, 'closed': {} },
Signals: { 'opened': {}, 'closed': {} }
}, class ModalDialog extends St.Widget {
_init(params) {
super._init({ visible: false,
@ -57,12 +57,9 @@ var ModalDialog = GObject.registerClass({
coordinate: Clutter.BindCoordinate.ALL });
this.add_constraint(constraint);
this.backgroundStack = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this._backgroundBin = new St.Bin({ child: this.backgroundStack });
this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._backgroundBin = new St.Bin({ child: this.backgroundStack,
x_fill: true, y_fill: true });
this._monitorConstraint = new Layout.MonitorConstraint();
this._backgroundBin.add_constraint(this._monitorConstraint);
this.add_actor(this._backgroundBin);
@ -124,7 +121,7 @@ var ModalDialog = GObject.registerClass({
this.dialogLayout.opacity = 255;
if (this._lightbox)
this._lightbox.lightOn();
this._lightbox.show();
this.opacity = 0;
this.show();
this.ease({
@ -134,7 +131,7 @@ var ModalDialog = GObject.registerClass({
onComplete: () => {
this._setState(State.OPENED);
this.emit('opened');
},
}
});
}
@ -183,7 +180,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0,
duration: OPEN_AND_CLOSE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._closeComplete(),
onComplete: () => this._closeComplete()
});
} else {
this._closeComplete();
@ -206,7 +203,7 @@ var ModalDialog = GObject.registerClass({
this._hasModal = false;
if (!this._shellReactive)
this.backgroundStack.set_child_above_sibling(this._eventBlocker, null);
this._eventBlocker.raise_top();
}
pushModal(timestamp) {
@ -219,8 +216,6 @@ var ModalDialog = GObject.registerClass({
if (!Main.pushModal(this, params))
return false;
Main.layoutManager.emit('system-modal-opened');
this._hasModal = true;
if (this._savedKeyFocus) {
this._savedKeyFocus.grab_key_focus();
@ -231,7 +226,7 @@ var ModalDialog = GObject.registerClass({
}
if (!this._shellReactive)
this.backgroundStack.set_child_below_sibling(this._eventBlocker, null);
this._eventBlocker.lower_bottom();
return true;
}
@ -258,7 +253,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (this.state = State.FADED_OUT),
onComplete: () => (this.state = State.FADED_OUT)
});
}
});

View File

@ -1,5 +1,5 @@
/* exported MediaSection */
const { Gio, GObject, Shell, St } = imports.gi;
const { Gio, Shell, St } = imports.gi;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
@ -19,10 +19,9 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
var MediaMessage = GObject.registerClass(
class MediaMessage extends MessageList.Message {
_init(player) {
super._init('', '');
var MediaMessage = class MediaMessage extends MessageList.Message {
constructor(player) {
super('', '');
this._player = player;
@ -44,20 +43,12 @@ class MediaMessage extends MessageList.Message {
this._player.next();
});
this._updateHandlerId =
this._player.connect('changed', this._update.bind(this));
this._closedHandlerId =
this._player.connect('closed', this.close.bind(this));
this._player.connect('changed', this._update.bind(this));
this._player.connect('closed', this.close.bind(this));
this._update();
}
_onDestroy() {
super._onDestroy();
this._player.disconnect(this._updateHandlerId);
this._player.disconnect(this._closedHandlerId);
}
vfunc_clicked() {
_onClicked() {
this._player.raise();
Main.panel.closeCalendar();
}
@ -72,7 +63,7 @@ class MediaMessage extends MessageList.Message {
if (this._player.trackCoverUrl) {
let file = Gio.File.new_for_uri(this._player.trackCoverUrl);
this._icon.gicon = new Gio.FileIcon({ file });
this._icon.gicon = new Gio.FileIcon({ file: file });
this._icon.remove_style_class_name('fallback');
} else {
this._icon.icon_name = 'audio-x-generic-symbolic';
@ -88,7 +79,7 @@ class MediaMessage extends MessageList.Message {
this._updateNavButton(this._prevButton, this._player.canGoPrevious);
this._updateNavButton(this._nextButton, this._player.canGoNext);
}
});
};
var MprisPlayer = class MprisPlayer {
constructor(busName) {
@ -103,7 +94,6 @@ var MprisPlayer = class MprisPlayer {
this._trackArtists = [];
this._trackTitle = '';
this._trackCoverUrl = '';
this._busName = busName;
}
get status() {
@ -186,39 +176,9 @@ var MprisPlayer = class MprisPlayer {
for (let prop in this._playerProxy.Metadata)
metadata[prop] = this._playerProxy.Metadata[prop].deep_unpack();
// Validate according to the spec; some clients send buggy metadata:
// https://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata
this._trackArtists = metadata['xesam:artist'];
if (!Array.isArray(this._trackArtists) ||
!this._trackArtists.every(artist => typeof artist === 'string')) {
if (typeof this._trackArtists !== 'undefined') {
log(`Received faulty track artist metadata from ${
this._busName}; expected an array of strings, got ${
this._trackArtists} (${typeof this._trackArtists})`);
}
this._trackArtists = [_("Unknown artist")];
}
this._trackTitle = metadata['xesam:title'];
if (typeof this._trackTitle !== 'string') {
if (typeof this._trackTitle !== 'undefined') {
log(`Received faulty track title metadata from ${
this._busName}; expected a string, got ${
this._trackTitle} (${typeof this._trackTitle})`);
}
this._trackTitle = _("Unknown title");
}
this._trackCoverUrl = metadata['mpris:artUrl'];
if (typeof this._trackCoverUrl !== 'string') {
if (typeof this._trackCoverUrl !== 'undefined') {
log(`Received faulty track cover art metadata from ${
this._busName}; expected a string, got ${
this._trackCoverUrl} (${typeof this._trackCoverUrl})`);
}
this._trackCoverUrl = '';
}
this._trackArtists = metadata['xesam:artist'] || [_("Unknown artist")];
this._trackTitle = metadata['xesam:title'] || _("Unknown title");
this._trackCoverUrl = metadata['mpris:artUrl'] || '';
this.emit('changed');
let visible = this._playerProxy.CanPlay;
@ -228,16 +188,15 @@ var MprisPlayer = class MprisPlayer {
if (visible)
this.emit('show');
else
this.emit('hide');
this._close();
}
}
};
Signals.addSignalMethods(MprisPlayer.prototype);
var MediaSection = GObject.registerClass(
class MediaSection extends MessageList.MessageListSection {
_init() {
super._init();
var MediaSection = class MediaSection extends MessageList.MessageListSection {
constructor() {
super();
this._players = new Map();
@ -256,20 +215,15 @@ class MediaSection extends MessageList.MessageListSection {
return;
let player = new MprisPlayer(busName);
let message = null;
player.connect('closed',
() => {
this._players.delete(busName);
});
player.connect('show', () => {
message = new MediaMessage(player);
this.addMessage(message, true);
});
player.connect('hide', () => {
this.removeMessage(message, true);
message = null;
});
player.connect('show',
() => {
let message = new MediaMessage(player);
this.addMessage(message, true);
});
this._players.set(busName, player);
}
@ -293,4 +247,4 @@ class MediaSection extends MessageList.MessageListSection {
if (newOwner && !oldOwner)
this._addPlayer(name);
}
});
};

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Config = imports.misc.config;
const Main = imports.ui.main;
@ -23,13 +23,13 @@ var NotificationClosedReason = {
EXPIRED: 1,
DISMISSED: 2,
APP_CLOSED: 3,
UNDEFINED: 4,
UNDEFINED: 4
};
var Urgency = {
LOW: 0,
NORMAL: 1,
CRITICAL: 2,
CRITICAL: 2
};
const rewriteRules = {
@ -39,8 +39,8 @@ const rewriteRules = {
{ pattern: /^XChat: New public message from: (\S*) \((.*)\)$/,
replacement: '$2 <$1>' },
{ pattern: /^XChat: Highlighted message from: (\S*) \((.*)\)$/,
replacement: '$2 <$1>' },
],
replacement: '$2 <$1>' }
]
};
var FdoNotificationDaemon = class FdoNotificationDaemon {
@ -201,13 +201,13 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
hints['image-data'] = hints['icon_data'];
}
let ndata = { appName,
icon,
summary,
body,
actions,
hints,
timeout };
let ndata = { appName: appName,
icon: icon,
summary: summary,
body: body,
actions: actions,
hints: hints,
timeout: timeout };
if (replacesId != 0 && this._notifications[replacesId]) {
ndata.id = id = replacesId;
ndata.notification = this._notifications[replacesId].notification;
@ -245,7 +245,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
return;
}
[pid] = result;
let [pid] = result;
source = this._getSource(appName, pid, ndata, sender, null);
this._senderToPid[sender] = pid;
@ -299,7 +299,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
else if (!gicon)
gicon = this._fallbackIconForNotificationData(hints);
notification.update(summary, body, { gicon,
notification.update(summary, body, { gicon: gicon,
bannerMarkup: true,
clear: true,
soundFile: hints['sound-file'],
@ -310,13 +310,12 @@ 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]];
if (actionId == 'default') {
if (actionId == 'default')
hasDefaultAction = true;
} else {
else
notification.addAction(label, () => {
this._emitActionInvoked(ndata.id, actionId);
});
}
}
}
@ -346,7 +345,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// of the 'transient' hint with hints['transient'] rather than hints.transient
notification.setTransient(!!hints['transient']);
let privacyScope = hints['x-gnome-privacy-scope'] || 'user';
let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
notification.setPrivacyScope(privacyScope == 'system'
? MessageTray.PrivacyScope.SYSTEM
: MessageTray.PrivacyScope.USER);
@ -384,7 +383,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
Config.PACKAGE_NAME,
'GNOME',
Config.PACKAGE_VERSION,
'1.2',
'1.2'
];
}
@ -413,10 +412,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
};
var FdoNotificationDaemonSource = GObject.registerClass(
var FdoNotificationDaemonSource =
class FdoNotificationDaemonSource extends MessageTray.Source {
_init(title, pid, sender, appId) {
super._init(title);
constructor(title, pid, sender, appId) {
super(title);
this.pid = pid;
this.app = this._getApp(appId);
@ -428,14 +427,13 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
else
this.useNotificationIcon = true;
if (sender) {
if (sender)
this._nameWatcherId = Gio.DBus.session.watch_name(sender,
Gio.BusNameWatcherFlags.NONE,
null,
this._onNameVanished.bind(this));
} else {
else
this._nameWatcherId = 0;
}
}
_createPolicy() {
@ -466,7 +464,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
if (notification.resident && this.app && tracker.focus_app == this.app)
this.pushNotification(notification);
else
this.showNotification(notification);
this.notify(notification);
}
_getApp(appId) {
@ -528,19 +526,19 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
return null;
}
}
});
};
const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW,
normal: MessageTray.Urgency.NORMAL,
high: MessageTray.Urgency.HIGH,
urgent: MessageTray.Urgency.CRITICAL,
urgent: MessageTray.Urgency.CRITICAL
};
var GtkNotificationDaemonNotification = GObject.registerClass(
var GtkNotificationDaemonNotification =
class GtkNotificationDaemonNotification extends MessageTray.Notification {
_init(source, notification) {
super._init(source);
constructor(source, notification) {
super(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { title,
@ -604,7 +602,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
serialize() {
return this._serialized;
}
});
};
const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application');
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
@ -620,9 +618,9 @@ function getPlatformData() {
function InvalidAppError() {}
var GtkNotificationDaemonAppSource = GObject.registerClass(
var GtkNotificationDaemonAppSource =
class GtkNotificationDaemonAppSource extends MessageTray.Source {
_init(appId) {
constructor(appId) {
let objectPath = objectPathFromAppId(appId);
if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError();
@ -631,7 +629,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!app)
throw new InvalidAppError();
super._init(app.get_name());
super(app.get_name());
this._appId = appId;
this._app = app;
@ -692,7 +690,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
this._notifications[notificationId] = notification;
if (showBanner)
this.showNotification(notification);
this.notify(notification);
else
this.pushNotification(notification);
@ -718,7 +716,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
}
return [this._appId, notifications];
}
});
};
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
@ -744,7 +742,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
delete this._sources[appId];
this._saveNotifications();
});
source.connect('notify::count', this._saveNotifications.bind(this));
source.connect('count-updated', this._saveNotifications.bind(this));
Main.messageTray.add(source);
this._sources[appId] = source;
return source;

View File

@ -1,33 +1,30 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdMonitorLabeler */
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const { Clutter, Gio, Meta, St } = imports.gi;
const Main = imports.ui.main;
var OsdMonitorLabel = GObject.registerClass(
class OsdMonitorLabel extends St.Widget {
_init(monitor, label) {
super._init({ x_expand: true, y_expand: true });
var OsdMonitorLabel = class {
constructor(monitor, label) {
this._actor = new St.Widget({ x_expand: true,
y_expand: true });
this._monitor = monitor;
this._box = new St.BoxLayout({ style_class: 'osd-window',
vertical: true });
this.add_actor(this._box);
this._actor.add_actor(this._box);
this._label = new St.Label({ style_class: 'osd-monitor-label',
text: label });
this._box.add(this._label);
Main.uiGroup.add_child(this);
Main.uiGroup.set_child_above_sibling(this, null);
Main.uiGroup.add_child(this._actor);
Main.uiGroup.set_child_above_sibling(this._actor, null);
this._position();
Meta.disable_unredirect_for_display(global.display);
this.connect('destroy', () => {
Meta.enable_unredirect_for_display(global.display);
});
}
_position() {
@ -40,7 +37,12 @@ class OsdMonitorLabel extends St.Widget {
this._box.y = workArea.y;
}
});
destroy() {
this._actor.destroy();
Meta.enable_unredirect_for_display(global.display);
}
};
var OsdMonitorLabeler = class {
constructor() {
@ -66,7 +68,7 @@ var OsdMonitorLabeler = class {
_trackClient(client) {
if (this._client)
return this._client == client;
return (this._client == client);
this._client = client;
this._clientWatchId = Gio.bus_watch_name(Gio.BusType.SESSION, client, 0, null,

View File

@ -41,42 +41,39 @@ class OsdWindowConstraint extends Clutter.Constraint {
}
});
var OsdWindow = GObject.registerClass(
class OsdWindow extends St.Widget {
_init(monitorIndex) {
super._init({
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
var OsdWindow = class {
constructor(monitorIndex) {
this.actor = new St.Widget({ x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
this._monitorIndex = monitorIndex;
let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
this.add_constraint(constraint);
this.actor.add_constraint(constraint);
this._boxConstraint = new OsdWindowConstraint();
this._box = new St.BoxLayout({ style_class: 'osd-window',
vertical: true });
this._box.add_constraint(this._boxConstraint);
this.add_actor(this._box);
this.actor.add_actor(this._box);
this._icon = new St.Icon({ y_expand: true });
this._box.add_child(this._icon);
this._icon = new St.Icon();
this._box.add(this._icon, { expand: true });
this._label = new St.Label();
this._box.add(this._label);
this._level = new BarLevel.BarLevel({
style_class: 'level',
value: 0,
value: 0
});
this._box.add(this._level);
this._hideTimeoutId = 0;
this._reset();
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._monitorsChangedId =
Main.layoutManager.connect('monitors-changed',
@ -86,7 +83,7 @@ class OsdWindow extends St.Widget {
themeContext.connect('notify::scale-factor',
this._relayout.bind(this));
this._relayout();
Main.uiGroup.add_child(this);
Main.uiGroup.add_child(this.actor);
}
_onDestroy() {
@ -105,22 +102,21 @@ class OsdWindow extends St.Widget {
}
setLabel(label) {
this._label.visible = label != undefined;
this._label.visible = (label != undefined);
if (label)
this._label.text = label;
}
setLevel(value) {
this._level.visible = value != undefined;
this._level.visible = (value != undefined);
if (value != undefined) {
if (this.visible) {
if (this.actor.visible)
this._level.ease_property('value', value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: LEVEL_ANIMATION_TIME,
duration: LEVEL_ANIMATION_TIME
});
} else {
else
this._level.value = value;
}
}
}
@ -132,16 +128,16 @@ class OsdWindow extends St.Widget {
if (!this._icon.gicon)
return;
if (!this.visible) {
if (!this.actor.visible) {
Meta.disable_unredirect_for_display(global.display);
super.show();
this.opacity = 0;
this.get_parent().set_child_above_sibling(this, null);
this.actor.show();
this.actor.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null);
this.ease({
this.actor.ease({
opacity: 255,
duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -162,20 +158,20 @@ class OsdWindow extends St.Widget {
_hide() {
this._hideTimeoutId = 0;
this.ease({
this.actor.ease({
opacity: 0,
duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._reset();
Meta.enable_unredirect_for_display(global.display);
},
}
});
return GLib.SOURCE_REMOVE;
}
_reset() {
super.hide();
this.actor.hide();
this.setLabel(null);
this.setMaxLevel(null);
this.setLevel(null);
@ -197,7 +193,7 @@ class OsdWindow extends St.Widget {
this._box.translation_y = Math.round(monitor.height / 4);
this._boxConstraint.minSize = popupSize;
}
});
};
var OsdWindowManager = class {
constructor() {
@ -214,7 +210,7 @@ var OsdWindowManager = class {
}
for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) {
this._osdWindows[i].destroy();
this._osdWindows[i].actor.destroy();
this._osdWindows[i] = null;
}

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
@ -72,109 +72,36 @@ var ShellInfo = class {
if (undoCallback)
notification.addAction(_("Undo"), this._onUndoClicked.bind(this));
this._source.showNotification(notification);
this._source.notify(notification);
}
};
var OverviewActor = GObject.registerClass(
class OverviewActor extends St.BoxLayout {
_init() {
super._init({
name: 'overview',
/* Translators: This is the main view to select
activities. See also note for "Activities" string. */
accessible_name: _("Overview"),
vertical: true,
});
this.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
// Add a clone of the panel to the overview so spacing and such is
// automatic
let panelGhost = new St.Bin({
child: new Clutter.Clone({ source: Main.panel }),
reactive: false,
opacity: 0,
});
this.add_actor(panelGhost);
this._searchEntry = new St.Entry({
style_class: 'search-entry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
characters. */
hint_text: _("Type to search…"),
track_hover: true,
can_focus: true,
});
this._searchEntry.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
let searchEntryBin = new St.Bin({
child: this._searchEntry,
x_align: Clutter.ActorAlign.CENTER,
});
this.add_actor(searchEntryBin);
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
// Add our same-line elements after the search entry
this.add_child(this._controls);
}
get dash() {
return this._controls.dash;
}
get searchEntry() {
return this._searchEntry;
}
get viewSelector() {
return this._controls.viewSelector;
}
});
var Overview = class {
constructor() {
this._overviewCreated = false;
this._initCalled = false;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
}
get dash() {
return this._overview.dash;
}
get dashIconSize() {
logError(new Error('Usage of Overview.\'dashIconSize\' is deprecated, ' +
'use \'dash.iconSize\' property instead'));
return this.dash.iconSize;
}
get viewSelector() {
return this._overview.viewSelector;
}
get animationInProgress() {
return this._animationInProgress;
}
get visible() {
return this._visible;
}
get visibleTarget() {
return this._visibleTarget;
}
_createOverview() {
if (this._overview)
if (this._overviewCreated)
return;
if (this.isDummy)
return;
this._overviewCreated = true;
this._overview = new St.BoxLayout({ name: 'overview',
/* Translators: This is the main view to select
activities. See also note for "Activities" string. */
accessible_name: _("Overview"),
vertical: true });
this._overview.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
this._overview._delegate = this;
// The main Background actors are inside global.window_group which are
// hidden when displaying the overview, so we create a new
// one. Instances of this class share a single CoglTexture behind the
@ -189,11 +116,11 @@ var Overview = class {
this._activationTime = 0;
this._visible = false; // animating to overview, in overview, animating out
this.visible = false; // animating to overview, in overview, animating out
this._shown = false; // show() and not hide()
this._modal = false; // have a modal grab
this._animationInProgress = false;
this._visibleTarget = false;
this.animationInProgress = false;
this.visibleTarget = false;
// During transitions, we raise this to the top to avoid having the overview
// area be reactive; it causes too many issues such as double clicks on
@ -202,11 +129,14 @@ var Overview = class {
reactive: true });
Main.layoutManager.overviewGroup.add_child(this._coverPane);
this._coverPane.connect('event', () => Clutter.EVENT_STOP);
Main.layoutManager.overviewGroup.add_child(this._overview);
this._coverPane.hide();
// XDND
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
dragMotion: this._onDragMotion.bind(this)
};
@ -245,11 +175,11 @@ var Overview = class {
for (let i = 0; i < backgrounds.length; i++) {
backgrounds[i].ease_property('brightness', 1.0, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
backgrounds[i].ease_property('vignette-sharpness', 0.0, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@ -259,11 +189,11 @@ var Overview = class {
for (let i = 0; i < backgrounds.length; i++) {
backgrounds[i].ease_property('brightness', Lightbox.VIGNETTE_BRIGHTNESS, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
backgrounds[i].ease_property('vignette-sharpness', Lightbox.VIGNETTE_SHARPNESS, {
duration: SHADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
}
@ -283,12 +213,41 @@ var Overview = class {
if (this.isDummy)
return;
this._overview = new OverviewActor();
this._overview._delegate = this;
Main.layoutManager.overviewGroup.add_child(this._overview);
this._shellInfo = new ShellInfo();
// Add a clone of the panel to the overview so spacing and such is
// automatic
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel }),
reactive: false,
opacity: 0 });
this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ style_class: 'search-entry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
characters. */
hint_text: _("Type to search…"),
track_hover: true,
can_focus: true });
this._searchEntryBin = new St.Bin({ child: this._searchEntry,
x_align: St.Align.MIDDLE });
this._overview.add_actor(this._searchEntryBin);
// Create controls
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
this._dash = this._controls.dash;
this.viewSelector = this._controls.viewSelector;
// Add our same-line elements after the search entry
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
// TODO - recalculate everything when desktop size changes
this.dashIconSize = this._dash.iconSize;
this._dash.connect('icon-size-changed', () => {
this.dashIconSize = this._dash.iconSize;
});
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
this._relayout();
}
@ -467,7 +426,7 @@ var Overview = class {
focusSearch() {
this.show();
this._overview.searchEntry.grab_key_focus();
this._searchEntry.grab_key_focus();
}
fadeInDesktop() {
@ -476,7 +435,7 @@ var Overview = class {
this._desktopFade.ease({
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
duration: ANIMATION_TIME
});
}
@ -494,7 +453,7 @@ var Overview = class {
this._desktopFade.ease({
opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
duration: ANIMATION_TIME
});
}
@ -505,11 +464,11 @@ var Overview = class {
// the overview if the user both triggered the hot corner and
// clicked the Activities button.
shouldToggleByCornerOrButton() {
if (this._animationInProgress)
if (this.animationInProgress)
return false;
if (this._inItemDrag || this._inWindowDrag)
return false;
if (!this._activationTime ||
if (this._activationTime == 0 ||
GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
return true;
return false;
@ -519,7 +478,7 @@ var Overview = class {
// We delay grab changes during animation so that when removing the
// overview we don't have a problem with the release of a press/release
// going to an application.
if (this._animationInProgress)
if (this.animationInProgress)
return true;
if (this._shown) {
@ -534,7 +493,6 @@ var Overview = class {
}
}
} else {
// eslint-disable-next-line no-lonely-if
if (this._modal) {
Main.popModal(this._overview);
this._modal = false;
@ -562,12 +520,12 @@ var Overview = class {
_animateVisible() {
if (this._visible || this._animationInProgress)
if (this.visible || this.animationInProgress)
return;
this._visible = true;
this._animationInProgress = true;
this._visibleTarget = true;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
Meta.disable_unredirect_for_display(global.display);
@ -578,18 +536,17 @@ var Overview = class {
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
onComplete: () => this._showDone(),
onComplete: () => this._showDone()
});
this._shadeBackgrounds();
Main.layoutManager.overviewGroup.set_child_above_sibling(
this._coverPane, null);
this._coverPane.raise_top();
this._coverPane.show();
this.emit('showing');
}
_showDone() {
this._animationInProgress = false;
this.animationInProgress = false;
this._desktopFade.hide();
this._coverPane.hide();
@ -615,8 +572,8 @@ var Overview = class {
let event = Clutter.get_current_event();
if (event) {
let type = event.type();
let button = type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE;
let button = (type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE);
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0;
if (button && ctrl)
return;
@ -629,11 +586,11 @@ var Overview = class {
}
_animateNotVisible() {
if (!this._visible || this._animationInProgress)
if (!this.visible || this.animationInProgress)
return;
this._animationInProgress = true;
this._visibleTarget = false;
this.animationInProgress = true;
this.visibleTarget = false;
this.viewSelector.animateFromOverview();
@ -642,12 +599,11 @@ var Overview = class {
opacity: 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME,
onComplete: () => this._hideDone(),
onComplete: () => this._hideDone()
});
this._unshadeBackgrounds();
Main.layoutManager.overviewGroup.set_child_above_sibling(
this._coverPane, null);
this._coverPane.raise_top();
this._coverPane.show();
this.emit('hiding');
}
@ -660,8 +616,8 @@ var Overview = class {
this._desktopFade.hide();
this._coverPane.hide();
this._visible = false;
this._animationInProgress = false;
this.visible = false;
this.animationInProgress = false;
this.emit('hidden');
// Handle any calls to show* while we were hiding
@ -677,17 +633,14 @@ var Overview = class {
if (this.isDummy)
return;
if (this._visible)
if (this.visible)
this.hide();
else
this.show();
}
getShowAppsButton() {
logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
'use \'dash.showAppsButton\' property instead'));
return this.dash.showAppsButton;
return this._dash.showAppsButton;
}
};
Signals.addSignalMethods(Overview.prototype);

View File

@ -12,17 +12,17 @@ const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
var SIDE_CONTROLS_ANIMATION_TIME = 160;
function getRtlSlideDirection(direction, actor) {
let rtl = actor.text_direction == Clutter.TextDirection.RTL;
if (rtl) {
direction = direction == SlideDirection.LEFT
let rtl = (actor.text_direction == Clutter.TextDirection.RTL);
if (rtl)
direction = (direction == SlideDirection.LEFT)
? SlideDirection.RIGHT : SlideDirection.LEFT;
}
return direction;
}
var SlideDirection = {
LEFT: 0,
RIGHT: 1,
RIGHT: 1
};
var SlideLayout = GObject.registerClass({
@ -34,8 +34,8 @@ var SlideLayout = GObject.registerClass({
'translation-x': GObject.ParamSpec.double(
'translation-x', 'translation-x', 'translation-x',
GObject.ParamFlags.READWRITE,
-Infinity, Infinity, 0),
},
-Infinity, Infinity, 0)
}
}, class SlideLayout extends Clutter.FixedLayout {
_init(params) {
this._slideX = 1;
@ -67,7 +67,7 @@ var SlideLayout = GObject.registerClass({
// flags only determine what to do if the allocated box is bigger
// than the actor's box.
let realDirection = getRtlSlideDirection(this._direction, child);
let alignX = realDirection == SlideDirection.LEFT
let alignX = (realDirection == SlideDirection.LEFT)
? availWidth - natWidth
: availWidth - natWidth * this._slideX;
@ -118,22 +118,19 @@ var SlideLayout = GObject.registerClass({
}
});
var SlidingControl = GObject.registerClass(
class SlidingControl extends St.Widget {
_init(params) {
var SlidingControl = class {
constructor(params) {
params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
this.layout = new SlideLayout();
this.layout.slideDirection = params.slideDirection;
super._init({
layout_manager: this.layout,
style_class: 'overview-controls',
clip_to_allocation: true,
});
this._visible = true;
this._inDrag = false;
this.layout = new SlideLayout();
this.layout.slideDirection = params.slideDirection;
this.actor = new St.Widget({ layout_manager: this.layout,
style_class: 'overview-controls',
clip_to_allocation: true });
Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
@ -150,25 +147,25 @@ class SlidingControl extends St.Widget {
}
_updateSlide() {
this.ease_property('@layout.slide-x', this._getSlide(), {
this.actor.ease_property('@layout.slide-x', this._getSlide(), {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME,
});
}
getVisibleWidth() {
let child = this.get_first_child();
let child = this.actor.get_first_child();
let [, , natWidth] = child.get_preferred_size();
return natWidth;
}
_getTranslation() {
let child = this.get_first_child();
let child = this.actor.get_first_child();
let direction = getRtlSlideDirection(this.layout.slideDirection, child);
let visibleWidth = this.getVisibleWidth();
if (direction == SlideDirection.LEFT)
return -visibleWidth;
return - visibleWidth;
else
return visibleWidth;
}
@ -178,17 +175,18 @@ class SlidingControl extends St.Widget {
let translationEnd = 0;
let translation = this._getTranslation();
let shouldShow = this._getSlide() > 0;
if (shouldShow)
let shouldShow = (this._getSlide() > 0);
if (shouldShow) {
translationStart = translation;
else
} else {
translationEnd = translation;
}
if (this.layout.translation_x == translationEnd)
return;
this.layout.translation_x = translationStart;
this.ease_property('@layout.translation-x', translationEnd, {
this.actor.ease_property('@layout.translation-x', translationEnd, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME,
});
@ -220,18 +218,18 @@ class SlidingControl extends St.Widget {
}
fadeIn() {
this.ease({
this.actor.ease({
opacity: 255,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
}
fadeHalf() {
this.ease({
this.actor.ease({
opacity: 128,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -251,38 +249,37 @@ class SlidingControl extends St.Widget {
// selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called,
// changing the visiblity
this.remove_transition('@layout.slide-x');
this.actor.remove_transition('@layout.slide-x');
this.layout.slide_x = this._getSlide();
this._updateTranslation();
}
});
};
var ThumbnailsSlider = GObject.registerClass(
class ThumbnailsSlider extends SlidingControl {
_init(thumbnailsBox) {
super._init({ slideDirection: SlideDirection.RIGHT });
var ThumbnailsSlider = class extends SlidingControl {
constructor(thumbnailsBox) {
super({ slideDirection: SlideDirection.RIGHT });
this._thumbnailsBox = thumbnailsBox;
this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
this.reactive = true;
this.track_hover = true;
this.add_actor(this._thumbnailsBox);
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
this.actor.reactive = true;
this.actor.track_hover = true;
this.actor.add_actor(this._thumbnailsBox);
Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
global.workspace_manager.connect('active-workspace-changed',
this._updateSlide.bind(this));
global.workspace_manager.connect('notify::n-workspaces',
this._updateSlide.bind(this));
this.connect('notify::hover', this._updateSlide.bind(this));
this._thumbnailsBox.bind_property('visible', this, 'visible', GObject.BindingFlags.SYNC_CREATE);
this.actor.connect('notify::hover', this._updateSlide.bind(this));
this._thumbnailsBox.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
}
_getAlwaysZoomOut() {
// Always show the pager on hover, during a drag, or if workspaces are
// actually used, e.g. there are windows on any non-active workspace
let workspaceManager = global.workspace_manager;
let alwaysZoomOut = this.hover ||
let alwaysZoomOut = this.actor.hover ||
this._inDrag ||
!Meta.prefs_get_dynamic_workspaces() ||
workspaceManager.n_workspaces > 2 ||
@ -307,12 +304,12 @@ class ThumbnailsSlider extends SlidingControl {
}
getNonExpandedWidth() {
let child = this.get_first_child();
let child = this.actor.get_first_child();
return child.get_theme_node().get_length('visible-width');
}
_onDragEnd() {
this.sync_hover();
this.actor.sync_hover();
super._onDragEnd();
}
@ -324,7 +321,7 @@ class ThumbnailsSlider extends SlidingControl {
if (alwaysZoomOut)
return 1;
let child = this.get_first_child();
let child = this.actor.get_first_child();
let preferredHeight = child.get_preferred_height(-1)[1];
let expandedWidth = child.get_preferred_width(preferredHeight)[1];
@ -338,25 +335,24 @@ class ThumbnailsSlider extends SlidingControl {
else
return this.getNonExpandedWidth();
}
});
};
var DashSlider = GObject.registerClass(
class DashSlider extends SlidingControl {
_init(dash) {
super._init({ slideDirection: SlideDirection.LEFT });
var DashSlider = class extends SlidingControl {
constructor(dash) {
super({ slideDirection: SlideDirection.LEFT });
this._dash = dash;
// SlideLayout reads the actor's expand flags to decide
// whether to allocate the natural size to its child, or the whole
// available allocation
this._dash.x_expand = true;
this._dash.actor.x_expand = true;
this.x_expand = true;
this.x_align = Clutter.ActorAlign.START;
this.y_expand = true;
this.actor.x_expand = true;
this.actor.x_align = Clutter.ActorAlign.START;
this.actor.y_expand = true;
this.add_actor(this._dash);
this.actor.add_actor(this._dash.actor);
this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
}
@ -375,7 +371,7 @@ class DashSlider extends SlidingControl {
_onWindowDragEnd() {
this.fadeIn();
}
});
};
var DashSpacer = GObject.registerClass(
class DashSpacer extends St.Widget {
@ -420,21 +416,12 @@ var ControlsLayout = GObject.registerClass({
}
});
var ControlsManager = GObject.registerClass(
class ControlsManager extends St.Widget {
_init(searchEntry) {
let layout = new ControlsLayout();
super._init({
layout_manager: layout,
x_expand: true,
y_expand: true,
clip_to_allocation: true,
});
var ControlsManager = class {
constructor(searchEntry) {
this.dash = new Dash.Dash();
this._dashSlider = new DashSlider(this.dash);
this._dashSpacer = new DashSpacer();
this._dashSpacer.setDashActor(this._dashSlider);
this._dashSpacer.setDashActor(this._dashSlider.actor);
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
@ -444,15 +431,20 @@ class ControlsManager extends St.Widget {
this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
let layout = new ControlsLayout();
this.actor = new St.Widget({ layout_manager: layout,
x_expand: true, y_expand: true,
clip_to_allocation: true });
this._group = new St.BoxLayout({ name: 'overview-group',
x_expand: true, y_expand: true });
this.add_actor(this._group);
this.actor.add_actor(this._group);
this.add_actor(this._dashSlider);
this.actor.add_actor(this._dashSlider.actor);
this._group.add_actor(this._dashSpacer);
this._group.add_child(this.viewSelector);
this._group.add_actor(this._thumbnailsSlider);
this._group.add(this.viewSelector.actor, { x_fill: true,
expand: true });
this._group.add_actor(this._thumbnailsSlider.actor);
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
@ -460,18 +452,18 @@ class ControlsManager extends St.Widget {
}
_updateWorkspacesGeometry() {
let [x, y] = this.get_transformed_position();
let [width, height] = this.get_transformed_size();
let geometry = { x, y, width, height };
let [x, y] = this.actor.get_transformed_position();
let [width, height] = this.actor.get_transformed_size();
let geometry = { x: x, y: y, width: width, height: height };
let spacing = this.get_theme_node().get_length('spacing');
let spacing = this.actor.get_theme_node().get_length('spacing');
let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
geometry.width -= dashWidth;
geometry.width -= thumbnailsWidth;
if (this.get_text_direction() == Clutter.TextDirection.LTR)
if (this.actor.get_text_direction() == Clutter.TextDirection.LTR)
geometry.x += dashWidth;
else
geometry.x += thumbnailsWidth;
@ -489,9 +481,9 @@ class ControlsManager extends St.Widget {
return;
let activePage = this.viewSelector.getActivePage();
let dashVisible = activePage == ViewSelector.ViewPage.WINDOWS ||
activePage == ViewSelector.ViewPage.APPS;
let thumbnailsVisible = activePage == ViewSelector.ViewPage.WINDOWS;
let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS ||
activePage == ViewSelector.ViewPage.APPS);
let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS);
if (dashVisible)
this._dashSlider.slideIn();
@ -509,7 +501,7 @@ class ControlsManager extends St.Widget {
return;
let activePage = this.viewSelector.getActivePage();
this._dashSpacer.visible = activePage == ViewSelector.ViewPage.WINDOWS;
this._dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS);
}
_onPageEmpty() {
@ -518,4 +510,4 @@ class ControlsManager extends St.Widget {
this._updateSpacerVisibility();
}
});
};

View File

@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PadOsd, PadOsdService */
/* exported PadOsdService */
const { Atk, Clutter, GDesktopEnums, Gio,
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
@ -22,45 +22,40 @@ const CCW = 1;
const UP = 0;
const DOWN = 1;
var PadChooser = GObject.registerClass({
Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } },
}, class PadChooser extends St.Button {
_init(device, groupDevices) {
super._init({
style_class: 'pad-chooser-button',
toggle_mode: true,
});
var PadChooser = class {
constructor(device, groupDevices) {
this.actor = new St.Button({ style_class: 'pad-chooser-button',
toggle_mode: true,
x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.currentDevice = device;
this._padChooserMenu = null;
let arrow = new St.Icon({
style_class: 'popup-menu-arrow',
icon_name: 'pan-down-symbolic',
accessible_role: Atk.Role.ARROW,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
this.set_child(arrow);
let arrow = new St.Icon({ style_class: 'popup-menu-arrow',
icon_name: 'pan-down-symbolic',
accessible_role: Atk.Role.ARROW });
this.actor.set_child(arrow);
this._ensureMenu(groupDevices);
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_clicked() {
if (this.get_checked()) {
if (this._padChooserMenu != null)
this._padChooserMenu.open(true);
else
this.set_checked(false);
} else {
this._padChooserMenu.close(true);
}
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('clicked', actor => {
if (actor.get_checked()) {
if (this._padChooserMenu != null)
this._padChooserMenu.open(true);
else
this.set_checked(false);
} else {
this._padChooserMenu.close(true);
}
});
}
_ensureMenu(devices) {
this._padChooserMenu = new PopupMenu.PopupMenu(this, 0.5, St.Side.TOP);
this._padChooserMenu = new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.TOP);
this._padChooserMenu.connect('menu-closed', () => {
this.set_checked(false);
this.actor.set_checked(false);
});
this._padChooserMenu.actor.hide();
Main.uiGroup.add_actor(this._padChooserMenu.actor);
@ -83,19 +78,24 @@ var PadChooser = GObject.registerClass({
update(devices) {
if (this._padChooserMenu)
this._padChooserMenu.actor.destroy();
this.set_checked(false);
this.actor.set_checked(false);
this._ensureMenu(devices);
}
});
var KeybindingEntry = GObject.registerClass({
Signals: { 'keybinding-edited': {} },
}, class KeybindingEntry extends St.Entry {
_init() {
super._init({ hint_text: _("New shortcut…"), style: 'width: 10em' });
destroy() {
this.actor.destroy();
}
};
Signals.addSignalMethods(PadChooser.prototype);
var KeybindingEntry = class {
constructor() {
this.actor = new St.Entry({ hint_text: _("New shortcut…"),
style: 'width: 10em' });
this.actor.connect('captured-event', this._onCapturedEvent.bind(this));
}
vfunc_captured_event(event) {
_onCapturedEvent(actor, event) {
if (event.type() != Clutter.EventType.KEY_PRESS)
return Clutter.EVENT_PROPAGATE;
@ -103,23 +103,23 @@ var KeybindingEntry = GObject.registerClass({
event.get_key_symbol(),
event.get_key_code(),
event.get_state());
this.set_text(str);
this.actor.set_text(str);
this.emit('keybinding-edited', str);
return Clutter.EVENT_STOP;
}
});
};
Signals.addSignalMethods(KeybindingEntry.prototype);
var ActionComboBox = GObject.registerClass({
Signals: { 'action-selected': { param_types: [GObject.TYPE_INT] } },
}, class ActionComboBox extends St.Button {
_init() {
super._init({ style_class: 'button' });
this.set_toggle_mode(true);
var ActionComboBox = class {
constructor() {
this.actor = new St.Button({ style_class: 'button' });
this.actor.connect('clicked', this._onButtonClicked.bind(this));
this.actor.set_toggle_mode(true);
let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
spacing: 6 });
let box = new St.Widget({ layout_manager: boxLayout });
this.set_child(box);
this.actor.set_child(box);
this._label = new St.Label({ style_class: 'combo-box-label' });
box.add_child(this._label);
@ -131,9 +131,9 @@ var ActionComboBox = GObject.registerClass({
y_align: Clutter.ActorAlign.CENTER });
box.add_child(arrow);
this._editMenu = new PopupMenu.PopupMenu(this, 0, St.Side.TOP);
this._editMenu = new PopupMenu.PopupMenu(this.actor, 0, St.Side.TOP);
this._editMenu.connect('menu-closed', () => {
this.set_checked(false);
this.actor.set_checked(false);
});
this._editMenu.actor.hide();
Main.uiGroup.add_actor(this._editMenu.actor);
@ -179,8 +179,8 @@ var ActionComboBox = GObject.registerClass({
this._editMenu.close(true);
}
vfunc_clicked() {
if (this.get_checked())
_onButtonClicked() {
if (this.actor.get_checked())
this.popup();
else
this.popdown();
@ -189,39 +189,38 @@ var ActionComboBox = GObject.registerClass({
setButtonActionsActive(active) {
this._buttonItems.forEach(item => item.setSensitive(active));
}
});
};
Signals.addSignalMethods(ActionComboBox.prototype);
var ActionEditor = GObject.registerClass({
Signals: { 'done': {} },
}, class ActionEditor extends St.Widget {
_init() {
var ActionEditor = class {
constructor() {
let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
spacing: 12 });
super._init({ layout_manager: boxLayout });
this.actor = new St.Widget({ layout_manager: boxLayout });
this._actionComboBox = new ActionComboBox();
this._actionComboBox.connect('action-selected', this._onActionSelected.bind(this));
this.add_actor(this._actionComboBox);
this.actor.add_actor(this._actionComboBox.actor);
this._keybindingEdit = new KeybindingEntry();
this._keybindingEdit.connect('keybinding-edited', this._onKeybindingEdited.bind(this));
this.add_actor(this._keybindingEdit);
this.actor.add_actor(this._keybindingEdit.actor);
this._doneButton = new St.Button({ label: _("Done"),
style_class: 'button',
x_expand: false });
this._doneButton.connect('clicked', this._onEditingDone.bind(this));
this.add_actor(this._doneButton);
this.actor.add_actor(this._doneButton);
}
_updateKeybindingEntryState() {
if (this._currentAction == GDesktopEnums.PadButtonAction.KEYBINDING) {
this._keybindingEdit.set_text(this._currentKeybinding);
this._keybindingEdit.show();
this._keybindingEdit.grab_key_focus();
this._keybindingEdit.actor.set_text(this._currentKeybinding);
this._keybindingEdit.actor.show();
this._keybindingEdit.actor.grab_key_focus();
} else {
this._keybindingEdit.hide();
this._keybindingEdit.actor.hide();
}
}
@ -233,13 +232,13 @@ var ActionEditor = GObject.registerClass({
this._actionComboBox.setAction(this._currentAction);
this._updateKeybindingEntryState();
let isButton = action == Meta.PadActionType.BUTTON;
let isButton = (action == Meta.PadActionType.BUTTON);
this._actionComboBox.setButtonActionsActive(isButton);
}
close() {
this._actionComboBox.popdown();
this.hide();
this.actor.hide();
}
_onKeybindingEdited(entry, keybinding) {
@ -273,7 +272,8 @@ var ActionEditor = GObject.registerClass({
this.close();
this.emit('done');
}
});
};
Signals.addSignalMethods(ActionEditor.prototype);
var PadDiagram = GObject.registerClass({
Properties: {
@ -291,7 +291,7 @@ var PadDiagram = GObject.registerClass({
'Editor actor',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
Clutter.Actor.$gtype),
Clutter.Actor.$gtype)
},
}, class PadDiagram extends St.DrawingArea {
_init(params) {
@ -344,19 +344,17 @@ var PadDiagram = GObject.registerClass({
}
_wrappingSvgHeader() {
return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
'xmlns:xi="http://www.w3.org/2001/XInclude" ' +
`width="${ // " (give xgettext the paired quotes it expects)
this._imageWidth
}" height="${this._imageHeight}"> ` + // "
'<style type="text/css">';
return ('<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
'xmlns:xi="http://www.w3.org/2001/XInclude" ' +
`width="${this._imageWidth}" height="${this._imageHeight}"> ` +
'<style type="text/css">');
}
_wrappingSvgFooter() {
return '</style>' +
return ('</style>' +
'<xi:include href="' + this._imagePath + '" />' +
'</svg>';
'</svg>');
}
_cssString() {
@ -617,21 +615,8 @@ var PadDiagram = GObject.registerClass({
}
});
var PadOsd = GObject.registerClass({
Signals: {
'pad-selected': { param_types: [Clutter.InputDevice.$gtype] },
'closed': {},
},
}, class PadOsd extends St.BoxLayout {
_init(padDevice, settings, imagePath, editionMode, monitorIndex) {
super._init({
style_class: 'pad-osd-window',
vertical: true,
x_expand: true,
y_expand: true,
reactive: true,
});
var PadOsd = class {
constructor(padDevice, settings, imagePath, editionMode, monitorIndex) {
this.padDevice = padDevice;
this._groupPads = [padDevice];
this._settings = settings;
@ -668,18 +653,23 @@ var PadOsd = GObject.registerClass({
this._groupPads.push(device);
});
this.connect('destroy', this._onDestroy.bind(this));
Main.uiGroup.add_actor(this);
this.actor = new St.BoxLayout({ style_class: 'pad-osd-window',
x_expand: true,
y_expand: true,
vertical: true,
reactive: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
Main.uiGroup.add_actor(this.actor);
this._monitorIndex = monitorIndex;
let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
this.add_constraint(constraint);
this.actor.add_constraint(constraint);
this._titleBox = new St.BoxLayout({ style_class: 'pad-osd-title-box',
vertical: false,
x_expand: false,
x_align: Clutter.ActorAlign.CENTER });
this.add_actor(this._titleBox);
this.actor.add_actor(this._titleBox);
let labelBox = new St.BoxLayout({ style_class: 'pad-osd-title-menu-box',
vertical: true });
@ -700,10 +690,10 @@ var PadOsd = GObject.registerClass({
this._padDiagram = new PadDiagram({ image: this._imagePath,
left_handed: settings.get_boolean('left-handed'),
editor_actor: this._actionEditor,
editor_actor: this._actionEditor.actor,
x_expand: true,
y_expand: true });
this.add_actor(this._padDiagram);
this.actor.add_actor(this._padDiagram);
// FIXME: Fix num buttons.
let i = 0;
@ -734,20 +724,18 @@ var PadOsd = GObject.registerClass({
x_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
this.add_actor(buttonBox);
this._editButton = new St.Button({
label: _('Edit…'),
style_class: 'button',
can_focus: true,
x_align: Clutter.ActorAlign.CENTER,
});
this.actor.add_actor(buttonBox);
this._editButton = new St.Button({ label: _("Edit…"),
style_class: 'button',
x_align: Clutter.ActorAlign.CENTER,
can_focus: true });
this._editButton.connect('clicked', () => {
this.setEditionMode(true);
});
buttonBox.add_actor(this._editButton);
this._syncEditionMode();
Main.pushModal(this);
Main.pushModal(this.actor);
}
_updatePadChooser() {
@ -757,7 +745,7 @@ var PadOsd = GObject.registerClass({
this._padChooser.connect('pad-selected', (chooser, pad) => {
this._requestForOtherPad(pad);
});
this._titleBox.add_child(this._padChooser);
this._titleBox.add_child(this._padChooser.actor);
} else {
this._padChooser.update(this._groupPads);
}
@ -797,7 +785,7 @@ var PadOsd = GObject.registerClass({
this._padDiagram.deactivateButton(event.get_button());
return Clutter.EVENT_STOP;
} else if (event.type() == Clutter.EventType.KEY_PRESS &&
(!this._editionMode || event.get_key_symbol() === Clutter.KEY_Escape)) {
(!this._editionMode || event.get_key_symbol() == Clutter.Escape)) {
if (this._editedAction != null)
this._endActionEdition();
else
@ -844,23 +832,22 @@ var PadOsd = GObject.registerClass({
this._tipLabel.set_text(_("Press any key to exit"));
}
this._titleLabel.clutter_text.set_markup(
`<span size="larger"><b>${title}</b></span>`);
this._titleLabel.clutter_text.set_markup('<span size="larger"><b>' + title + '</b></span>');
}
_isEditedAction(type, number, dir) {
if (!this._editedAction)
return false;
return this._editedAction.type == type &&
return (this._editedAction.type == type &&
this._editedAction.number == number &&
this._editedAction.dir == dir;
this._editedAction.dir == dir);
}
_followUpActionEdition(str) {
let { type, dir, number, mode } = this._editedAction;
let hasNextAction = type == Meta.PadActionType.RING && dir == CCW ||
type == Meta.PadActionType.STRIP && dir == UP;
let hasNextAction = (type == Meta.PadActionType.RING && dir == CCW ||
type == Meta.PadActionType.STRIP && dir == UP);
if (!hasNextAction)
return false;
@ -931,8 +918,12 @@ var PadOsd = GObject.registerClass({
this._syncEditionMode();
}
destroy() {
this.actor.destroy();
}
_onDestroy() {
Main.popModal(this);
Main.popModal(this.actor);
this._actionEditor.close();
let deviceManager = Clutter.DeviceManager.get_default();
@ -950,9 +941,11 @@ var PadOsd = GObject.registerClass({
this._capturedEventId = 0;
}
this.actor = null;
this.emit('closed');
}
});
};
Signals.addSignalMethods(PadOsd.prototype);
const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd');

View File

@ -1,15 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PageIndicators, AnimatedPageIndicators */
const { Clutter, GLib, Graphene, GObject, Meta, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const { ANIMATION_TIME_OUT, ANIMATION_MAX_DELAY_OUT_FOR_ITEM, AnimationDirection } = imports.ui.iconGrid;
const INDICATOR_INACTIVE_OPACITY = 128;
const INDICATOR_INACTIVE_OPACITY_HOVER = 255;
const INDICATOR_INACTIVE_SCALE = 2 / 3;
const INDICATOR_INACTIVE_SCALE_PRESSED = 0.5;
var INDICATORS_BASE_TIME = 250;
var INDICATORS_BASE_TIME_OUT = 125;
var INDICATORS_ANIMATION_DELAY = 125;
@ -17,27 +12,24 @@ var INDICATORS_ANIMATION_DELAY_OUT = 62.5;
var INDICATORS_ANIMATION_MAX_TIME = 750;
var SWITCH_TIME = 400;
var INDICATORS_ANIMATION_MAX_TIME_OUT =
Math.min(SWITCH_TIME,
ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
Math.min (SWITCH_TIME,
ANIMATION_TIME_OUT + ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
var ANIMATION_DELAY = 100;
var PageIndicators = GObject.registerClass({
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } },
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
}, class PageIndicators extends St.BoxLayout {
_init(orientation = Clutter.Orientation.VERTICAL) {
let vertical = orientation == Clutter.Orientation.VERTICAL;
super._init({
style_class: 'page-indicators',
vertical,
x_expand: true, y_expand: true,
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
reactive: true,
clip_to_allocation: true,
});
_init(vertical = true) {
super._init({ style_class: 'page-indicators',
vertical,
x_expand: true, y_expand: true,
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
reactive: true,
clip_to_allocation: true });
this._nPages = 0;
this._currentPosition = 0;
this._currentPage = undefined;
this._reactive = true;
this._reactive = true;
}
@ -71,21 +63,13 @@ var PageIndicators = GObject.registerClass({
button_mask: St.ButtonMask.ONE |
St.ButtonMask.TWO |
St.ButtonMask.THREE,
reactive: this._reactive });
indicator.child = new St.Widget({
style_class: 'page-indicator-icon',
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
toggle_mode: true,
reactive: this._reactive,
checked: pageIndex == this._currentPage });
indicator.child = new St.Widget({ style_class: 'page-indicator-icon' });
indicator.connect('clicked', () => {
this.emit('page-activated', pageIndex);
});
indicator.connect('notify::hover', () => {
this._updateIndicator(indicator, pageIndex);
});
indicator.connect('notify::pressed', () => {
this._updateIndicator(indicator, pageIndex);
});
this._updateIndicator(indicator, pageIndex);
this.add_actor(indicator);
}
} else {
@ -94,57 +78,33 @@ var PageIndicators = GObject.registerClass({
children[i].destroy();
}
this._nPages = nPages;
this.visible = this._nPages > 1;
this.visible = (this._nPages > 1);
}
_updateIndicator(indicator, pageIndex) {
let progress =
Math.max(1 - Math.abs(this._currentPosition - pageIndex), 0);
let inactiveScale = indicator.pressed
? INDICATOR_INACTIVE_SCALE_PRESSED : INDICATOR_INACTIVE_SCALE;
let inactiveOpacity = indicator.hover
? INDICATOR_INACTIVE_OPACITY_HOVER : INDICATOR_INACTIVE_OPACITY;
let scale = inactiveScale + (1 - inactiveScale) * progress;
let opacity = inactiveOpacity + (255 - inactiveOpacity) * progress;
indicator.child.set_scale(scale, scale);
indicator.child.opacity = opacity;
}
setCurrentPosition(currentPosition) {
this._currentPosition = currentPosition;
setCurrentPage(currentPage) {
this._currentPage = currentPage;
let children = this.get_children();
for (let i = 0; i < children.length; i++)
this._updateIndicator(children[i], i);
children[i].set_checked(i == this._currentPage);
}
});
var AnimatedPageIndicators = GObject.registerClass(
class AnimatedPageIndicators extends PageIndicators {
_init() {
super._init();
this.connect('destroy', this._onDestroy.bind(this));
}
super._init(true);
_onDestroy() {
if (this.animateLater) {
Meta.later_remove(this.animateLater);
this.animateLater = 0;
}
}
this.connect('notify::mapped', () => {
if (!this.mapped)
return;
vfunc_map() {
super.vfunc_map();
// Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler
this.animateLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateLater = 0;
this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE;
// Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE;
});
});
}
@ -183,7 +143,7 @@ class AnimatedPageIndicators extends PageIndicators {
translation_x: isAnimationIn ? 0 : offset,
duration: baseTime + delay * i,
mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
delay: isAnimationIn ? ANIMATION_DELAY : 0,
delay: isAnimationIn ? ANIMATION_DELAY : 0
});
}
}

View File

@ -57,7 +57,8 @@ function _unpremultiply(color) {
let red = Math.min((color.red * 255 + 127) / color.alpha, 255);
let green = Math.min((color.green * 255 + 127) / color.alpha, 255);
let blue = Math.min((color.blue * 255 + 127) / color.alpha, 255);
return new Clutter.Color({ red, green, blue, alpha: color.alpha });
return new Clutter.Color({ red: red, green: green,
blue: blue, alpha: color.alpha });
}
class AppMenu extends PopupMenu.PopupMenu {
@ -118,7 +119,7 @@ class AppMenu extends PopupMenu.PopupMenu {
_updateDetailsVisibility() {
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
this._detailsItem.visible = sw != null;
this._detailsItem.visible = (sw != null);
}
isEmpty() {
@ -169,13 +170,9 @@ class AppMenu extends PopupMenu.PopupMenu {
let windows = this._app.get_windows();
windows.forEach(window => {
let title = window.title || this._app.get_name();
let item = this._windowSection.addAction(title, event => {
this._windowSection.addAction(title, event => {
Main.activateWindow(window, event.get_time());
});
let id = window.connect('notify::title', () => {
item.label.text = window.title || this._app.get_name();
});
item.connect('destroy', () => window.disconnect(id));
});
}
}
@ -237,11 +234,8 @@ var AppMenuButton = GObject.registerClass({
this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this));
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, {
animate: true,
hideOnStop: true,
});
this._container.add_actor(this._spinner);
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
this._container.add_actor(this._spinner.actor);
let menu = new AppMenu(this);
this.setMenu(menu);
@ -270,7 +264,7 @@ var AppMenuButton = GObject.registerClass({
this.ease({
opacity: 255,
duration: Overview.ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@ -285,7 +279,7 @@ var AppMenuButton = GObject.registerClass({
opacity: 0,
mode: Clutter.Animation.EASE_OUT_QUAD,
duration: Overview.ANIMATION_TIME,
onComplete: () => this.hide(),
onComplete: () => this.hide()
});
}
@ -346,10 +340,9 @@ var AppMenuButton = GObject.registerClass({
if (focusedApp && focusedApp.is_on_workspace(workspace))
return focusedApp;
for (let i = 0; i < this._startingApps.length; i++) {
for (let i = 0; i < this._startingApps.length; i++)
if (this._startingApps[i].is_on_workspace(workspace))
return this._startingApps[i];
}
return null;
}
@ -372,21 +365,21 @@ var AppMenuButton = GObject.registerClass({
}
}
let visible = this._targetApp != null && !Main.overview.visibleTarget;
let visible = (this._targetApp != null && !Main.overview.visibleTarget);
if (visible)
this.fadeIn();
else
this.fadeOut();
let isBusy = this._targetApp != null &&
let isBusy = (this._targetApp != null &&
(this._targetApp.get_state() == Shell.AppState.STARTING ||
this._targetApp.get_busy());
this._targetApp.get_busy()));
if (isBusy)
this.startAnimation();
else
this.stopAnimation();
this.reactive = visible && !isBusy;
this.reactive = (visible && !isBusy);
this._syncIcon();
this.menu.setApp(this._targetApp);
@ -437,13 +430,16 @@ class ActivitiesButton extends PanelMenu.Button {
this.label_actor = this._label;
this.connect('captured-event', this._onCapturedEvent.bind(this));
this.connect_after('key-release-event', this._onKeyRelease.bind(this));
Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview');
this.add_accessible_state(Atk.StateType.CHECKED);
this.add_accessible_state (Atk.StateType.CHECKED);
});
Main.overview.connect('hiding', () => {
this.remove_style_pseudo_class('overview');
this.remove_accessible_state(Atk.StateType.CHECKED);
this.remove_accessible_state (Atk.StateType.CHECKED);
});
this._xdndTimeOut = 0;
@ -463,7 +459,7 @@ class ActivitiesButton extends PanelMenu.Button {
return DND.DragMotionResult.CONTINUE;
}
vfunc_captured_event(event) {
_onCapturedEvent(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS ||
event.type() == Clutter.EventType.TOUCH_BEGIN) {
if (!Main.overview.shouldToggleByCornerOrButton())
@ -472,25 +468,23 @@ class ActivitiesButton extends PanelMenu.Button {
return Clutter.EVENT_PROPAGATE;
}
vfunc_event(event) {
_onEvent(actor, event) {
super._onEvent(actor, event);
if (event.type() == Clutter.EventType.TOUCH_END ||
event.type() == Clutter.EventType.BUTTON_RELEASE) {
event.type() == Clutter.EventType.BUTTON_RELEASE)
if (Main.overview.shouldToggleByCornerOrButton())
Main.overview.toggle();
}
return Clutter.EVENT_PROPAGATE;
}
vfunc_key_release_event(keyEvent) {
let symbol = keyEvent.keyval;
_onKeyRelease(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
if (Main.overview.shouldToggleByCornerOrButton()) {
if (Main.overview.shouldToggleByCornerOrButton())
Main.overview.toggle();
return Clutter.EVENT_STOP;
}
}
return Clutter.EVENT_PROPAGATE;
}
@ -507,12 +501,13 @@ class ActivitiesButton extends PanelMenu.Button {
}
});
var PanelCorner = GObject.registerClass(
class PanelCorner extends St.DrawingArea {
_init(side) {
var PanelCorner = class {
constructor(side) {
this._side = side;
super._init({ style_class: 'panel-corner' });
this.actor = new St.DrawingArea({ style_class: 'panel-corner' });
this.actor.connect('style-changed', this._styleChanged.bind(this));
this.actor.connect('repaint', this._repaint.bind(this));
}
_findRightmostButton(container) {
@ -533,8 +528,8 @@ class PanelCorner extends St.DrawingArea {
if (index < 0)
return null;
if (!children[index].has_style_class_name('panel-menu') &&
!children[index].has_style_class_name('panel-button'))
if (!(children[index].has_style_class_name('panel-menu')) &&
!(children[index].has_style_class_name('panel-button')))
return this._findRightmostButton(children[index]);
return children[index];
@ -558,8 +553,8 @@ class PanelCorner extends St.DrawingArea {
if (index == children.length)
return null;
if (!children[index].has_style_class_name('panel-menu') &&
!children[index].has_style_class_name('panel-button'))
if (!(children[index].has_style_class_name('panel-menu')) &&
!(children[index].has_style_class_name('panel-button')))
return this._findLeftmostButton(children[index]);
return children[index];
@ -602,7 +597,7 @@ class PanelCorner extends St.DrawingArea {
this._buttonStyleChangedSignalId = button.connect('style-changed',
() => {
let pseudoClass = button.get_style_pseudo_class();
this.set_style_pseudo_class(pseudoClass);
this.actor.set_style_pseudo_class(pseudoClass);
});
// The corner doesn't support theme transitions, so override
@ -611,8 +606,8 @@ class PanelCorner extends St.DrawingArea {
}
}
vfunc_repaint() {
let node = this.get_theme_node();
_repaint() {
let node = this.actor.get_theme_node();
let cornerRadius = node.get_length("-panel-corner-radius");
let borderWidth = node.get_length('-panel-corner-border-width');
@ -623,19 +618,18 @@ class PanelCorner extends St.DrawingArea {
let overlap = borderColor.alpha != 0;
let offsetY = overlap ? 0 : borderWidth;
let cr = this.get_context();
let cr = this.actor.get_context();
cr.setOperator(Cairo.Operator.SOURCE);
cr.moveTo(0, offsetY);
if (this._side == St.Side.LEFT) {
if (this._side == St.Side.LEFT)
cr.arc(cornerRadius,
borderWidth + cornerRadius,
cornerRadius, Math.PI, 3 * Math.PI / 2);
} else {
else
cr.arc(0,
borderWidth + cornerRadius,
cornerRadius, 3 * Math.PI / 2, 2 * Math.PI);
}
cr.lineTo(cornerRadius, offsetY);
cr.closePath();
@ -651,7 +645,7 @@ class PanelCorner extends St.DrawingArea {
Clutter.cairo_set_source_color(cr, backgroundColor);
cr.save();
cr.translate(xOffsetDirection * offset, -offset);
cr.translate(xOffsetDirection * offset, - offset);
cr.appendPath(savedPath);
cr.fill();
cr.restore();
@ -660,17 +654,16 @@ class PanelCorner extends St.DrawingArea {
cr.$dispose();
}
vfunc_style_changed() {
super.vfunc_style_changed();
let node = this.get_theme_node();
_styleChanged() {
let node = this.actor.get_theme_node();
let cornerRadius = node.get_length("-panel-corner-radius");
let borderWidth = node.get_length('-panel-corner-border-width');
this.set_size(cornerRadius, borderWidth + cornerRadius);
this.set_anchor_point(0, borderWidth);
this.actor.set_size(cornerRadius, borderWidth + cornerRadius);
this.actor.set_anchor_point(0, borderWidth);
}
});
};
var AggregateLayout = GObject.registerClass(
class AggregateLayout extends Clutter.BoxLayout {
@ -713,15 +706,16 @@ class AggregateMenu extends PanelMenu.Button {
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
this.add_child(this._indicators);
if (Config.HAVE_NETWORKMANAGER)
if (Config.HAVE_NETWORKMANAGER) {
this._network = new imports.ui.status.network.NMApplet();
else
} else {
this._network = null;
if (Config.HAVE_BLUETOOTH)
}
if (Config.HAVE_BLUETOOTH) {
this._bluetooth = new imports.ui.status.bluetooth.Indicator();
else
} else {
this._bluetooth = null;
}
this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
this._power = new imports.ui.status.power.Indicator();
@ -734,41 +728,42 @@ class AggregateMenu extends PanelMenu.Button {
this._nightLight = new imports.ui.status.nightLight.Indicator();
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
this._indicators.add_child(this._thunderbolt);
this._indicators.add_child(this._screencast);
this._indicators.add_child(this._location);
this._indicators.add_child(this._nightLight);
if (this._network)
this._indicators.add_child(this._network);
if (this._bluetooth)
this._indicators.add_child(this._bluetooth);
this._indicators.add_child(this._remoteAccess);
this._indicators.add_child(this._rfkill);
this._indicators.add_child(this._volume);
this._indicators.add_child(this._power);
this._indicators.add_child(this._thunderbolt.indicators);
this._indicators.add_child(this._screencast.indicators);
this._indicators.add_child(this._location.indicators);
this._indicators.add_child(this._nightLight.indicators);
if (this._network) {
this._indicators.add_child(this._network.indicators);
}
if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators);
}
this._indicators.add_child(this._remoteAccess.indicators);
this._indicators.add_child(this._rfkill.indicators);
this._indicators.add_child(this._volume.indicators);
this._indicators.add_child(this._power.indicators);
this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.menu.addMenuItem(this._volume.menu);
this.menu.addMenuItem(this._brightness.menu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
if (this._network)
if (this._network) {
this.menu.addMenuItem(this._network.menu);
if (this._bluetooth)
}
if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu);
}
this.menu.addMenuItem(this._remoteAccess.menu);
this.menu.addMenuItem(this._location.menu);
this.menu.addMenuItem(this._rfkill.menu);
this.menu.addMenuItem(this._power.menu);
this.menu.addMenuItem(this._nightLight.menu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(this._system.menu);
menuLayout.addSizeChild(this._location.menu.actor);
menuLayout.addSizeChild(this._rfkill.menu.actor);
menuLayout.addSizeChild(this._power.menu.actor);
menuLayout.addSizeChild(this._system.menu.actor);
menuLayout.addSizeChild(this._system.buttonGroup);
}
});
@ -804,10 +799,14 @@ class Panel extends St.Widget {
this.add_child(this._rightBox);
this._leftCorner = new PanelCorner(St.Side.LEFT);
this.add_child(this._leftCorner);
this.add_child(this._leftCorner.actor);
this._rightCorner = new PanelCorner(St.Side.RIGHT);
this.add_child(this._rightCorner);
this.add_child(this._rightCorner.actor);
this.connect('button-press-event', this._onButtonPress.bind(this));
this.connect('touch-event', this._onButtonPress.bind(this));
this.connect('key-press-event', this._onKeyPress.bind(this));
Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview');
@ -896,65 +895,62 @@ class Panel extends St.Widget {
let cornerWidth, cornerHeight;
[, cornerWidth] = this._leftCorner.get_preferred_width(-1);
[, cornerHeight] = this._leftCorner.get_preferred_height(-1);
[, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
[, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
childBox.x1 = 0;
childBox.x2 = cornerWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._leftCorner.allocate(childBox, flags);
this._leftCorner.actor.allocate(childBox, flags);
[, cornerWidth] = this._rightCorner.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.get_preferred_height(-1);
[, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
childBox.x1 = allocWidth - cornerWidth;
childBox.x2 = allocWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._rightCorner.allocate(childBox, flags);
this._rightCorner.actor.allocate(childBox, flags);
}
_tryDragWindow(event) {
_onButtonPress(actor, event) {
if (Main.modalCount > 0)
return Clutter.EVENT_PROPAGATE;
if (event.source != this)
if (event.get_source() != actor)
return Clutter.EVENT_PROPAGATE;
let { x, y } = event;
let dragWindow = this._getDraggableWindowForPosition(x);
let type = event.type();
let isPress = type == Clutter.EventType.BUTTON_PRESS;
if (!isPress && type != Clutter.EventType.TOUCH_BEGIN)
return Clutter.EVENT_PROPAGATE;
let button = isPress ? event.get_button() : -1;
if (isPress && button != 1)
return Clutter.EVENT_PROPAGATE;
let [stageX, stageY] = event.get_coords();
let dragWindow = this._getDraggableWindowForPosition(stageX);
if (!dragWindow)
return Clutter.EVENT_PROPAGATE;
return global.display.begin_grab_op(
dragWindow,
Meta.GrabOp.MOVING,
false, /* pointer grab */
true, /* frame action */
event.button || -1,
event.modifier_state,
event.time,
x, y) ? Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE;
global.display.begin_grab_op(dragWindow,
Meta.GrabOp.MOVING,
false, /* pointer grab */
true, /* frame action */
button,
event.get_state(),
event.get_time(),
stageX, stageY);
return Clutter.EVENT_STOP;
}
vfunc_button_press_event(buttonEvent) {
if (buttonEvent.button != 1)
return Clutter.EVENT_PROPAGATE;
return this._tryDragWindow(buttonEvent);
}
vfunc_touch_event(touchEvent) {
if (touchEvent.type != Clutter.EventType.TOUCH_BEGIN)
return Clutter.EVENT_PROPAGATE;
return this._tryDragWindow(touchEvent);
}
vfunc_key_press_event(keyEvent) {
let symbol = keyEvent.keyval;
_onKeyPress(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Escape) {
global.display.focus_default_window(keyEvent.time);
global.display.focus_default_window(event.get_time());
return Clutter.EVENT_STOP;
}
@ -1108,7 +1104,7 @@ class Panel extends St.Widget {
let boxes = {
left: this._leftBox,
center: this._centerBox,
right: this._rightBox,
right: this._rightBox
};
let boxContainer = boxes[box] || this._rightBox;
this.statusArea[role] = indicator;
@ -1118,14 +1114,14 @@ class Panel extends St.Widget {
_addStyleClassName(className) {
this.add_style_class_name(className);
this._rightCorner.add_style_class_name(className);
this._leftCorner.add_style_class_name(className);
this._rightCorner.actor.add_style_class_name(className);
this._leftCorner.actor.add_style_class_name(className);
}
_removeStyleClassName(className) {
this.remove_style_class_name(className);
this._rightCorner.remove_style_class_name(className);
this._leftCorner.remove_style_class_name(className);
this._rightCorner.actor.remove_style_class_name(className);
this._leftCorner.actor.remove_style_class_name(className);
}
_onMenuSet(indicator) {

View File

@ -2,6 +2,7 @@
/* exported Button, SystemIndicator */
const { Atk, Clutter, GObject, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
const Params = imports.misc.params;
@ -10,17 +11,15 @@ const PopupMenu = imports.ui.popupMenu;
var ButtonBox = GObject.registerClass(
class ButtonBox extends St.Widget {
_init(params) {
params = Params.parse(params, {
style_class: 'panel-button',
x_expand: true,
y_expand: true,
}, true);
params = Params.parse(params, { style_class: 'panel-button' }, true);
super._init(params);
this._delegate = this;
this.container = new St.Bin({ child: this });
this.container = new St.Bin({ y_fill: true,
x_fill: true,
child: this });
this.connect('style-changed', this._onStyleChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
@ -102,6 +101,9 @@ var Button = GObject.registerClass({
accessible_name: nameText ? nameText : "",
accessible_role: Atk.Role.MENU });
this.connect('event', this._onEvent.bind(this));
this.connect('notify::visible', this._onVisibilityChanged.bind(this));
if (dontCreateMenu)
this.menu = new PopupMenu.PopupDummyMenu(this);
else
@ -130,7 +132,7 @@ var Button = GObject.registerClass({
this.emit('menu-set');
}
vfunc_event(event) {
_onEvent(actor, event) {
if (this.menu &&
(event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS))
@ -139,10 +141,11 @@ var Button = GObject.registerClass({
return Clutter.EVENT_PROPAGATE;
}
vfunc_hide() {
super.vfunc_hide();
_onVisibilityChanged() {
if (!this.menu)
return;
if (this.menu)
if (!this.visible)
this.menu.close();
}
@ -154,7 +157,7 @@ var Button = GObject.registerClass({
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
let group = global.focus_manager.get_group(this);
if (group) {
let direction = symbol == Clutter.KEY_Left ? St.DirectionType.LEFT : St.DirectionType.RIGHT;
let direction = (symbol == Clutter.KEY_Left) ? St.DirectionType.LEFT : St.DirectionType.RIGHT;
group.navigate_focus(this, direction, false);
return Clutter.EVENT_STOP;
}
@ -179,7 +182,7 @@ var Button = GObject.registerClass({
// measures are in logical pixels, so make sure to consider the scale
// factor when computing max-height
let maxHeight = Math.round((workArea.height - verticalMargins) / scaleFactor);
this.menu.actor.style = 'max-height: %spx;'.format(maxHeight);
this.menu.actor.style = ('max-height: %spx;').format(maxHeight);
}
_onDestroy() {
@ -197,33 +200,24 @@ var Button = GObject.registerClass({
* of an icon and a menu section, which will be composed into the
* aggregate menu.
*/
var SystemIndicator = GObject.registerClass(
class SystemIndicator extends St.BoxLayout {
_init() {
super._init({
style_class: 'panel-status-indicators-box',
reactive: true,
visible: false,
});
var SystemIndicator = class {
constructor() {
this.indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box',
reactive: true });
this.indicators.hide();
this.menu = new PopupMenu.PopupMenuSection();
}
get indicators() {
let klass = this.constructor.name;
let { stack } = new Error();
log(`Usage of indicator.indicators is deprecated for ${klass}\n${stack}`);
return this;
}
_syncIndicatorsVisible() {
this.visible = this.get_children().some(a => a.visible);
this.indicators.visible = this.indicators.get_children().some(a => a.visible);
}
_addIndicator() {
let icon = new St.Icon({ style_class: 'system-status-icon' });
this.add_actor(icon);
this.indicators.add_actor(icon);
icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this));
this._syncIndicatorsVisible();
return icon;
}
});
};
Signals.addSignalMethods(SystemIndicator.prototype);

View File

@ -10,8 +10,8 @@ var PieTimer = GObject.registerClass({
'angle': GObject.ParamSpec.double(
'angle', 'angle', 'angle',
GObject.ParamFlags.READWRITE,
0, 2 * Math.PI, 0),
},
0, 2 * Math.PI, 0)
}
}, class PieTimer extends St.DrawingArea {
_init() {
this._angle = 0;
@ -20,7 +20,7 @@ var PieTimer = GObject.registerClass({
opacity: 0,
visible: false,
can_focus: false,
reactive: false,
reactive: false
});
this.set_pivot_point(0.5, 0.5);
@ -84,13 +84,13 @@ var PieTimer = GObject.registerClass({
this.ease({
opacity: 255,
duration: duration / 4,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
this.ease_property('angle', 2 * Math.PI, {
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: this._onTransitionComplete.bind(this),
onComplete: this._onTransitionComplete.bind(this)
});
}
@ -101,7 +101,7 @@ var PieTimer = GObject.registerClass({
opacity: 0,
duration: SUCCESS_ZOOM_OUT_DURATION,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onStopped: () => this.destroy(),
onStopped: () => this.destroy()
});
}
});
@ -110,7 +110,7 @@ var PointerA11yTimeout = class PointerA11yTimeout {
constructor() {
let manager = Clutter.DeviceManager.get_default();
manager.connect('ptr-a11y-timeout-started', (o, device, type, timeout) => {
manager.connect('ptr-a11y-timeout-started', (manager, device, type, timeout) => {
let [x, y] = global.get_pointer();
this._pieTimer = new PieTimer();
@ -123,7 +123,7 @@ var PointerA11yTimeout = class PointerA11yTimeout {
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
});
manager.connect('ptr-a11y-timeout-stopped', (o, device, type, clicked) => {
manager.connect('ptr-a11y-timeout-stopped', (manager, device, type, clicked) => {
if (!clicked)
this._pieTimer.destroy();

View File

@ -3,7 +3,7 @@
PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */
const { Atk, Clutter, Gio, GObject, Graphene, Shell, St } = imports.gi;
const { Atk, Clutter, Gio, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const BoxPointer = imports.ui.boxpointer;
@ -19,17 +19,14 @@ var Ornament = {
};
function isPopupMenuItemVisible(child) {
if (child._delegate instanceof PopupMenuSection) {
if (child._delegate instanceof PopupMenuSection)
if (child._delegate.isEmpty())
return false;
}
return child.visible;
}
/**
* arrowIcon
* @param {St.Side} side - Side to which the arrow points.
* @returns {St.Icon} a new arrow icon
* @side Side to which the arrow points.
*/
function arrowIcon(side) {
let iconName;
@ -68,10 +65,10 @@ var PopupBaseMenuItem = GObject.registerClass({
},
Signals: {
'activate': { param_types: [Clutter.Event.$gtype] },
},
}
}, class PopupBaseMenuItem extends St.BoxLayout {
_init(params) {
params = Params.parse(params, {
params = Params.parse (params, {
reactive: true,
activate: true,
hover: true,
@ -100,6 +97,12 @@ var PopupBaseMenuItem = GObject.registerClass({
if (params.style_class)
this.add_style_class_name(params.style_class);
if (this._activatable) {
this.connect('button-press-event', this._onButtonPressEvent.bind(this));
this.connect('button-release-event', this._onButtonReleaseEvent.bind(this));
this.connect('touch-event', this._onTouchEvent.bind(this));
this.connect('key-press-event', this._onKeyPressEvent.bind(this));
}
if (params.reactive && params.hover)
this.bind_property('hover', this, 'active', GObject.BindingFlags.SYNC_CREATE);
}
@ -121,44 +124,32 @@ var PopupBaseMenuItem = GObject.registerClass({
this._parent = parent;
}
vfunc_button_press_event() {
if (!this._activatable)
return Clutter.EVENT_PROPAGATE;
_onButtonPressEvent() {
// This is the CSS active state
this.add_style_pseudo_class('active');
return Clutter.EVENT_PROPAGATE;
}
vfunc_button_release_event() {
if (!this._activatable)
return Clutter.EVENT_PROPAGATE;
_onButtonReleaseEvent(actor, event) {
this.remove_style_pseudo_class('active');
this.activate(Clutter.get_current_event());
this.activate(event);
return Clutter.EVENT_STOP;
}
vfunc_touch_event(touchEvent) {
if (!this._activatable)
return Clutter.EVENT_PROPAGATE;
if (touchEvent.type == Clutter.EventType.TOUCH_END) {
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
this.remove_style_pseudo_class('active');
this.activate(Clutter.get_current_event());
this.activate(event);
return Clutter.EVENT_STOP;
} else if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN) {
} else if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
// This is the CSS active state
this.add_style_pseudo_class('active');
}
return Clutter.EVENT_PROPAGATE;
}
vfunc_key_press_event(keyEvent) {
if (!this._activatable)
return super.vfunc_key_press_event(keyEvent);
let state = keyEvent.modifier_state;
_onKeyPressEvent(actor, event) {
let state = event.get_state();
// if user has a modifier down (except capslock and numlock)
// then don't handle the key press here
@ -169,9 +160,9 @@ var PopupBaseMenuItem = GObject.registerClass({
if (state)
return Clutter.EVENT_PROPAGATE;
let symbol = keyEvent.keyval;
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.activate(Clutter.get_current_event());
this.activate(event);
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
@ -272,7 +263,7 @@ class PopupMenuItem extends PopupBaseMenuItem {
_init(text, params) {
super._init(params);
this.label = new St.Label({ text });
this.label = new St.Label({ text: text });
this.add_child(this.label);
this.label_actor = this.label;
}
@ -294,10 +285,9 @@ class PopupSeparatorMenuItem extends PopupBaseMenuItem {
this._syncVisibility();
this._separator = new St.Widget({ style_class: 'popup-separator-menu-item',
x_expand: true,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this._separator);
this.add(this._separator, { expand: true });
}
_syncVisibility() {
@ -328,12 +318,12 @@ class Switch extends St.Bin {
});
var PopupSwitchMenuItem = GObject.registerClass({
Signals: { 'toggled': { param_types: [GObject.TYPE_BOOLEAN] } },
Signals: { 'toggled': { param_types: [GObject.TYPE_BOOLEAN] }, },
}, class PopupSwitchMenuItem extends PopupBaseMenuItem {
_init(text, active, params) {
super._init(params);
this.label = new St.Label({ text });
this.label = new St.Label({ text: text });
this._switch = new Switch(active);
this.accessible_role = Atk.Role.CHECK_MENU_ITEM;
@ -342,11 +332,8 @@ var PopupSwitchMenuItem = GObject.registerClass({
this.add_child(this.label);
this._statusBin = new St.Bin({
x_align: Clutter.ActorAlign.END,
x_expand: true,
});
this.add_child(this._statusBin);
this._statusBin = new St.Bin({ x_align: St.Align.END });
this.add(this._statusBin, { expand: true, x_align: St.Align.END });
this._statusLabel = new St.Label({
text: '',
@ -419,7 +406,7 @@ class PopupImageMenuItem extends PopupBaseMenuItem {
this._icon = new St.Icon({ style_class: 'popup-menu-icon',
x_align: Clutter.ActorAlign.END });
this.add_child(this._icon);
this.label = new St.Label({ text });
this.label = new St.Label({ text: text });
this.add_child(this.label);
this.label_actor = this.label;
@ -444,14 +431,12 @@ var PopupMenuBase = class {
this.focusActor = sourceActor;
this._parent = null;
this.box = new St.BoxLayout({
vertical: true,
x_expand: true,
y_expand: true,
});
if (styleClass !== undefined)
this.box.style_class = styleClass;
if (styleClass !== undefined) {
this.box = new St.BoxLayout({ style_class: styleClass,
vertical: true });
} else {
this.box = new St.BoxLayout({ vertical: true });
}
this.length = 0;
this.isOpen = false;
@ -510,7 +495,7 @@ var PopupMenuBase = class {
menuItem = new PopupMenuItem(title);
this.addMenuItem(menuItem);
menuItem.connect('activate', (o, event) => {
menuItem.connect('activate', (menuItem, event) => {
callback(event);
});
@ -568,7 +553,7 @@ var PopupMenuBase = class {
}
_connectItemSignals(menuItem) {
menuItem._activeChangeId = menuItem.connect('notify::active', () => {
menuItem._activeChangeId = menuItem.connect('notify::active', menuItem => {
let active = menuItem.active;
if (active && this._activeMenuItem != menuItem) {
if (this._activeMenuItem)
@ -592,7 +577,7 @@ var PopupMenuBase = class {
menuItem.actor.grab_key_focus();
}
});
menuItem._activateId = menuItem.connect_after('activate', () => {
menuItem._activateId = menuItem.connect_after('activate', (menuItem, _event) => {
this.emit('activate', menuItem);
this.itemActivated(BoxPointer.PopupAnimation.FULL);
});
@ -605,7 +590,7 @@ var PopupMenuBase = class {
// the menuItem may have, called destroyId
// (FIXME: in the future it may make sense to have container objects
// like PopupMenuManager does)
menuItem._popupMenuDestroyId = menuItem.connect('destroy', () => {
menuItem._popupMenuDestroyId = menuItem.connect('destroy', menuItem => {
menuItem.disconnect(menuItem._popupMenuDestroyId);
menuItem.disconnect(menuItem._activateId);
menuItem.disconnect(menuItem._activeChangeId);
@ -801,7 +786,10 @@ var PopupMenu = class extends PopupMenuBase {
this._arrowAlignment = arrowAlignment;
this._arrowSide = arrowSide;
this._boxPointer = new BoxPointer.BoxPointer(arrowSide);
this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
{ x_fill: true,
y_fill: true,
x_align: St.Align.START });
this.actor = this._boxPointer;
this.actor._delegate = this;
this.actor.style_class = 'popup-menu-boxpointer';
@ -812,12 +800,10 @@ var PopupMenu = class extends PopupMenuBase {
global.focus_manager.add_group(this.actor);
this.actor.reactive = true;
if (this.sourceActor) {
if (this.sourceActor)
this._keyPressId = this.sourceActor.connect('key-press-event',
this._onKeyPress.bind(this));
}
this._systemModalOpenedId = 0;
this._openedSubMenu = null;
}
@ -892,17 +878,12 @@ var PopupMenu = class extends PopupMenuBase {
if (this.isEmpty())
return;
if (!this._systemModalOpenedId) {
this._systemModalOpenedId =
Main.layoutManager.connect('system-modal-opened', () => this.close());
}
this.isOpen = true;
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.open(animate);
this.actor.get_parent().set_child_above_sibling(this.actor, null);
this.actor.raise_top();
this.emit('open-state-changed', true);
}
@ -927,11 +908,6 @@ var PopupMenu = class extends PopupMenuBase {
destroy() {
if (this._keyPressId)
this.sourceActor.disconnect(this._keyPressId);
if (this._systemModalOpenedId)
Main.layoutManager.disconnect(this._systemModalOpenedId);
this._systemModalOpenedId = 0;
super.destroy();
}
};
@ -1045,12 +1021,12 @@ var PopupSubMenu = class extends PopupMenuBase {
height: naturalHeight,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
onComplete: () => this.actor.set_height(-1),
onComplete: () => this.actor.set_height(-1)
});
this._arrow.ease({
rotation_angle_z: targetAngle,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
mode: Clutter.AnimationMode.EASE_OUT_EXPO
});
} else {
this._arrow.rotation_angle_z = targetAngle;
@ -1078,12 +1054,12 @@ var PopupSubMenu = class extends PopupMenuBase {
onComplete: () => {
this.actor.hide();
this.actor.set_height(-1);
},
}
});
this._arrow.ease({
rotation_angle_z: 0,
duration: 250,
mode: Clutter.AnimationMode.EASE_OUT_EXPO,
mode: Clutter.AnimationMode.EASE_OUT_EXPO
});
} else {
this._arrow.rotation_angle_z = 0;
@ -1144,20 +1120,17 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
this.add_child(this.icon);
}
this.label = new St.Label({ text,
this.label = new St.Label({ text: text,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this.label);
this.label_actor = this.label;
let expander = new St.Bin({
style_class: 'popup-menu-item-expander',
x_expand: true,
});
this.add_child(expander);
let expander = new St.Bin({ style_class: 'popup-menu-item-expander' });
this.add(expander, { expand: true });
this._triangle = arrowIcon(St.Side.RIGHT);
this._triangle.pivot_point = new Graphene.Point({ x: 0.5, y: 0.6 });
this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 });
this._triangleBin = new St.Widget({ y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
@ -1192,7 +1165,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
} else {
this.remove_style_pseudo_class('open');
this._getTopMenu()._setOpenedSubMenu(null);
this.remove_accessible_state(Atk.StateType.EXPANDED);
this.remove_accessible_state (Atk.StateType.EXPANDED);
this.remove_style_pseudo_class('checked');
}
}
@ -1212,8 +1185,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return this.menu.isOpen;
}
vfunc_key_press_event(keyPressEvent) {
let symbol = keyPressEvent.keyval;
_onKeyPressEvent(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Right) {
this._setOpenState(true);
@ -1224,14 +1197,14 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyPressEvent);
return super._onKeyPressEvent(actor, event);
}
activate(_event) {
this._setOpenState(true);
}
vfunc_button_release_event() {
_onButtonReleaseEvent() {
// Since we override the parent, we need to manage what the parent does
// with the active style class
this.remove_style_pseudo_class('active');
@ -1239,8 +1212,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_PROPAGATE;
}
vfunc_touch_event(touchEvent) {
if (touchEvent.type == Clutter.EventType.TOUCH_END) {
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
// Since we override the parent, we need to manage what the parent does
// with the active style class
this.remove_style_pseudo_class('active');
@ -1266,11 +1239,11 @@ var PopupMenuManager = class {
return;
let menudata = {
menu,
menu: menu,
openStateChangeId: menu.connect('open-state-changed', this._onMenuOpenState.bind(this)),
destroyId: menu.connect('destroy', this._onMenuDestroy.bind(this)),
enterId: 0,
focusInId: 0,
focusInId: 0
};
let source = menu.sourceActor;

View File

@ -181,7 +181,7 @@ function loadRemoteSearchProviders(searchSettings, callback) {
return -1;
// finally, if both providers are found, return their order in the list
return idxA - idxB;
return (idxA - idxB);
});
callback(loadedProviders);
@ -228,7 +228,8 @@ var RemoteSearchProvider = class {
}
if (gicon)
icon = new St.Icon({ gicon, icon_size: size });
icon = new St.Icon({ gicon: gicon,
icon_size: size });
return icon;
}

View File

@ -53,13 +53,13 @@ var Ripples = class Ripples {
ripple.visible = true;
ripple.opacity = 255 * Math.sqrt(startOpacity);
ripple.scale_x = ripple.scale_y = startScale;
ripple.set_translation(-this._px * ripple.width, -this._py * ripple.height, 0.0);
ripple.set_translation( - this._px * ripple.width, - this._py * ripple.height, 0.0);
ripple.ease({
opacity: 0,
delay,
duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
mode: Clutter.AnimationMode.EASE_IN_QUAD
});
ripple.ease({
scale_x: finalScale,
@ -67,7 +67,7 @@ var Ripples = class Ripples {
delay,
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => (ripple.visible = false),
onComplete: () => (ripple.visible = false)
});
}

View File

@ -57,7 +57,9 @@ class RunDialog extends ModalDialog.ModalDialog {
let label = new St.Label({ style_class: 'run-dialog-label',
text: _("Enter a Command") });
this.contentLayout.add_child(label);
this.contentLayout.add(label, { x_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
let entry = new St.Entry({ style_class: 'run-dialog-entry',
can_focus: true });
@ -66,36 +68,36 @@ class RunDialog extends ModalDialog.ModalDialog {
entry.label_actor = label;
this._entryText = entry.clutter_text;
this.contentLayout.add_child(entry);
this.contentLayout.add(entry, { y_align: St.Align.START });
this.setInitialKeyFocus(this._entryText);
this._errorBox = new St.BoxLayout({ style_class: 'run-dialog-error-box' });
this.contentLayout.add_child(this._errorBox);
this.contentLayout.add(this._errorBox, { expand: true });
let errorIcon = new St.Icon({ icon_name: 'dialog-error-symbolic',
icon_size: 24,
style_class: 'run-dialog-error-icon',
y_align: Clutter.ActorAlign.CENTER });
style_class: 'run-dialog-error-icon' });
this._errorBox.add_child(errorIcon);
this._errorBox.add(errorIcon, { y_align: St.Align.MIDDLE });
this._commandError = false;
this._errorMessage = new St.Label({
style_class: 'run-dialog-error-label',
y_align: Clutter.ActorAlign.CENTER,
});
this._errorMessage = new St.Label({ style_class: 'run-dialog-error-label' });
this._errorMessage.clutter_text.line_wrap = true;
this._errorBox.add_child(this._errorMessage);
this._errorBox.add(this._errorMessage, { expand: true,
x_align: St.Align.START,
x_fill: false,
y_align: St.Align.MIDDLE,
y_fill: false });
this._errorBox.hide();
this.setButtons([{
action: this.close.bind(this),
label: _("Close"),
key: Clutter.KEY_Escape,
key: Clutter.Escape,
}]);
this._pathCompleter = new Gio.FilenameCompleter();
@ -112,7 +114,7 @@ class RunDialog extends ModalDialog.ModalDialog {
});
this._entryText.connect('key-press-event', (o, e) => {
let symbol = e.get_key_symbol();
if (symbol === Clutter.KEY_Tab) {
if (symbol == Clutter.Tab) {
let text = o.get_text();
let prefix;
if (text.lastIndexOf(' ') == -1)
@ -175,10 +177,11 @@ class RunDialog extends ModalDialog.ModalDialog {
}
_getCompletion(text) {
if (text.includes('/'))
if (text.includes('/')) {
return this._pathCompleter.get_completion_suffix(text);
else
} else {
return this._getCommandCompletion(text);
}
}
_run(input, inTerminal) {
@ -209,7 +212,7 @@ class RunDialog extends ModalDialog.ModalDialog {
} else {
if (input.charAt(0) == '~')
input = input.slice(1);
path = `${GLib.get_home_dir()}/${input}`;
path = GLib.get_home_dir() + '/' + input;
}
if (GLib.file_test(path, GLib.FileTest.EXISTS)) {
@ -217,12 +220,12 @@ class RunDialog extends ModalDialog.ModalDialog {
try {
Gio.app_info_launch_default_for_uri(file.get_uri(),
global.create_app_launch_context(0, -1));
} catch (err) {
} catch (e) {
// The exception from gjs contains an error string like:
// Error invoking Gio.app_info_launch_default_for_uri: No application
// is registered as handling this file
// We are only interested in the part after the first colon.
let message = err.message.replace(/[^:]*: *(.+)/, '$1');
let message = e.message.replace(/[^:]*: *(.+)/, '$1');
this._showError(message);
}
} else {
@ -249,7 +252,7 @@ class RunDialog extends ModalDialog.ModalDialog {
onComplete: () => {
parentActor.set_height(-1);
this._errorBox.show();
},
}
});
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenshotService */
const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox;
@ -64,55 +65,7 @@ var ScreenshotService = class {
y + height <= global.screen_height;
}
*_resolveRelativeFilename(filename) {
if (GLib.str_has_suffix(filename, '.png'))
filename = filename.substr(0, -4);
let path = [
GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES),
GLib.get_home_dir(),
].find(p => GLib.file_test(p, GLib.FileTest.EXISTS));
if (!path)
return null;
yield Gio.File.new_for_path(
GLib.build_filenamev([path, `${filename}.png`]));
for (let idx = 1; ; idx++) {
yield Gio.File.new_for_path(
GLib.build_filenamev([path, `${filename}-${idx}.png`]));
}
}
_createStream(filename) {
if (filename == '')
return [Gio.MemoryOutputStream.new_resizable(), null];
if (GLib.path_is_absolute(filename)) {
try {
let file = Gio.File.new_for_path(filename);
let stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
return [stream, file];
} catch (e) {
return [null, null];
}
}
for (let file of this._resolveRelativeFilename(filename)) {
try {
let stream = file.create(Gio.FileCreateFlags.NONE, null);
return [stream, file];
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS))
return [null, null];
}
}
return [null, null];
}
_onScreenshotComplete(result, area, stream, file, flash, invocation) {
_onScreenshotComplete(result, area, filenameUsed, flash, invocation) {
if (result) {
if (flash) {
let flashspot = new Flashspot(area);
@ -124,17 +77,6 @@ var ScreenshotService = class {
}
}
stream.close(null);
let filenameUsed = '';
if (file) {
filenameUsed = file.get_path();
} else {
let bytes = stream.steal_as_bytes();
let clipboard = St.Clipboard.get_default();
clipboard.set_content(St.ClipboardType.CLIPBOARD, 'image/png', bytes);
}
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
invocation.return_value(retval);
}
@ -169,18 +111,15 @@ var ScreenshotService = class {
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_area(x, y, width, height, stream,
screenshot.screenshot_area (x, y, width, height, filename,
(o, res) => {
try {
let [result, area] =
let [result, area, filenameUsed] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
result, area, stream, file, flash, invocation);
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror(e);
invocation.return_gerror (e);
}
});
}
@ -190,18 +129,15 @@ var ScreenshotService = class {
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_window(includeFrame, includeCursor, stream,
screenshot.screenshot_window (includeFrame, includeCursor, filename,
(o, res) => {
try {
let [result, area] =
let [result, area, filenameUsed] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
result, area, stream, file, flash, invocation);
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror(e);
invocation.return_gerror (e);
}
});
}
@ -211,18 +147,15 @@ var ScreenshotService = class {
let screenshot = this._createScreenshot(invocation);
if (!screenshot)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot(includeCursor, stream,
screenshot.screenshot(includeCursor, filename,
(o, res) => {
try {
let [result, area] =
let [result, area, filenameUsed] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
result, area, stream, file, flash, invocation);
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror(e);
invocation.return_gerror (e);
}
});
}
@ -230,7 +163,7 @@ var ScreenshotService = class {
SelectAreaAsync(params, invocation) {
let selectArea = new SelectArea();
selectArea.show();
selectArea.connect('finished', (o, areaRectangle) => {
selectArea.connect('finished', (selectArea, areaRectangle) => {
if (areaRectangle) {
let retRectangle = this._unscaleArea(areaRectangle.x, areaRectangle.y,
areaRectangle.width, areaRectangle.height);
@ -252,7 +185,7 @@ var ScreenshotService = class {
"Invalid params");
return;
}
let flashspot = new Flashspot({ x, y, width, height });
let flashspot = new Flashspot({ x: x, y: y, width: width, height: height });
flashspot.fire();
invocation.return_value(null);
}
@ -260,20 +193,20 @@ var ScreenshotService = class {
PickColorAsync(params, invocation) {
let pickPixel = new PickPixel();
pickPixel.show();
pickPixel.connect('finished', (obj, coords) => {
pickPixel.connect('finished', (pickPixel, coords) => {
if (coords) {
let screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
screenshot.pick_color(coords.x, coords.y, (_o, res) => {
screenshot.pick_color(...coords, (o, res) => {
let [success_, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0,
]),
blue / 255.0
])
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
@ -286,61 +219,62 @@ var ScreenshotService = class {
}
};
var SelectArea = GObject.registerClass({
Signals: { 'finished': { param_types: [Meta.Rectangle.$gtype] } },
}, class SelectArea extends St.Widget {
_init() {
var SelectArea = class {
constructor() {
this._startX = -1;
this._startY = -1;
this._lastX = 0;
this._lastY = 0;
this._result = null;
super._init({
visible: false,
reactive: true,
x: 0,
y: 0,
});
Main.uiGroup.add_actor(this);
this._group = new St.Widget({ visible: false,
reactive: true,
x: 0,
y: 0 });
Main.uiGroup.add_actor(this._group);
this._grabHelper = new GrabHelper.GrabHelper(this);
this._grabHelper = new GrabHelper.GrabHelper(this._group);
this._group.connect('button-press-event',
this._onButtonPress.bind(this));
this._group.connect('button-release-event',
this._onButtonRelease.bind(this));
this._group.connect('motion-event',
this._onMotionEvent.bind(this));
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this.add_constraint(constraint);
this._group.add_constraint(constraint);
this._rubberband = new St.Widget({
style_class: 'select-area-rubberband',
visible: false,
visible: false
});
this.add_actor(this._rubberband);
this._group.add_actor(this._rubberband);
}
vfunc_show() {
if (!this._grabHelper.grab({ actor: this,
show() {
if (!this._grabHelper.grab({ actor: this._group,
onUngrab: this._onUngrab.bind(this) }))
return;
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this, null);
super.vfunc_show();
Main.uiGroup.set_child_above_sibling(this._group, null);
this._group.visible = true;
}
_getGeometry() {
return new Meta.Rectangle({
x: Math.min(this._startX, this._lastX),
y: Math.min(this._startY, this._lastY),
width: Math.abs(this._startX - this._lastX) + 1,
height: Math.abs(this._startY - this._lastY) + 1,
});
return { x: Math.min(this._startX, this._lastX),
y: Math.min(this._startY, this._lastY),
width: Math.abs(this._startX - this._lastX) + 1,
height: Math.abs(this._startY - this._lastY) + 1 };
}
vfunc_motion_event(motionEvent) {
_onMotionEvent(actor, event) {
if (this._startX == -1 || this._startY == -1 || this._result)
return Clutter.EVENT_PROPAGATE;
[this._lastX, this._lastY] = [motionEvent.x, motionEvent.y];
[this._lastX, this._lastY] = event.get_coords();
this._lastX = Math.floor(this._lastX);
this._lastY = Math.floor(this._lastY);
let geometry = this._getGeometry();
@ -352,8 +286,8 @@ var SelectArea = GObject.registerClass({
return Clutter.EVENT_PROPAGATE;
}
vfunc_button_press_event(buttonEvent) {
[this._startX, this._startY] = [buttonEvent.x, buttonEvent.y];
_onButtonPress(actor, event) {
[this._startX, this._startY] = event.get_coords();
this._startX = Math.floor(this._startX);
this._startY = Math.floor(this._startY);
this._rubberband.set_position(this._startX, this._startY);
@ -361,13 +295,13 @@ var SelectArea = GObject.registerClass({
return Clutter.EVENT_PROPAGATE;
}
vfunc_button_release_event() {
_onButtonRelease() {
this._result = this._getGeometry();
this.ease({
this._group.ease({
opacity: 0,
duration: 200,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._grabHelper.ungrab(),
onComplete: () => this._grabHelper.ungrab()
});
return Clutter.EVENT_PROPAGATE;
}
@ -377,42 +311,43 @@ var SelectArea = GObject.registerClass({
this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this.destroy();
this._group.destroy();
return GLib.SOURCE_REMOVE;
});
}
});
var PickPixel = GObject.registerClass({
Signals: { 'finished': { param_types: [Graphene.Point.$gtype] } },
}, class PickPixel extends St.Widget {
_init() {
super._init({ visible: false, reactive: true });
};
Signals.addSignalMethods(SelectArea.prototype);
var PickPixel = class {
constructor() {
this._result = null;
Main.uiGroup.add_actor(this);
this._group = new St.Widget({ visible: false,
reactive: true });
Main.uiGroup.add_actor(this._group);
this._grabHelper = new GrabHelper.GrabHelper(this);
this._grabHelper = new GrabHelper.GrabHelper(this._group);
this._group.connect('button-release-event',
this._onButtonRelease.bind(this));
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this.add_constraint(constraint);
this._group.add_constraint(constraint);
}
vfunc_show() {
if (!this._grabHelper.grab({ actor: this,
show() {
if (!this._grabHelper.grab({ actor: this._group,
onUngrab: this._onUngrab.bind(this) }))
return;
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this, null);
super.vfunc_show();
Main.uiGroup.set_child_above_sibling(this._group, null);
this._group.visible = true;
}
vfunc_button_release_event(buttonEvent) {
let { x, y } = buttonEvent;
this._result = new Graphene.Point({ x, y });
_onButtonRelease(actor, event) {
this._result = event.get_coords();
this._grabHelper.ungrab();
return Clutter.EVENT_PROPAGATE;
}
@ -422,29 +357,29 @@ var PickPixel = GObject.registerClass({
this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this.destroy();
this._group.destroy();
return GLib.SOURCE_REMOVE;
});
}
});
};
Signals.addSignalMethods(PickPixel.prototype);
var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
var Flashspot = GObject.registerClass(
class Flashspot extends Lightbox.Lightbox {
_init(area) {
super._init(Main.uiGroup, {
inhibitEvents: true,
width: area.width,
height: area.height,
});
this.style_class = 'flashspot';
this.set_position(area.x, area.y);
var Flashspot = class extends Lightbox.Lightbox {
constructor(area) {
super(Main.uiGroup, { inhibitEvents: true,
width: area.width,
height: area.height });
this.actor.style_class = 'flashspot';
this.actor.set_position(area.x, area.y);
}
fire(doneCallback) {
this.set({ visible: true, opacity: 255 });
this.ease({
this.actor.show();
this.actor.opacity = 255;
this.actor.ease({
opacity: 0,
duration: FLASHSPOT_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -452,7 +387,7 @@ class Flashspot extends Lightbox.Lightbox {
if (doneCallback)
doneCallback();
this.destroy();
},
}
});
}
});
};

View File

@ -32,8 +32,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
/**
* sleep:
* @param {number} milliseconds - number of milliseconds to wait
* @returns {Promise} that resolves after @milliseconds ms
* @milliseconds: number of milliseconds to wait
*
* Used within an automation script to pause the the execution of the
* current script for the specified amount of time. Use as
@ -51,7 +50,6 @@ function sleep(milliseconds) {
/**
* waitLeisure:
* @returns {Promise} that resolves when the shell is idle
*
* Used within an automation script to pause the the execution of the
* current script until the shell is completely idle. Use as
@ -92,13 +90,13 @@ function _callRemote(obj, method, ...args) {
/**
* createTestWindow:
* @param {Object} params: options for window creation.
* {number} [params.width=640] - width of window, in pixels
* {number} [params.height=480] - height of window, in pixels
* {bool} [params.alpha=false] - whether the window should have an alpha channel
* {bool} [params.maximized=false] - whether the window should be created maximized
* {bool} [params.redraws=false] - whether the window should continually redraw itself
* @returns {Promise}
* @params: options for window creation.
* width - width of window, in pixels (default 640)
* height - height of window, in pixels (default 480)
* alpha - whether the window should have an alpha channel (default false)
* maximized - whether the window should be created maximized (default false)
* redraws - whether the window should continually redraw itself (default false)
* @maximized: whethe the window should be created maximized
*
* Creates a window using gnome-shell-perf-helper for testing purposes.
* While this function can be used with yield in an automation
@ -121,7 +119,6 @@ function createTestWindow(params) {
/**
* waitTestWindows:
* @returns {Promise}
*
* Used within an automation script to pause until all windows previously
* created with createTestWindow have been mapped and exposed.
@ -133,7 +130,6 @@ function waitTestWindows() {
/**
* destroyTestWindows:
* @returns {Promise}
*
* Destroys all windows previously created with createTestWindow().
* While this function can be used with yield in an automation
@ -148,8 +144,8 @@ function destroyTestWindows() {
/**
* defineScriptEvent
* @param {string} name: The event will be called script.<name>
* @param {string} description: Short human-readable description of the event
* @name: The event will be called script.<name>
* @description: Short human-readable description of the event
*
* Convenience function to define a zero-argument performance event
* within the 'script' namespace that is reserved for events defined locally
@ -163,7 +159,7 @@ function defineScriptEvent(name, description) {
/**
* scriptEvent
* @param {string} name: Name registered with defineScriptEvent()
* @name: Name registered with defineScriptEvent()
*
* Convenience function to record a script-local performance event
* previously defined with defineScriptEvent
@ -204,8 +200,8 @@ function _collect(scriptModule, outputFile) {
let raw = f.replace(null, false,
Gio.FileCreateFlags.NONE,
null);
let out = Gio.BufferedOutputStream.new_sized(raw, 4096);
Shell.write_string_to_stream(out, "{\n");
let out = Gio.BufferedOutputStream.new_sized (raw, 4096);
Shell.write_string_to_stream (out, "{\n");
Shell.write_string_to_stream(out, '"events":\n');
Shell.PerfLog.get_default().dump_events(out);
@ -254,10 +250,10 @@ function _collect(scriptModule, outputFile) {
}
Shell.write_string_to_stream(out, ' ]');
Shell.write_string_to_stream(out, ',\n"log":\n');
Shell.write_string_to_stream (out, ',\n"log":\n');
Shell.PerfLog.get_default().dump_log(out);
Shell.write_string_to_stream(out, '\n}\n');
Shell.write_string_to_stream (out, '\n}\n');
out.close(null);
} else {
let metrics = [];
@ -266,21 +262,20 @@ function _collect(scriptModule, outputFile) {
metrics.sort();
print('------------------------------------------------------------');
print ('------------------------------------------------------------');
for (let i = 0; i < metrics.length; i++) {
let metric = metrics[i];
print(`# ${scriptModule.METRICS[metric].description}`);
print(`${metric}: ${scriptModule.METRICS[metric].value}${scriptModule.METRICS[metric].units}`);
print (`# ${scriptModule.METRICS[metric].description}`);
print (`${metric}: ${scriptModule.METRICS[metric].value}${scriptModule.METRICS[metric].units}`);
}
print('------------------------------------------------------------');
print ('------------------------------------------------------------');
}
}
/**
* runPerfScript
* @param {Object} scriptModule: module object with run and finish
* functions and event handlers
* @param {string} outputFile: path to write output to
* @scriptModule: module object with run and finish functions
* and event handlers
*
* Runs a script for automated collection of performance data. The
* script is defined as a Javascript module with specified contents.

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SearchResultsView */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid;
@ -32,79 +32,69 @@ class MaxWidthBox extends St.BoxLayout {
}
});
var SearchResult = GObject.registerClass(
class SearchResult extends St.Button {
_init(provider, metaInfo, resultsView) {
var SearchResult = class {
constructor(provider, metaInfo, resultsView) {
this.provider = provider;
this.metaInfo = metaInfo;
this._resultsView = resultsView;
super._init({
reactive: true,
can_focus: true,
track_hover: true,
});
}
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
vfunc_clicked() {
this.activate();
this.actor._delegate = this;
this.actor.connect('clicked', this.activate.bind(this));
}
activate() {
this.provider.activateResult(this.metaInfo.id, this._resultsView.terms);
if (this.metaInfo.clipboardText) {
St.Clipboard.get_default().set_text(
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
}
Main.overview.toggle();
this.emit('activate', this.metaInfo.id);
}
});
};
Signals.addSignalMethods(SearchResult.prototype);
var ListSearchResult = GObject.registerClass(
class ListSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
var ListSearchResult = class extends SearchResult {
this.style_class = 'list-search-result';
constructor(provider, metaInfo, resultsView) {
super(provider, metaInfo, resultsView);
let content = new St.BoxLayout({
style_class: 'list-search-result-content',
vertical: false,
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_expand: true,
});
this.set_child(content);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
this._termsChangedId = 0;
let titleBox = new St.BoxLayout({
style_class: 'list-search-result-title',
y_align: Clutter.ActorAlign.CENTER,
});
let titleBox = new St.BoxLayout({ style_class: 'list-search-result-title' });
content.add_child(titleBox);
content.add(titleBox, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon)
if (icon) {
titleBox.add(icon);
}
let title = new St.Label({
text: this.metaInfo['name'],
y_align: Clutter.ActorAlign.CENTER,
});
titleBox.add_child(title);
let title = new St.Label({ text: this.metaInfo['name'] });
titleBox.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this.label_actor = title;
this.actor.label_actor = title;
if (this.metaInfo['description']) {
this._descriptionLabel = new St.Label({
style_class: 'list-search-result-description',
y_align: Clutter.ActorAlign.CENTER,
});
content.add_child(this._descriptionLabel);
this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' });
content.add(this._descriptionLabel, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this._termsChangedId =
this._resultsView.connect('terms-changed',
@ -113,7 +103,7 @@ class ListSearchResult extends SearchResult {
this._highlightTerms();
}
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
}
get ICON_SIZE() {
@ -130,57 +120,50 @@ class ListSearchResult extends SearchResult {
this._resultsView.disconnect(this._termsChangedId);
this._termsChangedId = 0;
}
});
};
var GridSearchResult = GObject.registerClass(
class GridSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
var GridSearchResult = class extends SearchResult {
constructor(provider, metaInfo, resultsView) {
super(provider, metaInfo, resultsView);
this.style_class = 'grid-search-result';
this.actor.style_class = 'grid-search-result';
this.icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
let content = new St.Bin({
child: this.icon,
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_expand: true,
});
this.set_child(content);
this.label_actor = this.icon.label;
let content = new St.Bin({ child: this.icon });
this.actor.set_child(content);
this.actor.label_actor = this.icon.label;
}
});
var SearchResultsBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'focus-child': GObject.ParamSpec.object(
'focus-child', 'focus-child', 'focus-child',
GObject.ParamFlags.READABLE,
Clutter.Actor.$gtype),
},
}, class SearchResultsBase extends St.BoxLayout {
_init(provider, resultsView) {
super._init({ style_class: 'search-section', vertical: true });
};
var SearchResultsBase = class {
constructor(provider, resultsView) {
this.provider = provider;
this._resultsView = resultsView;
this._terms = [];
this._focusChild = null;
this._resultDisplayBin = new St.Bin();
this.add_child(this._resultDisplayBin);
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new St.Widget({ style_class: 'search-section-separator' });
this.add(separator);
this.actor.add(separator);
this._resultDisplays = {};
this._clipboard = St.Clipboard.get_default();
this._cancellable = new Gio.Cancellable();
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
this.actor.destroy();
}
_onDestroy() {
@ -197,21 +180,21 @@ var SearchResultsBase = GObject.registerClass({
clear() {
this._cancellable.cancel();
for (let resultId in this._resultDisplays)
this._resultDisplays[resultId].destroy();
this._resultDisplays[resultId].actor.destroy();
this._resultDisplays = {};
this._clearResultDisplay();
this.hide();
}
get focusChild() {
return this._focusChild;
this.actor.hide();
}
_keyFocusIn(actor) {
if (this._focusChild == actor)
return;
this._focusChild = actor;
this.notify('focus-child');
this.emit('key-focus-in', actor);
}
_activateResult(result, id) {
this.provider.activateResult(id, this._terms);
if (result.metaInfo.clipboardText)
this._clipboard.set_text(St.ClipboardType.CLIPBOARD, result.metaInfo.clipboardText);
Main.overview.toggle();
}
_setMoreCount(_count) {
@ -250,7 +233,8 @@ var SearchResultsBase = GObject.registerClass({
metasNeeded.forEach((resultId, i) => {
let meta = metas[i];
let display = this._createResultDisplay(meta);
display.connect('key-focus-in', this._keyFocusIn.bind(this));
display.connect('activate', this._activateResult.bind(this));
display.actor.connect('key-focus-in', this._keyFocusIn.bind(this));
this._resultDisplays[resultId] = display;
});
callback(true);
@ -262,7 +246,7 @@ var SearchResultsBase = GObject.registerClass({
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.hide();
this.actor.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
@ -281,23 +265,22 @@ var SearchResultsBase = GObject.registerClass({
// To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the
// content while filling in the results.
this.hide();
this.actor.hide();
this._clearResultDisplay();
results.forEach(resultId => {
this._addItem(this._resultDisplays[resultId]);
});
this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
this.show();
this.actor.show();
callback();
});
}
}
});
};
var ListSearchResults = GObject.registerClass(
class ListSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
var ListSearchResults = class extends SearchResultsBase {
constructor(provider, resultsView) {
super(provider, resultsView);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerInfo = new ProviderInfo(provider);
@ -308,14 +291,14 @@ class ListSearchResults extends SearchResultsBase {
Main.overview.toggle();
});
this._container.add_child(this.providerInfo);
this._container.add(this.providerInfo, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({
style_class: 'list-search-results',
vertical: true,
x_expand: true,
});
this._container.add_child(this._content);
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this._container.add(this._content, { expand: true });
this._resultDisplayBin.set_child(this._container);
}
@ -338,26 +321,26 @@ class ListSearchResults extends SearchResultsBase {
}
_addItem(display) {
this._content.add_actor(display);
this._content.add_actor(display.actor);
}
getFirstResult() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0);
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
};
Signals.addSignalMethods(ListSearchResults.prototype);
var GridSearchResults = GObject.registerClass(
class GridSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
var GridSearchResults = class extends SearchResultsBase {
constructor(provider, resultsView) {
super(provider, resultsView);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: Clutter.ActorAlign.CENTER });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid);
this._resultDisplayBin.set_child(this._bin);
@ -374,7 +357,7 @@ class GridSearchResults extends SearchResultsBase {
updateSearch(...args) {
if (this._notifyAllocationId)
this.disconnect(this._notifyAllocationId);
this.actor.disconnect(this._notifyAllocationId);
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
@ -382,7 +365,7 @@ class GridSearchResults extends SearchResultsBase {
// Make sure the maximum number of results calculated by
// _getMaxDisplayedResults() is updated after width changes.
this._notifyAllocationId = this.connect('notify::allocation', () => {
this._notifyAllocationId = this.actor.connect('notify::allocation', () => {
if (this._updateSearchLater)
return;
this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
@ -396,7 +379,7 @@ class GridSearchResults extends SearchResultsBase {
}
_getMaxDisplayedResults() {
let width = this.allocation.get_width();
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
if (width == 0)
return -1;
@ -419,30 +402,25 @@ class GridSearchResults extends SearchResultsBase {
getFirstResult() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0);
return this._grid.getItemAtIndex(0)._delegate;
else
return null;
}
});
};
Signals.addSignalMethods(GridSearchResults.prototype);
var SearchResultsView = GObject.registerClass({
Signals: { 'terms-changed': {} },
}, class SearchResultsView extends St.BoxLayout {
_init() {
super._init({ name: 'searchResults', vertical: true });
var SearchResults = class {
constructor() {
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this._content = new MaxWidthBox({
name: 'searchResultsContent',
vertical: true,
x_expand: true,
});
this._content = new MaxWidthBox({ name: 'searchResultsContent',
vertical: true });
this._scrollView = new St.ScrollView({
overlay_scrollbars: true,
style_class: 'search-display vfade',
x_expand: true,
y_expand: true,
});
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
overlay_scrollbars: true,
style_class: 'search-display vfade' });
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
this._scrollView.add_actor(this._content);
@ -450,15 +428,16 @@ var SearchResultsView = GObject.registerClass({
action.connect('pan', this._onPan.bind(this));
this._scrollView.add_action(action);
this.add_child(this._scrollView);
this.actor.add(this._scrollView, { x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this._statusText = new St.Label({
style_class: 'search-statustext',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
this._statusBin = new St.Bin({ y_expand: true });
this.add_child(this._statusBin);
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.actor.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._highlightDefault = false;
@ -488,10 +467,6 @@ var SearchResultsView = GObject.registerClass({
this._reloadRemoteProviders();
}
get terms() {
return this._terms;
}
_reloadRemoteProviders() {
let remoteProviders = this._providers.filter(p => p.isRemoteProvider);
remoteProviders.forEach(provider => {
@ -550,20 +525,19 @@ var SearchResultsView = GObject.registerClass({
provider.searchInProgress = true;
let previousProviderResults = previousResults[provider.id];
if (this._isSubSearch && previousProviderResults) {
if (this._isSubSearch && previousProviderResults)
provider.getSubsearchResultSet(previousProviderResults,
this._terms,
results => {
this._gotResults(results, provider);
},
this._cancellable);
} else {
else
provider.getInitialResultSet(this._terms,
results => {
this._gotResults(results, provider);
},
this._cancellable);
}
});
this._updateSearchProgress();
@ -617,12 +591,12 @@ var SearchResultsView = GObject.registerClass({
_onPan(action) {
let [dist_, dx_, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.height) * adjustment.page_size;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
}
_focusChildChanged(provider) {
Util.ensureActorVisibleInScrollView(this._scrollView, provider.focusChild);
_keyFocusIn(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
}
_ensureProviderDisplay(provider) {
@ -635,9 +609,9 @@ var SearchResultsView = GObject.registerClass({
else
providerDisplay = new GridSearchResults(provider, this);
providerDisplay.connect('notify::focus-child', this._focusChildChanged.bind(this));
providerDisplay.hide();
this._content.add(providerDisplay);
providerDisplay.connect('key-focus-in', this._keyFocusIn.bind(this));
providerDisplay.actor.hide();
this._content.add(providerDisplay.actor);
provider.display = providerDisplay;
}
@ -655,7 +629,7 @@ var SearchResultsView = GObject.registerClass({
let provider = providers[i];
let display = provider.display;
if (!display.visible)
if (!display.actor.visible)
continue;
let firstResult = display.getFirstResult();
@ -683,17 +657,18 @@ var SearchResultsView = GObject.registerClass({
_updateSearchProgress() {
let haveResults = this._providers.some(provider => {
let display = provider.display;
return display.getFirstResult() != null;
return (display.getFirstResult() != null);
});
this._scrollView.visible = haveResults;
this._statusBin.visible = !haveResults;
if (!haveResults) {
if (this.searchInProgress)
if (this.searchInProgress) {
this._statusText.set_text(_("Searching…"));
else
} else {
this._statusText.set_text(_("No results."));
}
}
}
@ -729,22 +704,22 @@ var SearchResultsView = GObject.registerClass({
this._doSearch();
if (this._defaultResult)
this._defaultResult.popup_menu();
this._defaultResult.actor.popup_menu();
}
navigateFocus(direction) {
let rtl = this.get_text_direction() == Clutter.TextDirection.RTL;
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == St.DirectionType.TAB_BACKWARD ||
direction == (rtl
? St.DirectionType.RIGHT
: St.DirectionType.LEFT) ||
direction == St.DirectionType.UP) {
this.navigate_focus(null, direction, false);
this.actor.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult : null;
this.navigate_focus(from, direction, false);
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
}
_setSelected(result, selected) {
@ -752,10 +727,10 @@ var SearchResultsView = GObject.registerClass({
return;
if (selected) {
result.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result);
result.actor.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
} else {
result.remove_style_pseudo_class('selected');
result.actor.remove_style_pseudo_class('selected');
}
}
@ -768,20 +743,18 @@ var SearchResultsView = GObject.registerClass({
return description.replace(this._highlightRegex, '<b>$1</b>');
}
});
};
Signals.addSignalMethods(SearchResults.prototype);
var ProviderInfo = GObject.registerClass(
class ProviderInfo extends St.Button {
_init(provider) {
this.provider = provider;
super._init({
style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true,
y_align: Clutter.ActorAlign.START,
});
super._init({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.BoxLayout({ vertical: false,
style_class: 'list-search-provider-content' });

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